From 3d2bc6db9ea13528e1fe30c91260ae1a0b239508 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 22 Sep 2021 19:03:12 +1000 Subject: [PATCH] Add executePayload --- beacon_node/execution_layer/src/engine_api.rs | 16 +++- .../execution_layer/src/engine_api/http.rs | 77 ++++++++++++++++++- 2 files changed, 88 insertions(+), 5 deletions(-) diff --git a/beacon_node/execution_layer/src/engine_api.rs b/beacon_node/execution_layer/src/engine_api.rs index e678c70e8c..8dae48a519 100644 --- a/beacon_node/execution_layer/src/engine_api.rs +++ b/beacon_node/execution_layer/src/engine_api.rs @@ -1,7 +1,8 @@ use async_trait::async_trait; use eth1::http::RpcError; +use serde::{Deserialize, Serialize}; -pub use types::{Address, Hash256}; +pub use types::{Address, EthSpec, ExecutionPayload, Hash256}; pub mod http; @@ -39,4 +40,17 @@ pub trait EngineApi { random: Hash256, fee_recipient: Address, ) -> Result; + + async fn execute_payload( + &self, + execution_payload: ExecutionPayload, + ) -> Result; +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename = "SCREAMING_SNAKE_CASE")] +pub enum ExecutePayloadResponse { + Valid, + Invalid, + Syncing, } diff --git a/beacon_node/execution_layer/src/engine_api/http.rs b/beacon_node/execution_layer/src/engine_api/http.rs index 78323c8731..40626685bd 100644 --- a/beacon_node/execution_layer/src/engine_api/http.rs +++ b/beacon_node/execution_layer/src/engine_api/http.rs @@ -6,10 +6,14 @@ use sensitive_url::SensitiveUrl; use serde::{Deserialize, Serialize}; use serde_json::json; use std::time::Duration; +use types::{execution_payload::serde_logs_bloom, EthSpec, FixedVector, Transaction, VariableList}; const ENGINE_PREPARE_PAYLOAD: &str = "engine_preparePayload"; const ENGINE_PREPARE_PAYLOAD_TIMEOUT: Duration = Duration::from_millis(500); +const ENGINE_EXECUTE_PAYLOAD: &str = "engine_executePayload"; +const ENGINE_EXECUTE_PAYLOAD_TIMEOUT: Duration = Duration::from_secs(2); + pub struct HttpJsonRpc { pub client: Client, pub url: SensitiveUrl, @@ -37,7 +41,7 @@ impl EngineApi for HttpJsonRpc { random: Hash256, fee_recipient: Address, ) -> Result { - let params = json!([PreparePayloadRequest { + let params = json!([JsonPreparePayloadRequest { parent_hash, timestamp, random, @@ -54,15 +58,35 @@ impl EngineApi for HttpJsonRpc { .map_err(Error::RequestFailed)?; let result = response_result_or_error(&response_body).map_err(Error::JsonRpc)?; - let response: PreparePayloadResponse = serde_json::from_value(result)?; + let response: JsonPreparePayloadResponse = serde_json::from_value(result)?; Ok(response.payload_id) } + + async fn execute_payload( + &self, + execution_payload: ExecutionPayload, + ) -> Result { + let params = json!([JsonExecutionPayload::from(execution_payload)]); + + let response_body = send_rpc_request( + &self.url, + ENGINE_EXECUTE_PAYLOAD, + params, + ENGINE_EXECUTE_PAYLOAD_TIMEOUT, + ) + .await + .map_err(Error::RequestFailed)?; + + let result = response_result_or_error(&response_body).map_err(Error::JsonRpc)?; + + serde_json::from_value(result).map_err(Into::into) + } } #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(rename = "camelCase")] -struct PreparePayloadRequest { +struct JsonPreparePayloadRequest { parent_hash: Hash256, #[serde(with = "eth2_serde_utils::u64_hex_be")] timestamp: u64, @@ -72,7 +96,52 @@ struct PreparePayloadRequest { #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(transparent, rename = "camelCase")] -struct PreparePayloadResponse { +struct JsonPreparePayloadResponse { #[serde(with = "eth2_serde_utils::u64_hex_be")] payload_id: u64, } + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(bound = "T: EthSpec")] +pub struct JsonExecutionPayload { + pub parent_hash: Hash256, + pub coinbase: Address, + pub state_root: Hash256, + pub receipt_root: Hash256, + #[serde(with = "serde_logs_bloom")] + pub logs_bloom: FixedVector, + pub random: Hash256, + #[serde(with = "eth2_serde_utils::u64_hex_be")] + pub block_number: u64, + #[serde(with = "eth2_serde_utils::u64_hex_be")] + pub gas_limit: u64, + #[serde(with = "eth2_serde_utils::u64_hex_be")] + pub gas_used: u64, + #[serde(with = "eth2_serde_utils::u64_hex_be")] + pub timestamp: u64, + pub base_fee_per_gas: Hash256, + pub block_hash: Hash256, + // FIXME(paul): add transaction parsing. + #[serde(default)] + pub transactions: VariableList, T::MaxTransactionsPerPayload>, +} + +impl From> for JsonExecutionPayload { + fn from(e: ExecutionPayload) -> Self { + Self { + parent_hash: e.parent_hash, + coinbase: e.coinbase, + state_root: e.state_root, + receipt_root: e.receipt_root, + logs_bloom: e.logs_bloom, + random: e.random, + block_number: e.block_number, + gas_limit: e.gas_limit, + gas_used: e.gas_used, + timestamp: e.timestamp, + base_fee_per_gas: e.base_fee_per_gas, + block_hash: e.block_hash, + transactions: e.transactions, + } + } +}