arb_rpc/
block_producer.rs

1//! Block producer trait for the `nitroexecution` RPC handler.
2//!
3//! Defines the interface for producing blocks from L1 incoming messages.
4//! The concrete implementation lives in `arb-node` where it has access
5//! to the full node infrastructure (database, EVM config, state).
6
7use alloy_primitives::B256;
8
9/// Result of producing a block.
10#[derive(Debug, Clone)]
11pub struct ProducedBlock {
12    /// Hash of the produced block.
13    pub block_hash: B256,
14    /// Send root from the block's extra_data.
15    pub send_root: B256,
16}
17
18/// Error type for block production.
19#[derive(Debug, thiserror::Error)]
20pub enum BlockProducerError {
21    #[error("state access: {0}")]
22    StateAccess(String),
23    #[error("execution: {0}")]
24    Execution(String),
25    #[error("storage: {0}")]
26    Storage(String),
27    #[error("parse: {0}")]
28    Parse(String),
29    #[error("unexpected: {0}")]
30    Unexpected(String),
31}
32
33/// Input for block production from an L1 incoming message.
34#[derive(Debug, Clone)]
35pub struct BlockProductionInput {
36    /// Message kind (L1MessageType_*).
37    pub kind: u8,
38    /// Message sender (poster address).
39    pub sender: alloy_primitives::Address,
40    /// L1 block number.
41    pub l1_block_number: u64,
42    /// L1 timestamp.
43    pub l1_timestamp: u64,
44    /// L1 request ID (for delayed messages).
45    pub request_id: Option<B256>,
46    /// L1 base fee.
47    pub l1_base_fee: Option<alloy_primitives::U256>,
48    /// L2 message payload (base64-decoded).
49    pub l2_msg: Vec<u8>,
50    /// Delayed messages read count.
51    pub delayed_messages_read: u64,
52    /// Legacy batch gas cost.
53    pub batch_gas_cost: Option<u64>,
54    /// Batch data stats (for newer batch posting reports).
55    pub batch_data_stats: Option<(u64, u64)>,
56}
57
58/// Trait for producing blocks from L1 messages.
59///
60/// Implemented by the node infrastructure where full database and EVM
61/// access is available.
62#[async_trait::async_trait]
63pub trait BlockProducer: Send + Sync + 'static {
64    /// Cache the Init message params for later use during block 1 execution.
65    ///
66    /// The Init message (Kind=11) does NOT produce a block. Its params are
67    /// applied during the first real block's pre-execution so that the
68    /// state root for block 1 includes both Init and execution changes.
69    fn cache_init_message(&self, l2_msg: &[u8]) -> Result<(), BlockProducerError>;
70
71    /// Produce a block from the given L1 incoming message.
72    ///
73    /// The implementation should:
74    /// 1. Parse the L1 message into transactions
75    /// 2. Open the state at the current head
76    /// 3. Execute transactions using the ArbOS pipeline
77    /// 4. Compute the state root
78    /// 5. Persist the block and state changes
79    /// 6. Return the block hash and send root
80    async fn produce_block(
81        &self,
82        msg_idx: u64,
83        input: BlockProductionInput,
84    ) -> Result<ProducedBlock, BlockProducerError>;
85}