mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat: add more beacon API types (#5292)
This commit is contained in:
4
crates/rpc/rpc-types/src/beacon/constants.rs
Normal file
4
crates/rpc/rpc-types/src/beacon/constants.rs
Normal file
@ -0,0 +1,4 @@
|
||||
pub const BLS_DST: &[u8] = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_";
|
||||
pub const BLS_PUBLIC_KEY_BYTES_LEN: usize = 48;
|
||||
pub const BLS_SECRET_KEY_BYTES_LEN: usize = 32;
|
||||
pub const BLS_SIGNATURE_BYTES_LEN: usize = 96;
|
||||
@ -270,7 +270,7 @@ pub struct PayloadAttributesData {
|
||||
///
|
||||
/// Note: this uses the beacon API format which uses snake-case and quoted decimals rather than
|
||||
/// big-endian hex.
|
||||
#[serde(with = "crate::eth::engine::payload::beacon_api_payload_attributes")]
|
||||
#[serde(with = "crate::beacon::payload::beacon_api_payload_attributes")]
|
||||
pub payload_attributes: PayloadAttributes,
|
||||
}
|
||||
|
||||
17
crates/rpc/rpc-types/src/beacon/mod.rs
Normal file
17
crates/rpc/rpc-types/src/beacon/mod.rs
Normal file
@ -0,0 +1,17 @@
|
||||
#![allow(missing_docs)]
|
||||
//! Types for the Ethereum 2.0 RPC protocol (beacon chain)
|
||||
|
||||
use alloy_primitives::FixedBytes;
|
||||
use constants::{BLS_PUBLIC_KEY_BYTES_LEN, BLS_SIGNATURE_BYTES_LEN};
|
||||
|
||||
pub mod constants;
|
||||
/// Beacon API events support.
|
||||
pub mod events;
|
||||
pub mod payload;
|
||||
pub mod withdrawals;
|
||||
|
||||
/// BLS signature type
|
||||
pub type BlsSignature = FixedBytes<BLS_SIGNATURE_BYTES_LEN>;
|
||||
|
||||
/// BLS public key type
|
||||
pub type BlsPublicKey = FixedBytes<BLS_PUBLIC_KEY_BYTES_LEN>;
|
||||
460
crates/rpc/rpc-types/src/beacon/payload.rs
Normal file
460
crates/rpc/rpc-types/src/beacon/payload.rs
Normal file
@ -0,0 +1,460 @@
|
||||
#![allow(missing_docs)]
|
||||
//! Payload support for the beacon API.
|
||||
//!
|
||||
//! Internal helper module to deserialize/serialize the payload attributes for the beacon API, which
|
||||
//! uses snake case and quoted decimals.
|
||||
//!
|
||||
//! This is necessary because we don't want to allow a mixture of both formats, hence `serde`
|
||||
//! aliases are not an option.
|
||||
//!
|
||||
//! See also <https://github.com/ethereum/consensus-specs/blob/master/specs/deneb/beacon-chain.md#executionpayload>
|
||||
|
||||
use crate::{
|
||||
beacon::withdrawals::BeaconWithdrawal, engine::ExecutionPayloadV3, ExecutionPayload,
|
||||
ExecutionPayloadV1, ExecutionPayloadV2, Withdrawal,
|
||||
};
|
||||
use alloy_primitives::{Address, Bloom, Bytes, B256, U256, U64};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use serde_with::{serde_as, DeserializeAs, DisplayFromStr, SerializeAs};
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct BeaconPayloadAttributes {
|
||||
#[serde_as(as = "DisplayFromStr")]
|
||||
timestamp: u64,
|
||||
prev_randao: B256,
|
||||
suggested_fee_recipient: Address,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[serde_as(as = "Option<Vec<BeaconWithdrawal>>")]
|
||||
withdrawals: Option<Vec<Withdrawal>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
parent_beacon_block_root: Option<B256>,
|
||||
#[cfg(feature = "optimism")]
|
||||
#[serde(flatten)]
|
||||
optimism_payload_attributes: BeaconOptimismPayloadAttributes,
|
||||
}
|
||||
|
||||
/// Optimism Payload Attributes
|
||||
#[cfg(feature = "optimism")]
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct BeaconOptimismPayloadAttributes {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
transactions: Option<Vec<Bytes>>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
no_tx_pool: Option<bool>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[serde_as(as = "Option<DisplayFromStr>")]
|
||||
gas_limit: Option<u64>,
|
||||
}
|
||||
|
||||
/// A helper module for serializing and deserializing the payload attributes for the beacon API.
|
||||
///
|
||||
/// The beacon API encoded object has equivalent fields to the
|
||||
/// [PayloadAttributes](crate::engine::PayloadAttributes) with two differences:
|
||||
/// 1) `snake_case` identifiers must be used rather than `camelCase`;
|
||||
/// 2) integers must be encoded as quoted decimals rather than big-endian hex.
|
||||
pub mod beacon_api_payload_attributes {
|
||||
use super::*;
|
||||
use crate::engine::PayloadAttributes;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
/// Serialize the payload attributes for the beacon API.
|
||||
pub fn serialize<S>(
|
||||
payload_attributes: &PayloadAttributes,
|
||||
serializer: S,
|
||||
) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let beacon_api_payload_attributes = BeaconPayloadAttributes {
|
||||
timestamp: payload_attributes.timestamp.to(),
|
||||
prev_randao: payload_attributes.prev_randao,
|
||||
suggested_fee_recipient: payload_attributes.suggested_fee_recipient,
|
||||
withdrawals: payload_attributes.withdrawals.clone(),
|
||||
parent_beacon_block_root: payload_attributes.parent_beacon_block_root,
|
||||
#[cfg(feature = "optimism")]
|
||||
optimism_payload_attributes: BeaconOptimismPayloadAttributes {
|
||||
transactions: payload_attributes.optimism_payload_attributes.transactions.clone(),
|
||||
no_tx_pool: payload_attributes.optimism_payload_attributes.no_tx_pool,
|
||||
gas_limit: payload_attributes.optimism_payload_attributes.gas_limit,
|
||||
},
|
||||
};
|
||||
beacon_api_payload_attributes.serialize(serializer)
|
||||
}
|
||||
|
||||
/// Deserialize the payload attributes for the beacon API.
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<PayloadAttributes, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let beacon_api_payload_attributes = BeaconPayloadAttributes::deserialize(deserializer)?;
|
||||
Ok(PayloadAttributes {
|
||||
timestamp: U64::from(beacon_api_payload_attributes.timestamp),
|
||||
prev_randao: beacon_api_payload_attributes.prev_randao,
|
||||
suggested_fee_recipient: beacon_api_payload_attributes.suggested_fee_recipient,
|
||||
withdrawals: beacon_api_payload_attributes.withdrawals,
|
||||
parent_beacon_block_root: beacon_api_payload_attributes.parent_beacon_block_root,
|
||||
#[cfg(feature = "optimism")]
|
||||
optimism_payload_attributes: crate::eth::engine::OptimismPayloadAttributes {
|
||||
transactions: beacon_api_payload_attributes
|
||||
.optimism_payload_attributes
|
||||
.transactions,
|
||||
no_tx_pool: beacon_api_payload_attributes.optimism_payload_attributes.no_tx_pool,
|
||||
gas_limit: beacon_api_payload_attributes.optimism_payload_attributes.gas_limit,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct BeaconExecutionPayloadV1<'a> {
|
||||
parent_hash: Cow<'a, B256>,
|
||||
fee_recipient: Cow<'a, Address>,
|
||||
state_root: Cow<'a, B256>,
|
||||
receipts_root: Cow<'a, B256>,
|
||||
logs_bloom: Cow<'a, Bloom>,
|
||||
prev_randao: Cow<'a, B256>,
|
||||
#[serde_as(as = "DisplayFromStr")]
|
||||
block_number: u64,
|
||||
#[serde_as(as = "DisplayFromStr")]
|
||||
gas_limit: u64,
|
||||
#[serde_as(as = "DisplayFromStr")]
|
||||
gas_used: u64,
|
||||
#[serde_as(as = "DisplayFromStr")]
|
||||
timestamp: u64,
|
||||
extra_data: Cow<'a, Bytes>,
|
||||
#[serde_as(as = "DisplayFromStr")]
|
||||
base_fee_per_gas: U256,
|
||||
block_hash: Cow<'a, B256>,
|
||||
transactions: Cow<'a, Vec<Bytes>>,
|
||||
}
|
||||
|
||||
impl<'a> From<BeaconExecutionPayloadV1<'a>> for ExecutionPayloadV1 {
|
||||
fn from(payload: BeaconExecutionPayloadV1<'a>) -> Self {
|
||||
let BeaconExecutionPayloadV1 {
|
||||
parent_hash,
|
||||
fee_recipient,
|
||||
state_root,
|
||||
receipts_root,
|
||||
logs_bloom,
|
||||
prev_randao,
|
||||
block_number,
|
||||
gas_limit,
|
||||
gas_used,
|
||||
timestamp,
|
||||
extra_data,
|
||||
base_fee_per_gas,
|
||||
block_hash,
|
||||
transactions,
|
||||
} = payload;
|
||||
ExecutionPayloadV1 {
|
||||
parent_hash: parent_hash.into_owned(),
|
||||
fee_recipient: fee_recipient.into_owned(),
|
||||
state_root: state_root.into_owned(),
|
||||
receipts_root: receipts_root.into_owned(),
|
||||
logs_bloom: logs_bloom.into_owned(),
|
||||
prev_randao: prev_randao.into_owned(),
|
||||
block_number: U64::from(block_number),
|
||||
gas_limit: U64::from(gas_limit),
|
||||
gas_used: U64::from(gas_used),
|
||||
timestamp: U64::from(timestamp),
|
||||
extra_data: extra_data.into_owned(),
|
||||
base_fee_per_gas,
|
||||
block_hash: block_hash.into_owned(),
|
||||
transactions: transactions.into_owned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ExecutionPayloadV1> for BeaconExecutionPayloadV1<'a> {
|
||||
fn from(value: &'a ExecutionPayloadV1) -> Self {
|
||||
let ExecutionPayloadV1 {
|
||||
parent_hash,
|
||||
fee_recipient,
|
||||
state_root,
|
||||
receipts_root,
|
||||
logs_bloom,
|
||||
prev_randao,
|
||||
block_number,
|
||||
gas_limit,
|
||||
gas_used,
|
||||
timestamp,
|
||||
extra_data,
|
||||
base_fee_per_gas,
|
||||
block_hash,
|
||||
transactions,
|
||||
} = value;
|
||||
|
||||
BeaconExecutionPayloadV1 {
|
||||
parent_hash: Cow::Borrowed(parent_hash),
|
||||
fee_recipient: Cow::Borrowed(fee_recipient),
|
||||
state_root: Cow::Borrowed(state_root),
|
||||
receipts_root: Cow::Borrowed(receipts_root),
|
||||
logs_bloom: Cow::Borrowed(logs_bloom),
|
||||
prev_randao: Cow::Borrowed(prev_randao),
|
||||
block_number: block_number.to(),
|
||||
gas_limit: gas_limit.to(),
|
||||
gas_used: gas_used.to(),
|
||||
timestamp: timestamp.to(),
|
||||
extra_data: Cow::Borrowed(extra_data),
|
||||
base_fee_per_gas: *base_fee_per_gas,
|
||||
block_hash: Cow::Borrowed(block_hash),
|
||||
transactions: Cow::Borrowed(transactions),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A helper serde module to convert from/to the Beacon API which uses quoted decimals rather than
|
||||
/// big-endian hex.
|
||||
pub mod beacon_payload_v1 {
|
||||
use super::*;
|
||||
use serde::{Deserializer, Serializer};
|
||||
|
||||
/// Serialize the payload attributes for the beacon API.
|
||||
pub fn serialize<S>(
|
||||
payload_attributes: &ExecutionPayloadV1,
|
||||
serializer: S,
|
||||
) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
BeaconExecutionPayloadV1::from(payload_attributes).serialize(serializer)
|
||||
}
|
||||
|
||||
/// Deserialize the payload attributes for the beacon API.
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<ExecutionPayloadV1, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
BeaconExecutionPayloadV1::deserialize(deserializer).map(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct BeaconExecutionPayloadV2<'a> {
|
||||
/// Inner V1 payload
|
||||
#[serde(flatten)]
|
||||
payload_inner: BeaconExecutionPayloadV1<'a>,
|
||||
/// Array of [`Withdrawal`] enabled with V2
|
||||
/// See <https://github.com/ethereum/execution-apis/blob/6709c2a795b707202e93c4f2867fa0bf2640a84f/src/engine/shanghai.md#executionpayloadv2>
|
||||
#[serde_as(as = "Vec<BeaconWithdrawal>")]
|
||||
withdrawals: Vec<Withdrawal>,
|
||||
}
|
||||
|
||||
impl<'a> From<BeaconExecutionPayloadV2<'a>> for ExecutionPayloadV2 {
|
||||
fn from(payload: BeaconExecutionPayloadV2<'a>) -> Self {
|
||||
let BeaconExecutionPayloadV2 { payload_inner, withdrawals } = payload;
|
||||
ExecutionPayloadV2 { payload_inner: payload_inner.into(), withdrawals }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ExecutionPayloadV2> for BeaconExecutionPayloadV2<'a> {
|
||||
fn from(value: &'a ExecutionPayloadV2) -> Self {
|
||||
let ExecutionPayloadV2 { payload_inner, withdrawals } = value;
|
||||
BeaconExecutionPayloadV2 {
|
||||
payload_inner: payload_inner.into(),
|
||||
withdrawals: withdrawals.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A helper serde module to convert from/to the Beacon API which uses quoted decimals rather than
|
||||
/// big-endian hex.
|
||||
pub mod beacon_payload_v2 {
|
||||
use super::*;
|
||||
use serde::{Deserializer, Serializer};
|
||||
|
||||
/// Serialize the payload attributes for the beacon API.
|
||||
pub fn serialize<S>(
|
||||
payload_attributes: &ExecutionPayloadV2,
|
||||
serializer: S,
|
||||
) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
BeaconExecutionPayloadV2::from(payload_attributes).serialize(serializer)
|
||||
}
|
||||
|
||||
/// Deserialize the payload attributes for the beacon API.
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<ExecutionPayloadV2, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
BeaconExecutionPayloadV2::deserialize(deserializer).map(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct BeaconExecutionPayloadV3<'a> {
|
||||
/// Inner V1 payload
|
||||
#[serde(flatten)]
|
||||
payload_inner: BeaconExecutionPayloadV2<'a>,
|
||||
/// Array of [`U64`] representing blob gas used, enabled with V3
|
||||
/// See <https://github.com/ethereum/execution-apis/blob/fe8e13c288c592ec154ce25c534e26cb7ce0530d/src/engine/cancun.md#ExecutionPayloadV3>
|
||||
#[serde_as(as = "DisplayFromStr")]
|
||||
blob_gas_used: u64,
|
||||
/// Array of [`U64`] representing excess blob gas, enabled with V3
|
||||
/// See <https://github.com/ethereum/execution-apis/blob/fe8e13c288c592ec154ce25c534e26cb7ce0530d/src/engine/cancun.md#ExecutionPayloadV3>
|
||||
#[serde_as(as = "DisplayFromStr")]
|
||||
excess_blob_gas: u64,
|
||||
}
|
||||
|
||||
impl<'a> From<BeaconExecutionPayloadV3<'a>> for ExecutionPayloadV3 {
|
||||
fn from(payload: BeaconExecutionPayloadV3<'a>) -> Self {
|
||||
let BeaconExecutionPayloadV3 { payload_inner, blob_gas_used, excess_blob_gas } = payload;
|
||||
ExecutionPayloadV3 {
|
||||
payload_inner: payload_inner.into(),
|
||||
blob_gas_used: U64::from(blob_gas_used),
|
||||
excess_blob_gas: U64::from(excess_blob_gas),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ExecutionPayloadV3> for BeaconExecutionPayloadV3<'a> {
|
||||
fn from(value: &'a ExecutionPayloadV3) -> Self {
|
||||
let ExecutionPayloadV3 { payload_inner, blob_gas_used, excess_blob_gas } = value;
|
||||
BeaconExecutionPayloadV3 {
|
||||
payload_inner: payload_inner.into(),
|
||||
blob_gas_used: blob_gas_used.to(),
|
||||
excess_blob_gas: excess_blob_gas.to(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A helper serde module to convert from/to the Beacon API which uses quoted decimals rather than
|
||||
/// big-endian hex.
|
||||
pub mod beacon_payload_v3 {
|
||||
use super::*;
|
||||
use serde::{Deserializer, Serializer};
|
||||
|
||||
/// Serialize the payload attributes for the beacon API.
|
||||
pub fn serialize<S>(
|
||||
payload_attributes: &ExecutionPayloadV3,
|
||||
serializer: S,
|
||||
) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
BeaconExecutionPayloadV3::from(payload_attributes).serialize(serializer)
|
||||
}
|
||||
|
||||
/// Deserialize the payload attributes for the beacon API.
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<ExecutionPayloadV3, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
BeaconExecutionPayloadV3::deserialize(deserializer).map(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents all possible payload versions.
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(untagged)]
|
||||
enum BeaconExecutionPayload<'a> {
|
||||
/// V1 payload
|
||||
V1(BeaconExecutionPayloadV1<'a>),
|
||||
/// V2 payload
|
||||
V2(BeaconExecutionPayloadV2<'a>),
|
||||
/// V3 payload
|
||||
V3(BeaconExecutionPayloadV3<'a>),
|
||||
}
|
||||
|
||||
// Deserializes untagged ExecutionPayload by trying each variant in falling order
|
||||
impl<'de> Deserialize<'de> for BeaconExecutionPayload<'de> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum BeaconExecutionPayloadDesc<'a> {
|
||||
V3(BeaconExecutionPayloadV3<'a>),
|
||||
V2(BeaconExecutionPayloadV2<'a>),
|
||||
V1(BeaconExecutionPayloadV1<'a>),
|
||||
}
|
||||
match BeaconExecutionPayloadDesc::deserialize(deserializer)? {
|
||||
BeaconExecutionPayloadDesc::V3(payload) => Ok(Self::V3(payload)),
|
||||
BeaconExecutionPayloadDesc::V2(payload) => Ok(Self::V2(payload)),
|
||||
BeaconExecutionPayloadDesc::V1(payload) => Ok(Self::V1(payload)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<BeaconExecutionPayload<'a>> for ExecutionPayload {
|
||||
fn from(payload: BeaconExecutionPayload<'a>) -> Self {
|
||||
match payload {
|
||||
BeaconExecutionPayload::V1(payload) => {
|
||||
ExecutionPayload::V1(ExecutionPayloadV1::from(payload))
|
||||
}
|
||||
BeaconExecutionPayload::V2(payload) => {
|
||||
ExecutionPayload::V2(ExecutionPayloadV2::from(payload))
|
||||
}
|
||||
BeaconExecutionPayload::V3(payload) => {
|
||||
ExecutionPayload::V3(ExecutionPayloadV3::from(payload))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ExecutionPayload> for BeaconExecutionPayload<'a> {
|
||||
fn from(value: &'a ExecutionPayload) -> Self {
|
||||
match value {
|
||||
ExecutionPayload::V1(payload) => {
|
||||
BeaconExecutionPayload::V1(BeaconExecutionPayloadV1::from(payload))
|
||||
}
|
||||
ExecutionPayload::V2(payload) => {
|
||||
BeaconExecutionPayload::V2(BeaconExecutionPayloadV2::from(payload))
|
||||
}
|
||||
ExecutionPayload::V3(payload) => {
|
||||
BeaconExecutionPayload::V3(BeaconExecutionPayloadV3::from(payload))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> SerializeAs<ExecutionPayload> for BeaconExecutionPayload<'a> {
|
||||
fn serialize_as<S>(source: &ExecutionPayload, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
beacon_payload::serialize(source, serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> DeserializeAs<'de, ExecutionPayload> for BeaconExecutionPayload<'de> {
|
||||
fn deserialize_as<D>(deserializer: D) -> Result<ExecutionPayload, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
beacon_payload::deserialize(deserializer)
|
||||
}
|
||||
}
|
||||
|
||||
pub mod beacon_payload {
|
||||
use super::*;
|
||||
use serde::{Deserializer, Serializer};
|
||||
|
||||
/// Serialize the payload attributes for the beacon API.
|
||||
pub fn serialize<S>(
|
||||
payload_attributes: &ExecutionPayload,
|
||||
serializer: S,
|
||||
) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
BeaconExecutionPayload::from(payload_attributes).serialize(serializer)
|
||||
}
|
||||
|
||||
/// Deserialize the payload attributes for the beacon API.
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<ExecutionPayload, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
BeaconExecutionPayload::deserialize(deserializer).map(Into::into)
|
||||
}
|
||||
}
|
||||
72
crates/rpc/rpc-types/src/beacon/withdrawals.rs
Normal file
72
crates/rpc/rpc-types/src/beacon/withdrawals.rs
Normal file
@ -0,0 +1,72 @@
|
||||
use alloy_primitives::Address;
|
||||
|
||||
use crate::Withdrawal;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use serde_with::{serde_as, DeserializeAs, DisplayFromStr, SerializeAs};
|
||||
|
||||
/// Same as [Withdrawal] but respects the Beacon API format which uses snake-case and quoted
|
||||
/// decimals.
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub(crate) struct BeaconWithdrawal {
|
||||
#[serde_as(as = "DisplayFromStr")]
|
||||
index: u64,
|
||||
#[serde_as(as = "DisplayFromStr")]
|
||||
validator_index: u64,
|
||||
address: Address,
|
||||
#[serde_as(as = "DisplayFromStr")]
|
||||
amount: u64,
|
||||
}
|
||||
|
||||
impl SerializeAs<Withdrawal> for BeaconWithdrawal {
|
||||
fn serialize_as<S>(source: &Withdrawal, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
beacon_withdrawals::serialize(source, serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> DeserializeAs<'de, Withdrawal> for BeaconWithdrawal {
|
||||
fn deserialize_as<D>(deserializer: D) -> Result<Withdrawal, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
beacon_withdrawals::deserialize(deserializer)
|
||||
}
|
||||
}
|
||||
|
||||
/// A helper serde module to convert from/to the Beacon API which uses quoted decimals rather than
|
||||
/// big-endian hex.
|
||||
pub mod beacon_withdrawals {
|
||||
use super::*;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
/// Serialize the payload attributes for the beacon API.
|
||||
pub fn serialize<S>(payload_attributes: &Withdrawal, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let withdrawal = BeaconWithdrawal {
|
||||
index: payload_attributes.index,
|
||||
validator_index: payload_attributes.validator_index,
|
||||
address: payload_attributes.address,
|
||||
amount: payload_attributes.amount,
|
||||
};
|
||||
withdrawal.serialize(serializer)
|
||||
}
|
||||
|
||||
/// Deserialize the payload attributes for the beacon API.
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Withdrawal, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let withdrawal = BeaconWithdrawal::deserialize(deserializer)?;
|
||||
Ok(Withdrawal {
|
||||
index: withdrawal.index,
|
||||
validator_index: withdrawal.validator_index,
|
||||
address: withdrawal.address,
|
||||
amount: withdrawal.amount,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1,2 +0,0 @@
|
||||
/// Beacon API events support.
|
||||
pub mod events;
|
||||
@ -1,6 +1,5 @@
|
||||
//! Engine API types: <https://github.com/ethereum/execution-apis/blob/main/src/engine/authentication.md> and <https://eips.ethereum.org/EIPS/eip-3675> following the execution specs <https://github.com/ethereum/execution-apis/tree/6709c2a795b707202e93c4f2867fa0bf2640a84f/src/engine>
|
||||
|
||||
#![allow(missing_docs)]
|
||||
//! Engine API types: <https://github.com/ethereum/execution-apis/blob/main/src/engine/authentication.md> and <https://eips.ethereum.org/EIPS/eip-3675> following the execution specs <https://github.com/ethereum/execution-apis/tree/6709c2a795b707202e93c4f2867fa0bf2640a84f/src/engine>
|
||||
|
||||
mod cancun;
|
||||
mod forkchoice;
|
||||
@ -8,9 +7,6 @@ pub mod payload;
|
||||
mod transition;
|
||||
pub use self::{cancun::*, forkchoice::*, payload::*, transition::*};
|
||||
|
||||
/// Beacon API types
|
||||
pub mod beacon_api;
|
||||
|
||||
/// The list of all supported Engine capabilities available over the engine endpoint.
|
||||
pub const CAPABILITIES: [&str; 12] = [
|
||||
"engine_forkchoiceUpdatedV1",
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
use crate::eth::{transaction::BlobTransactionSidecar, withdrawal::BeaconAPIWithdrawal};
|
||||
use crate::eth::transaction::BlobTransactionSidecar;
|
||||
pub use crate::Withdrawal;
|
||||
use alloy_primitives::{Address, Bloom, Bytes, B256, B64, U256, U64};
|
||||
use c_kzg::{Blob, Bytes48};
|
||||
use serde::{ser::SerializeMap, Deserialize, Serialize, Serializer};
|
||||
use serde_with::{serde_as, DisplayFromStr};
|
||||
use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
/// The execution payload body response that allows for `null` values.
|
||||
pub type ExecutionPayloadBodiesV1 = Vec<Option<ExecutionPayloadBodyV1>>;
|
||||
@ -229,7 +228,8 @@ impl BlobsBundleV1 {
|
||||
|
||||
/// An execution payload, which can be either [ExecutionPayloadV1], [ExecutionPayloadV2], or
|
||||
/// [ExecutionPayloadV3].
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum ExecutionPayload {
|
||||
/// V1 payload
|
||||
V1(ExecutionPayloadV1),
|
||||
@ -304,6 +304,27 @@ impl From<ExecutionPayloadV3> for ExecutionPayload {
|
||||
}
|
||||
}
|
||||
|
||||
// Deserializes untagged ExecutionPayload by trying each variant in falling order
|
||||
impl<'de> Deserialize<'de> for ExecutionPayload {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum ExecutionPayloadDesc {
|
||||
V3(ExecutionPayloadV3),
|
||||
V2(ExecutionPayloadV2),
|
||||
V1(ExecutionPayloadV1),
|
||||
}
|
||||
match ExecutionPayloadDesc::deserialize(deserializer)? {
|
||||
ExecutionPayloadDesc::V3(payload) => Ok(Self::V3(payload)),
|
||||
ExecutionPayloadDesc::V2(payload) => Ok(Self::V2(payload)),
|
||||
ExecutionPayloadDesc::V1(payload) => Ok(Self::V1(payload)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Error that can occur when handling payloads.
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum PayloadError {
|
||||
@ -405,71 +426,6 @@ pub struct OptimismPayloadAttributes {
|
||||
pub gas_limit: Option<u64>,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct BeaconAPIPayloadAttributes {
|
||||
#[serde_as(as = "DisplayFromStr")]
|
||||
timestamp: u64,
|
||||
prev_randao: B256,
|
||||
suggested_fee_recipient: Address,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[serde_as(as = "Option<Vec<BeaconAPIWithdrawal>>")]
|
||||
withdrawals: Option<Vec<Withdrawal>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
parent_beacon_block_root: Option<B256>,
|
||||
#[cfg(feature = "optimism")]
|
||||
#[serde(flatten)]
|
||||
optimism_payload_attributes: OptimismPayloadAttributes,
|
||||
}
|
||||
|
||||
/// A helper module for serializing and deserializing the payload attributes for the beacon API.
|
||||
///
|
||||
/// The beacon API encoded object has equivalent fields to the [PayloadAttributes] with two
|
||||
/// differences:
|
||||
/// 1) `snake_case` identifiers must be used rather than `camelCase`;
|
||||
/// 2) integers must be encoded as quoted decimals rather than big-endian hex.
|
||||
pub mod beacon_api_payload_attributes {
|
||||
use super::*;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
/// Serialize the payload attributes for the beacon API.
|
||||
pub fn serialize<S>(
|
||||
payload_attributes: &PayloadAttributes,
|
||||
serializer: S,
|
||||
) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let beacon_api_payload_attributes = BeaconAPIPayloadAttributes {
|
||||
timestamp: payload_attributes.timestamp.to(),
|
||||
prev_randao: payload_attributes.prev_randao,
|
||||
suggested_fee_recipient: payload_attributes.suggested_fee_recipient,
|
||||
withdrawals: payload_attributes.withdrawals.clone(),
|
||||
parent_beacon_block_root: payload_attributes.parent_beacon_block_root,
|
||||
#[cfg(feature = "optimism")]
|
||||
optimism_payload_attributes: payload_attributes.optimism_payload_attributes.clone(),
|
||||
};
|
||||
beacon_api_payload_attributes.serialize(serializer)
|
||||
}
|
||||
|
||||
/// Deserialize the payload attributes for the beacon API.
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<PayloadAttributes, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let beacon_api_payload_attributes = BeaconAPIPayloadAttributes::deserialize(deserializer)?;
|
||||
Ok(PayloadAttributes {
|
||||
timestamp: U64::from(beacon_api_payload_attributes.timestamp),
|
||||
prev_randao: beacon_api_payload_attributes.prev_randao,
|
||||
suggested_fee_recipient: beacon_api_payload_attributes.suggested_fee_recipient,
|
||||
withdrawals: beacon_api_payload_attributes.withdrawals,
|
||||
parent_beacon_block_root: beacon_api_payload_attributes.parent_beacon_block_root,
|
||||
#[cfg(feature = "optimism")]
|
||||
optimism_payload_attributes: beacon_api_payload_attributes.optimism_payload_attributes,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// This structure contains the result of processing a payload or fork choice update.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
@ -715,6 +671,9 @@ mod tests {
|
||||
let s = r#"{"parentHash":"0x67ead97eb79b47a1638659942384143f36ed44275d4182799875ab5a87324055","feeRecipient":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x4e3c608a9f2e129fccb91a1dae7472e78013b8e654bccc8d224ce3d63ae17006","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","prevRandao":"0x44bb4b98c59dbb726f96ffceb5ee028dcbe35b9bba4f9ffd56aeebf8d1e4db62","blockNumber":"0x1","gasLimit":"0x2fefd8","gasUsed":"0xa860","timestamp":"0x1235","extraData":"0x8b726574682f76302e312e30","baseFeePerGas":"0x342770c0","blockHash":"0x5655011482546f16b2312ef18e9fad03d6a52b1be95401aea884b222477f9e64","transactions":["0xf865808506fc23ac00830124f8940000000000000000000000000000000000000316018032a044b25a8b9b247d01586b3d59c71728ff49c9b84928d9e7fa3377ead3b5570b5da03ceac696601ff7ee6f5fe8864e2998db9babdf5eeba1a0cd5b4d44b3fcbd181b"]}"#;
|
||||
let payload: ExecutionPayloadV1 = serde_json::from_str(s).unwrap();
|
||||
assert_eq!(serde_json::to_string(&payload).unwrap(), s);
|
||||
|
||||
let any_payload: ExecutionPayload = serde_json::from_str(s).unwrap();
|
||||
assert_eq!(any_payload, payload.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -723,6 +682,9 @@ mod tests {
|
||||
let s = r#"{"parentHash":"0x67ead97eb79b47a1638659942384143f36ed44275d4182799875ab5a87324055","feeRecipient":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x4e3c608a9f2e129fccb91a1dae7472e78013b8e654bccc8d224ce3d63ae17006","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","prevRandao":"0x44bb4b98c59dbb726f96ffceb5ee028dcbe35b9bba4f9ffd56aeebf8d1e4db62","blockNumber":"0x1","gasLimit":"0x2fefd8","gasUsed":"0xa860","timestamp":"0x1235","extraData":"0x8b726574682f76302e312e30","baseFeePerGas":"0x342770c0","blockHash":"0x5655011482546f16b2312ef18e9fad03d6a52b1be95401aea884b222477f9e64","transactions":["0xf865808506fc23ac00830124f8940000000000000000000000000000000000000316018032a044b25a8b9b247d01586b3d59c71728ff49c9b84928d9e7fa3377ead3b5570b5da03ceac696601ff7ee6f5fe8864e2998db9babdf5eeba1a0cd5b4d44b3fcbd181b"],"withdrawals":[],"blobGasUsed":"0xb10b","excessBlobGas":"0xb10b"}"#;
|
||||
let payload: ExecutionPayloadV3 = serde_json::from_str(s).unwrap();
|
||||
assert_eq!(serde_json::to_string(&payload).unwrap(), s);
|
||||
|
||||
let any_payload: ExecutionPayload = serde_json::from_str(s).unwrap();
|
||||
assert_eq!(any_payload, payload.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -731,6 +693,9 @@ mod tests {
|
||||
let s = r#"{"parentHash":"0x67ead97eb79b47a1638659942384143f36ed44275d4182799875ab5a87324055","feeRecipient":"0x0000000000000000000000000000000000000000","stateRoot":"0x76a03cbcb7adce07fd284c61e4fa31e5e786175cefac54a29e46ec8efa28ea41","receiptsRoot":"0x4e3c608a9f2e129fccb91a1dae7472e78013b8e654bccc8d224ce3d63ae17006","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","prevRandao":"0x028111cb7d25918386a69656b3d17b2febe95fd0f11572c1a55c14f99fdfe3df","blockNumber":"0x1","gasLimit":"0x2fefd8","gasUsed":"0xa860","timestamp":"0x1235","extraData":"0x8b726574682f76302e312e30","baseFeePerGas":"0x342770c0","blockHash":"0xa6f40ed042e61e88e76125dede8fff8026751ea14454b68fb534cea99f2b2a77","transactions":["0xf865808506fc23ac00830124f8940000000000000000000000000000000000000316018032a044b25a8b9b247d01586b3d59c71728ff49c9b84928d9e7fa3377ead3b5570b5da03ceac696601ff7ee6f5fe8864e2998db9babdf5eeba1a0cd5b4d44b3fcbd181b"]}"#;
|
||||
let payload: ExecutionPayloadV1 = serde_json::from_str(s).unwrap();
|
||||
assert_eq!(serde_json::to_string(&payload).unwrap(), s);
|
||||
|
||||
let any_payload: ExecutionPayload = serde_json::from_str(s).unwrap();
|
||||
assert_eq!(any_payload, payload.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -739,6 +704,9 @@ mod tests {
|
||||
let s = r#"{"parentHash":"0x67ead97eb79b47a1638659942384143f36ed44275d4182799875ab5a87324055","feeRecipient":"0x0000000000000000000000000000000000000000","stateRoot":"0x76a03cbcb7adce07fd284c61e4fa31e5e786175cefac54a29e46ec8efa28ea41","receiptsRoot":"0x4e3c608a9f2e129fccb91a1dae7472e78013b8e654bccc8d224ce3d63ae17006","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","prevRandao":"0x028111cb7d25918386a69656b3d17b2febe95fd0f11572c1a55c14f99fdfe3df","blockNumber":"0x1","gasLimit":"0x2fefd8","gasUsed":"0xa860","timestamp":"0x1235","extraData":"0x8b726574682f76302e312e30","baseFeePerGas":"0x342770c0","blockHash":"0xa6f40ed042e61e88e76125dede8fff8026751ea14454b68fb534cea99f2b2a77","transactions":["0xf865808506fc23ac00830124f8940000000000000000000000000000000000000316018032a044b25a8b9b247d01586b3d59c71728ff49c9b84928d9e7fa3377ead3b5570b5da03ceac696601ff7ee6f5fe8864e2998db9babdf5eeba1a0cd5b4d44b3fcbd181b"],"withdrawals":[],"blobGasUsed":"0xb10b","excessBlobGas":"0xb10b"}"#;
|
||||
let payload: ExecutionPayloadV3 = serde_json::from_str(s).unwrap();
|
||||
assert_eq!(serde_json::to_string(&payload).unwrap(), s);
|
||||
|
||||
let any_payload: ExecutionPayload = serde_json::from_str(s).unwrap();
|
||||
assert_eq!(any_payload, payload.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -927,7 +895,7 @@ mod tests {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
struct Event {
|
||||
#[serde(with = "beacon_api_payload_attributes")]
|
||||
#[serde(with = "crate::beacon::payload::beacon_api_payload_attributes")]
|
||||
payload: PayloadAttributes,
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ pub mod raw_log;
|
||||
pub mod state;
|
||||
mod syncing;
|
||||
pub mod trace;
|
||||
mod transaction;
|
||||
pub mod transaction;
|
||||
pub mod txpool;
|
||||
pub mod withdrawal;
|
||||
mod work;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
//! RPC types for transactions
|
||||
|
||||
pub use access_list::{AccessList, AccessListItem, AccessListWithGasUsed};
|
||||
use alloy_primitives::{Address, Bytes, B256, U128, U256, U64};
|
||||
pub use common::TransactionInfo;
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
//! Withdrawal type and serde helpers.
|
||||
|
||||
use std::mem;
|
||||
|
||||
use crate::serde_helpers::u64_hex;
|
||||
use alloy_primitives::{Address, U256};
|
||||
use alloy_rlp::{RlpDecodable, RlpEncodable};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use serde_with::{serde_as, DeserializeAs, DisplayFromStr, SerializeAs};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::mem;
|
||||
|
||||
/// Multiplier for converting gwei to wei.
|
||||
pub const GWEI_TO_WEI: u64 = 1_000_000_000;
|
||||
@ -42,73 +40,6 @@ impl Withdrawal {
|
||||
}
|
||||
}
|
||||
|
||||
/// Same as [Withdrawal] but respects the Beacon API format which uses snake-case and quoted
|
||||
/// decimals.
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub(crate) struct BeaconAPIWithdrawal {
|
||||
#[serde_as(as = "DisplayFromStr")]
|
||||
index: u64,
|
||||
#[serde_as(as = "DisplayFromStr")]
|
||||
validator_index: u64,
|
||||
address: Address,
|
||||
#[serde_as(as = "DisplayFromStr")]
|
||||
amount: u64,
|
||||
}
|
||||
|
||||
impl SerializeAs<Withdrawal> for BeaconAPIWithdrawal {
|
||||
fn serialize_as<S>(source: &Withdrawal, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
beacon_api_withdrawals::serialize(source, serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> DeserializeAs<'de, Withdrawal> for BeaconAPIWithdrawal {
|
||||
fn deserialize_as<D>(deserializer: D) -> Result<Withdrawal, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
beacon_api_withdrawals::deserialize(deserializer)
|
||||
}
|
||||
}
|
||||
|
||||
/// A helper serde module to convert from/to the Beacon API which uses quoted decimals rather than
|
||||
/// big-endian hex.
|
||||
pub mod beacon_api_withdrawals {
|
||||
use super::*;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
/// Serialize the payload attributes for the beacon API.
|
||||
pub fn serialize<S>(payload_attributes: &Withdrawal, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let withdrawal = BeaconAPIWithdrawal {
|
||||
index: payload_attributes.index,
|
||||
validator_index: payload_attributes.validator_index,
|
||||
address: payload_attributes.address,
|
||||
amount: payload_attributes.amount,
|
||||
};
|
||||
withdrawal.serialize(serializer)
|
||||
}
|
||||
|
||||
/// Deserialize the payload attributes for the beacon API.
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Withdrawal, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let withdrawal = BeaconAPIWithdrawal::deserialize(deserializer)?;
|
||||
Ok(Withdrawal {
|
||||
index: withdrawal.index,
|
||||
validator_index: withdrawal.validator_index,
|
||||
address: withdrawal.address,
|
||||
amount: withdrawal.amount,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@ -12,11 +12,13 @@
|
||||
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
|
||||
|
||||
mod admin;
|
||||
pub mod beacon;
|
||||
mod eth;
|
||||
mod mev;
|
||||
mod net;
|
||||
mod otterscan;
|
||||
mod peer;
|
||||
pub mod relay;
|
||||
mod rpc;
|
||||
mod serde_helpers;
|
||||
|
||||
|
||||
243
crates/rpc/rpc-types/src/relay.rs
Normal file
243
crates/rpc/rpc-types/src/relay.rs
Normal file
File diff suppressed because one or more lines are too long
@ -23,7 +23,7 @@ use reth::{
|
||||
ext::{RethCliExt, RethNodeCommandConfig},
|
||||
Cli,
|
||||
},
|
||||
rpc::types::engine::beacon_api::events::PayloadAttributesEvent,
|
||||
rpc::types::beacon::events::PayloadAttributesEvent,
|
||||
tasks::TaskSpawner,
|
||||
};
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
|
||||
Reference in New Issue
Block a user