ethrex_rpc/debug/
execution_witness.rs1use ethrex_common::types::block_execution_witness::RpcExecutionWitness;
2use serde_json::Value;
3use tracing::debug;
4
5use crate::{RpcApiContext, RpcErr, RpcHandler, types::block_identifier::BlockIdentifier};
6
7pub struct ExecutionWitnessRequest {
8 pub from: BlockIdentifier,
9 pub to: Option<BlockIdentifier>,
10}
11
12impl RpcHandler for ExecutionWitnessRequest {
13 fn parse(params: &Option<Vec<Value>>) -> Result<Self, RpcErr> {
14 let params = params
15 .as_ref()
16 .ok_or(RpcErr::BadParams("No params provided".to_owned()))?;
17 if params.len() > 2 {
18 return Err(RpcErr::BadParams(format!(
19 "Expected one or two params and {} were provided",
20 params.len()
21 )));
22 }
23
24 let from = BlockIdentifier::parse(params[0].clone(), 0)?;
25 let to = if let Some(param) = params.get(1) {
26 Some(BlockIdentifier::parse(param.clone(), 1)?)
27 } else {
28 None
29 };
30
31 Ok(ExecutionWitnessRequest { from, to })
32 }
33
34 async fn handle(&self, context: RpcApiContext) -> Result<Value, RpcErr> {
35 let from_block_number = self
36 .from
37 .resolve_block_number(&context.storage)
38 .await?
39 .ok_or(RpcErr::Internal(
40 "Failed to resolve block number".to_string(),
41 ))?;
42 let to_block_number = self
43 .to
44 .as_ref()
45 .unwrap_or(&self.from)
46 .resolve_block_number(&context.storage)
47 .await?
48 .ok_or(RpcErr::Internal(
49 "Failed to resolve block number".to_string(),
50 ))?;
51
52 if from_block_number > to_block_number {
53 return Err(RpcErr::BadParams(
54 "From block number is greater than To block number".to_string(),
55 ));
56 }
57
58 if self.to.is_some() {
59 debug!(
60 "Requested execution witness from block: {from_block_number} to {to_block_number}",
61 );
62 } else {
63 debug!("Requested execution witness for block: {from_block_number}",);
64 }
65
66 let mut blocks = Vec::new();
67 for block_number in from_block_number..=to_block_number {
68 let header = context
69 .storage
70 .get_block_header(block_number)?
71 .ok_or(RpcErr::Internal("Could not get block header".to_string()))?;
72 let block = context
73 .storage
74 .get_block_by_hash(header.hash())
75 .await?
76 .ok_or(RpcErr::Internal("Could not get block body".to_string()))?;
77 blocks.push(block);
78 }
79
80 if blocks.len() == 1 {
81 let block = &blocks[0];
84 if let Some(json_bytes) = context
85 .storage
86 .get_witness_json_bytes(block.header.number, block.hash())?
87 {
88 return serde_json::from_slice(&json_bytes)
90 .map_err(|e| RpcErr::Internal(format!("Failed to parse cached witness: {e}")));
91 }
92 }
93
94 let execution_witness = context
95 .blockchain
96 .generate_witness_for_blocks(&blocks)
97 .await
98 .map_err(|e| RpcErr::Internal(format!("Failed to build execution witness {e}")))?;
99
100 let rpc_execution_witness = RpcExecutionWitness::try_from(execution_witness)
101 .map_err(|e| RpcErr::Internal(format!("Failed to create rpc execution witness {e}")))?;
102
103 serde_json::to_value(rpc_execution_witness)
104 .map_err(|error| RpcErr::Internal(error.to_string()))
105 }
106}