Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
d80987f
tests: add test fixture for easier abstraction
greged93 Nov 3, 2025
0e79430
Merge branch 'main' into tests/improve-framework
greged93 Nov 3, 2025
395add0
fix: lints
greged93 Nov 3, 2025
3c6f416
fix: smol rework
greged93 Nov 3, 2025
e7da229
fix: fmt
greged93 Nov 3, 2025
81c5db8
tests: extend helpers and migrate
greged93 Nov 5, 2025
2d48822
tests: answer comments + finish migration
greged93 Nov 6, 2025
fe784c1
tests: migrate remaining tests
greged93 Nov 6, 2025
066609d
Merge branch 'main' into tests/improve-framework
greged93 Nov 6, 2025
8c2bfc7
tests: migration after merge
greged93 Nov 6, 2025
a64812f
tests: cleaning + fix
greged93 Nov 6, 2025
02bbc3e
tests: disable eth wire bridge
greged93 Nov 6, 2025
537b6a9
tests: use expect_tx
greged93 Nov 6, 2025
a94f09b
fix: clippy
greged93 Nov 6, 2025
1a95fd3
Merge branch 'main' into tests/improve-framework
greged93 Nov 16, 2025
7d8ab02
chore: answer comments
greged93 Nov 16, 2025
c3a51d6
Merge branch 'main' into tests/improve-framework
yiweichi Nov 17, 2025
361a66e
merge main branch
yiweichi Nov 17, 2025
b50e8c0
test: add anvil to testFixture
yiweichi Nov 17, 2025
c820cbb
test: add anvil to test fixture
yiweichi Nov 18, 2025
3d0c580
Merge branch 'main' into morty-add-anvil-to-test-fixture
yiweichi Nov 18, 2025
4df57f1
feat: add test l1 reorg
yiweichi Nov 20, 2025
46638aa
feat: add test l1 reorg
yiweichi Nov 21, 2025
c703985
Merge branch 'main' into morty-add-anvil-to-test-fixture
yiweichi Nov 21, 2025
82d4178
test: add test_l1_sync_batch_commit
yiweichi Nov 25, 2025
14ccd64
test: add test_l1_sync_batch_finalized
yiweichi Nov 26, 2025
b38b802
test: add l1 reorg tests
yiweichi Nov 27, 2025
8765085
test: add l1 reorg tests
yiweichi Nov 27, 2025
0b8dd48
fix: chainspec dev l1 config
yiweichi Nov 28, 2025
d560c36
Merge branch 'main' into morty-add-anvil-to-test-fixture
yiweichi Nov 28, 2025
371bc70
fix: ci
yiweichi Nov 28, 2025
7672169
improve anvil config
yiweichi Nov 28, 2025
a66cae7
improve comments
yiweichi Nov 28, 2025
1eb8f41
fix: l1 sync test && address some comments
yiweichi Dec 1, 2025
11344f8
fix: l1 reorg test
yiweichi Dec 1, 2025
c50f330
address comment
yiweichi Dec 1, 2025
29dee41
feat: use AnvilApi
yiweichi Dec 2, 2025
6e2db8a
fix ci
yiweichi Dec 2, 2025
c7fa7e4
Merge branch 'main' into morty-add-anvil-to-test-fixture
yiweichi Dec 2, 2025
e7f00c3
fix: read test tx in one
yiweichi Dec 2, 2025
731ae47
add test-utils
yiweichi Dec 2, 2025
5a03a6b
fix ci
yiweichi Dec 2, 2025
10b540c
fix: address comment
yiweichi Dec 2, 2025
926f00e
test: add test_l1_sync_batch_revert_before_l1_synced
yiweichi Dec 2, 2025
a1aac4f
Merge branch 'main' into morty-add-anvil-to-test-fixture
yiweichi Dec 2, 2025
18c2a4c
fix: ci
yiweichi Dec 2, 2025
61ee962
add database to test fixture
yiweichi Dec 2, 2025
618bd53
fix: test_l1_sync_batch_finalized
yiweichi Dec 3, 2025
8c9f40f
update comment
yiweichi Dec 3, 2025
087ff57
fix: patch svm-rs and svm-rs-builder
yiweichi Dec 4, 2025
aad3527
Merge branch 'main' into morty-add-anvil-to-test-fixture
yiweichi Dec 4, 2025
1c168fa
clean up anvil_state.json (this is not a fix)
yiweichi Dec 4, 2025
23c0d99
clean up anvil_state.json (this is not a fix)
yiweichi Dec 4, 2025
b503a8e
feat: remove svm patch
yiweichi Dec 4, 2025
6cbd20d
put finalized_block fix behind #[cfg(feature = test-utils)]
yiweichi Dec 4, 2025
94736e7
fmt
yiweichi Dec 4, 2025
42a991c
fix: use database handle from chain-orchastrator handle
yiweichi Dec 5, 2025
fd91faf
Merge branch 'main' into morty-add-anvil-to-test-fixture
yiweichi Dec 5, 2025
27c3434
feat: add reboot tests (#467)
yiweichi Jan 4, 2026
cbd6096
merge mian
yiweichi Jan 4, 2026
46e2d5d
merge mian
yiweichi Jan 4, 2026
3db8192
fix: tests
yiweichi Jan 5, 2026
bc57c6c
fix: ci
yiweichi Jan 6, 2026
8a0db0b
fix: ci
yiweichi Jan 7, 2026
12181a9
Merge branch 'main' into morty-add-anvil-to-test-fixture
yiweichi Jan 7, 2026
dcd83c8
increase DEFAULT_EVENT_WAIT_TIMEOUT for ci
yiweichi Jan 7, 2026
a803877
make DEFAULT_EVENT_WAIT_TIMEOUT configurable
yiweichi Jan 7, 2026
1ec255e
ci: log failure event waiting
yiweichi Jan 7, 2026
a4a433f
test
yiweichi Jan 7, 2026
c2ba869
test
yiweichi Jan 7, 2026
866663d
test
yiweichi Jan 7, 2026
f994717
test
yiweichi Jan 7, 2026
8a0f806
test
yiweichi Jan 7, 2026
dffda1e
test
yiweichi Jan 7, 2026
372323d
test
yiweichi Jan 7, 2026
a538e83
test
yiweichi Jan 7, 2026
005a130
test
yiweichi Jan 7, 2026
5fba429
test
yiweichi Jan 7, 2026
01509c1
test
yiweichi Jan 7, 2026
f396937
feat: shutdown refactor (#472)
frisitano Jan 12, 2026
5966e72
fix: comment
yiweichi Jan 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,845 changes: 2,560 additions & 285 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,13 @@ alloy-consensus = { version = "1.0.37", default-features = false }
alloy-eips = { version = "1.0.37", default-features = false }
alloy-json-rpc = { version = "1.0.37", default-features = false }
alloy-network = { version = "1.0.37", default-features = false }
alloy-node-bindings = { version = "1.0.37", default-features = false }
alloy-primitives = { version = "1.4.1", default-features = false }
alloy-provider = { version = "1.0.37", default-features = false }
alloy-rpc-client = { version = "1.0.37", default-features = false }
alloy-rpc-types-engine = { version = "1.0.37", default-features = false }
alloy-rpc-types-eth = { version = "1.0.37", default-features = false }
alloy-rpc-types-anvil = { version = "1.0.37", default-features = false }
alloy-sol-types = { version = "1.4.1", default-features = false }
alloy-signer = { version = "1.0.37", default-features = false }
alloy-signer-local = { version = "1.0.37", default-features = false }
Expand All @@ -150,9 +152,11 @@ scroll-alloy-rpc-types-engine = { git = "https://github.com/scroll-tech/reth.git

# reth
reth-chainspec = { git = "https://github.com/scroll-tech/reth.git", tag = "scroll-v91.4", default-features = false }
reth-db = { git = "https://github.com/scroll-tech/reth.git", tag = "scroll-v91.4", default-features = false }
reth-e2e-test-utils = { git = "https://github.com/scroll-tech/reth.git", tag = "scroll-v91.4" }
reth-eth-wire = { git = "https://github.com/scroll-tech/reth.git", tag = "scroll-v91.4", default-features = false }
reth-eth-wire-types = { git = "https://github.com/scroll-tech/reth.git", tag = "scroll-v91.4", default-features = false }
reth-fs-util = { git = "https://github.com/scroll-tech/reth.git", tag = "scroll-v91.4", default-features = false }
reth-network = { git = "https://github.com/scroll-tech/reth.git", tag = "scroll-v91.4", default-features = false }
reth-network-api = { git = "https://github.com/scroll-tech/reth.git", tag = "scroll-v91.4", default-features = false }
reth-network-p2p = { git = "https://github.com/scroll-tech/reth.git", tag = "scroll-v91.4", default-features = false }
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ lint: fmt lint-toml clippy udeps codespell zepter

.PHONY: test
test:
cargo nextest run \
cargo +nightly-2026-01-05 nextest run \
--workspace \
--locked \
--all-features \
Expand Down
4 changes: 3 additions & 1 deletion crates/chain-orchestrator/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub enum ChainOrchestratorEvent {
l1_block_number: u64,
},
/// A batch has been finalized returning a list of finalized batches.
BatchFinalized {
BatchFinalizeIndexed {
/// The L1 block info at which the batch finalization event was received.
l1_block_info: BlockInfo,
/// The list of batches that have been triggered for the derivation pipeline.
Expand Down Expand Up @@ -119,4 +119,6 @@ pub enum ChainOrchestratorEvent {
},
/// The head of the fork choice state has been updated in the engine driver.
FcsHeadUpdated(BlockInfo),
/// The chain orchestrator is shutting down.
Shutdown,
}
3 changes: 2 additions & 1 deletion crates/chain-orchestrator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ impl<
biased;

_guard = &mut shutdown => {
self.notify(ChainOrchestratorEvent::Shutdown);
break;
}
Some(command) = self.handle_rx.recv() => {
Expand Down Expand Up @@ -838,7 +839,7 @@ impl<
self.derivation_pipeline.push_batch(*batch, BatchStatus::Finalized).await;
}

Ok(Some(ChainOrchestratorEvent::BatchFinalized { l1_block_info, triggered_batches }))
Ok(Some(ChainOrchestratorEvent::BatchFinalizeIndexed { l1_block_info, triggered_batches }))
}

/// Handles a batch revert event by updating the database.
Expand Down
12 changes: 12 additions & 0 deletions crates/node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,14 @@ aws-sdk-kms = "1.76.0"

# test-utils
alloy-eips = { workspace = true, optional = true }
anvil = { git = "https://github.com/foundry-rs/foundry.git", rev = "2c84e1c970d11ef5023a77d8002a1cb70b143888", default-features = false, optional = true }
alloy-rpc-types-eth = { workspace = true, optional = true }
alloy-rpc-types-engine = { workspace = true, optional = true }
alloy-rpc-types-anvil = { workspace = true, optional = true }
reth-db = { workspace = true, optional = true, features = ["test-utils"] }
reth-e2e-test-utils = { workspace = true, optional = true }
reth-engine-local = { workspace = true, optional = true }
reth-fs-util = { workspace = true, optional = true }
reth-provider = { workspace = true, optional = true }
reth-rpc-layer = { workspace = true, optional = true }
reth-rpc-server-types = { workspace = true, optional = true }
Expand Down Expand Up @@ -110,6 +114,7 @@ console-subscriber = "0.5.0"
alloy-chains.workspace = true
alloy-eips.workspace = true
futures.workspace = true
reth-db = { workspace = true, features = ["test-utils"] }
reth-e2e-test-utils.workspace = true
reth-node-core.workspace = true
reth-provider.workspace = true
Expand All @@ -130,7 +135,9 @@ alloy-rpc-types-eth = { workspace = true }
[features]
js-tracer = ["reth-scroll-node/js-tracer", "reth-scroll-rpc/js-tracer"]
test-utils = [
"reth-db",
"reth-engine-local",
"reth-fs-util",
"reth-trie-db/test-utils",
"reth-chainspec/test-utils",
"reth-evm/test-utils",
Expand All @@ -156,6 +163,11 @@ test-utils = [
"rollup-node-chain-orchestrator/test-utils",
"scroll-network/test-utils",
"alloy-eips",
"anvil",
"reth-storage-api",
"alloy-rpc-types-eth",
"alloy-rpc-types-anvil",
"alloy-provider/anvil-api",
"alloy-provider/anvil-node",
"reth-db?/test-utils",
]
126 changes: 71 additions & 55 deletions crates/node/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use rollup_node_providers::{
use rollup_node_sequencer::{
L1MessageInclusionMode, PayloadBuildingConfig, Sequencer, SequencerConfig,
};
use rollup_node_watcher::{L1Watcher, L1WatcherHandle};
use rollup_node_watcher::{L1Watcher, L1WatcherCommand};
use scroll_alloy_hardforks::ScrollHardforks;
use scroll_alloy_network::Scroll;
use scroll_alloy_provider::{ScrollAuthApiEngineClient, ScrollEngineApi};
Expand All @@ -53,12 +53,23 @@ use scroll_network::ScrollNetworkManager;
use scroll_wire::ScrollWireEvent;
use tokio::sync::mpsc::UnboundedReceiver;

/// A struct that represents the arguments for the rollup node.
#[derive(Debug, Clone, clap::Args)]
pub struct ScrollRollupNodeConfig {
/// Test-related configuration arguments.
#[derive(Debug, Clone, Default, clap::Args)]
pub struct TestArgs {
/// Whether the rollup node should be run in test mode.
#[arg(long)]
pub test: bool,
/// Test mode: skip L1 watcher Synced notifications.
#[arg(long, default_value = "false")]
pub skip_l1_synced: bool,
}

/// A struct that represents the arguments for the rollup node.
#[derive(Debug, Clone, clap::Args)]
pub struct ScrollRollupNodeConfig {
/// Test-related arguments
#[command(flatten)]
pub test_args: TestArgs,
/// Consensus args
#[command(flatten)]
pub consensus_args: ConsensusArgs,
Expand Down Expand Up @@ -136,6 +147,7 @@ impl ScrollRollupNodeConfig {
) -> eyre::Result<()> {
// Instantiate the database
let db_path = node_config.datadir().db();

let database_path = if let Some(database_path) = &self.database_args.rn_db_path {
database_path.to_string_lossy().to_string()
} else {
Expand Down Expand Up @@ -235,7 +247,7 @@ impl ScrollRollupNodeConfig {
// Run the database migrations
if let Some(named) = chain_spec.chain().named() {
named
.migrate(db.inner().get_connection(), self.test)
.migrate(db.inner().get_connection(), self.test_args.test)
.await
.expect("failed to perform migration");
} else {
Expand Down Expand Up @@ -349,49 +361,45 @@ impl ScrollRollupNodeConfig {
};
let consensus = self.consensus_args.consensus(authorized_signer)?;

// Define some types to support definitions of return type of following function in no_std.
#[cfg(feature = "test-utils")]
type L1WatcherMockOpt = Option<rollup_node_watcher::test_utils::L1WatcherMock>;

#[cfg(not(feature = "test-utils"))]
type L1WatcherMockOpt = Option<std::convert::Infallible>;

let (_l1_watcher_mock, l1_watcher_handle): (L1WatcherMockOpt, Option<L1WatcherHandle>) =
if let Some(provider) = l1_provider.filter(|_| !self.test) {
tracing::info!(target: "scroll::node::args", ?l1_block_startup_info, "Starting L1 watcher");
(
None,
Some(
L1Watcher::spawn(
provider,
l1_block_startup_info,
node_config,
self.l1_provider_args.logs_query_block_range,
)
.await,
),
)
} else {
// Create a channel for L1 notifications that we can use to inject L1 messages for
// testing
let is_anvil_provider = self.blob_provider_args.anvil_url.is_some();

let (_l1_notification_tx, _l1_command_rx, l1_watcher_handle): (_, _, _) = if let Some(
provider,
) =
l1_provider.filter(|_| !self.test_args.test || is_anvil_provider)
{
tracing::info!(target: "scroll::node::args", ?l1_block_startup_info, "Starting L1 watcher");

#[cfg(feature = "test-utils")]
let skip_synced = self.test_args.test && self.test_args.skip_l1_synced;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need both or can we just use self.test_args.skip_l1_synced?


let (notification_tx, handle) = L1Watcher::spawn(
provider,
l1_block_startup_info,
node_config,
self.l1_provider_args.logs_query_block_range,
#[cfg(feature = "test-utils")]
{
let (notification_tx, notification_rx) = tokio::sync::mpsc::channel(1000);
let (command_tx, command_rx) = tokio::sync::mpsc::unbounded_channel();
let handle =
rollup_node_watcher::L1WatcherHandle::new(command_tx, notification_rx);
let watcher_mock = rollup_node_watcher::test_utils::L1WatcherMock {
command_rx: Arc::new(tokio::sync::Mutex::new(command_rx)),
notification_tx,
};
(Some(watcher_mock), Some(handle))
}

#[cfg(not(feature = "test-utils"))]
{
(None, None)
}
};
skip_synced,
)
.await;
(Some(notification_tx), None::<UnboundedReceiver<L1WatcherCommand>>, Some(handle))
} else {
// Create a channel for L1 notifications that we can use to inject L1 messages for
// testing
#[cfg(feature = "test-utils")]
{
let (notification_tx, notification_rx) = tokio::sync::mpsc::channel(1000);
let (command_tx, command_rx) = tokio::sync::mpsc::unbounded_channel();
let handle = rollup_node_watcher::L1WatcherHandle::new(command_tx, notification_rx);

(Some(notification_tx), Some(command_rx), Some(handle))
}

#[cfg(not(feature = "test-utils"))]
{
(None, None, None)
}
};

// Construct the l1 provider.
let l1_messages_provider = db.clone();
Expand Down Expand Up @@ -433,7 +441,7 @@ impl ScrollRollupNodeConfig {
let signer = if let Some(configured_signer) = self.signer_args.signer(chain_id).await? {
// Use the signer configured by SignerArgs
Some(rollup_node_signer::Signer::spawn(configured_signer))
} else if self.test {
} else if self.test_args.test {
// Use a random private key signer for testing
Some(rollup_node_signer::Signer::spawn(PrivateKeySigner::random()))
} else {
Expand Down Expand Up @@ -465,7 +473,8 @@ impl ScrollRollupNodeConfig {
)
.await;

let (chain_orchestrator, handle) = ChainOrchestrator::new(
#[cfg_attr(not(feature = "test-utils"), allow(unused_mut))]
let (chain_orchestrator, mut handle) = ChainOrchestrator::new(
Comment on lines +476 to +477
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

combine this suggestion with the one below.

Suggested change
#[cfg_attr(not(feature = "test-utils"), allow(unused_mut))]
let (chain_orchestrator, mut handle) = ChainOrchestrator::new(
let (chain_orchestrator, handle) = ChainOrchestrator::new(

db,
config,
Arc::new(block_client),
Expand All @@ -481,7 +490,14 @@ impl ScrollRollupNodeConfig {
.await?;

#[cfg(feature = "test-utils")]
let handle = handle.with_l1_watcher_mock(_l1_watcher_mock);
{
let command_rx = _l1_command_rx.map(|rx| Arc::new(tokio::sync::Mutex::new(rx)));
let l1_watcher_mock = rollup_node_watcher::test_utils::L1WatcherMock {
command_rx,
notification_tx: _l1_notification_tx.expect("L1 notification sender should be set"),
};
handle = handle.with_l1_watcher_mock(Some(l1_watcher_mock));
}
Comment on lines +493 to +500
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update

        #[cfg(feature = "test-utils")]
        let handle = {
            let command_rx = _l1_command_rx.map(|rx| Arc::new(tokio::sync::Mutex::new(rx)));
            let l1_watcher_mock = rollup_node_watcher::test_utils::L1WatcherMock {
                command_rx,
                notification_tx: _l1_notification_tx.expect("L1 notification sender should be set"),
            };
            handle.with_l1_watcher_mock(Some(l1_watcher_mock))
        };


Ok((chain_orchestrator, handle))
}
Expand Down Expand Up @@ -919,7 +935,7 @@ mod tests {
#[test]
fn test_validate_sequencer_enabled_without_any_signer_fails() {
let config = ScrollRollupNodeConfig {
test: false,
test_args: TestArgs::default(),
sequencer_args: SequencerArgs { sequencer_enabled: true, ..Default::default() },
signer_args: SignerArgs { key_file: None, aws_kms_key_id: None, private_key: None },
database_args: RollupNodeDatabaseArgs::default(),
Expand Down Expand Up @@ -947,7 +963,7 @@ mod tests {
#[test]
fn test_validate_sequencer_enabled_with_both_signers_fails() {
let config = ScrollRollupNodeConfig {
test: false,
test_args: TestArgs::default(),
sequencer_args: SequencerArgs { sequencer_enabled: true, ..Default::default() },
signer_args: SignerArgs {
key_file: Some(PathBuf::from("/path/to/key")),
Expand Down Expand Up @@ -977,7 +993,7 @@ mod tests {
#[test]
fn test_validate_sequencer_enabled_with_key_file_succeeds() {
let config = ScrollRollupNodeConfig {
test: false,
test_args: TestArgs::default(),
sequencer_args: SequencerArgs { sequencer_enabled: true, ..Default::default() },
signer_args: SignerArgs {
key_file: Some(PathBuf::from("/path/to/key")),
Expand All @@ -1002,7 +1018,7 @@ mod tests {
#[test]
fn test_validate_sequencer_enabled_with_aws_kms_succeeds() {
let config = ScrollRollupNodeConfig {
test: false,
test_args: TestArgs::default(),
sequencer_args: SequencerArgs { sequencer_enabled: true, ..Default::default() },
signer_args: SignerArgs {
key_file: None,
Expand All @@ -1027,7 +1043,7 @@ mod tests {
#[test]
fn test_validate_sequencer_disabled_without_any_signer_succeeds() {
let config = ScrollRollupNodeConfig {
test: false,
test_args: TestArgs::default(),
sequencer_args: SequencerArgs { sequencer_enabled: false, ..Default::default() },
signer_args: SignerArgs { key_file: None, aws_kms_key_id: None, private_key: None },
database_args: RollupNodeDatabaseArgs::default(),
Expand Down
3 changes: 2 additions & 1 deletion crates/node/src/test_utils/block_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ impl<'a> BlockBuilder<'a> {

/// Build the block and validate against expectations.
pub async fn build_and_await_block(self) -> eyre::Result<ScrollBlock> {
let sequencer_node = &self.fixture.nodes[0];
let sequencer_node =
self.fixture.nodes[0].as_ref().expect("sequencer node has been shutdown");

// Get the sequencer from the rollup manager handle
let handle = &sequencer_node.rollup_manager_handle;
Expand Down
Loading