Add missing beacon API eventstream-types (#5200)

Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
Aditya Pandey
2023-10-31 23:55:35 +05:30
committed by GitHub
parent 3ed8e43aed
commit e0276d278f
7 changed files with 526 additions and 71 deletions

2
Cargo.lock generated
View File

@ -685,6 +685,8 @@ dependencies = [
"futures-util",
"mev-share-sse",
"reth",
"serde",
"serde_json",
"tokio",
"tracing",
]

View File

@ -1,71 +0,0 @@
//! Support for the Beacon API events
//!
//! See also [ethereum-beacon-API eventstream](https://ethereum.github.io/beacon-APIs/#/Events/eventstream)
use crate::engine::PayloadAttributes;
use alloy_primitives::B256;
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, DisplayFromStr};
/// Event for the `payload_attributes` topic of the beacon API node event stream.
///
/// This event gives block builders and relays sufficient information to construct or verify a block
/// at `proposal_slot`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PayloadAttributesEvent {
/// the identifier of the beacon hard fork at `proposal_slot`, e.g `"bellatrix"`, `"capella"`.
pub version: String,
/// Wrapped data of the event.
pub data: PayloadAttributesData,
}
impl PayloadAttributesEvent {
/// Returns the payload attributes
pub fn attributes(&self) -> &PayloadAttributes {
&self.data.payload_attributes
}
}
/// Data of the event that contains the payload attributes
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PayloadAttributesData {
/// The slot at which a block using these payload attributes may be built
#[serde_as(as = "DisplayFromStr")]
pub proposal_slot: u64,
/// the beacon block root of the parent block to be built upon.
pub parent_block_root: B256,
/// he execution block number of the parent block.
#[serde_as(as = "DisplayFromStr")]
pub parent_block_number: u64,
/// the execution block hash of the parent block.
pub parent_block_hash: B256,
/// The execution block number of the parent block.
/// the validator index of the proposer at `proposal_slot` on the chain identified by
/// `parent_block_root`.
#[serde_as(as = "DisplayFromStr")]
pub proposer_index: u64,
/// Beacon API encoding of `PayloadAttributesV<N>` as defined by the `execution-apis`
/// specification
///
/// 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")]
pub payload_attributes: PayloadAttributes,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn serde_payload_attributes_event() {
let s = r#"{"version":"capella","data":{"proposal_slot":"173332","proposer_index":"649112","parent_block_root":"0x5a49069647f6bf8f25d76b55ce920947654ade4ba1c6ab826d16712dd62b42bf","parent_block_number":"161093","parent_block_hash":"0x608b3d140ecb5bbcd0019711ac3704ece7be8e6d100816a55db440c1bcbb0251","payload_attributes":{"timestamp":"1697982384","prev_randao":"0x3142abd98055871ebf78f0f8e758fd3a04df3b6e34d12d09114f37a737f8f01e","suggested_fee_recipient":"0x0000000000000000000000000000000000000001","withdrawals":[{"index":"2461612","validator_index":"853570","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"45016211"},{"index":"2461613","validator_index":"853571","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5269785"},{"index":"2461614","validator_index":"853572","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5275106"},{"index":"2461615","validator_index":"853573","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5235962"},{"index":"2461616","validator_index":"853574","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5252171"},{"index":"2461617","validator_index":"853575","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5221319"},{"index":"2461618","validator_index":"853576","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5260879"},{"index":"2461619","validator_index":"853577","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5285244"},{"index":"2461620","validator_index":"853578","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5266681"},{"index":"2461621","validator_index":"853579","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5271322"},{"index":"2461622","validator_index":"853580","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5231327"},{"index":"2461623","validator_index":"853581","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5276761"},{"index":"2461624","validator_index":"853582","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5246244"},{"index":"2461625","validator_index":"853583","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5261011"},{"index":"2461626","validator_index":"853584","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5276477"},{"index":"2461627","validator_index":"853585","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5275319"}]}}}"#;
let event = serde_json::from_str::<PayloadAttributesEvent>(s).unwrap();
let input = serde_json::from_str::<serde_json::Value>(s).unwrap();
let json = serde_json::to_value(event).unwrap();
assert_eq!(input, json);
}
}

View File

