ethrex_rpc/debug/
execution_witness_by_hash.rs1use ethrex_common::types::BlockHash;
2use ethrex_common::types::block_execution_witness::RpcExecutionWitness;
3use serde_json::Value;
4use tracing::debug;
5
6use crate::{RpcApiContext, RpcErr, RpcHandler};
7
8pub struct ExecutionWitnessByBlockHashRequest {
9 pub block_hash: BlockHash,
10}
11
12impl RpcHandler for ExecutionWitnessByBlockHashRequest {
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() != 1 {
18 return Err(RpcErr::BadParams(format!(
19 "Expected one param and {} were provided",
20 params.len()
21 )));
22 }
23
24 let block_hash: BlockHash = serde_json::from_value(params[0].clone())
25 .map_err(|e| RpcErr::BadParams(format!("Invalid block hash: {e}")))?;
26
27 Ok(ExecutionWitnessByBlockHashRequest { block_hash })
28 }
29
30 async fn handle(&self, context: RpcApiContext) -> Result<Value, RpcErr> {
31 debug!(
32 "Requested execution witness for block hash: {:?}",
33 self.block_hash
34 );
35
36 let block = context
37 .storage
38 .get_block_by_hash(self.block_hash)
39 .await?
40 .ok_or(RpcErr::Internal("Block not found".to_string()))?;
41
42 if let Some(json_bytes) = context
44 .storage
45 .get_witness_json_bytes(block.header.number, block.hash())?
46 {
47 return serde_json::from_slice(&json_bytes)
48 .map_err(|e| RpcErr::Internal(format!("Failed to parse cached witness: {e}")));
49 }
50
51 let execution_witness = context
52 .blockchain
53 .generate_witness_for_blocks(&[block])
54 .await
55 .map_err(|e| RpcErr::Internal(format!("Failed to build execution witness {e}")))?;
56
57 let rpc_execution_witness = RpcExecutionWitness::try_from(execution_witness)
58 .map_err(|e| RpcErr::Internal(format!("Failed to create rpc execution witness {e}")))?;
59
60 serde_json::to_value(rpc_execution_witness)
61 .map_err(|error| RpcErr::Internal(error.to_string()))
62 }
63}