From a8288d76fb1a81c10a71e63a7112a36c3ac54d03 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Mon, 1 Sep 2025 10:09:29 +0800 Subject: [PATCH 1/8] add command to enable/disable automatic sequencing in rollup node manager --- crates/manager/src/manager/command.rs | 4 ++++ crates/manager/src/manager/handle.rs | 14 ++++++++++++++ crates/manager/src/manager/mod.rs | 26 ++++++++++++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/crates/manager/src/manager/command.rs b/crates/manager/src/manager/command.rs index dea7d012..1d7d8d1b 100644 --- a/crates/manager/src/manager/command.rs +++ b/crates/manager/src/manager/command.rs @@ -20,4 +20,8 @@ pub enum RollupManagerCommand>), /// Update the head of the fcs in the engine driver. UpdateFcsHead(BlockInfo), + /// Enable automatic sequencing. + EnableAutomaticSequencing(oneshot::Sender), + /// Disable automatic sequencing. + DisableAutomaticSequencing(oneshot::Sender), } diff --git a/crates/manager/src/manager/handle.rs b/crates/manager/src/manager/handle.rs index 01063170..651ce436 100644 --- a/crates/manager/src/manager/handle.rs +++ b/crates/manager/src/manager/handle.rs @@ -52,4 +52,18 @@ impl> RollupManagerHandle Result { + let (tx, rx) = oneshot::channel(); + self.send_command(RollupManagerCommand::EnableAutomaticSequencing(tx)).await; + rx.await + } + + /// Sends a command to the rollup manager to disable automatic sequencing. + pub async fn disable_automatic_sequencing(&self) -> Result { + let (tx, rx) = oneshot::channel(); + self.send_command(RollupManagerCommand::DisableAutomaticSequencing(tx)).await; + rx.await + } } diff --git a/crates/manager/src/manager/mod.rs b/crates/manager/src/manager/mod.rs index eabe7a4f..264ef801 100644 --- a/crates/manager/src/manager/mod.rs +++ b/crates/manager/src/manager/mod.rs @@ -112,6 +112,8 @@ pub struct RollupNodeManager< signer: Option, /// The trigger for the block building process. block_building_trigger: Option, + /// The original block time configuration for restoring automatic sequencing. + block_time_config: Option, } /// The current status of the rollup manager. @@ -145,6 +147,7 @@ impl< .field("event_sender", &self.event_sender) .field("sequencer", &self.sequencer) .field("block_building_trigger", &self.block_building_trigger) + .field("block_time_config", &self.block_time_config) .finish() } } @@ -189,6 +192,7 @@ where sequencer, signer, block_building_trigger: block_time.map(delayed_interval), + block_time_config: block_time, }; (rnm, RollupManagerHandle::new(handle_tx)) } @@ -512,6 +516,28 @@ where tx.send(network_handle.clone()) .expect("Failed to send network handle to handle"); } + RollupManagerCommand::EnableAutomaticSequencing(tx) => { + let success = if let Some(block_time) = this.block_time_config { + if this.block_building_trigger.is_none() { + this.block_building_trigger = Some(delayed_interval(block_time)); + info!(target: "scroll::node::manager", "Enabled automatic sequencing with interval {}ms", block_time); + true + } else { + info!(target: "scroll::node::manager", "Automatic sequencing already enabled"); + true + } + } else { + warn!(target: "scroll::node::manager", "Cannot enable automatic sequencing: no block time configured"); + false + }; + tx.send(success).expect("Failed to send enable automatic sequencing response"); + } + RollupManagerCommand::DisableAutomaticSequencing(tx) => { + let was_enabled = this.block_building_trigger.is_some(); + this.block_building_trigger = None; + info!(target: "scroll::node::manager", "Disabled automatic sequencing (was enabled: {})", was_enabled); + tx.send(true).expect("Failed to send disable automatic sequencing response"); + } } } From 5fbbc775706760bbbdbb8011613e81914a1f41ab Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Tue, 2 Sep 2025 11:33:22 +0800 Subject: [PATCH 2/8] add rpc extension --- Cargo.lock | 1 + crates/manager/src/manager/mod.rs | 5 +-- crates/node/Cargo.toml | 1 + crates/node/src/add_ons/mod.rs | 13 +++++++ crates/node/src/add_ons/rpc.rs | 64 +++++++++++++++++++++++++++++++ 5 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 crates/node/src/add_ons/rpc.rs diff --git a/Cargo.lock b/Cargo.lock index a924fae7..3526b248 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10382,6 +10382,7 @@ dependencies = [ "color-eyre", "eyre", "futures", + "jsonrpsee", "reqwest", "reth-chainspec", "reth-cli-util", diff --git a/crates/manager/src/manager/mod.rs b/crates/manager/src/manager/mod.rs index 264ef801..f6696009 100644 --- a/crates/manager/src/manager/mod.rs +++ b/crates/manager/src/manager/mod.rs @@ -38,7 +38,7 @@ use tokio::{ time::Interval, }; use tokio_stream::wrappers::ReceiverStream; -use tracing::{error, trace, warn}; +use tracing::{error, info, trace, warn}; use rollup_node_providers::{L1MessageProvider, L1Provider}; use scroll_db::{Database, DatabaseError}; @@ -521,11 +521,10 @@ where if this.block_building_trigger.is_none() { this.block_building_trigger = Some(delayed_interval(block_time)); info!(target: "scroll::node::manager", "Enabled automatic sequencing with interval {}ms", block_time); - true } else { info!(target: "scroll::node::manager", "Automatic sequencing already enabled"); - true } + true } else { warn!(target: "scroll::node::manager", "Cannot enable automatic sequencing: no block time configured"); false diff --git a/crates/node/Cargo.toml b/crates/node/Cargo.toml index 9cdf45c0..d339d36f 100644 --- a/crates/node/Cargo.toml +++ b/crates/node/Cargo.toml @@ -88,6 +88,7 @@ scroll-network.workspace = true auto_impl.workspace = true clap = { workspace = true, features = ["derive", "env"] } eyre.workspace = true +jsonrpsee = { version = "0.25.1", features = ["server", "macros"] } reqwest.workspace = true tokio.workspace = true tracing.workspace = true diff --git a/crates/node/src/add_ons/mod.rs b/crates/node/src/add_ons/mod.rs index ab77e4c3..d266444a 100644 --- a/crates/node/src/add_ons/mod.rs +++ b/crates/node/src/add_ons/mod.rs @@ -31,6 +31,9 @@ use scroll_wire::ScrollWireEvent; mod handle; pub use handle::ScrollAddOnsHandle; +mod rpc; +pub use rpc::{RollupNodeExtApiServer, RollupNodeRpcExt}; + mod rollup; pub use rollup::IsDevChain; use rollup::RollupManagerAddOn; @@ -123,9 +126,19 @@ where rpc_add_ons.eth_api_builder.with_propagate_local_transactions( !ctx.config.txpool.no_local_transactions_propagation, ); + + let (tx, rx) = tokio::sync::oneshot::channel(); + let rollup_node_rpc_ext = RollupNodeRpcExt::::new(rx); + rpc_add_ons = rpc_add_ons.extend_rpc_modules(move |ctx| { + ctx.modules.merge_configured(rollup_node_rpc_ext.into_rpc())?; + Ok(()) + }); + let rpc_handle = rpc_add_ons.launch_add_ons_with(ctx.clone(), |_| Ok(())).await?; let (rollup_manager_handle, l1_watcher_tx) = rollup_node_manager_addon.launch(ctx.clone(), rpc_handle.clone()).await?; + + tx.send(rollup_manager_handle.clone()).map_err(|_| eyre::eyre!("failed to send rollup manager handle"))?; Ok(ScrollAddOnsHandle { rollup_manager_handle, rpc_handle, diff --git a/crates/node/src/add_ons/rpc.rs b/crates/node/src/add_ons/rpc.rs new file mode 100644 index 00000000..7b66ee10 --- /dev/null +++ b/crates/node/src/add_ons/rpc.rs @@ -0,0 +1,64 @@ +use jsonrpsee::{core::RpcResult, proc_macros::rpc}; +use reth_network_api::FullNetwork; +use reth_scroll_node::ScrollNetworkPrimitives; +use rollup_node_manager::RollupManagerHandle; +use tokio::sync::{oneshot, Mutex, OnceCell}; + + +pub struct RollupNodeRpcExt +where + N: FullNetwork, +{ + /// The rollup manager handle + handle: tokio::sync::OnceCell>, + /// Oneshot channel for receiving the rollup manager handle + rx: Mutex>>>, +} + +impl RollupNodeRpcExt +where + N: FullNetwork, +{ + pub fn new(rx: oneshot::Receiver>) -> Self { + Self { rx: Mutex::new(Some(rx)), handle: OnceCell::new() } + } + + async fn rollup_manager_handle(&self) -> eyre::Result<&RollupManagerHandle> { + self.handle + .get_or_try_init(|| async { + let rx = { + let mut g = self.rx.lock().await; + g.take().ok_or_else(|| eyre::eyre!("receiver already consumed"))? + }; + rx.await.map_err(|e| eyre::eyre!("failed to receive handle: {e}")) + }) + .await + } +} + + +/// This defines an additional namespace for rollup management functions. +#[cfg_attr(not(test), rpc(server, namespace = "rollupNode"))] +#[cfg_attr(test, rpc(server, client, namespace = "rollupNode"))] +pub trait RollupNodeExtApi { + /// Enable automatic sequencing + #[method(name = "enableAutomaticSequencing")] + fn enable_automatic_sequencing(&self) -> RpcResult; + + /// Disable automatic sequencing + #[method(name = "disableAutomaticSequencing")] + fn disable_automatic_sequencing(&self) -> RpcResult; +} + +impl RollupNodeExtApiServer for RollupNodeRpcExt +where + N: FullNetwork, +{ + fn enable_automatic_sequencing(&self) -> RpcResult { + Ok(true) + } + + fn disable_automatic_sequencing(&self) -> RpcResult { + Ok(true) + } +} From 4d46249d9ed9f64ae4ea5758373761380824cbdc Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Tue, 2 Sep 2025 13:06:16 +0800 Subject: [PATCH 3/8] implement async trait that actually enables/disables sequencer --- Cargo.lock | 1 + crates/manager/src/manager/mod.rs | 2 +- crates/node/Cargo.toml | 3 ++ crates/node/src/add_ons/mod.rs | 4 +- crates/node/src/add_ons/rpc.rs | 85 ++++++++++++++++++++++++++----- 5 files changed, 79 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3526b248..f5bc475c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10375,6 +10375,7 @@ dependencies = [ "alloy-signer-aws", "alloy-signer-local", "alloy-transport", + "async-trait", "auto_impl", "aws-config", "aws-sdk-kms", diff --git a/crates/manager/src/manager/mod.rs b/crates/manager/src/manager/mod.rs index f6696009..cc405a70 100644 --- a/crates/manager/src/manager/mod.rs +++ b/crates/manager/src/manager/mod.rs @@ -526,7 +526,7 @@ where } true } else { - warn!(target: "scroll::node::manager", "Cannot enable automatic sequencing: no block time configured"); + warn!(target: "scroll::node::manager", "Cannot enable automatic sequencing: sequencer and block time not configured"); false }; tx.send(success).expect("Failed to send enable automatic sequencing response"); diff --git a/crates/node/Cargo.toml b/crates/node/Cargo.toml index d339d36f..29f2158b 100644 --- a/crates/node/Cargo.toml +++ b/crates/node/Cargo.toml @@ -14,6 +14,9 @@ path = "src/main.rs" workspace = true [dependencies] +# async trait support +async-trait.workspace = true + # alloy alloy-chains.workspace = true alloy-primitives.workspace = true diff --git a/crates/node/src/add_ons/mod.rs b/crates/node/src/add_ons/mod.rs index d266444a..f22f8547 100644 --- a/crates/node/src/add_ons/mod.rs +++ b/crates/node/src/add_ons/mod.rs @@ -138,7 +138,9 @@ where let (rollup_manager_handle, l1_watcher_tx) = rollup_node_manager_addon.launch(ctx.clone(), rpc_handle.clone()).await?; - tx.send(rollup_manager_handle.clone()).map_err(|_| eyre::eyre!("failed to send rollup manager handle"))?; + tx.send(rollup_manager_handle.clone()) + .map_err(|_| eyre::eyre!("failed to send rollup manager handle"))?; + Ok(ScrollAddOnsHandle { rollup_manager_handle, rpc_handle, diff --git a/crates/node/src/add_ons/rpc.rs b/crates/node/src/add_ons/rpc.rs index 7b66ee10..a24ddbdf 100644 --- a/crates/node/src/add_ons/rpc.rs +++ b/crates/node/src/add_ons/rpc.rs @@ -1,17 +1,27 @@ -use jsonrpsee::{core::RpcResult, proc_macros::rpc}; +use async_trait::async_trait; +use jsonrpsee::{ + core::RpcResult, + proc_macros::rpc, + types::{error, ErrorObjectOwned}, +}; use reth_network_api::FullNetwork; use reth_scroll_node::ScrollNetworkPrimitives; use rollup_node_manager::RollupManagerHandle; use tokio::sync::{oneshot, Mutex, OnceCell}; - +/// RPC extension for rollup node management operations. +/// +/// This struct provides a custom JSON-RPC namespace (`rollupNode`) that exposes +/// rollup management functionality to RPC clients. It manages a connection to the +/// rollup manager through a handle that is initialized lazily via a oneshot channel./// +#[derive(Debug)] pub struct RollupNodeRpcExt where N: FullNetwork, { - /// The rollup manager handle + /// Cached rollup manager handle, initialized lazily via `OnceCell` handle: tokio::sync::OnceCell>, - /// Oneshot channel for receiving the rollup manager handle + /// Oneshot channel receiver for obtaining the rollup manager handle during initialization rx: Mutex>>>, } @@ -19,10 +29,15 @@ impl RollupNodeRpcExt where N: FullNetwork, { + /// Creates a new RPC extension with a receiver for the rollup manager handle. pub fn new(rx: oneshot::Receiver>) -> Self { Self { rx: Mutex::new(Some(rx)), handle: OnceCell::new() } } + /// Gets or initializes the rollup manager handle. + /// + /// This method lazily initializes the rollup manager handle by consuming the oneshot + /// receiver. Subsequent calls will return the cached handle. async fn rollup_manager_handle(&self) -> eyre::Result<&RollupManagerHandle> { self.handle .get_or_try_init(|| async { @@ -36,29 +51,71 @@ where } } - -/// This defines an additional namespace for rollup management functions. +/// Defines the `rollupNode` JSON-RPC namespace for rollup management operations. +/// +/// This trait provides a custom RPC namespace that exposes rollup node management +/// functionality to external clients. The namespace is exposed as `rollupNode` and +/// provides methods for controlling automatic sequencing behavior. +/// +/// # Usage +/// These methods can be called via JSON-RPC using the `rollupNode` namespace: +/// ```json +/// {"jsonrpc": "2.0", "method": "rollupNode_enableAutomaticSequencing", "params": [], "id": 1} +/// ``` +/// or using cast: +/// ```bash +/// cast rpc rollupNode_enableAutomaticSequencing +/// ``` #[cfg_attr(not(test), rpc(server, namespace = "rollupNode"))] #[cfg_attr(test, rpc(server, client, namespace = "rollupNode"))] pub trait RollupNodeExtApi { - /// Enable automatic sequencing + /// Enables automatic sequencing in the rollup node. #[method(name = "enableAutomaticSequencing")] - fn enable_automatic_sequencing(&self) -> RpcResult; + async fn enable_automatic_sequencing(&self) -> RpcResult; - /// Disable automatic sequencing + /// Disables automatic sequencing in the rollup node. #[method(name = "disableAutomaticSequencing")] - fn disable_automatic_sequencing(&self) -> RpcResult; + async fn disable_automatic_sequencing(&self) -> RpcResult; } +#[async_trait] impl RollupNodeExtApiServer for RollupNodeRpcExt where N: FullNetwork, { - fn enable_automatic_sequencing(&self) -> RpcResult { - Ok(true) + async fn enable_automatic_sequencing(&self) -> RpcResult { + let handle = self.rollup_manager_handle().await.map_err(|e| { + ErrorObjectOwned::owned( + error::INTERNAL_ERROR_CODE, + format!("Failed to get rollup manager handle: {}", e), + None::<()>, + ) + })?; + + handle.enable_automatic_sequencing().await.map_err(|e| { + ErrorObjectOwned::owned( + error::INTERNAL_ERROR_CODE, + format!("Failed to enable automatic sequencing: {}", e), + None::<()>, + ) + }) } - fn disable_automatic_sequencing(&self) -> RpcResult { - Ok(true) + async fn disable_automatic_sequencing(&self) -> RpcResult { + let handle = self.rollup_manager_handle().await.map_err(|e| { + ErrorObjectOwned::owned( + error::INTERNAL_ERROR_CODE, + format!("Failed to get rollup manager handle: {}", e), + None::<()>, + ) + })?; + + handle.disable_automatic_sequencing().await.map_err(|e| { + ErrorObjectOwned::owned( + error::INTERNAL_ERROR_CODE, + format!("Failed to disable automatic sequencing: {}", e), + None::<()>, + ) + }) } } From 1c21edbcf4255df55ccae54d0c0bcf6038b8761d Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Tue, 2 Sep 2025 19:32:18 +0800 Subject: [PATCH 4/8] address review comments --- crates/node/src/add_ons/rpc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/node/src/add_ons/rpc.rs b/crates/node/src/add_ons/rpc.rs index a24ddbdf..357bdcaf 100644 --- a/crates/node/src/add_ons/rpc.rs +++ b/crates/node/src/add_ons/rpc.rs @@ -13,7 +13,7 @@ use tokio::sync::{oneshot, Mutex, OnceCell}; /// /// This struct provides a custom JSON-RPC namespace (`rollupNode`) that exposes /// rollup management functionality to RPC clients. It manages a connection to the -/// rollup manager through a handle that is initialized lazily via a oneshot channel./// +/// rollup manager through a handle that is initialized lazily via a oneshot channel. #[derive(Debug)] pub struct RollupNodeRpcExt where From 22efb2cb0b9d9891ebf9f0f39f2c227e47d230d5 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Tue, 2 Sep 2025 19:55:29 +0800 Subject: [PATCH 5/8] add e2e test --- crates/node/Cargo.toml | 2 +- crates/node/src/add_ons/mod.rs | 2 ++ crates/node/src/add_ons/rpc.rs | 2 +- crates/node/src/lib.rs | 1 + crates/node/tests/e2e.rs | 66 +++++++++++++++++++++++++++++++++- 5 files changed, 70 insertions(+), 3 deletions(-) diff --git a/crates/node/Cargo.toml b/crates/node/Cargo.toml index 29f2158b..217d0cc5 100644 --- a/crates/node/Cargo.toml +++ b/crates/node/Cargo.toml @@ -91,7 +91,7 @@ scroll-network.workspace = true auto_impl.workspace = true clap = { workspace = true, features = ["derive", "env"] } eyre.workspace = true -jsonrpsee = { version = "0.25.1", features = ["server", "macros"] } +jsonrpsee = { version = "0.25.1", features = ["server", "client", "macros"] } reqwest.workspace = true tokio.workspace = true tracing.workspace = true diff --git a/crates/node/src/add_ons/mod.rs b/crates/node/src/add_ons/mod.rs index f22f8547..906c8473 100644 --- a/crates/node/src/add_ons/mod.rs +++ b/crates/node/src/add_ons/mod.rs @@ -33,6 +33,8 @@ pub use handle::ScrollAddOnsHandle; mod rpc; pub use rpc::{RollupNodeExtApiServer, RollupNodeRpcExt}; +#[cfg(test)] +pub use rpc::RollupNodeExtApiClient; mod rollup; pub use rollup::IsDevChain; diff --git a/crates/node/src/add_ons/rpc.rs b/crates/node/src/add_ons/rpc.rs index 357bdcaf..f860a273 100644 --- a/crates/node/src/add_ons/rpc.rs +++ b/crates/node/src/add_ons/rpc.rs @@ -66,7 +66,7 @@ where /// ```bash /// cast rpc rollupNode_enableAutomaticSequencing /// ``` -#[cfg_attr(not(test), rpc(server, namespace = "rollupNode"))] +#[cfg_attr(not(test), rpc(server, client, namespace = "rollupNode"))] #[cfg_attr(test, rpc(server, client, namespace = "rollupNode"))] pub trait RollupNodeExtApi { /// Enables automatic sequencing in the rollup node. diff --git a/crates/node/src/lib.rs b/crates/node/src/lib.rs index 0a5981ca..b4abf7bc 100644 --- a/crates/node/src/lib.rs +++ b/crates/node/src/lib.rs @@ -8,6 +8,7 @@ mod node; #[cfg(feature = "test-utils")] pub mod test_utils; +pub use add_ons::*; pub use args::*; pub use context::RollupNodeContext; pub use node::ScrollRollupNode; diff --git a/crates/node/tests/e2e.rs b/crates/node/tests/e2e.rs index 974d5d03..4a4dde48 100644 --- a/crates/node/tests/e2e.rs +++ b/crates/node/tests/e2e.rs @@ -26,7 +26,8 @@ use rollup_node::{ }, BeaconProviderArgs, ChainOrchestratorArgs, ConsensusAlgorithm, ConsensusArgs, DatabaseArgs, EngineDriverArgs, GasPriceOracleArgs, L1ProviderArgs, NetworkArgs as ScrollNetworkArgs, - RollupNodeContext, ScrollRollupNode, ScrollRollupNodeConfig, SequencerArgs, + RollupNodeContext, RollupNodeExtApiClient, ScrollRollupNode, ScrollRollupNodeConfig, + SequencerArgs, }; use rollup_node_chain_orchestrator::ChainOrchestratorEvent; use rollup_node_manager::{RollupManagerCommand, RollupManagerEvent}; @@ -1274,6 +1275,69 @@ async fn can_handle_l1_message_reorg() -> eyre::Result<()> { Ok(()) } +#[tokio::test] +async fn can_rpc_enable_disable_sequencing() -> eyre::Result<()> { + reth_tracing::init_test_tracing(); + color_eyre::install()?; + let chain_spec = (*SCROLL_DEV).clone(); + + // Launch 1 sequencer node with automatic sequencing initially disabled (block_time = 0) + let mut config = default_sequencer_test_scroll_rollup_node_config(); + config.sequencer_args.block_time = 0; // Disable automatic block production + + let (mut nodes, _tasks, _) = setup_engine(config, 1, chain_spec.clone(), false, false).await?; + let node0 = nodes.remove(0); + + // Get handles + let node0_rnm_handle = node0.inner.add_ons_handle.rollup_manager_handle.clone(); + let mut node0_rnm_events = node0_rnm_handle.get_event_listener().await?; + + // Create RPC client + let client0 = node0.rpc_client().expect("RPC client should be available"); + + // Test that sequencing is initially disabled (no blocks produced automatically) + tokio::time::sleep(Duration::from_millis(100)).await; + assert_eq!(latest_block(&node0).await?.header.number, 0, "Should start at genesis block"); + + // Enable automatic sequencing via RPC + let result = RollupNodeExtApiClient::enable_automatic_sequencing(&client0).await?; + assert!(result, "Enable automatic sequencing should return true"); + + // // Wait for automatic blocks to be produced + // wait_for_block_sequenced_5s(&mut node0_rnm_events, 1).await?; + // wait_for_block_sequenced_5s(&mut node0_rnm_events, 2).await?; + + // // Verify blocks are being produced automatically + // let latest_block_num = latest_block(&node0).await?.header.number; + // assert!(latest_block_num >= 2, "Should have produced at least 2 blocks automatically"); + + // // Disable automatic sequencing via RPC + // let result = RollupNodeExtApiClient::disable_automatic_sequencing(&client).await?; + // assert!(result, "Disable automatic sequencing should return true"); + + // // Wait a bit and verify no more blocks are produced automatically + // let block_num_before_wait = latest_block(&node0).await?.header.number; + // tokio::time::sleep(Duration::from_millis(500)).await; + // let block_num_after_wait = latest_block(&node0).await?.header.number; + // assert_eq!( + // block_num_before_wait, block_num_after_wait, + // "No blocks should be produced automatically after disabling" + // ); + + // // Verify manual block building still works + // node0_rnm_handle.build_block().await; + // wait_for_block_sequenced_5s(&mut node0_rnm_events, block_num_after_wait + 1).await?; + + // let final_block_num = latest_block(&node0).await?.header.number; + // assert_eq!( + // final_block_num, + // block_num_after_wait + 1, + // "Manual block building should still work after disabling automatic sequencing" + // ); + + Ok(()) +} + /// Tests that a follower node correctly rejects L2 blocks containing L1 messages it hasn't received /// yet. /// From 14d0c37e01cf2a76f47ff2f786e39bff5a282968 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Wed, 3 Sep 2025 07:59:59 +0800 Subject: [PATCH 6/8] fix issues with test and finish implementing e2e test --- crates/node/src/add_ons/mod.rs | 6 ++- crates/node/src/add_ons/rpc.rs | 4 +- crates/node/tests/e2e.rs | 74 +++++++++++++++++----------------- 3 files changed, 43 insertions(+), 41 deletions(-) diff --git a/crates/node/src/add_ons/mod.rs b/crates/node/src/add_ons/mod.rs index 906c8473..e671a026 100644 --- a/crates/node/src/add_ons/mod.rs +++ b/crates/node/src/add_ons/mod.rs @@ -32,10 +32,12 @@ mod handle; pub use handle::ScrollAddOnsHandle; mod rpc; -pub use rpc::{RollupNodeExtApiServer, RollupNodeRpcExt}; -#[cfg(test)] + +#[cfg(feature = "test-utils")] pub use rpc::RollupNodeExtApiClient; +pub use rpc::{RollupNodeExtApiServer, RollupNodeRpcExt}; + mod rollup; pub use rollup::IsDevChain; use rollup::RollupManagerAddOn; diff --git a/crates/node/src/add_ons/rpc.rs b/crates/node/src/add_ons/rpc.rs index f860a273..939fe893 100644 --- a/crates/node/src/add_ons/rpc.rs +++ b/crates/node/src/add_ons/rpc.rs @@ -66,8 +66,8 @@ where /// ```bash /// cast rpc rollupNode_enableAutomaticSequencing /// ``` -#[cfg_attr(not(test), rpc(server, client, namespace = "rollupNode"))] -#[cfg_attr(test, rpc(server, client, namespace = "rollupNode"))] +#[cfg_attr(not(feature = "test-utils"), rpc(server, namespace = "rollupNode"))] +#[cfg_attr(feature = "test-utils", rpc(server, client, namespace = "rollupNode"))] pub trait RollupNodeExtApi { /// Enables automatic sequencing in the rollup node. #[method(name = "enableAutomaticSequencing")] diff --git a/crates/node/tests/e2e.rs b/crates/node/tests/e2e.rs index 4a4dde48..591ce037 100644 --- a/crates/node/tests/e2e.rs +++ b/crates/node/tests/e2e.rs @@ -1281,59 +1281,59 @@ async fn can_rpc_enable_disable_sequencing() -> eyre::Result<()> { color_eyre::install()?; let chain_spec = (*SCROLL_DEV).clone(); - // Launch 1 sequencer node with automatic sequencing initially disabled (block_time = 0) + // Launch sequencer node with automatic sequencing enabled. let mut config = default_sequencer_test_scroll_rollup_node_config(); - config.sequencer_args.block_time = 0; // Disable automatic block production + config.sequencer_args.block_time = 40; // Enable automatic block production - let (mut nodes, _tasks, _) = setup_engine(config, 1, chain_spec.clone(), false, false).await?; + let (mut nodes, _tasks, _) = setup_engine(config, 2, chain_spec.clone(), false, false).await?; let node0 = nodes.remove(0); + let node1 = nodes.remove(0); // Get handles let node0_rnm_handle = node0.inner.add_ons_handle.rollup_manager_handle.clone(); let mut node0_rnm_events = node0_rnm_handle.get_event_listener().await?; + let node1_rnm_handle = node1.inner.add_ons_handle.rollup_manager_handle.clone(); + let mut node1_rnm_events = node1_rnm_handle.get_event_listener().await?; + // Create RPC client let client0 = node0.rpc_client().expect("RPC client should be available"); - // Test that sequencing is initially disabled (no blocks produced automatically) + // Test that sequencing is initially enabled (blocks produced automatically) tokio::time::sleep(Duration::from_millis(100)).await; - assert_eq!(latest_block(&node0).await?.header.number, 0, "Should start at genesis block"); + assert_ne!(latest_block(&node0).await?.header.number, 0, "Should produce blocks"); + + // Disable automatic sequencing via RPC + let result = RollupNodeExtApiClient::disable_automatic_sequencing(&client0).await?; + assert!(result, "Disable automatic sequencing should return true"); + + // Wait a bit and verify no more blocks are produced automatically. + // +1 blocks is okay due to still being processed + let block_num_before_wait = latest_block(&node0).await?.header.number; + tokio::time::sleep(Duration::from_millis(300)).await; + let block_num_after_wait = latest_block(&node0).await?.header.number; + assert!( + (block_num_before_wait..=block_num_before_wait + 1).contains(&block_num_after_wait), + "No blocks should be produced automatically after disabling" + ); + + // Make sure follower is at same block + assert_eq!(block_num_after_wait, latest_block(&node1).await?.header.number); + + // Verify manual block building still works + node0_rnm_handle.build_block().await; + wait_for_block_sequenced_5s(&mut node0_rnm_events, block_num_after_wait + 1).await?; + + // Wait for the follower to import the block + wait_for_block_imported_5s(&mut node1_rnm_events, block_num_after_wait + 1).await?; - // Enable automatic sequencing via RPC + // Enable sequencing again let result = RollupNodeExtApiClient::enable_automatic_sequencing(&client0).await?; assert!(result, "Enable automatic sequencing should return true"); - // // Wait for automatic blocks to be produced - // wait_for_block_sequenced_5s(&mut node0_rnm_events, 1).await?; - // wait_for_block_sequenced_5s(&mut node0_rnm_events, 2).await?; - - // // Verify blocks are being produced automatically - // let latest_block_num = latest_block(&node0).await?.header.number; - // assert!(latest_block_num >= 2, "Should have produced at least 2 blocks automatically"); - - // // Disable automatic sequencing via RPC - // let result = RollupNodeExtApiClient::disable_automatic_sequencing(&client).await?; - // assert!(result, "Disable automatic sequencing should return true"); - - // // Wait a bit and verify no more blocks are produced automatically - // let block_num_before_wait = latest_block(&node0).await?.header.number; - // tokio::time::sleep(Duration::from_millis(500)).await; - // let block_num_after_wait = latest_block(&node0).await?.header.number; - // assert_eq!( - // block_num_before_wait, block_num_after_wait, - // "No blocks should be produced automatically after disabling" - // ); - - // // Verify manual block building still works - // node0_rnm_handle.build_block().await; - // wait_for_block_sequenced_5s(&mut node0_rnm_events, block_num_after_wait + 1).await?; - - // let final_block_num = latest_block(&node0).await?.header.number; - // assert_eq!( - // final_block_num, - // block_num_after_wait + 1, - // "Manual block building should still work after disabling automatic sequencing" - // ); + // Make sure automatic sequencing resumes + wait_for_block_sequenced_5s(&mut node0_rnm_events, block_num_after_wait + 2).await?; + wait_for_block_imported_5s(&mut node1_rnm_events, block_num_after_wait + 2).await?; Ok(()) } From e96870db79cbc18245fb9079f5c3b4cec45fb5b1 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Wed, 3 Sep 2025 08:06:14 +0800 Subject: [PATCH 7/8] add wait_for to test --- crates/node/tests/e2e.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/node/tests/e2e.rs b/crates/node/tests/e2e.rs index 591ce037..a4b70515 100644 --- a/crates/node/tests/e2e.rs +++ b/crates/node/tests/e2e.rs @@ -1318,6 +1318,7 @@ async fn can_rpc_enable_disable_sequencing() -> eyre::Result<()> { ); // Make sure follower is at same block + wait_for_block_imported_5s(&mut node1_rnm_events, block_num_after_wait).await?; assert_eq!(block_num_after_wait, latest_block(&node1).await?.header.number); // Verify manual block building still works From 8a909356752e97d65782f67ecd08c23efcb38932 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Wed, 3 Sep 2025 13:08:28 +0800 Subject: [PATCH 8/8] do not gate client for tests --- crates/node/src/add_ons/mod.rs | 6 +----- crates/node/src/add_ons/rpc.rs | 3 +-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/crates/node/src/add_ons/mod.rs b/crates/node/src/add_ons/mod.rs index e671a026..faef8b86 100644 --- a/crates/node/src/add_ons/mod.rs +++ b/crates/node/src/add_ons/mod.rs @@ -32,11 +32,7 @@ mod handle; pub use handle::ScrollAddOnsHandle; mod rpc; - -#[cfg(feature = "test-utils")] -pub use rpc::RollupNodeExtApiClient; - -pub use rpc::{RollupNodeExtApiServer, RollupNodeRpcExt}; +pub use rpc::{RollupNodeExtApiClient, RollupNodeExtApiServer, RollupNodeRpcExt}; mod rollup; pub use rollup::IsDevChain; diff --git a/crates/node/src/add_ons/rpc.rs b/crates/node/src/add_ons/rpc.rs index 939fe893..b253c7fc 100644 --- a/crates/node/src/add_ons/rpc.rs +++ b/crates/node/src/add_ons/rpc.rs @@ -66,8 +66,7 @@ where /// ```bash /// cast rpc rollupNode_enableAutomaticSequencing /// ``` -#[cfg_attr(not(feature = "test-utils"), rpc(server, namespace = "rollupNode"))] -#[cfg_attr(feature = "test-utils", rpc(server, client, namespace = "rollupNode"))] +#[rpc(server, client, namespace = "rollupNode")] pub trait RollupNodeExtApi { /// Enables automatic sequencing in the rollup node. #[method(name = "enableAutomaticSequencing")]