Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
akhercha committed Oct 2, 2024
2 parents d854d3a + 2e1c739 commit 424d3bf
Show file tree
Hide file tree
Showing 9 changed files with 230 additions and 21 deletions.
37 changes: 19 additions & 18 deletions .github/workflows/docker-build.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
name: Build and Push Docker Image to GitHub Container Registry
name: Build/Push Docker Image to ghcr

on:
release:
types: [published]
workflow_dispatch:

permissions:
contents: read
packages: write

jobs:
build:
build_and_push:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
with:
install: true
driver: docker-container
driver: docker

- name: Log in to GitHub Container Registry
uses: docker/login-action@v2
Expand All @@ -26,20 +28,19 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push Docker image to GitHub Container Registry
- name: Set Docker image tag
id: vars
run: |
if [ "${{ github.event_name }}" == "release" ]; then
echo "TAG=${{ github.event.release.tag_name }}" >> $GITHUB_ENV
else
echo "TAG=latest" >> $GITHUB_ENV
fi
- name: Build and push Docker image
uses: docker/build-push-action@v4
with:
context: .
file: ./Dockerfile
push: true
tags: |
ghcr.io/${{ github.repository_owner }}/madara:latest
ghcr.io/${{ github.repository_owner }}/madara:${{ github.event.release.tag_name }}
labels: |
org.opencontainers.image.source=${{ github.repository.html_url }}
org.opencontainers.image.version=${{ github.event.release.tag_name }}
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Post successful message
run: echo "Docker image built and pushed successfully"
tags: ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ env.TAG }}
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- feat: `exex_pragma_dispatch` implementation
- feat: Madara ExExs proof of concept
- test: add block conversion task test
- fix(docs): updated readme and fixed launcher
- fix(ci): added gateway key to fix rate limit on tests
- feat(cli): launcher script and release workflows
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions crates/client/block_import/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ repository.workspace = true
version.workspace = true
license.workspace = true

[features]
default = []
testing = []
[dependencies]
anyhow.workspace = true
bitvec.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/client/block_import/src/tests.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
#[cfg(test)]
#[cfg(any(test, feature = "testing"))]
pub mod block_import_utils;
28 changes: 27 additions & 1 deletion crates/client/block_import/src/tests/block_import_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ use mp_block::header::{GasPrices, L1DataAvailabilityMode};
use mp_block::Header;
use mp_chain_config::StarknetVersion;
use mp_state_update::StateDiff;
use starknet_core::types::Felt;

use crate::{
BlockValidationContext, PreValidatedBlock, PreValidatedPendingBlock, UnverifiedHeader, ValidatedCommitments,
BlockValidationContext, PreValidatedBlock, PreValidatedPendingBlock, UnverifiedCommitments, UnverifiedFullBlock,
UnverifiedHeader, ValidatedCommitments,
};
use starknet_api::{core::ChainId, felt};

Expand Down Expand Up @@ -105,6 +107,30 @@ pub fn create_dummy_block() -> PreValidatedBlock {
}
}

/// Creates a dummy PreValidatedBlock for testing purposes.
///
/// This function generates a PreValidatedBlock with predefined values,
/// useful for testing update_tries scenarios.
pub fn create_dummy_unverified_full_block() -> UnverifiedFullBlock {
UnverifiedFullBlock {
header: UnverifiedHeader {
parent_block_hash: Some(Felt::ZERO),
sequencer_address: Felt::ZERO,
block_timestamp: 0,
protocol_version: StarknetVersion::default(),
l1_gas_price: GasPrices::default(),
l1_da_mode: L1DataAvailabilityMode::Blob,
},
transactions: vec![],
unverified_block_number: Some(0),
state_diff: StateDiff::default(),
receipts: vec![],
declared_classes: vec![],
commitments: UnverifiedCommitments::default(),
trusted_converted_classes: vec![],
}
}

