Skip to content

Commit

Permalink
Use RawExecutionRequests in engine_getPayloadV4 response, add basic t…
Browse files Browse the repository at this point in the history
…ests
  • Loading branch information
Tumas committed Oct 18, 2024
1 parent 8825698 commit 05da9f1
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 47 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion eth1_api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ prometheus_metrics = { workspace = true }
reqwest = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
serde_utils = { workspace = true }
ssz = { workspace = true }
static_assertions = { workspace = true }
std_ext = { workspace = true }
Expand Down
128 changes: 88 additions & 40 deletions eth1_api/src/eth1_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,20 @@ use execution_engine::{
EngineGetPayloadV1Response, EngineGetPayloadV2Response, EngineGetPayloadV3Response,
EngineGetPayloadV4Response, ExecutionPayloadV1, ExecutionPayloadV2, ExecutionPayloadV3,
ForkChoiceStateV1, ForkChoiceUpdatedResponse, PayloadAttributes, PayloadId, PayloadStatusV1,
RawExecutionRequests,
};
use futures::{channel::mpsc::UnboundedSender, lock::Mutex, Future};
use log::warn;
use prometheus_metrics::Metrics;
use reqwest::{header::HeaderMap, Client, Url};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serde::{de::DeserializeOwned, Deserialize};
use serde_json::Value;
use ssz::ContiguousList;
use static_assertions::const_assert_eq;
use std_ext::CopyExt;
use thiserror::Error;
use types::{
combined::{ExecutionPayload, ExecutionPayloadParams},
config::Config,
electra::containers::{
ConsolidationRequest, DepositRequest, ExecutionRequests, WithdrawalRequest,
},
nonstandard::{Phase, WithBlobsAndMev},
phase0::primitives::{ExecutionBlockHash, ExecutionBlockNumber},
preset::Preset,
Expand Down Expand Up @@ -562,40 +559,6 @@ struct RawForkChoiceUpdatedResponse {
payload_id: Option<H64>,
}

#[derive(Deserialize, Serialize)]
struct RawExecutionRequests<P: Preset>(
#[serde(with = "crate::ssz_as_prefixed_hex_or_bytes")]
ContiguousList<DepositRequest, P::MaxDepositRequestsPerPayload>,
#[serde(with = "crate::ssz_as_prefixed_hex_or_bytes")]
ContiguousList<WithdrawalRequest, P::MaxWithdrawalRequestsPerPayload>,
#[serde(with = "crate::ssz_as_prefixed_hex_or_bytes")]
ContiguousList<ConsolidationRequest, P::MaxConsolidationRequestsPerPayload>,
);

impl<P: Preset> From<ExecutionRequests<P>> for RawExecutionRequests<P> {
fn from(execution_requests: ExecutionRequests<P>) -> Self {
let ExecutionRequests {
deposits,
withdrawals,
consolidations,
} = execution_requests;

Self(deposits, withdrawals, consolidations)
}
}

impl<P: Preset> From<RawExecutionRequests<P>> for ExecutionRequests<P> {
fn from(raw_execution_requests: RawExecutionRequests<P>) -> Self {
let RawExecutionRequests(deposits, withdrawals, consolidations) = raw_execution_requests;

Self {
deposits,
withdrawals,
consolidations,
}
}
}

#[derive(Debug, Error)]
enum Error {
#[error("all Eth1 RPC endpoints exhausted")]
Expand All @@ -617,7 +580,7 @@ mod tests {
use serde_json::json;
use types::{
bellatrix::containers::ExecutionPayload as BellatrixExecutionPayload,
phase0::primitives::H256, preset::Mainnet,
electra::containers::ExecutionRequests, phase0::primitives::H256, preset::Mainnet,
};

use super::*;
Expand Down Expand Up @@ -753,6 +716,91 @@ mod tests {
Ok(())
}

#[tokio::test]
async fn test_electra_payload_deserialization_with_default_execution_requests() -> Result<()> {
let body = json!({
"jsonrpc": "2.0",
"id": 0,
"result": {
"executionPayload": {
"parentHash": "0x128133536f44733af5e59ba865744690498529592c1e85655348ec6bb559c658",
"feeRecipient": "0x8943545177806ed17b9f23f0a21ee5948ecaa776",
"stateRoot": "0xfb458127dfb40b16693e70886d0f503160be2ad409ab885fb4051d96b07bdef1",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"prevRandao": "0x4c2db6d476f102aa7b68808f9262c70760e6cd5f23213c039cbe7309437a8d9d",
"blockNumber": "0x29",
"gasLimit": "0x1c9c380",
"gasUsed": "0x0",
"timestamp": "0x671214b3",
"extraData": "0xd883010e0c846765746888676f312e32332e32856c696e7578",
"baseFeePerGas": "0x403226",
"blockHash": "0x49a38631ab242befe4d9fbb1a49c7059c21363a534542f8bcf419a82b92a229b",
"transactions": [],
"withdrawals": [
{
"index": "0xbb",
"validatorIndex": "0xd1",
"address": "0x65d08a056c17ae13370565b04cf77d2afa1cb9fa",
"amount": "0x51f0"
},
{
"index": "0xbc",
"validatorIndex": "0xd2",
"address": "0x65d08a056c17ae13370565b04cf77d2afa1cb9fa",
"amount": "0x51f0"
}
],
"blobGasUsed": "0x0",
"excessBlobGas": "0x0"
},
"blockValue": "0x0",
"blobsBundle": {
"commitments": [],
"proofs": [],
"blobs": []
},
"executionRequests": [
"0x",
"0x",
"0x"
],
"shouldOverrideBuilder": false
}
});

let server = MockServer::start();

server.mock(|when, then| {
when.method(Method::POST).path("/");
then.status(200).body(body.to_string());
});

let config = Arc::new(Config::mainnet());
let auth = Arc::default();
let server_url = server.url("/").parse()?;

let eth1_api = Arc::new(Eth1Api::new(
config,
Client::new(),
auth,
vec![server_url],
None,
None,
));

let payload_id = PayloadId::Electra(H64(hex!("a5f7426cdca69a73")));
let payload = eth1_api.get_payload::<Mainnet>(payload_id).await?;

assert_eq!(payload.value.phase(), Phase::Deneb);
assert_eq!(
payload.execution_requests,
Some(ExecutionRequests::default())
);

Ok(())
}

#[tokio::test]
async fn test_valid_payload_status_deserialization() -> Result<()> {
let body = json!({
Expand Down
1 change: 0 additions & 1 deletion eth1_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,3 @@ mod eth1_execution_engine;
mod execution_service;
mod messages;
mod misc;
mod ssz_as_prefixed_hex_or_bytes;
3 changes: 2 additions & 1 deletion execution_engine/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ pub use crate::{
EngineGetPayloadV4Response, ExecutionPayloadV1, ExecutionPayloadV2, ExecutionPayloadV3,
ForkChoiceStateV1, ForkChoiceUpdatedResponse, PayloadAttributes, PayloadAttributesV1,
PayloadAttributesV2, PayloadAttributesV3, PayloadId, PayloadStatus, PayloadStatusV1,
PayloadStatusWithBlockHash, PayloadValidationStatus,
PayloadStatusWithBlockHash, PayloadValidationStatus, RawExecutionRequests,
},
};

mod execution_engine;
mod ssz_as_prefixed_hex_or_bytes;
mod types;
50 changes: 47 additions & 3 deletions execution_engine/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ use types::{
containers::ExecutionPayload as DenebExecutionPayload,
primitives::{Blob, KzgCommitment, KzgProof},
},
electra::containers::ExecutionRequests,
electra::containers::{
ConsolidationRequest, DepositRequest, ExecutionRequests, WithdrawalRequest,
},
nonstandard::{Phase, WithBlobsAndMev},
phase0::primitives::{
ExecutionAddress, ExecutionBlockHash, ExecutionBlockNumber, Gwei, UnixSeconds,
Expand Down Expand Up @@ -499,7 +501,7 @@ pub struct EngineGetPayloadV4Response<P: Preset> {
pub block_value: Wei,
pub blobs_bundle: BlobsBundleV1<P>,
pub should_override_builder: bool,
pub execution_requests: ExecutionRequests<P>,
pub execution_requests: RawExecutionRequests<P>,
}

impl<P: Preset> From<EngineGetPayloadV4Response<P>> for WithBlobsAndMev<ExecutionPayload<P>, P> {
Expand All @@ -526,7 +528,7 @@ impl<P: Preset> From<EngineGetPayloadV4Response<P>> for WithBlobsAndMev<Executio
Some(proofs),
Some(blobs),
Some(block_value),
Some(execution_requests),
Some(execution_requests.into()),
)
}
}
Expand Down Expand Up @@ -687,6 +689,41 @@ impl From<PayloadStatus> for PayloadStatusV1 {
}
}

#[derive(Deserialize, Serialize)]
#[cfg_attr(test, derive(Default))]
pub struct RawExecutionRequests<P: Preset>(
#[serde(with = "crate::ssz_as_prefixed_hex_or_bytes")]
ContiguousList<DepositRequest, P::MaxDepositRequestsPerPayload>,
#[serde(with = "crate::ssz_as_prefixed_hex_or_bytes")]
ContiguousList<WithdrawalRequest, P::MaxWithdrawalRequestsPerPayload>,
#[serde(with = "crate::ssz_as_prefixed_hex_or_bytes")]
ContiguousList<ConsolidationRequest, P::MaxConsolidationRequestsPerPayload>,
);

impl<P: Preset> From<ExecutionRequests<P>> for RawExecutionRequests<P> {
fn from(execution_requests: ExecutionRequests<P>) -> Self {
let ExecutionRequests {
deposits,
withdrawals,
consolidations,
} = execution_requests;

Self(deposits, withdrawals, consolidations)
}
}

impl<P: Preset> From<RawExecutionRequests<P>> for ExecutionRequests<P> {
fn from(raw_execution_requests: RawExecutionRequests<P>) -> Self {
let RawExecutionRequests(deposits, withdrawals, consolidations) = raw_execution_requests;

Self {
deposits,
withdrawals,
consolidations,
}
}
}

#[cfg(test)]
mod tests {
use anyhow::Result;
Expand Down Expand Up @@ -767,6 +804,13 @@ mod tests {
Ok(())
}

#[test]
fn test_default_raw_execution_requests_serialization() -> Result<()> {
let serialized = serde_json::to_value(RawExecutionRequests::<Mainnet>::default())?;
assert_eq!(serialized, json!(vec!["0x", "0x", "0x"]));
Ok(())
}

#[test]
fn test_payload_status_v1_round_trip() -> Result<()> {
let json = json!({
Expand Down

0 comments on commit 05da9f1

Please sign in to comment.