Skip to main content

ethrex_rpc/engine/
exchange_transition_config.rs

1use ethrex_common::{H256, serde_utils};
2use serde::{Deserialize, Serialize};
3use serde_json::Value;
4use tracing::{debug, warn};
5
6use crate::{
7    rpc::{RpcApiContext, RpcHandler},
8    utils::RpcErr,
9};
10
11#[derive(Debug, Serialize, Deserialize)]
12#[serde(rename_all = "camelCase")]
13pub struct ExchangeTransitionConfigPayload {
14    #[serde(with = "serde_utils::u128::hex_str")]
15    terminal_total_difficulty: u128,
16    terminal_block_hash: H256,
17    #[serde(with = "serde_utils::u64::hex_str")]
18    terminal_block_number: u64,
19}
20
21#[derive(Debug)]
22pub struct ExchangeTransitionConfigV1Req {
23    payload: ExchangeTransitionConfigPayload,
24}
25
26impl std::fmt::Display for ExchangeTransitionConfigV1Req {
27    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28        write!(
29            f,
30            "ExchangeTransitionConfigV1Req {{ terminal_total_difficulty: {}, terminal_block_hash: {:?}, terminal_block_number: {} }}",
31            self.payload.terminal_total_difficulty,
32            self.payload.terminal_block_hash,
33            self.payload.terminal_block_number
34        )
35    }
36}
37
38impl RpcHandler for ExchangeTransitionConfigV1Req {
39    fn parse(params: &Option<Vec<Value>>) -> Result<ExchangeTransitionConfigV1Req, RpcErr> {
40        let params = params
41            .as_ref()
42            .ok_or(RpcErr::BadParams("No params provided".to_owned()))?;
43        if params.len() != 1 {
44            return Err(RpcErr::BadParams("Expected 1 param".to_owned()));
45        };
46        let payload: ExchangeTransitionConfigPayload = serde_json::from_value(params[0].clone())?;
47        Ok(ExchangeTransitionConfigV1Req { payload })
48    }
49
50    async fn handle(&self, context: RpcApiContext) -> Result<Value, RpcErr> {
51        debug!("Requested new engine request: {self}");
52        let payload = &self.payload;
53
54        let chain_config = context.storage.get_chain_config();
55        let terminal_total_difficulty = chain_config.terminal_total_difficulty;
56
57        if terminal_total_difficulty.unwrap_or_default() != payload.terminal_total_difficulty {
58            warn!(
59                "Invalid terminal total difficulty configured: execution {:?} consensus {}",
60                terminal_total_difficulty, payload.terminal_total_difficulty
61            );
62        };
63
64        let block = context
65            .storage
66            .get_block_header(payload.terminal_block_number)?;
67        let terminal_block_hash = block.map_or(H256::zero(), |block| block.hash());
68
69        serde_json::to_value(ExchangeTransitionConfigPayload {
70            terminal_block_hash,
71            terminal_block_number: payload.terminal_block_number,
72            terminal_total_difficulty: terminal_total_difficulty.unwrap_or_default(),
73        })
74        .map_err(|error| RpcErr::Internal(error.to_string()))
75    }
76}