/// Creates a dummy PreValidatedPendingBlock for testing purposes.
pub fn create_dummy_pending_block() -> PreValidatedPendingBlock {
PreValidatedPendingBlock {
Expand Down
3 changes: 3 additions & 0 deletions crates/client/sync/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ mp-class = { workspace = true }
mp-convert = { workspace = true }
mp-exex = { workspace = true }
mp-receipt = { workspace = true }
mp-state-update = { workspace = true }
mp-transactions = { workspace = true }
mp-utils = { workspace = true }

Expand Down Expand Up @@ -62,3 +63,5 @@ url = { workspace = true }
httpmock = { workspace = true }
tempfile = { workspace = true }
rstest = { workspace = true }
mc-db = { workspace = true, features = ["testing"] }
mc-block-import = { workspace = true, features = ["testing"] }
174 changes: 174 additions & 0 deletions crates/client/sync/src/l2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,3 +265,177 @@ pub async fn sync(

Ok(())
}

#[cfg(test)]
mod tests {
use super::*;
use crate::tests::utils::gateway::{test_setup, TestContext};
use mc_block_import::tests::block_import_utils::create_dummy_unverified_full_block;
use mc_block_import::BlockImporter;
use mc_db::{db_block_id::DbBlockId, MadaraBackend};
use mc_metrics::MetricsRegistry;
use mc_telemetry::TelemetryService;
use mp_block::header::L1DataAvailabilityMode;
use mp_block::MadaraBlock;
use mp_chain_config::StarknetVersion;
use rstest::rstest;
use starknet_types_core::felt::Felt;
use std::sync::Arc;
use tokio::sync::mpsc;

/// Test the `l2_verify_and_apply_task` function.
///
///
/// This test verifies the behavior of the `l2_verify_and_apply_task` by simulating
/// a block verification and application process.
///
/// # Test Steps
/// 1. Initialize the backend and necessary components.
/// 2. Create a mock block.
/// 3. Spawn the `l2_verify_and_apply_task` in a new thread.
/// 4. Send the mock block for verification and application.
/// 5. Wait for the task to complete or for a timeout to occur.
/// 6. Verify that the block has been correctly applied to the backend.
///
/// # Panics
/// - If the task fails or if the waiting timeout is exceeded.
/// - If the block is not correctly applied to the backend.
#[rstest]
#[tokio::test]
async fn test_l2_verify_and_apply_task(test_setup: Arc<MadaraBackend>) {
let backend = test_setup;
let (block_conv_sender, block_conv_receiver) = mpsc::channel(100);
let block_importer =
Arc::new(BlockImporter::new(backend.clone(), &MetricsRegistry::dummy(), None, true).unwrap());
let validation = BlockValidationContext::new(backend.chain_config().chain_id.clone());
let telemetry = TelemetryService::new(true, vec![]).unwrap().new_handle();

let mock_block = create_dummy_unverified_full_block();

let task_handle = tokio::spawn(l2_verify_and_apply_task(
backend.clone(),
block_conv_receiver,
block_importer.clone(),
validation.clone(),
Some(1),
telemetry,
));

let mock_pre_validated_block = block_importer.pre_validate(mock_block, validation.clone()).await.unwrap();
block_conv_sender.send(mock_pre_validated_block).await.unwrap();

drop(block_conv_sender);

match tokio::time::timeout(std::time::Duration::from_secs(120), task_handle).await {
Ok(Ok(_)) => (),
Ok(Err(e)) => panic!("Task failed: {:?}", e),
Err(_) => panic!("Timeout reached while waiting for task completion"),
}

let applied_block = backend.get_block(&DbBlockId::BlockN(0)).unwrap();
assert!(applied_block.is_some(), "The block was not applied correctly");
let applied_block = MadaraBlock::try_from(applied_block.unwrap()).unwrap();

assert_eq!(applied_block.info.header.block_number, 0, "Block number does not match");
assert_eq!(applied_block.info.header.block_timestamp, 0, "Block timestamp does not match");
assert_eq!(applied_block.info.header.parent_block_hash, Felt::ZERO, "Parent block hash does not match");
assert!(applied_block.inner.transactions.is_empty(), "Block should not contain any transactions");
assert_eq!(
applied_block.info.header.protocol_version,
StarknetVersion::default(),
"Protocol version does not match"
);
assert_eq!(applied_block.info.header.sequencer_address, Felt::ZERO, "Sequencer address does not match");
assert_eq!(applied_block.info.header.l1_gas_price.eth_l1_gas_price, 0, "L1 gas price (ETH) does not match");
assert_eq!(applied_block.info.header.l1_gas_price.strk_l1_gas_price, 0, "L1 gas price (STRK) does not match");
assert_eq!(applied_block.info.header.l1_da_mode, L1DataAvailabilityMode::Blob, "L1 DA mode does not match");
}

/// Test the `l2_block_conversion_task` function.
///
/// Steps:
/// 1. Initialize necessary components.
/// 2. Create a mock block.
/// 3. Send the mock block to updates_sender
/// 4. Call the `l2_block_conversion_task` function with the mock data.
/// 5. Verify the results and ensure the function behaves as expected.
#[rstest]
#[tokio::test]
async fn test_l2_block_conversion_task(test_setup: Arc<MadaraBackend>) {
let backend = test_setup;
let (updates_sender, updates_receiver) = mpsc::channel(100);
let (output_sender, mut output_receiver) = mpsc::channel(100);
let block_import =
Arc::new(BlockImporter::new(backend.clone(), &MetricsRegistry::dummy(), None, true).unwrap());
let validation = BlockValidationContext::new(backend.chain_config().chain_id.clone());

let mock_block = create_dummy_unverified_full_block();

updates_sender.send(mock_block).await.unwrap();

let task_handle =
tokio::spawn(l2_block_conversion_task(updates_receiver, output_sender, block_import, validation));

let result = tokio::time::timeout(std::time::Duration::from_secs(5), output_receiver.recv()).await;
match result {
Ok(Some(b)) => {
assert_eq!(b.unverified_block_number, Some(0), "Block number does not match");
}
Ok(None) => panic!("Channel closed without receiving a result"),
Err(_) => panic!("Timeout reached while waiting for result"),
}

// Close the updates_sender channel to allow the task to complete
drop(updates_sender);

match tokio::time::timeout(std::time::Duration::from_secs(5), task_handle).await {
Ok(Ok(_)) => (),
Ok(Err(e)) => panic!("Task failed: {:?}", e),
Err(_) => panic!("Timeout reached while waiting for task completion"),
}
}

/// Test the `l2_pending_block_task` function.
///
/// This test function verifies the behavior of the `l2_pending_block_task`.
/// It simulates the necessary environment and checks that the task executes correctly
/// within a specified timeout.
///
/// # Test Steps
/// 1. Initialize the backend and test context.
/// 2. Create a `BlockImporter` and a `BlockValidationContext`.
/// 3. Spawn the `l2_pending_block_task` in a new thread.
/// 4. Simulate the "once_caught_up" signal.
/// 5. Wait for the task to complete or for a timeout to occur.
///
/// # Panics
/// - If the task fails or if the waiting timeout is exceeded.
#[rstest]
#[tokio::test]
async fn test_l2_pending_block_task(test_setup: Arc<MadaraBackend>) {
let backend = test_setup;
let ctx = TestContext::new(backend.clone());
let block_import =
Arc::new(BlockImporter::new(backend.clone(), &MetricsRegistry::dummy(), None, true).unwrap());
let validation = BlockValidationContext::new(backend.chain_config().chain_id.clone());

let task_handle = tokio::spawn(l2_pending_block_task(
backend.clone(),
block_import.clone(),
validation.clone(),
ctx.once_caught_up_receiver,
ctx.provider.clone(),
std::time::Duration::from_secs(5),
));

// Simulate the "once_caught_up" signal
ctx.once_caught_up_sender.send(()).unwrap();

// Wait for the task to complete
match tokio::time::timeout(std::time::Duration::from_secs(120), task_handle).await {
Ok(Ok(_)) => (),
Ok(Err(e)) => panic!("Task failed: {:?}", e),
Err(_) => panic!("Timeout reached while waiting for task completion"),
}
}
}
2 changes: 1 addition & 1 deletion scripts/launcher
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ tput rc
tput ed

# Check if the image is available locally
IMAGE_NAME="ghcr.io/madara-alliance/madara/madara:latest"
IMAGE_NAME="ghcr.io/madara-alliance/madara:latest"
if docker images --format "{{.Repository}}:{{.Tag}}" | grep -q "$IMAGE_NAME"; then
echo -e "\n📦 ${GREEN}Docker image '$IMAGE_NAME' is already available locally.${NC}"
else
Expand Down

0 comments on commit 424d3bf

Please sign in to comment.