diff --git a/crates/chain-orchestrator/Cargo.toml b/crates/chain-orchestrator/Cargo.toml index eef8dc9f..1596a1f4 100644 --- a/crates/chain-orchestrator/Cargo.toml +++ b/crates/chain-orchestrator/Cargo.toml @@ -117,4 +117,5 @@ serde = [ "scroll-alloy-hardforks/serde", "scroll-engine/serde", "scroll-network/serde", + "rollup-node-primitives/serde", ] diff --git a/crates/chain-orchestrator/src/handle/command.rs b/crates/chain-orchestrator/src/handle/command.rs index a485c1eb..90edd353 100644 --- a/crates/chain-orchestrator/src/handle/command.rs +++ b/crates/chain-orchestrator/src/handle/command.rs @@ -3,7 +3,7 @@ use crate::{ChainOrchestratorEvent, ChainOrchestratorStatus}; use reth_network_api::FullNetwork; use reth_scroll_node::ScrollNetworkPrimitives; use reth_tokio_util::EventStream; -use rollup_node_primitives::BlockInfo; +use rollup_node_primitives::{BlockInfo, L1MessageEnvelope}; use scroll_network::ScrollNetworkHandle; use tokio::sync::oneshot; @@ -24,7 +24,16 @@ pub enum ChainOrchestratorCommand), /// Disable automatic sequencing. DisableAutomaticSequencing(oneshot::Sender), + /// Send a database query to the rollup manager. + DatabaseQuery(DatabaseQuery), /// Enable gossiping of blocks to peers. #[cfg(feature = "test-utils")] SetGossip((bool, oneshot::Sender<()>)), } + +/// The database queries that can be sent to the rollup manager. +#[derive(Debug)] +pub enum DatabaseQuery { + /// Get L1 message by its index. + GetL1MessageByIndex(u64, oneshot::Sender>), +} diff --git a/crates/chain-orchestrator/src/handle/mod.rs b/crates/chain-orchestrator/src/handle/mod.rs index 329e088a..b9f0a7a6 100644 --- a/crates/chain-orchestrator/src/handle/mod.rs +++ b/crates/chain-orchestrator/src/handle/mod.rs @@ -5,13 +5,13 @@ use super::ChainOrchestratorEvent; use reth_network_api::FullNetwork; use reth_scroll_node::ScrollNetworkPrimitives; use reth_tokio_util::EventStream; -use rollup_node_primitives::BlockInfo; +use rollup_node_primitives::{BlockInfo, L1MessageEnvelope}; use scroll_network::ScrollNetworkHandle; use tokio::sync::{mpsc, oneshot}; use tracing::error; mod command; -pub use command::ChainOrchestratorCommand; +pub use command::{ChainOrchestratorCommand, DatabaseQuery}; mod metrics; use metrics::ChainOrchestratorHandleMetrics; @@ -90,6 +90,18 @@ impl> ChainOrchestratorHand rx.await } + /// Get an L1 message by its index. + pub async fn get_l1_message_by_index( + &self, + index: u64, + ) -> Result, oneshot::error::RecvError> { + let (tx, rx) = oneshot::channel(); + self.send_command(ChainOrchestratorCommand::DatabaseQuery( + DatabaseQuery::GetL1MessageByIndex(index, tx), + )); + rx.await + } + /// Sends a command to the rollup manager to enable or disable gossiping of blocks to peers. #[cfg(feature = "test-utils")] pub async fn set_gossip(&self, enabled: bool) -> Result<(), oneshot::error::RecvError> { diff --git a/crates/chain-orchestrator/src/lib.rs b/crates/chain-orchestrator/src/lib.rs index 62e3ecbb..442431b0 100644 --- a/crates/chain-orchestrator/src/lib.rs +++ b/crates/chain-orchestrator/src/lib.rs @@ -59,7 +59,7 @@ mod error; pub use error::ChainOrchestratorError; mod handle; -pub use handle::{ChainOrchestratorCommand, ChainOrchestratorHandle}; +pub use handle::{ChainOrchestratorCommand, ChainOrchestratorHandle, DatabaseQuery}; mod metrics; pub use metrics::{ChainOrchestratorItem, ChainOrchestratorMetrics}; @@ -376,6 +376,16 @@ impl< let _ = tx.send(false); } } + ChainOrchestratorCommand::DatabaseQuery(query) => match query { + DatabaseQuery::GetL1MessageByIndex(index, sender) => { + let l1_message = self + .database + .get_n_l1_messages(Some(L1MessageKey::from_queue_index(index)), 1) + .await? + .pop(); + let _ = sender.send(l1_message); + } + }, #[cfg(feature = "test-utils")] ChainOrchestratorCommand::SetGossip((enabled, tx)) => { self.network.handle().set_gossip(enabled).await; diff --git a/crates/engine/Cargo.toml b/crates/engine/Cargo.toml index a537011b..a87365cc 100644 --- a/crates/engine/Cargo.toml +++ b/crates/engine/Cargo.toml @@ -75,4 +75,5 @@ serde = [ "reth-primitives-traits/serde", "alloy-consensus/serde", "scroll-alloy-consensus/serde", + "rollup-node-primitives/serde", ] diff --git a/crates/network/Cargo.toml b/crates/network/Cargo.toml index 430a169f..6971d279 100644 --- a/crates/network/Cargo.toml +++ b/crates/network/Cargo.toml @@ -50,6 +50,7 @@ serde = [ "reth-primitives-traits/serde", "reth-storage-api/serde", "scroll-alloy-hardforks/serde", + "rollup-node-primitives/serde", ] test-utils = [ "reth-chainspec/test-utils", diff --git a/crates/node/src/add_ons/rpc.rs b/crates/node/src/add_ons/rpc.rs index 70ca1cb8..22c90b41 100644 --- a/crates/node/src/add_ons/rpc.rs +++ b/crates/node/src/add_ons/rpc.rs @@ -7,6 +7,7 @@ use jsonrpsee::{ use reth_network_api::FullNetwork; use reth_scroll_node::ScrollNetworkPrimitives; use rollup_node_chain_orchestrator::{ChainOrchestratorHandle, ChainOrchestratorStatus}; +use rollup_node_primitives::L1MessageEnvelope; use tokio::sync::{oneshot, Mutex, OnceCell}; /// RPC extension for rollup node management operations. @@ -79,6 +80,10 @@ pub trait RollupNodeExtApi { /// Returns the current status of the rollup node. #[method(name = "status")] async fn status(&self) -> RpcResult; + + /// Returns the L1 message by index. + #[method(name = "getL1MessageByIndex")] + async fn get_l1_message_by_index(&self, index: u64) -> RpcResult>; } #[async_trait] @@ -139,4 +144,22 @@ where ) }) } + + async fn get_l1_message_by_index(&self, index: u64) -> 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.get_l1_message_by_index(index).await.map_err(|e| { + ErrorObjectOwned::owned( + error::INTERNAL_ERROR_CODE, + format!("Failed to get L1 message by index: {}", e), + None::<()>, + ) + }) + } } diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 948c1d48..30f3de58 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -67,3 +67,14 @@ arbitrary = [ "alloy-chains/arbitrary", "reth-chainspec/arbitrary", ] +serde = [ + "alloy-chains/serde", + "alloy-consensus/serde", + "alloy-eips/serde", + "alloy-primitives/serde", + "alloy-rpc-types-engine/serde", + "reth-primitives-traits/serde", + "reth-scroll-primitives/serde", + "scroll-alloy-consensus/serde", + "scroll-alloy-rpc-types-engine/serde", +] diff --git a/crates/primitives/src/transaction.rs b/crates/primitives/src/transaction.rs index 7193220d..2f899c0e 100644 --- a/crates/primitives/src/transaction.rs +++ b/crates/primitives/src/transaction.rs @@ -3,6 +3,7 @@ use scroll_alloy_consensus::TxL1Message; /// A L1 message envelope, containing extra information about the message. #[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct L1MessageEnvelope { /// The L1 transaction. pub transaction: TxL1Message,