diff --git a/crates/l2/networking/rpc/l2/execution_witness.rs b/crates/l2/networking/rpc/l2/execution_witness.rs new file mode 100644 index 00000000000..c00831dbbc5 --- /dev/null +++ b/crates/l2/networking/rpc/l2/execution_witness.rs @@ -0,0 +1,83 @@ +use ethrex_rpc::{ + RpcErr, + debug::execution_witness::{ExecutionWitnessRequest, RpcExecutionWitness}, +}; +use serde_json::Value; +use tracing::debug; + +use crate::rpc::RpcApiContext; + +/// Copy of the L1 handler for execution witness, but +/// fetches fee configs from the rollup store, as they can vary from block to block. +pub async fn handle_execution_witness( + request: &ExecutionWitnessRequest, + context: RpcApiContext, +) -> Result { + let from_block_number = request + .from + .resolve_block_number(&context.l1_ctx.storage) + .await? + .ok_or(RpcErr::Internal( + "Failed to resolve block number".to_string(), + ))?; + let to_block_number = request + .to + .as_ref() + .unwrap_or(&request.from) + .resolve_block_number(&context.l1_ctx.storage) + .await? + .ok_or(RpcErr::Internal( + "Failed to resolve block number".to_string(), + ))?; + + if from_block_number > to_block_number { + return Err(RpcErr::BadParams( + "From block number is greater than To block number".to_string(), + )); + } + + if request.to.is_some() { + debug!("Requested execution witness from block: {from_block_number} to {to_block_number}",); + } else { + debug!("Requested execution witness for block: {from_block_number}",); + } + + let mut blocks = Vec::new(); + let mut fee_configs = Vec::new(); + for block_number in from_block_number..=to_block_number { + let header = context + .l1_ctx + .storage + .get_block_header(block_number)? + .ok_or(RpcErr::Internal("Could not get block header".to_string()))?; + let block = context + .l1_ctx + .storage + .get_block_by_hash(header.hash()) + .await? + .ok_or(RpcErr::Internal("Could not get block body".to_string()))?; + let fee_config = context + .rollup_store + .get_fee_config_by_block(block_number) + .await + .map_err(|e| RpcErr::Internal(format!("Failed to get fee config {e}")))? + .ok_or(RpcErr::Internal(format!( + "Fee config not found for block {}", + block_number + )))?; + + blocks.push(block); + fee_configs.push(fee_config); + } + + let execution_witness = context + .l1_ctx + .blockchain + .generate_witness_for_blocks_with_fee_configs(&blocks, Some(&fee_configs)) + .await + .map_err(|e| RpcErr::Internal(format!("Failed to build execution witness {e}")))?; + + let rpc_execution_witness = RpcExecutionWitness::from(execution_witness); + + serde_json::to_value(rpc_execution_witness).map_err(|error| RpcErr::Internal(error.to_string())) +} diff --git a/crates/l2/networking/rpc/l2/mod.rs b/crates/l2/networking/rpc/l2/mod.rs index 7ee748e885a..8a44f1a97b1 100644 --- a/crates/l2/networking/rpc/l2/mod.rs +++ b/crates/l2/networking/rpc/l2/mod.rs @@ -1,4 +1,5 @@ pub mod batch; +pub mod execution_witness; pub mod fees; pub mod l1_message; pub mod transaction; diff --git a/crates/l2/networking/rpc/rpc.rs b/crates/l2/networking/rpc/rpc.rs index 126dd51b50c..65b88040b7e 100644 --- a/crates/l2/networking/rpc/rpc.rs +++ b/crates/l2/networking/rpc/rpc.rs @@ -1,4 +1,5 @@ use crate::l2::batch::{BatchNumberRequest, GetBatchByBatchNumberRequest}; +use crate::l2::execution_witness::handle_execution_witness; use crate::l2::fees::{ GetBaseFeeVaultAddress, GetL1BlobBaseFeeRequest, GetOperatorFee, GetOperatorFeeVaultAddress, }; @@ -14,6 +15,7 @@ use ethrex_p2p::sync_manager::SyncManager; use ethrex_p2p::types::Node; use ethrex_p2p::types::NodeRecord; use ethrex_rpc::RpcHandler as L1RpcHandler; +use ethrex_rpc::debug::execution_witness::ExecutionWitnessRequest; use ethrex_rpc::{ GasTipEstimator, NodeData, RpcRequestWrapper, types::transaction::SendRawTransactionRequest, @@ -207,6 +209,12 @@ pub async fn map_eth_requests(req: &RpcRequest, context: RpcApiContext) -> Resul .await .map_err(RpcErr::L1RpcErr) } + "debug_executionWitness" => { + let request = ExecutionWitnessRequest::parse(&req.params)?; + handle_execution_witness(&request, context) + .await + .map_err(RpcErr::L1RpcErr) + } _other_eth_method => ethrex_rpc::map_eth_requests(req, context.l1_ctx) .await .map_err(RpcErr::L1RpcErr), diff --git a/crates/networking/rpc/debug/execution_witness.rs b/crates/networking/rpc/debug/execution_witness.rs index 16b626fa73f..2bcd285155e 100644 --- a/crates/networking/rpc/debug/execution_witness.rs +++ b/crates/networking/rpc/debug/execution_witness.rs @@ -133,19 +133,11 @@ impl RpcHandler for ExecutionWitnessRequest { } let mut blocks = Vec::new(); - let mut block_headers = Vec::new(); for block_number in from_block_number..=to_block_number { let header = context .storage .get_block_header(block_number)? .ok_or(RpcErr::Internal("Could not get block header".to_string()))?; - let parent_header = context - .storage - .get_block_header_by_hash(header.parent_hash)? - .ok_or(RpcErr::Internal( - "Could not get parent block header".to_string(), - ))?; - block_headers.push(parent_header); let block = context .storage .get_block_by_hash(header.hash())