@ -0,0 +1,30 @@
use alloy_primitives::B256;
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, DisplayFromStr};
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AttestationData {
#[serde_as(as = "DisplayFromStr")]
pub slot: u64,
#[serde_as(as = "DisplayFromStr")]
pub index: u64,
pub beacon_block_root: B256,
pub source: Source,
pub target: Target,
}
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Source {
#[serde_as(as = "DisplayFromStr")]
pub epoch: u64,
pub root: B256,
}
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Target {
#[serde_as(as = "DisplayFromStr")]
pub epoch: u64,
pub root: B256,
}

View File

@ -0,0 +1,54 @@
use alloy_primitives::{Bytes, B256};
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, DisplayFromStr};
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct LightClientFinalityData {
pub attested_header: AttestedHeader,
pub finalized_header: FinalizedHeader,
pub finality_branch: Vec<String>,
pub sync_aggregate: SyncAggregate,
#[serde_as(as = "DisplayFromStr")]
pub signature_slot: u64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AttestedHeader {
pub beacon: Beacon,
}
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Beacon {
#[serde_as(as = "DisplayFromStr")]
pub slot: u64,
#[serde_as(as = "DisplayFromStr")]
pub proposer_index: u64,
pub parent_root: B256,
pub state_root: B256,
pub body_root: B256,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct FinalizedHeader {
pub beacon: Beacon2,
}
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Beacon2 {
#[serde_as(as = "DisplayFromStr")]
pub slot: u64,
#[serde_as(as = "DisplayFromStr")]
pub proposer_index: u64,
pub parent_root: B256,
pub state_root: B256,
pub body_root: B256,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SyncAggregate {
pub sync_committee_bits: Bytes,
pub sync_committee_signature: Bytes,
}

View File

@ -0,0 +1,35 @@
use alloy_primitives::{Bytes, B256};
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, DisplayFromStr};
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct LightClientOptimisticData {
pub attested_header: AttestedHeader,
pub sync_aggregate: SyncAggregate,
#[serde_as(as = "DisplayFromStr")]
pub signature_slot: u64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AttestedHeader {
pub beacon: Beacon,
}
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Beacon {
#[serde_as(as = "DisplayFromStr")]
pub slot: u64,
#[serde_as(as = "DisplayFromStr")]
pub proposer_index: u64,
pub parent_root: B256,
pub state_root: B256,
pub body_root: B256,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SyncAggregate {
pub sync_committee_bits: Bytes,
pub sync_committee_signature: Bytes,
}

View File

@ -0,0 +1,403 @@
//! Support for the Beacon API events
//!
//! See also [ethereum-beacon-API eventstream](https://ethereum.github.io/beacon-APIs/#/Events/eventstream)
use crate::engine::PayloadAttributes;
use alloy_primitives::{Address, Bytes, B256};
use attestation::AttestationData;
use light_client_finality::LightClientFinalityData;
use light_client_optimistic::LightClientOptimisticData;
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, DisplayFromStr};
pub mod attestation;
pub mod light_client_finality;
pub mod light_client_optimistic;
/// Topic variant for the eventstream API
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BeaconNodeEventTopic {
PayloadAttributes,
Head,
Block,
Attestation,
VoluntaryExit,
BlsToExecutionChange,
FinalizedCheckpoint,
ChainReorg,
ContributionAndProof,
LightClientFinalityUpdate,
LightClientOptimisticUpdate,
BlobSidecar,
}
impl BeaconNodeEventTopic {
/// Returns the identifier value for the eventstream query
pub fn query_value(&self) -> &'static str {
match self {
BeaconNodeEventTopic::PayloadAttributes => "payload_attributes",
BeaconNodeEventTopic::Head => "head",
BeaconNodeEventTopic::Block => "block",
BeaconNodeEventTopic::Attestation => "attestation",
BeaconNodeEventTopic::VoluntaryExit => "voluntary_exit",
BeaconNodeEventTopic::BlsToExecutionChange => "bls_to_execution_change",
BeaconNodeEventTopic::FinalizedCheckpoint => "finalized_checkpoint",
BeaconNodeEventTopic::ChainReorg => "chain_reorg",
BeaconNodeEventTopic::ContributionAndProof => "contribution_and_proof",
BeaconNodeEventTopic::LightClientFinalityUpdate => "light_client_finality_update",
BeaconNodeEventTopic::LightClientOptimisticUpdate => "light_client_optimistic_update",
BeaconNodeEventTopic::BlobSidecar => "blob_sidecar",
}
}
}
/// Event for the `payload_attributes` topic of the beacon API node event stream.
///
/// This event gives block builders and relays sufficient information to construct or verify a block
/// at `proposal_slot`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PayloadAttributesEvent {
/// the identifier of the beacon hard fork at `proposal_slot`, e.g `"bellatrix"`, `"capella"`.
pub version: String,
/// Wrapped data of the event.
pub data: PayloadAttributesData,
}
/// Event for the `Head` topic of the beacon API node event stream.
///
/// The node has finished processing, resulting in a new head. previous_duty_dependent_root is
/// \`get_block_root_at_slot(state, compute_start_slot_at_epoch(epoch - 1) - 1)\` and
/// current_duty_dependent_root is \`get_block_root_at_slot(state,
/// compute_start_slot_at_epoch(epoch)
/// - 1)\`. Both dependent roots use the genesis block root in the case of underflow.
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct HeadEvent {
#[serde_as(as = "DisplayFromStr")]
pub slot: u64,
pub block: B256,
pub state: B256,
pub epoch_transition: bool,
pub previous_duty_dependent_root: B256,
pub current_duty_dependent_root: B256,
pub execution_optimistic: bool,
}
/// Event for the `Block` topic of the beacon API node event stream.
///
/// The node has received a valid block (from P2P or API)
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BlockEvent {
#[serde_as(as = "DisplayFromStr")]
pub slot: u64,
pub block: B256,
pub execution_optimistic: bool,
}
/// Event for the `Attestation` topic of the beacon API node event stream.
///
/// The node has received a valid attestation (from P2P or API)
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AttestationEvent {
pub aggregation_bits: Bytes,
pub signature: Bytes,
pub data: AttestationData,
}
/// Event for the `VoluntaryExit` topic of the beacon API node event stream.
///
/// The node has received a valid voluntary exit (from P2P or API)
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct VoluntaryExitEvent {
pub message: VoluntaryExitMessage,
pub signature: Bytes,
}
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct VoluntaryExitMessage {
#[serde_as(as = "DisplayFromStr")]
pub epoch: u64,
#[serde_as(as = "DisplayFromStr")]
pub validator_index: u64,
}
/// Event for the `BlsToExecutionChange` topic of the beacon API node event stream.
///
/// The node has received a BLS to execution change (from P2P or API)
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BlsToExecutionChangeEvent {
pub message: BlsToExecutionChangeMessage,
pub signature: Bytes,
}
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BlsToExecutionChangeMessage {
#[serde_as(as = "DisplayFromStr")]
pub validator_index: u64,
pub from_bls_pubkey: String,
pub to_execution_address: Address,
}
/// Event for the `Deposit` topic of the beacon API node event stream.
///
/// Finalized checkpoint has been updated
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct FinalizedCheckpointEvent {
pub block: B256,
pub state: B256,
#[serde_as(as = "DisplayFromStr")]
pub epoch: u64,
pub execution_optimistic: bool,
}
/// Event for the `ChainReorg` topic of the beacon API node event stream.
///
/// The node has reorganized its chain
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ChainReorgEvent {
#[serde_as(as = "DisplayFromStr")]
pub slot: u64,
#[serde_as(as = "DisplayFromStr")]
pub depth: u64,
pub old_head_block: B256,
pub new_head_block: B256,
pub old_head_state: B256,
pub new_head_state: B256,
#[serde_as(as = "DisplayFromStr")]
pub epoch: u64,
pub execution_optimistic: bool,
}
/// Event for the `ContributionAndProof` topic of the beacon API node event stream.
///
/// The node has received a valid sync committee SignedContributionAndProof (from P2P or API)
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ContributionAndProofEvent {
pub message: ContributionAndProofMessage,
pub signature: Bytes,
}
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ContributionAndProofMessage {
#[serde_as(as = "DisplayFromStr")]
pub aggregator_index: u64,
pub contribution: Contribution,
pub selection_proof: Bytes,
}
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Contribution {
#[serde_as(as = "DisplayFromStr")]
pub slot: u64,
pub beacon_block_root: B256,
#[serde_as(as = "DisplayFromStr")]
pub subcommittee_index: u64,
pub aggregation_bits: Bytes,
pub signature: Bytes,
}
/// Event for the `LightClientFinalityUpdate` topic of the beacon API node event stream.
///
/// The node's latest known `LightClientFinalityUpdate` has been updated
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct LightClientFinalityUpdateEvent {
pub version: String,
pub data: LightClientFinalityData,
}
/// Event for the `LightClientOptimisticUpdate` topic of the beacon API node event stream.
///
/// The node's latest known `LightClientOptimisticUpdate` has been updated
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct LightClientOptimisticUpdateEvent {
pub version: String,
pub data: LightClientOptimisticData,
}
/// Event for the `BlobSidecar` topic of the beacon API node event stream.
///
/// The node has received a BlobSidecar (from P2P or API) that passes all gossip validations on the
/// blob_sidecar_{subnet_id} topic
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BlobSidecarEvent {
pub block_root: B256,
#[serde_as(as = "DisplayFromStr")]
pub index: u64,
#[serde_as(as = "DisplayFromStr")]
pub slot: u64,
pub kzg_commitment: Bytes,
pub versioned_hash: B256,
}
impl PayloadAttributesEvent {
/// Returns the payload attributes
pub fn attributes(&self) -> &PayloadAttributes {
&self.data.payload_attributes
}
}
/// Data of the event that contains the payload attributes
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PayloadAttributesData {
/// The slot at which a block using these payload attributes may be built
#[serde_as(as = "DisplayFromStr")]
pub proposal_slot: u64,
/// the beacon block root of the parent block to be built upon.
pub parent_block_root: B256,
/// the execution block number of the parent block.
#[serde_as(as = "DisplayFromStr")]
pub parent_block_number: u64,
/// the execution block hash of the parent block.
pub parent_block_hash: B256,
/// The execution block number of the parent block.
/// the validator index of the proposer at `proposal_slot` on the chain identified by
/// `parent_block_root`.
#[serde_as(as = "DisplayFromStr")]
pub proposer_index: u64,
/// Beacon API encoding of `PayloadAttributesV<N>` as defined by the `execution-apis`
/// specification
///
/// 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")]
pub payload_attributes: PayloadAttributes,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn serde_payload_attributes_event() {
let s = r#"{"version":"capella","data":{"proposal_slot":"173332","proposer_index":"649112","parent_block_root":"0x5a49069647f6bf8f25d76b55ce920947654ade4ba1c6ab826d16712dd62b42bf","parent_block_number":"161093","parent_block_hash":"0x608b3d140ecb5bbcd0019711ac3704ece7be8e6d100816a55db440c1bcbb0251","payload_attributes":{"timestamp":"1697982384","prev_randao":"0x3142abd98055871ebf78f0f8e758fd3a04df3b6e34d12d09114f37a737f8f01e","suggested_fee_recipient":"0x0000000000000000000000000000000000000001","withdrawals":[{"index":"2461612","validator_index":"853570","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"45016211"},{"index":"2461613","validator_index":"853571","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5269785"},{"index":"2461614","validator_index":"853572","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5275106"},{"index":"2461615","validator_index":"853573","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5235962"},{"index":"2461616","validator_index":"853574","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5252171"},{"index":"2461617","validator_index":"853575","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5221319"},{"index":"2461618","validator_index":"853576","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5260879"},{"index":"2461619","validator_index":"853577","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5285244"},{"index":"2461620","validator_index":"853578","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5266681"},{"index":"2461621","validator_index":"853579","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5271322"},{"index":"2461622","validator_index":"853580","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5231327"},{"index":"2461623","validator_index":"853581","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5276761"},{"index":"2461624","validator_index":"853582","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5246244"},{"index":"2461625","validator_index":"853583","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5261011"},{"index":"2461626","validator_index":"853584","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5276477"},{"index":"2461627","validator_index":"853585","address":"0x778f5f13c4be78a3a4d7141bcb26999702f407cf","amount":"5275319"}]}}}"#;
let event: PayloadAttributesEvent =
serde_json::from_str::<PayloadAttributesEvent>(s).unwrap();
let input = serde_json::from_str::<serde_json::Value>(s).unwrap();
let json = serde_json::to_value(event).unwrap();
assert_eq!(input, json);
}
#[test]
fn serde_head_event() {
let s = r#"{"slot":"10", "block":"0x9a2fefd2fdb57f74993c7780ea5b9030d2897b615b89f808011ca5aebed54eaf", "state":"0x600e852a08c1200654ddf11025f1ceacb3c2e74bdd5c630cde0838b2591b69f9", "epoch_transition":false, "previous_duty_dependent_root":"0x5e0043f107cb57913498fbf2f99ff55e730bf1e151f02f221e977c91a90a0e91", "current_duty_dependent_root":"0x5e0043f107cb57913498fbf2f99ff55e730bf1e151f02f221e977c91a90a0e91", "execution_optimistic": false}"#;
let event: HeadEvent = serde_json::from_str::<HeadEvent>(s).unwrap();
let input = serde_json::from_str::<serde_json::Value>(s).unwrap();
let json = serde_json::to_value(event).unwrap();
assert_eq!(input, json);
}
#[test]
fn serde_block_event() {
let s = r#"{"slot":"10", "block":"0x9a2fefd2fdb57f74993c7780ea5b9030d2897b615b89f808011ca5aebed54eaf", "execution_optimistic": false}"#;
let event: BlockEvent = serde_json::from_str::<BlockEvent>(s).unwrap();
let input = serde_json::from_str::<serde_json::Value>(s).unwrap();
let json = serde_json::to_value(event).unwrap();
assert_eq!(input, json);
}
#[test]
fn serde_attestation_event() {
let s = r#"{"aggregation_bits":"0x01", "signature":"0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", "data":{"slot":"1", "index":"1", "beacon_block_root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "source":{"epoch":"1", "root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"}, "target":{"epoch":"1", "root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"}}}"#;
let event: AttestationEvent = serde_json::from_str::<AttestationEvent>(s).unwrap();
let input = serde_json::from_str::<serde_json::Value>(s).unwrap();
let json = serde_json::to_value(event).unwrap();
assert_eq!(input, json);
}
#[test]
fn serde_voluntary_exit_event() {
let s = r#"{"message":{"epoch":"1", "validator_index":"1"}, "signature":"0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"}"#;
let event: VoluntaryExitEvent = serde_json::from_str::<VoluntaryExitEvent>(s).unwrap();
let input = serde_json::from_str::<serde_json::Value>(s).unwrap();
let json = serde_json::to_value(event).unwrap();
assert_eq!(input, json);
}
#[test]
fn serde_bls_to_execution_change_event() {
let s = r#"{"message":{"validator_index":"1", "from_bls_pubkey":"0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f7329267a8811c397529dac52ae1342ba58c95", "to_execution_address":"0x9be8d619c56699667c1fedcd15f6b14d8b067f72"}, "signature":"0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"}"#;
let event: BlsToExecutionChangeEvent =
serde_json::from_str::<BlsToExecutionChangeEvent>(s).unwrap();
let input = serde_json::from_str::<serde_json::Value>(s).unwrap();
let json = serde_json::to_value(event).unwrap();
assert_eq!(input, json);
}
#[test]
fn serde_finalize_checkpoint_event() {
let s = r#"{"block":"0x9a2fefd2fdb57f74993c7780ea5b9030d2897b615b89f808011ca5aebed54eaf", "state":"0x600e852a08c1200654ddf11025f1ceacb3c2e74bdd5c630cde0838b2591b69f9", "epoch":"2", "execution_optimistic": false }"#;
let event: FinalizedCheckpointEvent =
serde_json::from_str::<FinalizedCheckpointEvent>(s).unwrap();
let input = serde_json::from_str::<serde_json::Value>(s).unwrap();
let json = serde_json::to_value(event).unwrap();
assert_eq!(input, json);
}
#[test]
fn serde_chain_reorg_event() {
let s = r#"{"slot":"200", "depth":"50", "old_head_block":"0x9a2fefd2fdb57f74993c7780ea5b9030d2897b615b89f808011ca5aebed54eaf", "new_head_block":"0x76262e91970d375a19bfe8a867288d7b9cde43c8635f598d93d39d041706fc76", "old_head_state":"0x9a2fefd2fdb57f74993c7780ea5b9030d2897b615b89f808011ca5aebed54eaf", "new_head_state":"0x600e852a08c1200654ddf11025f1ceacb3c2e74bdd5c630cde0838b2591b69f9", "epoch":"2", "execution_optimistic": false}"#;
let event: ChainReorgEvent = serde_json::from_str::<ChainReorgEvent>(s).unwrap();
let input = serde_json::from_str::<serde_json::Value>(s).unwrap();
let json = serde_json::to_value(event).unwrap();
assert_eq!(input, json);
}
#[test]
fn serde_contribution_and_proof_event() {
let s = r#"{"message": {"aggregator_index": "997", "contribution": {"slot": "168097", "beacon_block_root": "0x56f1fd4262c08fa81e27621c370e187e621a67fc80fe42340b07519f84b42ea1", "subcommittee_index": "0", "aggregation_bits": "0xffffffffffffffffffffffffffffffff", "signature": "0x85ab9018e14963026476fdf784cc674da144b3dbdb47516185438768774f077d882087b90ad642469902e782a8b43eed0cfc1b862aa9a473b54c98d860424a702297b4b648f3f30bdaae8a8b7627d10d04cb96a2cc8376af3e54a9aa0c8145e3"}, "selection_proof": "0x87c305f04bfe5db27c2b19fc23e00d7ac496ec7d3e759cbfdd1035cb8cf6caaa17a36a95a08ba78c282725e7b66a76820ca4eb333822bd399ceeb9807a0f2926c67ce67cfe06a0b0006838203b493505a8457eb79913ce1a3bcd1cc8e4ef30ed"}, "signature": "0xac118511474a94f857300b315c50585c32a713e4452e26a6bb98cdb619936370f126ed3b6bb64469259ee92e69791d9e12d324ce6fd90081680ce72f39d85d50b0ff977260a8667465e613362c6d6e6e745e1f9323ec1d6f16041c4e358839ac"}"#;
let event: ContributionAndProofEvent =
serde_json::from_str::<ContributionAndProofEvent>(s).unwrap();
let input = serde_json::from_str::<serde_json::Value>(s).unwrap();
let json = serde_json::to_value(event).unwrap();
assert_eq!(input, json);
}
#[test]
fn serde_light_client_finality_update_event() {
let s = r#"{"version":"phase0", "data": {"attested_header": {"beacon": {"slot":"1", "proposer_index":"1", "parent_root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "state_root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "body_root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"}}, "finalized_header": {"beacon": {"slot":"1", "proposer_index":"1", "parent_root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "state_root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "body_root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"}}, "finality_branch": ["0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"], "sync_aggregate": {"sync_committee_bits":"0x01", "sync_committee_signature":"0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"}, "signature_slot":"1"}}"#;
let event: LightClientFinalityUpdateEvent =
serde_json::from_str::<LightClientFinalityUpdateEvent>(s).unwrap();
let input = serde_json::from_str::<serde_json::Value>(s).unwrap();
let json = serde_json::to_value(event).unwrap();
assert_eq!(input, json);
}
#[test]
fn serde_light_client_optimistic_update_event() {
let s = r#"{"version":"phase0", "data": {"attested_header": {"beacon": {"slot":"1", "proposer_index":"1", "parent_root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "state_root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "body_root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"}}, "sync_aggregate": {"sync_committee_bits":"0x01", "sync_committee_signature":"0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"}, "signature_slot":"1"}}"#;
let event: LightClientOptimisticUpdateEvent =
serde_json::from_str::<LightClientOptimisticUpdateEvent>(s).unwrap();
let input = serde_json::from_str::<serde_json::Value>(s).unwrap();
let json = serde_json::to_value(event).unwrap();
assert_eq!(input, json);
}
#[test]
fn serde_blob_sidecar_event() {
let s = r#"{"block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "index": "1", "slot": "1", "kzg_commitment": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", "versioned_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"}"#;
let event: BlobSidecarEvent = serde_json::from_str::<BlobSidecarEvent>(s).unwrap();
let input = serde_json::from_str::<serde_json::Value>(s).unwrap();
let json = serde_json::to_value(event).unwrap();
assert_eq!(input, json);
}
}

View File

@ -9,6 +9,8 @@ license.workspace = true
reth.workspace = true
eyre.workspace = true
clap.workspace = true
serde.workspace = true
serde_json.workspace = true
tracing.workspace = true
futures-util.workspace = true
tokio = { workspace = true, features = ["time"] }