use async_trait::async_trait; use eth1::http::RpcError; use reqwest::StatusCode; use serde::{Deserialize, Serialize}; pub const LATEST_TAG: &str = "latest"; use crate::engines::ForkChoiceState; pub use json_structures::TransitionConfigurationV1; pub use types::{Address, EthSpec, ExecutionBlockHash, ExecutionPayload, Hash256, Uint256}; pub mod auth; pub mod http; pub mod json_structures; pub type PayloadId = [u8; 8]; #[derive(Debug)] pub enum Error { Reqwest(reqwest::Error), Auth(auth::Error), BadResponse(String), RequestFailed(String), InvalidExecutePayloadResponse(&'static str), JsonRpc(RpcError), Json(serde_json::Error), ServerMessage { code: i64, message: String }, Eip155Failure, IsSyncing, ExecutionBlockNotFound(ExecutionBlockHash), ExecutionHeadBlockNotFound, ParentHashEqualsBlockHash(ExecutionBlockHash), PayloadIdUnavailable, TransitionConfigurationMismatch, } impl From for Error { fn from(e: reqwest::Error) -> Self { if matches!( e.status(), Some(StatusCode::UNAUTHORIZED) | Some(StatusCode::FORBIDDEN) ) { Error::Auth(auth::Error::InvalidToken) } else { Error::Reqwest(e) } } } impl From for Error { fn from(e: serde_json::Error) -> Self { Error::Json(e) } } impl From for Error { fn from(e: auth::Error) -> Self { Error::Auth(e) } } /// A generic interface for an execution engine API. #[async_trait] pub trait EngineApi { async fn upcheck(&self) -> Result<(), Error>; async fn get_block_by_number<'a>( &self, block_by_number: BlockByNumberQuery<'a>, ) -> Result, Error>; async fn get_block_by_hash<'a>( &self, block_hash: ExecutionBlockHash, ) -> Result, Error>; async fn new_payload_v1( &self, execution_payload: ExecutionPayload, ) -> Result; async fn get_payload_v1( &self, payload_id: PayloadId, ) -> Result, Error>; async fn forkchoice_updated_v1( &self, forkchoice_state: ForkChoiceState, payload_attributes: Option, ) -> Result; async fn exchange_transition_configuration_v1( &self, transition_configuration: TransitionConfigurationV1, ) -> Result; } #[derive(Clone, Copy, Debug, PartialEq)] pub enum PayloadStatusV1Status { Valid, Invalid, Syncing, Accepted, InvalidBlockHash, InvalidTerminalBlock, } #[derive(Clone, Debug, PartialEq)] pub struct PayloadStatusV1 { pub status: PayloadStatusV1Status, pub latest_valid_hash: Option, pub validation_error: Option, } #[derive(Clone, Copy, Debug, PartialEq, Serialize)] #[serde(untagged)] pub enum BlockByNumberQuery<'a> { Tag(&'a str), } #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ExecutionBlock { #[serde(rename = "hash")] pub block_hash: ExecutionBlockHash, #[serde(rename = "number", with = "eth2_serde_utils::u64_hex_be")] pub block_number: u64, pub parent_hash: ExecutionBlockHash, pub total_difficulty: Uint256, } #[derive(Clone, Copy, Debug)] pub struct PayloadAttributes { pub timestamp: u64, pub prev_randao: Hash256, pub suggested_fee_recipient: Address, } #[derive(Clone, Debug, PartialEq)] pub struct ForkchoiceUpdatedResponse { pub payload_status: PayloadStatusV1, pub payload_id: Option, }