mirror of
https://github.com/sigp/lighthouse.git
synced 2026-06-15 09:48:20 +00:00
merge conflicts
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
use super::{AttestationBase, AttestationElectra, AttestationRef};
|
||||
use super::{
|
||||
ChainSpec, Domain, EthSpec, Fork, Hash256, PublicKey, SecretKey, SelectionProof, Signature,
|
||||
SignedRoot,
|
||||
ChainSpec, Domain, EthSpec, Fork, ForkName, Hash256, PublicKey, SecretKey, SelectionProof,
|
||||
Signature, SignedRoot,
|
||||
};
|
||||
use crate::context_deserialize;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::Attestation;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -26,6 +27,7 @@ use tree_hash_derive::TreeHash;
|
||||
TestRandom,
|
||||
TreeHash,
|
||||
),
|
||||
context_deserialize(ForkName),
|
||||
serde(bound = "E: EthSpec"),
|
||||
arbitrary(bound = "E: EthSpec"),
|
||||
),
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
use crate::context_deserialize;
|
||||
use crate::slot_data::SlotData;
|
||||
use crate::{test_utils::TestRandom, Hash256, Slot};
|
||||
use crate::{Checkpoint, ForkVersionDeserialize};
|
||||
use crate::{Checkpoint, ContextDeserialize, ForkName};
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use ssz_types::BitVector;
|
||||
use std::collections::HashSet;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use superstruct::superstruct;
|
||||
use test_random_derive::TestRandom;
|
||||
@@ -15,7 +17,7 @@ use super::{
|
||||
Signature, SignedRoot,
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum Error {
|
||||
SszTypesError(ssz_types::Error),
|
||||
BitfieldError(ssz::BitfieldError),
|
||||
@@ -46,6 +48,7 @@ impl From<ssz_types::Error> for Error {
|
||||
arbitrary::Arbitrary,
|
||||
TreeHash,
|
||||
),
|
||||
context_deserialize(ForkName),
|
||||
derivative(PartialEq, Hash(bound = "E: EthSpec")),
|
||||
serde(bound = "E: EthSpec", deny_unknown_fields),
|
||||
arbitrary(bound = "E: EthSpec"),
|
||||
@@ -210,6 +213,13 @@ impl<E: EthSpec> Attestation<E> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_committee_indices_map(&self) -> HashSet<u64> {
|
||||
match self {
|
||||
Attestation::Base(att) => HashSet::from([att.data.index]),
|
||||
Attestation::Electra(att) => att.get_committee_indices().into_iter().collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_aggregation_bits_zero(&self) -> bool {
|
||||
match self {
|
||||
Attestation::Base(att) => att.aggregation_bits.is_zero(),
|
||||
@@ -293,7 +303,11 @@ impl<E: EthSpec> AttestationRef<'_, E> {
|
||||
|
||||
impl<E: EthSpec> AttestationElectra<E> {
|
||||
pub fn committee_index(&self) -> Option<u64> {
|
||||
self.get_committee_indices().first().cloned()
|
||||
self.committee_bits
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|&(_, bit)| bit)
|
||||
.map(|(index, _)| index as u64)
|
||||
}
|
||||
|
||||
pub fn get_aggregation_bits(&self) -> Vec<u64> {
|
||||
@@ -520,45 +534,44 @@ impl<'a, E: EthSpec> From<AttestationRefOnDisk<'a, E>> for AttestationRef<'a, E>
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> ForkVersionDeserialize for Attestation<E> {
|
||||
fn deserialize_by_fork<'de, D: serde::Deserializer<'de>>(
|
||||
value: serde_json::Value,
|
||||
fork_name: crate::ForkName,
|
||||
) -> Result<Self, D::Error> {
|
||||
if fork_name.electra_enabled() {
|
||||
let attestation: AttestationElectra<E> =
|
||||
serde_json::from_value(value).map_err(serde::de::Error::custom)?;
|
||||
Ok(Attestation::Electra(attestation))
|
||||
impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for Attestation<E> {
|
||||
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
if context.electra_enabled() {
|
||||
AttestationElectra::<E>::deserialize(deserializer)
|
||||
.map_err(serde::de::Error::custom)
|
||||
.map(Attestation::Electra)
|
||||
} else {
|
||||
let attestation: AttestationBase<E> =
|
||||
serde_json::from_value(value).map_err(serde::de::Error::custom)?;
|
||||
Ok(Attestation::Base(attestation))
|
||||
AttestationBase::<E>::deserialize(deserializer)
|
||||
.map_err(serde::de::Error::custom)
|
||||
.map(Attestation::Base)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> ForkVersionDeserialize for Vec<Attestation<E>> {
|
||||
fn deserialize_by_fork<'de, D: serde::Deserializer<'de>>(
|
||||
value: serde_json::Value,
|
||||
fork_name: crate::ForkName,
|
||||
) -> Result<Self, D::Error> {
|
||||
if fork_name.electra_enabled() {
|
||||
let attestations: Vec<AttestationElectra<E>> =
|
||||
serde_json::from_value(value).map_err(serde::de::Error::custom)?;
|
||||
Ok(attestations
|
||||
.into_iter()
|
||||
.map(Attestation::Electra)
|
||||
.collect::<Vec<_>>())
|
||||
/*
|
||||
impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for Vec<Attestation<E>> {
|
||||
fn context_deserialize<D>(
|
||||
deserializer: D,
|
||||
context: ForkName,
|
||||
) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
if context.electra_enabled() {
|
||||
<Vec<AttestationElectra<E>>>::deserialize(deserializer)
|
||||
.map_err(serde::de::Error::custom)
|
||||
.map(|vec| vec.into_iter().map(Attestation::Electra).collect::<Vec<_>>())
|
||||
} else {
|
||||
let attestations: Vec<AttestationBase<E>> =
|
||||
serde_json::from_value(value).map_err(serde::de::Error::custom)?;
|
||||
Ok(attestations
|
||||
.into_iter()
|
||||
.map(Attestation::Base)
|
||||
.collect::<Vec<_>>())
|
||||
<Vec<AttestationBase<E>>>::deserialize(deserializer)
|
||||
.map_err(serde::de::Error::custom)
|
||||
.map(|vec| vec.into_iter().map(Attestation::Base).collect::<Vec<_>>())
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
@@ -573,6 +586,7 @@ impl<E: EthSpec> ForkVersionDeserialize for Vec<Attestation<E>> {
|
||||
TreeHash,
|
||||
PartialEq,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct SingleAttestation {
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub committee_index: u64,
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::{Checkpoint, Hash256, SignedRoot, Slot};
|
||||
|
||||
use crate::slot_data::SlotData;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::{Checkpoint, ForkName, Hash256, SignedRoot, Slot};
|
||||
use context_deserialize_derive::context_deserialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use test_random_derive::TestRandom;
|
||||
use tree_hash_derive::TreeHash;
|
||||
|
||||
/// The data upon which an attestation is based.
|
||||
///
|
||||
/// Spec v0.12.1
|
||||
@@ -25,6 +24,7 @@ use tree_hash_derive::TreeHash;
|
||||
TestRandom,
|
||||
Default,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct AttestationData {
|
||||
pub slot: Slot,
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
use crate::context_deserialize;
|
||||
use crate::indexed_attestation::{
|
||||
IndexedAttestationBase, IndexedAttestationElectra, IndexedAttestationRef,
|
||||
};
|
||||
use crate::{test_utils::TestRandom, EthSpec};
|
||||
use crate::{ContextDeserialize, ForkName};
|
||||
use derivative::Derivative;
|
||||
use rand::{Rng, RngCore};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use superstruct::superstruct;
|
||||
use test_random_derive::TestRandom;
|
||||
@@ -25,6 +27,7 @@ use tree_hash_derive::TreeHash;
|
||||
TestRandom,
|
||||
arbitrary::Arbitrary
|
||||
),
|
||||
context_deserialize(ForkName),
|
||||
derivative(PartialEq, Eq, Hash(bound = "E: EthSpec")),
|
||||
serde(bound = "E: EthSpec"),
|
||||
arbitrary(bound = "E: EthSpec")
|
||||
@@ -171,25 +174,27 @@ impl<E: EthSpec> TestRandom for AttesterSlashing<E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> crate::ForkVersionDeserialize for Vec<AttesterSlashing<E>> {
|
||||
fn deserialize_by_fork<'de, D: serde::Deserializer<'de>>(
|
||||
value: serde_json::Value,
|
||||
fork_name: crate::ForkName,
|
||||
) -> Result<Self, D::Error> {
|
||||
if fork_name.electra_enabled() {
|
||||
let slashings: Vec<AttesterSlashingElectra<E>> =
|
||||
serde_json::from_value(value).map_err(serde::de::Error::custom)?;
|
||||
Ok(slashings
|
||||
.into_iter()
|
||||
.map(AttesterSlashing::Electra)
|
||||
.collect::<Vec<_>>())
|
||||
impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for Vec<AttesterSlashing<E>> {
|
||||
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
if context.electra_enabled() {
|
||||
<Vec<AttesterSlashingElectra<E>>>::deserialize(deserializer)
|
||||
.map_err(serde::de::Error::custom)
|
||||
.map(|vec| {
|
||||
vec.into_iter()
|
||||
.map(AttesterSlashing::Electra)
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
} else {
|
||||
let slashings: Vec<AttesterSlashingBase<E>> =
|
||||
serde_json::from_value(value).map_err(serde::de::Error::custom)?;
|
||||
Ok(slashings
|
||||
.into_iter()
|
||||
.map(AttesterSlashing::Base)
|
||||
.collect::<Vec<_>>())
|
||||
<Vec<AttesterSlashingBase<E>>>::deserialize(deserializer)
|
||||
.map_err(serde::de::Error::custom)
|
||||
.map(|vec| {
|
||||
vec.into_iter()
|
||||
.map(AttesterSlashing::Base)
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::attestation::AttestationBase;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::*;
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use ssz::{Decode, DecodeError};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use std::fmt;
|
||||
@@ -802,23 +802,21 @@ impl<E: EthSpec> From<BeaconBlock<E, FullPayload<E>>>
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec, Payload: AbstractExecPayload<E>> ForkVersionDeserialize
|
||||
impl<'de, E: EthSpec, Payload: AbstractExecPayload<E>> ContextDeserialize<'de, ForkName>
|
||||
for BeaconBlock<E, Payload>
|
||||
{
|
||||
fn deserialize_by_fork<'de, D: serde::Deserializer<'de>>(
|
||||
value: serde_json::value::Value,
|
||||
fork_name: ForkName,
|
||||
) -> Result<Self, D::Error> {
|
||||
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
Ok(map_fork_name!(
|
||||
fork_name,
|
||||
context,
|
||||
Self,
|
||||
serde_json::from_value(value).map_err(|e| serde::de::Error::custom(format!(
|
||||
"BeaconBlock failed to deserialize: {:?}",
|
||||
e
|
||||
)))?
|
||||
serde::Deserialize::deserialize(deserializer)?
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub enum BlockImportSource {
|
||||
Gossip,
|
||||
Lookup,
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::*;
|
||||
use derivative::Derivative;
|
||||
use merkle_proof::{MerkleTree, MerkleTreeError};
|
||||
use metastruct::metastruct;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use std::marker::PhantomData;
|
||||
use superstruct::superstruct;
|
||||
@@ -48,6 +48,7 @@ pub const BLOB_KZG_COMMITMENTS_INDEX: usize = 11;
|
||||
deny_unknown_fields
|
||||
),
|
||||
arbitrary(bound = "E: EthSpec, Payload: AbstractExecPayload<E>"),
|
||||
context_deserialize(ForkName),
|
||||
),
|
||||
specific_variant_attributes(
|
||||
Base(metastruct(mappings(beacon_block_body_base_fields(groups(fields))))),
|
||||
@@ -62,10 +63,11 @@ pub const BLOB_KZG_COMMITMENTS_INDEX: usize = 11;
|
||||
cast_error(ty = "Error", expr = "Error::IncorrectStateVariant"),
|
||||
partial_getter_error(ty = "Error", expr = "Error::IncorrectStateVariant")
|
||||
)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Derivative, arbitrary::Arbitrary)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Derivative, TreeHash, arbitrary::Arbitrary)]
|
||||
#[derivative(PartialEq, Hash(bound = "E: EthSpec"))]
|
||||
#[serde(untagged)]
|
||||
#[serde(bound = "E: EthSpec, Payload: AbstractExecPayload<E>")]
|
||||
#[tree_hash(enum_behaviour = "transparent")]
|
||||
#[arbitrary(bound = "E: EthSpec, Payload: AbstractExecPayload<E>")]
|
||||
pub struct BeaconBlockBody<E: EthSpec, Payload: AbstractExecPayload<E> = FullPayload<E>> {
|
||||
pub randao_reveal: Signature,
|
||||
@@ -1088,6 +1090,21 @@ impl<E: EthSpec> From<BeaconBlockBody<E, FullPayload<E>>>
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, E: EthSpec, Payload: AbstractExecPayload<E>> ContextDeserialize<'de, ForkName>
|
||||
for BeaconBlockBody<E, Payload>
|
||||
{
|
||||
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
Ok(map_fork_name!(
|
||||
context,
|
||||
Self,
|
||||
serde::Deserialize::deserialize(deserializer)?
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// Util method helpful for logging.
|
||||
pub fn format_kzg_commitments(commitments: &[KzgCommitment]) -> String {
|
||||
let commitment_strings: Vec<String> = commitments.iter().map(|x| x.to_string()).collect();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::*;
|
||||
|
||||
use context_deserialize_derive::context_deserialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use test_random_derive::TestRandom;
|
||||
@@ -24,6 +25,7 @@ use tree_hash_derive::TreeHash;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct BeaconBlockHeader {
|
||||
pub slot: Slot,
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
|
||||
239
consensus/types/src/beacon_response.rs
Normal file
239
consensus/types/src/beacon_response.rs
Normal file
@@ -0,0 +1,239 @@
|
||||
use crate::{ContextDeserialize, ForkName};
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use serde_json::value::Value;
|
||||
|
||||
pub trait ForkVersionDecode: Sized {
|
||||
/// SSZ decode with explicit fork variant.
|
||||
fn from_ssz_bytes_by_fork(bytes: &[u8], fork_name: ForkName) -> Result<Self, ssz::DecodeError>;
|
||||
}
|
||||
|
||||
/// The metadata of type M should be set to `EmptyMetadata` if you don't care about adding fields other than
|
||||
/// version. If you *do* care about adding other fields you can mix in any type that implements
|
||||
/// `Deserialize`.
|
||||
#[derive(Debug, PartialEq, Clone, Serialize)]
|
||||
pub struct ForkVersionedResponse<T, M = EmptyMetadata> {
|
||||
pub version: ForkName,
|
||||
#[serde(flatten)]
|
||||
pub metadata: M,
|
||||
pub data: T,
|
||||
}
|
||||
|
||||
// Used for responses to V1 endpoints that don't have a version field.
|
||||
/// The metadata of type M should be set to `EmptyMetadata` if you don't care about adding fields other than
|
||||
/// version. If you *do* care about adding other fields you can mix in any type that implements
|
||||
/// `Deserialize`.
|
||||
#[derive(Debug, PartialEq, Clone, Serialize)]
|
||||
pub struct UnversionedResponse<T, M = EmptyMetadata> {
|
||||
pub metadata: M,
|
||||
pub data: T,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum BeaconResponse<T, M = EmptyMetadata> {
|
||||
ForkVersioned(ForkVersionedResponse<T, M>),
|
||||
Unversioned(UnversionedResponse<T, M>),
|
||||
}
|
||||
|
||||
impl<T, M> BeaconResponse<T, M> {
|
||||
pub fn version(&self) -> Option<ForkName> {
|
||||
match self {
|
||||
BeaconResponse::ForkVersioned(response) => Some(response.version),
|
||||
BeaconResponse::Unversioned(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn data(&self) -> &T {
|
||||
match self {
|
||||
BeaconResponse::ForkVersioned(response) => &response.data,
|
||||
BeaconResponse::Unversioned(response) => &response.data,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn metadata(&self) -> &M {
|
||||
match self {
|
||||
BeaconResponse::ForkVersioned(response) => &response.metadata,
|
||||
BeaconResponse::Unversioned(response) => &response.metadata,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Metadata type similar to unit (i.e. `()`) but deserializes from a map (`serde_json::Value`).
|
||||
///
|
||||
/// Unfortunately the braces are semantically significant, i.e. `struct EmptyMetadata;` does not
|
||||
/// work.
|
||||
#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
|
||||
pub struct EmptyMetadata {}
|
||||
|
||||
/// Fork versioned response with extra information about finalization & optimistic execution.
|
||||
pub type ExecutionOptimisticFinalizedBeaconResponse<T> =
|
||||
BeaconResponse<T, ExecutionOptimisticFinalizedMetadata>;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
pub struct ExecutionOptimisticFinalizedMetadata {
|
||||
pub execution_optimistic: Option<bool>,
|
||||
pub finalized: Option<bool>,
|
||||
}
|
||||
|
||||
impl<'de, T, M> Deserialize<'de> for ForkVersionedResponse<T, M>
|
||||
where
|
||||
T: ContextDeserialize<'de, ForkName>,
|
||||
M: DeserializeOwned,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
#[derive(Deserialize)]
|
||||
struct Helper {
|
||||
version: ForkName,
|
||||
#[serde(flatten)]
|
||||
metadata: Value,
|
||||
data: Value,
|
||||
}
|
||||
|
||||
let helper = Helper::deserialize(deserializer)?;
|
||||
|
||||
// Deserialize metadata
|
||||
let metadata = serde_json::from_value(helper.metadata).map_err(serde::de::Error::custom)?;
|
||||
|
||||
// Deserialize `data` using ContextDeserialize
|
||||
let data = T::context_deserialize(helper.data, helper.version)
|
||||
.map_err(serde::de::Error::custom)?;
|
||||
|
||||
Ok(ForkVersionedResponse {
|
||||
version: helper.version,
|
||||
metadata,
|
||||
data,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, T, M> Deserialize<'de> for UnversionedResponse<T, M>
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
M: DeserializeOwned,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
#[derive(Deserialize)]
|
||||
struct Helper<T, M> {
|
||||
#[serde(flatten)]
|
||||
metadata: M,
|
||||
data: T,
|
||||
}
|
||||
|
||||
let helper = Helper::deserialize(deserializer)?;
|
||||
|
||||
Ok(UnversionedResponse {
|
||||
metadata: helper.metadata,
|
||||
data: helper.data,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, M> BeaconResponse<T, M> {
|
||||
pub fn map_data<U>(self, f: impl FnOnce(T) -> U) -> BeaconResponse<U, M> {
|
||||
match self {
|
||||
BeaconResponse::ForkVersioned(response) => {
|
||||
BeaconResponse::ForkVersioned(response.map_data(f))
|
||||
}
|
||||
BeaconResponse::Unversioned(response) => {
|
||||
BeaconResponse::Unversioned(response.map_data(f))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_data(self) -> T {
|
||||
match self {
|
||||
BeaconResponse::ForkVersioned(response) => response.data,
|
||||
BeaconResponse::Unversioned(response) => response.data,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, M> UnversionedResponse<T, M> {
|
||||
pub fn map_data<U>(self, f: impl FnOnce(T) -> U) -> UnversionedResponse<U, M> {
|
||||
let UnversionedResponse { metadata, data } = self;
|
||||
UnversionedResponse {
|
||||
metadata,
|
||||
data: f(data),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, M> ForkVersionedResponse<T, M> {
|
||||
/// Apply a function to the inner `data`, potentially changing its type.
|
||||
pub fn map_data<U>(self, f: impl FnOnce(T) -> U) -> ForkVersionedResponse<U, M> {
|
||||
let ForkVersionedResponse {
|
||||
version,
|
||||
metadata,
|
||||
data,
|
||||
} = self;
|
||||
ForkVersionedResponse {
|
||||
version,
|
||||
metadata,
|
||||
data: f(data),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, M> From<ForkVersionedResponse<T, M>> for BeaconResponse<T, M> {
|
||||
fn from(response: ForkVersionedResponse<T, M>) -> Self {
|
||||
BeaconResponse::ForkVersioned(response)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, M> From<UnversionedResponse<T, M>> for BeaconResponse<T, M> {
|
||||
fn from(response: UnversionedResponse<T, M>) -> Self {
|
||||
BeaconResponse::Unversioned(response)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod fork_version_response_tests {
|
||||
use crate::{
|
||||
ExecutionPayload, ExecutionPayloadBellatrix, ForkName, ForkVersionedResponse,
|
||||
MainnetEthSpec,
|
||||
};
|
||||
use serde_json::json;
|
||||
|
||||
#[test]
|
||||
fn fork_versioned_response_deserialize_correct_fork() {
|
||||
type E = MainnetEthSpec;
|
||||
|
||||
let response_json =
|
||||
serde_json::to_string(&json!(ForkVersionedResponse::<ExecutionPayload<E>> {
|
||||
version: ForkName::Bellatrix,
|
||||
metadata: Default::default(),
|
||||
data: ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix::default()),
|
||||
}))
|
||||
.unwrap();
|
||||
|
||||
let result: Result<ForkVersionedResponse<ExecutionPayload<E>>, _> =
|
||||
serde_json::from_str(&response_json);
|
||||
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fork_versioned_response_deserialize_incorrect_fork() {
|
||||
type E = MainnetEthSpec;
|
||||
|
||||
let response_json =
|
||||
serde_json::to_string(&json!(ForkVersionedResponse::<ExecutionPayload<E>> {
|
||||
version: ForkName::Capella,
|
||||
metadata: Default::default(),
|
||||
data: ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix::default()),
|
||||
}))
|
||||
.unwrap();
|
||||
|
||||
let result: Result<ForkVersionedResponse<ExecutionPayload<E>>, _> =
|
||||
serde_json::from_str(&response_json);
|
||||
|
||||
assert!(result.is_err());
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
use self::committee_cache::get_active_validator_indices;
|
||||
use crate::historical_summary::HistoricalSummary;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::ContextDeserialize;
|
||||
use crate::FixedBytesExtended;
|
||||
use crate::*;
|
||||
use compare_fields::CompareFields;
|
||||
@@ -11,7 +12,7 @@ use int_to_bytes::{int_to_bytes4, int_to_bytes8};
|
||||
use metastruct::{metastruct, NumFields};
|
||||
pub use pubkey_cache::PubkeyCache;
|
||||
use safe_arith::{ArithError, SafeArith};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use ssz::{ssz_encode, Decode, DecodeError, Encode};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use std::hash::Hash;
|
||||
@@ -2896,18 +2897,15 @@ impl<E: EthSpec> CompareFields for BeaconState<E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> ForkVersionDeserialize for BeaconState<E> {
|
||||
fn deserialize_by_fork<'de, D: serde::Deserializer<'de>>(
|
||||
value: serde_json::value::Value,
|
||||
fork_name: ForkName,
|
||||
) -> Result<Self, D::Error> {
|
||||
impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for BeaconState<E> {
|
||||
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
Ok(map_fork_name!(
|
||||
fork_name,
|
||||
context,
|
||||
Self,
|
||||
serde_json::from_value(value).map_err(|e| serde::de::Error::custom(format!(
|
||||
"BeaconState failed to deserialize: {:?}",
|
||||
e
|
||||
)))?
|
||||
serde::Deserialize::deserialize(deserializer)?
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use crate::context_deserialize;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::{
|
||||
beacon_block_body::BLOB_KZG_COMMITMENTS_INDEX, AbstractExecPayload, BeaconBlockHeader,
|
||||
BeaconStateError, Blob, ChainSpec, Epoch, EthSpec, FixedVector, ForkName,
|
||||
ForkVersionDeserialize, Hash256, KzgProofs, RuntimeFixedVector, RuntimeVariableList,
|
||||
SignedBeaconBlock, SignedBeaconBlockHeader, Slot, VariableList,
|
||||
BeaconStateError, Blob, ChainSpec, Epoch, EthSpec, FixedVector, ForkName, Hash256, KzgProofs,
|
||||
RuntimeFixedVector, RuntimeVariableList, SignedBeaconBlock, SignedBeaconBlockHeader, Slot,
|
||||
VariableList,
|
||||
};
|
||||
use bls::Signature;
|
||||
use derivative::Derivative;
|
||||
@@ -25,6 +26,7 @@ use tree_hash_derive::TreeHash;
|
||||
#[derive(
|
||||
Serialize, Deserialize, Encode, Decode, TreeHash, Copy, Clone, Debug, PartialEq, Eq, Hash,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct BlobIdentifier {
|
||||
pub block_root: Hash256,
|
||||
pub index: u64,
|
||||
@@ -54,6 +56,7 @@ impl Ord for BlobIdentifier {
|
||||
Derivative,
|
||||
arbitrary::Arbitrary,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
#[serde(bound = "E: EthSpec")]
|
||||
#[arbitrary(bound = "E: EthSpec")]
|
||||
#[derivative(PartialEq, Eq, Hash(bound = "E: EthSpec"))]
|
||||
@@ -296,12 +299,3 @@ pub type BlobSidecarList<E> = RuntimeVariableList<Arc<BlobSidecar<E>>>;
|
||||
/// Alias for a non length-constrained list of `BlobSidecar`s.
|
||||
pub type FixedBlobSidecarList<E> = RuntimeFixedVector<Option<Arc<BlobSidecar<E>>>>;
|
||||
pub type BlobsList<E> = VariableList<Blob<E>, <E as EthSpec>::MaxBlobCommitmentsPerBlock>;
|
||||
|
||||
impl<E: EthSpec> ForkVersionDeserialize for BlobSidecarList<E> {
|
||||
fn deserialize_by_fork<'de, D: serde::Deserializer<'de>>(
|
||||
value: serde_json::value::Value,
|
||||
_: ForkName,
|
||||
) -> Result<Self, D::Error> {
|
||||
serde_json::from_value::<BlobSidecarList<E>>(value).map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ use tree_hash_derive::TreeHash;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct BlsToExecutionChange {
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub validator_index: u64,
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use crate::beacon_block_body::KzgCommitments;
|
||||
use crate::{
|
||||
ChainSpec, EthSpec, ExecutionPayloadHeaderBellatrix, ExecutionPayloadHeaderCapella,
|
||||
ExecutionPayloadHeaderDeneb, ExecutionPayloadHeaderEip7805, ExecutionPayloadHeaderElectra,
|
||||
ExecutionPayloadHeaderFulu, ExecutionPayloadHeaderRef, ExecutionPayloadHeaderRefMut,
|
||||
ExecutionRequests, ForkName, ForkVersionDecode, ForkVersionDeserialize, SignedRoot, Uint256,
|
||||
ChainSpec, ContextDeserialize, EthSpec, ExecutionPayloadHeaderBellatrix,
|
||||
ExecutionPayloadHeaderCapella, ExecutionPayloadHeaderDeneb, ExecutionPayloadHeaderEip7805,
|
||||
ExecutionPayloadHeaderElectra, ExecutionPayloadHeaderFulu, ExecutionPayloadHeaderRef,
|
||||
ExecutionPayloadHeaderRefMut, ExecutionRequests, ForkName, ForkVersionDecode,
|
||||
SignedRoot, Uint256,
|
||||
};
|
||||
use bls::PublicKeyBytes;
|
||||
use bls::Signature;
|
||||
@@ -11,6 +12,8 @@ use serde::{Deserialize, Deserializer, Serialize};
|
||||
use ssz::Decode;
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use superstruct::superstruct;
|
||||
use crate::test_utils::TestRandom;
|
||||
use test_random_derive::TestRandom;
|
||||
use tree_hash_derive::TreeHash;
|
||||
|
||||
#[superstruct(
|
||||
@@ -24,7 +27,8 @@ use tree_hash_derive::TreeHash;
|
||||
Deserialize,
|
||||
TreeHash,
|
||||
Decode,
|
||||
Clone
|
||||
Clone,
|
||||
TestRandom
|
||||
),
|
||||
serde(bound = "E: EthSpec", deny_unknown_fields)
|
||||
),
|
||||
@@ -128,47 +132,61 @@ impl<E: EthSpec> ForkVersionDecode for SignedBuilderBid<E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> ForkVersionDeserialize for BuilderBid<E> {
|
||||
fn deserialize_by_fork<'de, D: Deserializer<'de>>(
|
||||
value: serde_json::value::Value,
|
||||
fork_name: ForkName,
|
||||
) -> Result<Self, D::Error> {
|
||||
impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for BuilderBid<E> {
|
||||
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let convert_err =
|
||||
|e| serde::de::Error::custom(format!("BuilderBid failed to deserialize: {:?}", e));
|
||||
|
||||
Ok(match fork_name {
|
||||
Ok(match context {
|
||||
ForkName::Bellatrix => {
|
||||
Self::Bellatrix(serde_json::from_value(value).map_err(convert_err)?)
|
||||
Self::Bellatrix(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Capella => {
|
||||
Self::Capella(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Deneb => {
|
||||
Self::Deneb(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Electra => {
|
||||
Self::Electra(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Eip7805 => {
|
||||
Self::Eip7805(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Fulu => {
|
||||
Self::Fulu(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Capella => Self::Capella(serde_json::from_value(value).map_err(convert_err)?),
|
||||
ForkName::Deneb => Self::Deneb(serde_json::from_value(value).map_err(convert_err)?),
|
||||
ForkName::Electra => Self::Electra(serde_json::from_value(value).map_err(convert_err)?),
|
||||
ForkName::Eip7805 => Self::Eip7805(serde_json::from_value(value).map_err(convert_err)?),
|
||||
ForkName::Fulu => Self::Fulu(serde_json::from_value(value).map_err(convert_err)?),
|
||||
ForkName::Base | ForkName::Altair => {
|
||||
return Err(serde::de::Error::custom(format!(
|
||||
"BuilderBid failed to deserialize: unsupported fork '{}'",
|
||||
fork_name
|
||||
context
|
||||
)));
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> ForkVersionDeserialize for SignedBuilderBid<E> {
|
||||
fn deserialize_by_fork<'de, D: Deserializer<'de>>(
|
||||
value: serde_json::value::Value,
|
||||
fork_name: ForkName,
|
||||
) -> Result<Self, D::Error> {
|
||||
impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for SignedBuilderBid<E> {
|
||||
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
#[derive(Deserialize)]
|
||||
struct Helper {
|
||||
pub message: serde_json::Value,
|
||||
pub signature: Signature,
|
||||
message: serde_json::Value,
|
||||
signature: Signature,
|
||||
}
|
||||
let helper: Helper = serde_json::from_value(value).map_err(serde::de::Error::custom)?;
|
||||
|
||||
Ok(Self {
|
||||
message: BuilderBid::deserialize_by_fork::<'de, D>(helper.message, fork_name)?,
|
||||
let helper = Helper::deserialize(deserializer)?;
|
||||
|
||||
// Deserialize `data` using ContextDeserialize
|
||||
let message = BuilderBid::<E>::context_deserialize(helper.message, context)
|
||||
.map_err(serde::de::Error::custom)?;
|
||||
|
||||
Ok(SignedBuilderBid {
|
||||
message,
|
||||
signature: helper.signature,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::application_domain::{ApplicationDomain, APPLICATION_DOMAIN_BUILDER};
|
||||
use crate::blob_sidecar::BlobIdentifier;
|
||||
use crate::data_column_sidecar::DataColumnIdentifier;
|
||||
use crate::data_column_sidecar::DataColumnsByRootIdentifier;
|
||||
use crate::*;
|
||||
use int_to_bytes::int_to_bytes4;
|
||||
use safe_arith::{ArithError, SafeArith};
|
||||
@@ -219,10 +219,9 @@ pub struct ChainSpec {
|
||||
pub boot_nodes: Vec<String>,
|
||||
pub network_id: u8,
|
||||
pub target_aggregators_per_committee: u64,
|
||||
pub gossip_max_size: u64,
|
||||
pub max_payload_size: u64,
|
||||
max_request_blocks: u64,
|
||||
pub min_epochs_for_block_requests: u64,
|
||||
pub max_chunk_size: u64,
|
||||
pub ttfb_timeout: u64,
|
||||
pub resp_timeout: u64,
|
||||
pub attestation_propagation_slot_range: u64,
|
||||
@@ -250,6 +249,11 @@ pub struct ChainSpec {
|
||||
blob_sidecar_subnet_count_electra: u64,
|
||||
max_request_blob_sidecars_electra: u64,
|
||||
|
||||
/*
|
||||
* Networking Fulu
|
||||
*/
|
||||
max_blobs_per_block_fulu: u64,
|
||||
|
||||
/*
|
||||
* Networking Derived
|
||||
*
|
||||
@@ -684,7 +688,9 @@ impl ChainSpec {
|
||||
|
||||
/// Return the value of `MAX_BLOBS_PER_BLOCK` appropriate for `fork`.
|
||||
pub fn max_blobs_per_block_by_fork(&self, fork_name: ForkName) -> u64 {
|
||||
if fork_name.electra_enabled() {
|
||||
if fork_name.fulu_enabled() {
|
||||
self.max_blobs_per_block_fulu
|
||||
} else if fork_name.electra_enabled() {
|
||||
self.max_blobs_per_block_electra
|
||||
} else {
|
||||
self.max_blobs_per_block
|
||||
@@ -744,6 +750,35 @@ impl ChainSpec {
|
||||
(0..self.data_column_sidecar_subnet_count).map(DataColumnSubnetId::new)
|
||||
}
|
||||
|
||||
/// Worst-case compressed length for a given payload of size n when using snappy.
|
||||
///
|
||||
/// https://github.com/google/snappy/blob/32ded457c0b1fe78ceb8397632c416568d6714a0/snappy.cc#L218C1-L218C47
|
||||
/// https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#max_compressed_len
|
||||
fn max_compressed_len_snappy(n: usize) -> Option<usize> {
|
||||
32_usize.checked_add(n)?.checked_add(n / 6)
|
||||
}
|
||||
|
||||
/// Max compressed length of a message that we receive over gossip.
|
||||
pub fn max_compressed_len(&self) -> usize {
|
||||
Self::max_compressed_len_snappy(self.max_payload_size as usize)
|
||||
.expect("should not overflow")
|
||||
}
|
||||
|
||||
/// Max allowed size of a raw, compressed message received over the network.
|
||||
///
|
||||
/// https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#max_compressed_len
|
||||
pub fn max_message_size(&self) -> usize {
|
||||
std::cmp::max(
|
||||
// 1024 to account for framing + encoding overhead
|
||||
Self::max_compressed_len_snappy(self.max_payload_size as usize)
|
||||
.expect("should not overflow")
|
||||
.safe_add(1024)
|
||||
.expect("should not overflow"),
|
||||
//1MB
|
||||
1024 * 1024,
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns a `ChainSpec` compatible with the Ethereum Foundation specification.
|
||||
pub fn mainnet() -> Self {
|
||||
Self {
|
||||
@@ -911,7 +946,7 @@ impl ChainSpec {
|
||||
* Electra hard fork params
|
||||
*/
|
||||
electra_fork_version: [0x05, 00, 00, 00],
|
||||
electra_fork_epoch: None,
|
||||
electra_fork_epoch: Some(Epoch::new(364032)),
|
||||
unset_deposit_requests_start_index: u64::MAX,
|
||||
full_exit_request_amount: 0,
|
||||
min_activation_balance: option_wrapper(|| {
|
||||
@@ -966,9 +1001,8 @@ impl ChainSpec {
|
||||
subnets_per_node: 2,
|
||||
maximum_gossip_clock_disparity_millis: default_maximum_gossip_clock_disparity_millis(),
|
||||
target_aggregators_per_committee: 16,
|
||||
gossip_max_size: default_gossip_max_size(),
|
||||
max_payload_size: default_max_payload_size(),
|
||||
min_epochs_for_block_requests: default_min_epochs_for_block_requests(),
|
||||
max_chunk_size: default_max_chunk_size(),
|
||||
ttfb_timeout: default_ttfb_timeout(),
|
||||
resp_timeout: default_resp_timeout(),
|
||||
message_domain_invalid_snappy: default_message_domain_invalid_snappy(),
|
||||
@@ -1001,6 +1035,11 @@ impl ChainSpec {
|
||||
blob_sidecar_subnet_count_electra: default_blob_sidecar_subnet_count_electra(),
|
||||
max_request_blob_sidecars_electra: default_max_request_blob_sidecars_electra(),
|
||||
|
||||
/*
|
||||
* Networking Fulu specific
|
||||
*/
|
||||
max_blobs_per_block_fulu: default_max_blobs_per_block_fulu(),
|
||||
|
||||
/*
|
||||
* Application specific
|
||||
*/
|
||||
@@ -1252,7 +1291,7 @@ impl ChainSpec {
|
||||
* Electra hard fork params
|
||||
*/
|
||||
electra_fork_version: [0x05, 0x00, 0x00, 0x64],
|
||||
electra_fork_epoch: None,
|
||||
electra_fork_epoch: Some(Epoch::new(1337856)),
|
||||
unset_deposit_requests_start_index: u64::MAX,
|
||||
full_exit_request_amount: 0,
|
||||
min_activation_balance: option_wrapper(|| {
|
||||
@@ -1274,7 +1313,7 @@ impl ChainSpec {
|
||||
})
|
||||
.expect("calculation does not overflow"),
|
||||
max_per_epoch_activation_exit_churn_limit: option_wrapper(|| {
|
||||
u64::checked_pow(2, 8)?.checked_mul(u64::checked_pow(10, 9)?)
|
||||
u64::checked_pow(2, 6)?.checked_mul(u64::checked_pow(10, 9)?)
|
||||
})
|
||||
.expect("calculation does not overflow"),
|
||||
|
||||
@@ -1307,9 +1346,8 @@ impl ChainSpec {
|
||||
subnets_per_node: 4, // Make this larger than usual to avoid network damage
|
||||
maximum_gossip_clock_disparity_millis: default_maximum_gossip_clock_disparity_millis(),
|
||||
target_aggregators_per_committee: 16,
|
||||
gossip_max_size: default_gossip_max_size(),
|
||||
max_payload_size: default_max_payload_size(),
|
||||
min_epochs_for_block_requests: 33024,
|
||||
max_chunk_size: default_max_chunk_size(),
|
||||
ttfb_timeout: default_ttfb_timeout(),
|
||||
resp_timeout: default_resp_timeout(),
|
||||
message_domain_invalid_snappy: default_message_domain_invalid_snappy(),
|
||||
@@ -1325,7 +1363,7 @@ impl ChainSpec {
|
||||
max_request_data_column_sidecars: default_max_request_data_column_sidecars(),
|
||||
min_epochs_for_blob_sidecars_requests: 16384,
|
||||
blob_sidecar_subnet_count: default_blob_sidecar_subnet_count(),
|
||||
max_blobs_per_block: default_max_blobs_per_block(),
|
||||
max_blobs_per_block: 2,
|
||||
|
||||
/*
|
||||
* Derived Deneb Specific
|
||||
@@ -1338,9 +1376,14 @@ impl ChainSpec {
|
||||
/*
|
||||
* Networking Electra specific
|
||||
*/
|
||||
max_blobs_per_block_electra: default_max_blobs_per_block_electra(),
|
||||
blob_sidecar_subnet_count_electra: default_blob_sidecar_subnet_count_electra(),
|
||||
max_request_blob_sidecars_electra: default_max_request_blob_sidecars_electra(),
|
||||
max_blobs_per_block_electra: 2,
|
||||
blob_sidecar_subnet_count_electra: 2,
|
||||
max_request_blob_sidecars_electra: 256,
|
||||
|
||||
/*
|
||||
* Networking Fulu specific
|
||||
*/
|
||||
max_blobs_per_block_fulu: default_max_blobs_per_block_fulu(),
|
||||
|
||||
/*
|
||||
* Application specific
|
||||
@@ -1489,18 +1532,15 @@ pub struct Config {
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
gas_limit_adjustment_factor: u64,
|
||||
|
||||
#[serde(default = "default_gossip_max_size")]
|
||||
#[serde(default = "default_max_payload_size")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
gossip_max_size: u64,
|
||||
max_payload_size: u64,
|
||||
#[serde(default = "default_max_request_blocks")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
max_request_blocks: u64,
|
||||
#[serde(default = "default_min_epochs_for_block_requests")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
min_epochs_for_block_requests: u64,
|
||||
#[serde(default = "default_max_chunk_size")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
max_chunk_size: u64,
|
||||
#[serde(default = "default_ttfb_timeout")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
ttfb_timeout: u64,
|
||||
@@ -1572,6 +1612,9 @@ pub struct Config {
|
||||
#[serde(default = "default_custody_requirement")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
custody_requirement: u64,
|
||||
#[serde(default = "default_max_blobs_per_block_fulu")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
max_blobs_per_block_fulu: u64,
|
||||
}
|
||||
|
||||
fn default_bellatrix_fork_version() -> [u8; 4] {
|
||||
@@ -1640,7 +1683,7 @@ const fn default_gas_limit_adjustment_factor() -> u64 {
|
||||
1024
|
||||
}
|
||||
|
||||
const fn default_gossip_max_size() -> u64 {
|
||||
const fn default_max_payload_size() -> u64 {
|
||||
10485760
|
||||
}
|
||||
|
||||
@@ -1648,10 +1691,6 @@ const fn default_min_epochs_for_block_requests() -> u64 {
|
||||
33024
|
||||
}
|
||||
|
||||
const fn default_max_chunk_size() -> u64 {
|
||||
10485760
|
||||
}
|
||||
|
||||
const fn default_ttfb_timeout() -> u64 {
|
||||
5
|
||||
}
|
||||
@@ -1718,6 +1757,10 @@ const fn default_max_blobs_per_block_electra() -> u64 {
|
||||
9
|
||||
}
|
||||
|
||||
const fn default_max_blobs_per_block_fulu() -> u64 {
|
||||
12
|
||||
}
|
||||
|
||||
const fn default_attestation_propagation_slot_range() -> u64 {
|
||||
32
|
||||
}
|
||||
@@ -1771,15 +1814,21 @@ fn max_blobs_by_root_request_common(max_request_blob_sidecars: u64) -> usize {
|
||||
.len()
|
||||
}
|
||||
|
||||
fn max_data_columns_by_root_request_common(max_request_data_column_sidecars: u64) -> usize {
|
||||
let max_request_data_column_sidecars = max_request_data_column_sidecars as usize;
|
||||
let empty_data_column_id = DataColumnIdentifier {
|
||||
fn max_data_columns_by_root_request_common(
|
||||
max_request_blocks: u64,
|
||||
number_of_columns: u64,
|
||||
) -> usize {
|
||||
let max_request_blocks = max_request_blocks as usize;
|
||||
let number_of_columns = number_of_columns as usize;
|
||||
|
||||
let empty_data_columns_by_root_id = DataColumnsByRootIdentifier {
|
||||
block_root: Hash256::zero(),
|
||||
index: 0,
|
||||
columns: RuntimeVariableList::from_vec(vec![0; number_of_columns], number_of_columns),
|
||||
};
|
||||
RuntimeVariableList::from_vec(
|
||||
vec![empty_data_column_id; max_request_data_column_sidecars],
|
||||
max_request_data_column_sidecars,
|
||||
|
||||
RuntimeVariableList::<DataColumnsByRootIdentifier>::from_vec(
|
||||
vec![empty_data_columns_by_root_id; max_request_blocks],
|
||||
max_request_blocks,
|
||||
)
|
||||
.as_ssz_bytes()
|
||||
.len()
|
||||
@@ -1798,7 +1847,10 @@ fn default_max_blobs_by_root_request() -> usize {
|
||||
}
|
||||
|
||||
fn default_data_columns_by_root_request() -> usize {
|
||||
max_data_columns_by_root_request_common(default_max_request_data_column_sidecars())
|
||||
max_data_columns_by_root_request_common(
|
||||
default_max_request_blocks_deneb(),
|
||||
default_number_of_columns(),
|
||||
)
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
@@ -1922,10 +1974,9 @@ impl Config {
|
||||
|
||||
gas_limit_adjustment_factor: spec.gas_limit_adjustment_factor,
|
||||
|
||||
gossip_max_size: spec.gossip_max_size,
|
||||
max_payload_size: spec.max_payload_size,
|
||||
max_request_blocks: spec.max_request_blocks,
|
||||
min_epochs_for_block_requests: spec.min_epochs_for_block_requests,
|
||||
max_chunk_size: spec.max_chunk_size,
|
||||
ttfb_timeout: spec.ttfb_timeout,
|
||||
resp_timeout: spec.resp_timeout,
|
||||
attestation_propagation_slot_range: spec.attestation_propagation_slot_range,
|
||||
@@ -1951,6 +2002,7 @@ impl Config {
|
||||
data_column_sidecar_subnet_count: spec.data_column_sidecar_subnet_count,
|
||||
samples_per_slot: spec.samples_per_slot,
|
||||
custody_requirement: spec.custody_requirement,
|
||||
max_blobs_per_block_fulu: spec.max_blobs_per_block_fulu,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2005,9 +2057,8 @@ impl Config {
|
||||
deposit_network_id,
|
||||
deposit_contract_address,
|
||||
gas_limit_adjustment_factor,
|
||||
gossip_max_size,
|
||||
max_payload_size,
|
||||
min_epochs_for_block_requests,
|
||||
max_chunk_size,
|
||||
ttfb_timeout,
|
||||
resp_timeout,
|
||||
message_domain_invalid_snappy,
|
||||
@@ -2032,6 +2083,7 @@ impl Config {
|
||||
data_column_sidecar_subnet_count,
|
||||
samples_per_slot,
|
||||
custody_requirement,
|
||||
max_blobs_per_block_fulu,
|
||||
} = self;
|
||||
|
||||
if preset_base != E::spec_name().to_string().as_str() {
|
||||
@@ -2078,9 +2130,8 @@ impl Config {
|
||||
terminal_total_difficulty,
|
||||
terminal_block_hash,
|
||||
terminal_block_hash_activation_epoch,
|
||||
gossip_max_size,
|
||||
max_payload_size,
|
||||
min_epochs_for_block_requests,
|
||||
max_chunk_size,
|
||||
ttfb_timeout,
|
||||
resp_timeout,
|
||||
message_domain_invalid_snappy,
|
||||
@@ -2109,7 +2160,8 @@ impl Config {
|
||||
),
|
||||
max_blobs_by_root_request: max_blobs_by_root_request_common(max_request_blob_sidecars),
|
||||
max_data_columns_by_root_request: max_data_columns_by_root_request_common(
|
||||
max_request_data_column_sidecars,
|
||||
max_request_blocks_deneb,
|
||||
number_of_columns,
|
||||
),
|
||||
|
||||
number_of_columns,
|
||||
@@ -2117,6 +2169,7 @@ impl Config {
|
||||
data_column_sidecar_subnet_count,
|
||||
samples_per_slot,
|
||||
custody_requirement,
|
||||
max_blobs_per_block_fulu,
|
||||
|
||||
..chain_spec.clone()
|
||||
})
|
||||
@@ -2386,9 +2439,8 @@ mod yaml_tests {
|
||||
check_default!(terminal_block_hash);
|
||||
check_default!(terminal_block_hash_activation_epoch);
|
||||
check_default!(bellatrix_fork_version);
|
||||
check_default!(gossip_max_size);
|
||||
check_default!(max_payload_size);
|
||||
check_default!(min_epochs_for_block_requests);
|
||||
check_default!(max_chunk_size);
|
||||
check_default!(ttfb_timeout);
|
||||
check_default!(resp_timeout);
|
||||
check_default!(message_domain_invalid_snappy);
|
||||
@@ -2414,4 +2466,17 @@ mod yaml_tests {
|
||||
[0, 0, 0, 1]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_max_network_limits_overflow() {
|
||||
let mut spec = MainnetEthSpec::default_spec();
|
||||
// Should not overflow
|
||||
let _ = spec.max_message_size();
|
||||
let _ = spec.max_compressed_len();
|
||||
|
||||
spec.max_payload_size *= 10;
|
||||
// Should not overflow even with a 10x increase in max
|
||||
let _ = spec.max_message_size();
|
||||
let _ = spec.max_compressed_len();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::{Epoch, Hash256};
|
||||
use crate::{Epoch, ForkName, Hash256};
|
||||
use context_deserialize_derive::context_deserialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use test_random_derive::TestRandom;
|
||||
@@ -24,6 +25,7 @@ use tree_hash_derive::TreeHash;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct Checkpoint {
|
||||
pub epoch: Epoch,
|
||||
pub root: Hash256,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::{test_utils::TestRandom, Address, PublicKeyBytes, SignedRoot};
|
||||
use crate::context_deserialize;
|
||||
use crate::{test_utils::TestRandom, Address, ForkName, PublicKeyBytes, SignedRoot};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz::Encode;
|
||||
use ssz_derive::{Decode, Encode};
|
||||
@@ -19,6 +20,7 @@ use tree_hash_derive::TreeHash;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct ConsolidationRequest {
|
||||
pub source_address: Address,
|
||||
pub source_pubkey: PublicKeyBytes,
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use super::{
|
||||
ChainSpec, EthSpec, Fork, Hash256, SecretKey, Signature, SignedRoot, SyncCommitteeContribution,
|
||||
SyncSelectionProof,
|
||||
ChainSpec, EthSpec, Fork, ForkName, Hash256, SecretKey, Signature, SignedRoot,
|
||||
SyncCommitteeContribution, SyncSelectionProof,
|
||||
};
|
||||
use crate::context_deserialize;
|
||||
use crate::test_utils::TestRandom;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
@@ -23,6 +24,7 @@ use tree_hash_derive::TreeHash;
|
||||
)]
|
||||
#[serde(bound = "E: EthSpec")]
|
||||
#[arbitrary(bound = "E: EthSpec")]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct ContributionAndProof<E: EthSpec> {
|
||||
/// The index of the validator that created the sync contribution.
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
use crate::beacon_block_body::{KzgCommitments, BLOB_KZG_COMMITMENTS_INDEX};
|
||||
use crate::context_deserialize;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::BeaconStateError;
|
||||
use crate::{BeaconBlockHeader, Epoch, EthSpec, Hash256, KzgProofs, SignedBeaconBlockHeader, Slot};
|
||||
use crate::{
|
||||
BeaconBlockHeader, BeaconStateError, Epoch, EthSpec, ForkName, Hash256, RuntimeVariableList,
|
||||
SignedBeaconBlockHeader, Slot,
|
||||
};
|
||||
use bls::Signature;
|
||||
use derivative::Derivative;
|
||||
use kzg::Error as KzgError;
|
||||
@@ -9,11 +12,10 @@ use kzg::{KzgCommitment, KzgProof};
|
||||
use merkle_proof::verify_merkle_proof;
|
||||
use safe_arith::ArithError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz::Encode;
|
||||
use ssz::{DecodeError, Encode};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use ssz_types::Error as SszError;
|
||||
use ssz_types::{FixedVector, VariableList};
|
||||
use std::hash::Hash;
|
||||
use std::sync::Arc;
|
||||
use test_random_derive::TestRandom;
|
||||
use tree_hash::TreeHash;
|
||||
@@ -23,13 +25,47 @@ pub type ColumnIndex = u64;
|
||||
pub type Cell<E> = FixedVector<u8, <E as EthSpec>::BytesPerCell>;
|
||||
pub type DataColumn<E> = VariableList<Cell<E>, <E as EthSpec>::MaxBlobCommitmentsPerBlock>;
|
||||
|
||||
/// Container of the data that identifies an individual data column.
|
||||
#[derive(
|
||||
Serialize, Deserialize, Encode, Decode, TreeHash, Copy, Clone, Debug, PartialEq, Eq, Hash,
|
||||
)]
|
||||
pub struct DataColumnIdentifier {
|
||||
/// Identifies a set of data columns associated with a specific beacon block.
|
||||
#[derive(Encode, Clone, Debug, PartialEq)]
|
||||
pub struct DataColumnsByRootIdentifier {
|
||||
pub block_root: Hash256,
|
||||
pub index: ColumnIndex,
|
||||
pub columns: RuntimeVariableList<ColumnIndex>,
|
||||
}
|
||||
|
||||
impl RuntimeVariableList<DataColumnsByRootIdentifier> {
|
||||
pub fn from_ssz_bytes_with_nested(
|
||||
bytes: &[u8],
|
||||
max_len: usize,
|
||||
num_columns: usize,
|
||||
) -> Result<Self, DecodeError> {
|
||||
if bytes.is_empty() {
|
||||
return Ok(RuntimeVariableList::empty(max_len));
|
||||
}
|
||||
|
||||
let vec = ssz::decode_list_of_variable_length_items::<Vec<u8>, Vec<Vec<u8>>>(
|
||||
bytes,
|
||||
Some(max_len),
|
||||
)?
|
||||
.into_iter()
|
||||
.map(|bytes| {
|
||||
let mut builder = ssz::SszDecoderBuilder::new(&bytes);
|
||||
builder.register_type::<Hash256>()?;
|
||||
builder.register_anonymous_variable_length_item()?;
|
||||
|
||||
let mut decoder = builder.build()?;
|
||||
let block_root = decoder.decode_next()?;
|
||||
let columns = decoder.decode_next_with(|bytes| {
|
||||
RuntimeVariableList::from_ssz_bytes(bytes, num_columns)
|
||||
})?;
|
||||
Ok(DataColumnsByRootIdentifier {
|
||||
block_root,
|
||||
columns,
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
Ok(RuntimeVariableList::from_vec(vec, max_len))
|
||||
}
|
||||
}
|
||||
|
||||
pub type DataColumnSidecarList<E> = Vec<Arc<DataColumnSidecar<E>>>;
|
||||
@@ -49,6 +85,7 @@ pub type DataColumnSidecarList<E> = Vec<Arc<DataColumnSidecar<E>>>;
|
||||
#[serde(bound = "E: EthSpec")]
|
||||
#[arbitrary(bound = "E: EthSpec")]
|
||||
#[derivative(PartialEq, Eq, Hash(bound = "E: EthSpec"))]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct DataColumnSidecar<E: EthSpec> {
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub index: ColumnIndex,
|
||||
@@ -56,7 +93,7 @@ pub struct DataColumnSidecar<E: EthSpec> {
|
||||
pub column: DataColumn<E>,
|
||||
/// All the KZG commitments and proofs associated with the block, used for verifying sample cells.
|
||||
pub kzg_commitments: KzgCommitments<E>,
|
||||
pub kzg_proofs: KzgProofs<E>,
|
||||
pub kzg_proofs: VariableList<KzgProof, E::MaxBlobCommitmentsPerBlock>,
|
||||
pub signed_block_header: SignedBeaconBlockHeader,
|
||||
/// An inclusion proof, proving the inclusion of `blob_kzg_commitments` in `BeaconBlockBody`.
|
||||
pub kzg_commitments_inclusion_proof: FixedVector<Hash256, E::KzgCommitmentsInclusionProofDepth>,
|
||||
@@ -132,13 +169,6 @@ impl<E: EthSpec> DataColumnSidecar<E> {
|
||||
.as_ssz_bytes()
|
||||
.len()
|
||||
}
|
||||
|
||||
pub fn id(&self) -> DataColumnIdentifier {
|
||||
DataColumnIdentifier {
|
||||
block_root: self.block_root(),
|
||||
index: self.index,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -178,3 +208,45 @@ impl From<SszError> for DataColumnSidecarError {
|
||||
Self::SszError(e)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use bls::FixedBytesExtended;
|
||||
|
||||
#[test]
|
||||
fn round_trip_dcbroot_list() {
|
||||
let max_outer = 5;
|
||||
let max_inner = 10;
|
||||
|
||||
let data = vec![
|
||||
DataColumnsByRootIdentifier {
|
||||
block_root: Hash256::from_low_u64_be(10),
|
||||
columns: RuntimeVariableList::<ColumnIndex>::from_vec(vec![1u64, 2, 3], max_inner),
|
||||
},
|
||||
DataColumnsByRootIdentifier {
|
||||
block_root: Hash256::from_low_u64_be(20),
|
||||
columns: RuntimeVariableList::<ColumnIndex>::from_vec(vec![4u64, 5], max_inner),
|
||||
},
|
||||
];
|
||||
|
||||
let list = RuntimeVariableList::from_vec(data.clone(), max_outer);
|
||||
|
||||
let ssz_bytes = list.as_ssz_bytes();
|
||||
|
||||
let decoded =
|
||||
RuntimeVariableList::<DataColumnsByRootIdentifier>::from_ssz_bytes_with_nested(
|
||||
&ssz_bytes, max_outer, max_inner,
|
||||
)
|
||||
.expect("should decode list of DataColumnsByRootIdentifier");
|
||||
|
||||
assert_eq!(decoded.len(), data.len());
|
||||
for (original, decoded) in data.iter().zip(decoded.iter()) {
|
||||
assert_eq!(decoded.block_root, original.block_root);
|
||||
assert_eq!(
|
||||
decoded.columns.iter().copied().collect::<Vec<_>>(),
|
||||
original.columns.iter().copied().collect::<Vec<_>>()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::context_deserialize;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -24,6 +25,7 @@ pub const DEPOSIT_TREE_DEPTH: usize = 32;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct Deposit {
|
||||
pub proof: FixedVector<Hash256, U33>,
|
||||
pub data: DepositData,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::*;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use test_random_derive::TestRandom;
|
||||
@@ -22,6 +21,7 @@ use tree_hash_derive::TreeHash;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct DepositData {
|
||||
pub pubkey: PublicKeyBytes,
|
||||
pub withdrawal_credentials: Hash256,
|
||||
|
||||
@@ -21,6 +21,7 @@ use tree_hash_derive::TreeHash;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct DepositMessage {
|
||||
pub pubkey: PublicKeyBytes,
|
||||
pub withdrawal_credentials: Hash256,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::context_deserialize;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::{Hash256, PublicKeyBytes};
|
||||
use crate::{ForkName, Hash256, PublicKeyBytes};
|
||||
use bls::SignatureBytes;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz::Encode;
|
||||
@@ -20,6 +21,7 @@ use tree_hash_derive::TreeHash;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct DepositRequest {
|
||||
pub pubkey: PublicKeyBytes,
|
||||
pub withdrawal_credentials: Hash256,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use super::Hash256;
|
||||
use crate::context_deserialize;
|
||||
use crate::test_utils::TestRandom;
|
||||
|
||||
use crate::ForkName;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use test_random_derive::TestRandom;
|
||||
@@ -24,6 +25,7 @@ use tree_hash_derive::TreeHash;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct Eth1Data {
|
||||
pub deposit_root: Hash256,
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
|
||||
@@ -4,8 +4,8 @@ use safe_arith::SafeArith;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_types::typenum::{
|
||||
bit::B0, UInt, U0, U1, U10, U1024, U1048576, U1073741824, U1099511627776, U128, U131072,
|
||||
U134217728, U16, U16777216, U17, U2, U2048, U256, U262144, U32, U4, U4096, U512, U625, U64,
|
||||
U65536, U8, U8192,
|
||||
U134217728, U16, U16777216, U17, U2, U2048, U256, U262144, U32, U33554432, U4, U4096, U512,
|
||||
U625, U64, U65536, U8, U8192,
|
||||
};
|
||||
use std::fmt::{self, Debug};
|
||||
use std::str::FromStr;
|
||||
@@ -146,6 +146,11 @@ pub trait EthSpec:
|
||||
/// Must be set to `BytesPerFieldElement * FieldElementsPerCell`.
|
||||
type BytesPerCell: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
||||
|
||||
/// The maximum number of cell commitments per block
|
||||
///
|
||||
/// FieldElementsPerExtBlob * MaxBlobCommitmentsPerBlock
|
||||
type MaxCellsPerBlock: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
||||
|
||||
/*
|
||||
* New in Electra
|
||||
*/
|
||||
@@ -437,6 +442,7 @@ impl EthSpec for MainnetEthSpec {
|
||||
type FieldElementsPerExtBlob = U8192;
|
||||
type BytesPerBlob = U131072;
|
||||
type BytesPerCell = U2048;
|
||||
type MaxCellsPerBlock = U33554432;
|
||||
type KzgCommitmentInclusionProofDepth = U17;
|
||||
type KzgCommitmentsInclusionProofDepth = U4; // inclusion of the whole list of commitments
|
||||
type SyncSubcommitteeSize = U128; // 512 committee size / 4 sync committee subnet count
|
||||
@@ -492,6 +498,7 @@ impl EthSpec for MinimalEthSpec {
|
||||
type MaxWithdrawalRequestsPerPayload = U2;
|
||||
type FieldElementsPerCell = U64;
|
||||
type FieldElementsPerExtBlob = U8192;
|
||||
type MaxCellsPerBlock = U33554432;
|
||||
type BytesPerCell = U2048;
|
||||
type KzgCommitmentsInclusionProofDepth = U4;
|
||||
|
||||
@@ -586,6 +593,7 @@ impl EthSpec for GnosisEthSpec {
|
||||
type MaxPendingDepositsPerEpoch = U16;
|
||||
type FieldElementsPerCell = U64;
|
||||
type FieldElementsPerExtBlob = U8192;
|
||||
type MaxCellsPerBlock = U33554432;
|
||||
type BytesPerCell = U2048;
|
||||
type KzgCommitmentsInclusionProofDepth = U4;
|
||||
type InclusionListCommitteeSize = U16;
|
||||
|
||||
@@ -112,3 +112,22 @@ impl fmt::Display for ExecutionBlockHash {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Hash256> for ExecutionBlockHash {
|
||||
fn from(hash: Hash256) -> Self {
|
||||
Self(hash)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_from_hash256() {
|
||||
let hash = Hash256::random();
|
||||
let ex_hash = ExecutionBlockHash::from(hash);
|
||||
|
||||
assert_eq!(ExecutionBlockHash(hash), ex_hash);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{test_utils::TestRandom, *};
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use ssz::{Decode, Encode};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use test_random_derive::TestRandom;
|
||||
@@ -30,6 +30,7 @@ pub type Withdrawals<E> = VariableList<Withdrawal, <E as EthSpec>::MaxWithdrawal
|
||||
Derivative,
|
||||
arbitrary::Arbitrary
|
||||
),
|
||||
context_deserialize(ForkName),
|
||||
derivative(PartialEq, Hash(bound = "E: EthSpec")),
|
||||
serde(bound = "E: EthSpec", deny_unknown_fields),
|
||||
arbitrary(bound = "E: EthSpec")
|
||||
@@ -134,29 +135,38 @@ impl<E: EthSpec> ExecutionPayload<E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> ForkVersionDeserialize for ExecutionPayload<E> {
|
||||
fn deserialize_by_fork<'de, D: serde::Deserializer<'de>>(
|
||||
value: serde_json::value::Value,
|
||||
fork_name: ForkName,
|
||||
) -> Result<Self, D::Error> {
|
||||
impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for ExecutionPayload<E> {
|
||||
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let convert_err = |e| {
|
||||
serde::de::Error::custom(format!("ExecutionPayload failed to deserialize: {:?}", e))
|
||||
};
|
||||
|
||||
Ok(match fork_name {
|
||||
ForkName::Bellatrix => {
|
||||
Self::Bellatrix(serde_json::from_value(value).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Capella => Self::Capella(serde_json::from_value(value).map_err(convert_err)?),
|
||||
ForkName::Deneb => Self::Deneb(serde_json::from_value(value).map_err(convert_err)?),
|
||||
ForkName::Electra => Self::Electra(serde_json::from_value(value).map_err(convert_err)?),
|
||||
ForkName::Eip7805 => Self::Eip7805(serde_json::from_value(value).map_err(convert_err)?),
|
||||
ForkName::Fulu => Self::Fulu(serde_json::from_value(value).map_err(convert_err)?),
|
||||
Ok(match context {
|
||||
ForkName::Base | ForkName::Altair => {
|
||||
return Err(serde::de::Error::custom(format!(
|
||||
"ExecutionPayload failed to deserialize: unsupported fork '{}'",
|
||||
fork_name
|
||||
)));
|
||||
context
|
||||
)))
|
||||
}
|
||||
ForkName::Bellatrix => {
|
||||
Self::Bellatrix(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Capella => {
|
||||
Self::Capella(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Deneb => {
|
||||
Self::Deneb(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Electra => {
|
||||
Self::Electra(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Eip7805 => {
|
||||
Self::Eip7805(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Fulu => {
|
||||
Self::Fulu(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{test_utils::TestRandom, *};
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use ssz::{Decode, Encode};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use test_random_derive::TestRandom;
|
||||
@@ -25,7 +25,8 @@ use tree_hash_derive::TreeHash;
|
||||
),
|
||||
derivative(PartialEq, Hash(bound = "E: EthSpec")),
|
||||
serde(bound = "E: EthSpec", deny_unknown_fields),
|
||||
arbitrary(bound = "E: EthSpec")
|
||||
arbitrary(bound = "E: EthSpec"),
|
||||
context_deserialize(ForkName),
|
||||
),
|
||||
ref_attributes(
|
||||
derive(PartialEq, TreeHash, Debug),
|
||||
@@ -545,32 +546,41 @@ impl<E: EthSpec> TryFrom<ExecutionPayloadHeader<E>> for ExecutionPayloadHeaderFu
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> ForkVersionDeserialize for ExecutionPayloadHeader<E> {
|
||||
fn deserialize_by_fork<'de, D: serde::Deserializer<'de>>(
|
||||
value: serde_json::value::Value,
|
||||
fork_name: ForkName,
|
||||
) -> Result<Self, D::Error> {
|
||||
impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for ExecutionPayloadHeader<E> {
|
||||
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let convert_err = |e| {
|
||||
serde::de::Error::custom(format!(
|
||||
"ExecutionPayloadHeader failed to deserialize: {:?}",
|
||||
e
|
||||
))
|
||||
};
|
||||
|
||||
Ok(match fork_name {
|
||||
ForkName::Bellatrix => {
|
||||
Self::Bellatrix(serde_json::from_value(value).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Capella => Self::Capella(serde_json::from_value(value).map_err(convert_err)?),
|
||||
ForkName::Deneb => Self::Deneb(serde_json::from_value(value).map_err(convert_err)?),
|
||||
ForkName::Electra => Self::Electra(serde_json::from_value(value).map_err(convert_err)?),
|
||||
ForkName::Eip7805 => Self::Eip7805(serde_json::from_value(value).map_err(convert_err)?),
|
||||
ForkName::Fulu => Self::Fulu(serde_json::from_value(value).map_err(convert_err)?),
|
||||
Ok(match context {
|
||||
ForkName::Base | ForkName::Altair => {
|
||||
return Err(serde::de::Error::custom(format!(
|
||||
"ExecutionPayloadHeader failed to deserialize: unsupported fork '{}'",
|
||||
fork_name
|
||||
)));
|
||||
context
|
||||
)))
|
||||
}
|
||||
ForkName::Bellatrix => {
|
||||
Self::Bellatrix(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Capella => {
|
||||
Self::Capella(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Deneb => {
|
||||
Self::Deneb(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Electra => {
|
||||
Self::Electra(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Eip7805 => {
|
||||
Self::Eip7805(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Fulu => {
|
||||
Self::Fulu(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::context_deserialize;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::{ConsolidationRequest, DepositRequest, EthSpec, Hash256, WithdrawalRequest};
|
||||
use crate::{ConsolidationRequest, DepositRequest, EthSpec, ForkName, Hash256, WithdrawalRequest};
|
||||
use alloy_primitives::Bytes;
|
||||
use derivative::Derivative;
|
||||
use ethereum_hashing::{DynamicContext, Sha256Context};
|
||||
@@ -33,6 +34,7 @@ pub type ConsolidationRequests<E> =
|
||||
#[serde(bound = "E: EthSpec")]
|
||||
#[arbitrary(bound = "E: EthSpec")]
|
||||
#[derivative(PartialEq, Eq, Hash(bound = "E: EthSpec"))]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct ExecutionRequests<E: EthSpec> {
|
||||
pub deposits: DepositRequests<E>,
|
||||
pub withdrawals: WithdrawalRequests<E>,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::Epoch;
|
||||
use crate::{Epoch, ForkName};
|
||||
use context_deserialize_derive::context_deserialize;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
@@ -23,6 +24,7 @@ use tree_hash_derive::TreeHash;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct Fork {
|
||||
#[serde(with = "serde_utils::bytes_4_hex")]
|
||||
pub previous_version: [u8; 4],
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::{Hash256, SignedRoot};
|
||||
use crate::{ForkName, Hash256, SignedRoot};
|
||||
use context_deserialize_derive::context_deserialize;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
@@ -22,6 +23,7 @@ use tree_hash_derive::TreeHash;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct ForkData {
|
||||
#[serde(with = "serde_utils::bytes_4_hex")]
|
||||
pub current_version: [u8; 4],
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
use crate::ForkName;
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use serde_json::value::Value;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub trait ForkVersionDecode: Sized {
|
||||
/// SSZ decode with explicit fork variant.
|
||||
fn from_ssz_bytes_by_fork(bytes: &[u8], fork_name: ForkName) -> Result<Self, ssz::DecodeError>;
|
||||
}
|
||||
|
||||
pub trait ForkVersionDeserialize: Sized + DeserializeOwned {
|
||||
fn deserialize_by_fork<'de, D: Deserializer<'de>>(
|
||||
value: Value,
|
||||
fork_name: ForkName,
|
||||
) -> Result<Self, D::Error>;
|
||||
}
|
||||
|
||||
/// Deserialize is only implemented for types that implement ForkVersionDeserialize.
|
||||
///
|
||||
/// The metadata of type M should be set to `EmptyMetadata` if you don't care about adding fields other than
|
||||
/// version. If you *do* care about adding other fields you can mix in any type that implements
|
||||
/// `Deserialize`.
|
||||
#[derive(Debug, PartialEq, Clone, Serialize)]
|
||||
pub struct ForkVersionedResponse<T, M = EmptyMetadata> {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub version: Option<ForkName>,
|
||||
#[serde(flatten)]
|
||||
pub metadata: M,
|
||||
pub data: T,
|
||||
}
|
||||
|
||||
/// Metadata type similar to unit (i.e. `()`) but deserializes from a map (`serde_json::Value`).
|
||||
///
|
||||
/// Unfortunately the braces are semantically significant, i.e. `struct EmptyMetadata;` does not
|
||||
/// work.
|
||||
#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
|
||||
pub struct EmptyMetadata {}
|
||||
|
||||
/// Fork versioned response with extra information about finalization & optimistic execution.
|
||||
pub type ExecutionOptimisticFinalizedForkVersionedResponse<T> =
|
||||
ForkVersionedResponse<T, ExecutionOptimisticFinalizedMetadata>;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
pub struct ExecutionOptimisticFinalizedMetadata {
|
||||
pub execution_optimistic: Option<bool>,
|
||||
pub finalized: Option<bool>,
|
||||
}
|
||||
|
||||
impl<'de, F, M> serde::Deserialize<'de> for ForkVersionedResponse<F, M>
|
||||
where
|
||||
F: ForkVersionDeserialize,
|
||||
M: DeserializeOwned,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
#[derive(Deserialize)]
|
||||
struct Helper {
|
||||
version: Option<ForkName>,
|
||||
#[serde(flatten)]
|
||||
metadata: serde_json::Value,
|
||||
data: serde_json::Value,
|
||||
}
|
||||
|
||||
let helper = Helper::deserialize(deserializer)?;
|
||||
let data = match helper.version {
|
||||
Some(fork_name) => F::deserialize_by_fork::<'de, D>(helper.data, fork_name)?,
|
||||
None => serde_json::from_value(helper.data).map_err(serde::de::Error::custom)?,
|
||||
};
|
||||
let metadata = serde_json::from_value(helper.metadata).map_err(serde::de::Error::custom)?;
|
||||
|
||||
Ok(ForkVersionedResponse {
|
||||
version: helper.version,
|
||||
metadata,
|
||||
data,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: ForkVersionDeserialize> ForkVersionDeserialize for Arc<F> {
|
||||
fn deserialize_by_fork<'de, D: Deserializer<'de>>(
|
||||
value: Value,
|
||||
fork_name: ForkName,
|
||||
) -> Result<Self, D::Error> {
|
||||
Ok(Arc::new(F::deserialize_by_fork::<'de, D>(
|
||||
value, fork_name,
|
||||
)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, M> ForkVersionedResponse<T, M> {
|
||||
/// Apply a function to the inner `data`, potentially changing its type.
|
||||
pub fn map_data<U>(self, f: impl FnOnce(T) -> U) -> ForkVersionedResponse<U, M> {
|
||||
let ForkVersionedResponse {
|
||||
version,
|
||||
metadata,
|
||||
data,
|
||||
} = self;
|
||||
ForkVersionedResponse {
|
||||
version,
|
||||
metadata,
|
||||
data: f(data),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod fork_version_response_tests {
|
||||
use crate::{
|
||||
ExecutionPayload, ExecutionPayloadBellatrix, ForkName, ForkVersionedResponse,
|
||||
MainnetEthSpec,
|
||||
};
|
||||
use serde_json::json;
|
||||
|
||||
#[test]
|
||||
fn fork_versioned_response_deserialize_correct_fork() {
|
||||
type E = MainnetEthSpec;
|
||||
|
||||
let response_json =
|
||||
serde_json::to_string(&json!(ForkVersionedResponse::<ExecutionPayload<E>> {
|
||||
version: Some(ForkName::Bellatrix),
|
||||
metadata: Default::default(),
|
||||
data: ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix::default()),
|
||||
}))
|
||||
.unwrap();
|
||||
|
||||
let result: Result<ForkVersionedResponse<ExecutionPayload<E>>, _> =
|
||||
serde_json::from_str(&response_json);
|
||||
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fork_versioned_response_deserialize_incorrect_fork() {
|
||||
type E = MainnetEthSpec;
|
||||
|
||||
let response_json =
|
||||
serde_json::to_string(&json!(ForkVersionedResponse::<ExecutionPayload<E>> {
|
||||
version: Some(ForkName::Capella),
|
||||
metadata: Default::default(),
|
||||
data: ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix::default()),
|
||||
}))
|
||||
.unwrap();
|
||||
|
||||
let result: Result<ForkVersionedResponse<ExecutionPayload<E>>, _> =
|
||||
serde_json::from_str(&response_json);
|
||||
|
||||
assert!(result.is_err());
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ use tree_hash_derive::TreeHash;
|
||||
arbitrary::Arbitrary,
|
||||
)]
|
||||
#[arbitrary(bound = "E: EthSpec")]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct HistoricalBatch<E: EthSpec> {
|
||||
#[test_random(default)]
|
||||
pub block_roots: Vector<Hash256, E::SlotsPerHistoricalRoot>,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::context_deserialize;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::{BeaconState, EthSpec, Hash256};
|
||||
use crate::{BeaconState, EthSpec, ForkName, Hash256};
|
||||
use compare_fields_derive::CompareFields;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
@@ -28,6 +29,7 @@ use tree_hash_derive::TreeHash;
|
||||
Default,
|
||||
arbitrary::Arbitrary,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct HistoricalSummary {
|
||||
block_summary_root: Hash256,
|
||||
state_summary_root: Hash256,
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use crate::{test_utils::TestRandom, AggregateSignature, AttestationData, EthSpec, VariableList};
|
||||
use crate::context_deserialize;
|
||||
use crate::{
|
||||
test_utils::TestRandom, AggregateSignature, AttestationData, EthSpec, ForkName, VariableList,
|
||||
};
|
||||
use core::slice::Iter;
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -29,6 +32,7 @@ use tree_hash_derive::TreeHash;
|
||||
arbitrary::Arbitrary,
|
||||
TreeHash,
|
||||
),
|
||||
context_deserialize(ForkName),
|
||||
derivative(PartialEq, Hash(bound = "E: EthSpec")),
|
||||
serde(bound = "E: EthSpec", deny_unknown_fields),
|
||||
arbitrary(bound = "E: EthSpec"),
|
||||
|
||||
@@ -22,6 +22,7 @@ pub mod beacon_block;
|
||||
pub mod beacon_block_body;
|
||||
pub mod beacon_block_header;
|
||||
pub mod beacon_committee;
|
||||
pub mod beacon_response;
|
||||
pub mod beacon_state;
|
||||
pub mod bls_to_execution_change;
|
||||
pub mod builder_bid;
|
||||
@@ -44,7 +45,6 @@ pub mod execution_payload_header;
|
||||
pub mod fork;
|
||||
pub mod fork_data;
|
||||
pub mod fork_name;
|
||||
pub mod fork_versioned_response;
|
||||
pub mod graffiti;
|
||||
pub mod historical_batch;
|
||||
pub mod historical_summary;
|
||||
@@ -141,6 +141,9 @@ pub use crate::beacon_block_body::{
|
||||
};
|
||||
pub use crate::beacon_block_header::BeaconBlockHeader;
|
||||
pub use crate::beacon_committee::{BeaconCommittee, OwnedBeaconCommittee};
|
||||
pub use crate::beacon_response::{
|
||||
BeaconResponse, ForkVersionDecode, ForkVersionedResponse, UnversionedResponse,
|
||||
};
|
||||
pub use crate::beacon_state::{Error as BeaconStateError, *};
|
||||
pub use crate::blob_sidecar::{BlobIdentifier, BlobSidecar, BlobSidecarList, BlobsList};
|
||||
pub use crate::bls_to_execution_change::BlsToExecutionChange;
|
||||
@@ -152,7 +155,7 @@ pub use crate::config_and_preset::{
|
||||
pub use crate::consolidation_request::ConsolidationRequest;
|
||||
pub use crate::contribution_and_proof::ContributionAndProof;
|
||||
pub use crate::data_column_sidecar::{
|
||||
ColumnIndex, DataColumnIdentifier, DataColumnSidecar, DataColumnSidecarList,
|
||||
ColumnIndex, DataColumnSidecar, DataColumnSidecarList, DataColumnsByRootIdentifier,
|
||||
};
|
||||
pub use crate::data_column_subnet_id::DataColumnSubnetId;
|
||||
pub use crate::deposit::{Deposit, DEPOSIT_TREE_DEPTH};
|
||||
@@ -181,9 +184,6 @@ pub use crate::fork::Fork;
|
||||
pub use crate::fork_context::ForkContext;
|
||||
pub use crate::fork_data::ForkData;
|
||||
pub use crate::fork_name::{ForkName, InconsistentFork};
|
||||
pub use crate::fork_versioned_response::{
|
||||
ForkVersionDecode, ForkVersionDeserialize, ForkVersionedResponse,
|
||||
};
|
||||
pub use crate::graffiti::{Graffiti, GRAFFITI_BYTES_LEN};
|
||||
pub use crate::historical_batch::HistoricalBatch;
|
||||
pub use crate::inclusion_list::{InclusionList, InclusionListTransactions, SignedInclusionList};
|
||||
@@ -280,7 +280,14 @@ pub type Address = fixed_bytes::Address;
|
||||
pub type ForkVersion = [u8; 4];
|
||||
pub type BLSFieldElement = Uint256;
|
||||
pub type Blob<E> = FixedVector<u8, <E as EthSpec>::BytesPerBlob>;
|
||||
pub type KzgProofs<E> = VariableList<KzgProof, <E as EthSpec>::MaxBlobCommitmentsPerBlock>;
|
||||
// Note on List limit:
|
||||
// - Deneb to Electra: `MaxBlobCommitmentsPerBlock`
|
||||
// - Fulu: `MaxCellsPerBlock`
|
||||
// We choose to use a single type (with the larger value from Fulu as `N`) instead of having to
|
||||
// introduce a new type for Fulu. This is to avoid messy conversions and having to add extra types
|
||||
// with no gains - as `N` does not impact serialisation at all, and only affects merkleization,
|
||||
// which we don't current do on `KzgProofs` anyway.
|
||||
pub type KzgProofs<E> = VariableList<KzgProof, <E as EthSpec>::MaxCellsPerBlock>;
|
||||
pub type VersionedHash = Hash256;
|
||||
pub type Hash64 = alloy_primitives::B64;
|
||||
|
||||
@@ -288,6 +295,8 @@ pub use bls::{
|
||||
AggregatePublicKey, AggregateSignature, Keypair, PublicKey, PublicKeyBytes, SecretKey,
|
||||
Signature, SignatureBytes,
|
||||
};
|
||||
pub use context_deserialize::ContextDeserialize;
|
||||
pub use context_deserialize_derive::context_deserialize;
|
||||
pub use kzg::{KzgCommitment, KzgProof, VERSIONED_HASH_VERSION_KZG};
|
||||
pub use milhouse::{self, List, Vector};
|
||||
pub use ssz_types::{typenum, typenum::Unsigned, BitList, BitVector, FixedVector, VariableList};
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use crate::context_deserialize;
|
||||
use crate::{
|
||||
light_client_update::*, test_utils::TestRandom, BeaconState, ChainSpec, EthSpec, FixedVector,
|
||||
ForkName, ForkVersionDeserialize, Hash256, LightClientHeader, LightClientHeaderAltair,
|
||||
light_client_update::*, test_utils::TestRandom, BeaconState, ChainSpec, ContextDeserialize,
|
||||
EthSpec, FixedVector, ForkName, Hash256, LightClientHeader, LightClientHeaderAltair,
|
||||
LightClientHeaderCapella, LightClientHeaderDeneb, LightClientHeaderElectra,
|
||||
LightClientHeaderFulu, SignedBlindedBeaconBlock, Slot, SyncCommittee,
|
||||
};
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use serde_json::Value;
|
||||
use ssz::{Decode, Encode};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use std::sync::Arc;
|
||||
@@ -34,6 +34,7 @@ use tree_hash_derive::TreeHash;
|
||||
),
|
||||
serde(bound = "E: EthSpec", deny_unknown_fields),
|
||||
arbitrary(bound = "E: EthSpec"),
|
||||
context_deserialize(ForkName),
|
||||
)
|
||||
)]
|
||||
#[derive(
|
||||
@@ -217,20 +218,40 @@ impl<E: EthSpec> LightClientBootstrap<E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> ForkVersionDeserialize for LightClientBootstrap<E> {
|
||||
fn deserialize_by_fork<'de, D: Deserializer<'de>>(
|
||||
value: Value,
|
||||
fork_name: ForkName,
|
||||
) -> Result<Self, D::Error> {
|
||||
if fork_name.altair_enabled() {
|
||||
Ok(serde_json::from_value::<LightClientBootstrap<E>>(value)
|
||||
.map_err(serde::de::Error::custom))?
|
||||
} else {
|
||||
Err(serde::de::Error::custom(format!(
|
||||
"LightClientBootstrap failed to deserialize: unsupported fork '{}'",
|
||||
fork_name
|
||||
)))
|
||||
}
|
||||
impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for LightClientBootstrap<E> {
|
||||
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let convert_err = |e| {
|
||||
serde::de::Error::custom(format!(
|
||||
"LightClientBootstrap failed to deserialize: {:?}",
|
||||
e
|
||||
))
|
||||
};
|
||||
Ok(match context {
|
||||
ForkName::Base => {
|
||||
return Err(serde::de::Error::custom(format!(
|
||||
"LightClientBootstrap failed to deserialize: unsupported fork '{}'",
|
||||
context
|
||||
)))
|
||||
}
|
||||
ForkName::Altair | ForkName::Bellatrix => {
|
||||
Self::Altair(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Capella => {
|
||||
Self::Capella(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Deneb => {
|
||||
Self::Deneb(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Electra | ForkName::Eip7805 => {
|
||||
Self::Electra(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Fulu => {
|
||||
Self::Fulu(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use super::{EthSpec, FixedVector, Hash256, LightClientHeader, Slot, SyncAggregate};
|
||||
use crate::context_deserialize;
|
||||
use crate::ChainSpec;
|
||||
use crate::{
|
||||
light_client_update::*, test_utils::TestRandom, ForkName, ForkVersionDeserialize,
|
||||
light_client_update::*, test_utils::TestRandom, ContextDeserialize, ForkName,
|
||||
LightClientHeaderAltair, LightClientHeaderCapella, LightClientHeaderDeneb,
|
||||
LightClientHeaderElectra, LightClientHeaderFulu, SignedBlindedBeaconBlock,
|
||||
};
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use serde_json::Value;
|
||||
use ssz::{Decode, Encode};
|
||||
use ssz_derive::Decode;
|
||||
use ssz_derive::Encode;
|
||||
@@ -33,11 +33,10 @@ use tree_hash_derive::TreeHash;
|
||||
),
|
||||
serde(bound = "E: EthSpec", deny_unknown_fields),
|
||||
arbitrary(bound = "E: EthSpec"),
|
||||
context_deserialize(ForkName),
|
||||
)
|
||||
)]
|
||||
#[derive(
|
||||
Debug, Clone, Serialize, Encode, TreeHash, Deserialize, arbitrary::Arbitrary, PartialEq,
|
||||
)]
|
||||
#[derive(Debug, Clone, Serialize, Encode, TreeHash, arbitrary::Arbitrary, PartialEq)]
|
||||
#[serde(untagged)]
|
||||
#[tree_hash(enum_behaviour = "transparent")]
|
||||
#[ssz(enum_behaviour = "transparent")]
|
||||
@@ -237,20 +236,40 @@ impl<E: EthSpec> LightClientFinalityUpdate<E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> ForkVersionDeserialize for LightClientFinalityUpdate<E> {
|
||||
fn deserialize_by_fork<'de, D: Deserializer<'de>>(
|
||||
value: Value,
|
||||
fork_name: ForkName,
|
||||
) -> Result<Self, D::Error> {
|
||||
if fork_name.altair_enabled() {
|
||||
serde_json::from_value::<LightClientFinalityUpdate<E>>(value)
|
||||
.map_err(serde::de::Error::custom)
|
||||
} else {
|
||||
Err(serde::de::Error::custom(format!(
|
||||
"LightClientFinalityUpdate failed to deserialize: unsupported fork '{}'",
|
||||
fork_name
|
||||
)))
|
||||
}
|
||||
impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for LightClientFinalityUpdate<E> {
|
||||
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let convert_err = |e| {
|
||||
serde::de::Error::custom(format!(
|
||||
"LightClientFinalityUpdate failed to deserialize: {:?}",
|
||||
e
|
||||
))
|
||||
};
|
||||
Ok(match context {
|
||||
ForkName::Base => {
|
||||
return Err(serde::de::Error::custom(format!(
|
||||
"LightClientFinalityUpdate failed to deserialize: unsupported fork '{}'",
|
||||
context
|
||||
)))
|
||||
}
|
||||
ForkName::Altair | ForkName::Bellatrix => {
|
||||
Self::Altair(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Capella => {
|
||||
Self::Capella(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Deneb => {
|
||||
Self::Deneb(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Electra | ForkName::Eip7805 => {
|
||||
Self::Electra(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Fulu => {
|
||||
Self::Fulu(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use crate::context_deserialize;
|
||||
use crate::ChainSpec;
|
||||
use crate::ForkName;
|
||||
use crate::ForkVersionDeserialize;
|
||||
use crate::{light_client_update::*, BeaconBlockBody};
|
||||
use crate::{
|
||||
test_utils::TestRandom, EthSpec, ExecutionPayloadHeaderCapella, ExecutionPayloadHeaderDeneb,
|
||||
@@ -8,8 +7,9 @@ use crate::{
|
||||
SignedBlindedBeaconBlock,
|
||||
};
|
||||
use crate::{BeaconBlockHeader, ExecutionPayloadHeader};
|
||||
use crate::{ContextDeserialize, ForkName};
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use ssz::Decode;
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use std::marker::PhantomData;
|
||||
@@ -35,11 +35,10 @@ use tree_hash_derive::TreeHash;
|
||||
),
|
||||
serde(bound = "E: EthSpec", deny_unknown_fields),
|
||||
arbitrary(bound = "E: EthSpec"),
|
||||
context_deserialize(ForkName),
|
||||
)
|
||||
)]
|
||||
#[derive(
|
||||
Debug, Clone, Serialize, TreeHash, Encode, Deserialize, arbitrary::Arbitrary, PartialEq,
|
||||
)]
|
||||
#[derive(Debug, Clone, Serialize, TreeHash, Encode, arbitrary::Arbitrary, PartialEq)]
|
||||
#[serde(untagged)]
|
||||
#[tree_hash(enum_behaviour = "transparent")]
|
||||
#[ssz(enum_behaviour = "transparent")]
|
||||
@@ -334,31 +333,40 @@ impl<E: EthSpec> Default for LightClientHeaderFulu<E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> ForkVersionDeserialize for LightClientHeader<E> {
|
||||
fn deserialize_by_fork<'de, D: serde::Deserializer<'de>>(
|
||||
value: serde_json::value::Value,
|
||||
fork_name: ForkName,
|
||||
) -> Result<Self, D::Error> {
|
||||
match fork_name {
|
||||
ForkName::Altair | ForkName::Bellatrix => serde_json::from_value(value)
|
||||
.map(|light_client_header| Self::Altair(light_client_header))
|
||||
.map_err(serde::de::Error::custom),
|
||||
ForkName::Capella => serde_json::from_value(value)
|
||||
.map(|light_client_header| Self::Capella(light_client_header))
|
||||
.map_err(serde::de::Error::custom),
|
||||
ForkName::Deneb => serde_json::from_value(value)
|
||||
.map(|light_client_header| Self::Deneb(light_client_header))
|
||||
.map_err(serde::de::Error::custom),
|
||||
ForkName::Electra | ForkName::Eip7805 => serde_json::from_value(value)
|
||||
.map(|light_client_header| Self::Electra(light_client_header))
|
||||
.map_err(serde::de::Error::custom),
|
||||
ForkName::Fulu => serde_json::from_value(value)
|
||||
.map(|light_client_header| Self::Fulu(light_client_header))
|
||||
.map_err(serde::de::Error::custom),
|
||||
ForkName::Base => Err(serde::de::Error::custom(format!(
|
||||
"LightClientHeader deserialization for {fork_name} not implemented"
|
||||
))),
|
||||
}
|
||||
impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for LightClientHeader<E> {
|
||||
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let convert_err = |e| {
|
||||
serde::de::Error::custom(format!(
|
||||
"LightClientFinalityUpdate failed to deserialize: {:?}",
|
||||
e
|
||||
))
|
||||
};
|
||||
Ok(match context {
|
||||
ForkName::Base => {
|
||||
return Err(serde::de::Error::custom(format!(
|
||||
"LightClientFinalityUpdate failed to deserialize: unsupported fork '{}'",
|
||||
context
|
||||
)))
|
||||
}
|
||||
ForkName::Altair | ForkName::Bellatrix => {
|
||||
Self::Altair(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Capella => {
|
||||
Self::Capella(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Deneb => {
|
||||
Self::Deneb(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Electra | ForkName::Eip7805 => {
|
||||
Self::Electra(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Fulu => {
|
||||
Self::Fulu(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use super::{EthSpec, ForkName, ForkVersionDeserialize, LightClientHeader, Slot, SyncAggregate};
|
||||
use super::{ContextDeserialize, EthSpec, ForkName, LightClientHeader, Slot, SyncAggregate};
|
||||
use crate::context_deserialize;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::{
|
||||
light_client_update::*, ChainSpec, LightClientHeaderAltair, LightClientHeaderCapella,
|
||||
@@ -7,7 +8,6 @@ use crate::{
|
||||
};
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use serde_json::Value;
|
||||
use ssz::{Decode, Encode};
|
||||
use ssz_derive::Decode;
|
||||
use ssz_derive::Encode;
|
||||
@@ -36,11 +36,10 @@ use tree_hash_derive::TreeHash;
|
||||
),
|
||||
serde(bound = "E: EthSpec", deny_unknown_fields),
|
||||
arbitrary(bound = "E: EthSpec"),
|
||||
context_deserialize(ForkName),
|
||||
)
|
||||
)]
|
||||
#[derive(
|
||||
Debug, Clone, Serialize, Encode, TreeHash, Deserialize, arbitrary::Arbitrary, PartialEq,
|
||||
)]
|
||||
#[derive(Debug, Clone, Serialize, Encode, TreeHash, arbitrary::Arbitrary, PartialEq)]
|
||||
#[serde(untagged)]
|
||||
#[tree_hash(enum_behaviour = "transparent")]
|
||||
#[ssz(enum_behaviour = "transparent")]
|
||||
@@ -210,22 +209,40 @@ impl<E: EthSpec> LightClientOptimisticUpdate<E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> ForkVersionDeserialize for LightClientOptimisticUpdate<E> {
|
||||
fn deserialize_by_fork<'de, D: Deserializer<'de>>(
|
||||
value: Value,
|
||||
fork_name: ForkName,
|
||||
) -> Result<Self, D::Error> {
|
||||
if fork_name.altair_enabled() {
|
||||
Ok(
|
||||
serde_json::from_value::<LightClientOptimisticUpdate<E>>(value)
|
||||
.map_err(serde::de::Error::custom),
|
||||
)?
|
||||
} else {
|
||||
Err(serde::de::Error::custom(format!(
|
||||
"LightClientOptimisticUpdate failed to deserialize: unsupported fork '{}'",
|
||||
fork_name
|
||||
)))
|
||||
}
|
||||
impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for LightClientOptimisticUpdate<E> {
|
||||
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let convert_err = |e| {
|
||||
serde::de::Error::custom(format!(
|
||||
"LightClientOptimisticUpdate failed to deserialize: {:?}",
|
||||
e
|
||||
))
|
||||
};
|
||||
Ok(match context {
|
||||
ForkName::Base => {
|
||||
return Err(serde::de::Error::custom(format!(
|
||||
"LightClientOptimisticUpdate failed to deserialize: unsupported fork '{}'",
|
||||
context
|
||||
)))
|
||||
}
|
||||
ForkName::Altair | ForkName::Bellatrix => {
|
||||
Self::Altair(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Capella => {
|
||||
Self::Capella(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Deneb => {
|
||||
Self::Deneb(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Electra | ForkName::Eip7805 => {
|
||||
Self::Electra(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Fulu => {
|
||||
Self::Fulu(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use super::{EthSpec, FixedVector, Hash256, Slot, SyncAggregate, SyncCommittee};
|
||||
use crate::context_deserialize;
|
||||
use crate::light_client_header::LightClientHeaderElectra;
|
||||
use crate::LightClientHeader;
|
||||
use crate::{
|
||||
beacon_state, test_utils::TestRandom, ChainSpec, Epoch, ForkName, ForkVersionDeserialize,
|
||||
beacon_state, test_utils::TestRandom, ChainSpec, ContextDeserialize, Epoch, ForkName,
|
||||
LightClientHeaderAltair, LightClientHeaderCapella, LightClientHeaderDeneb,
|
||||
LightClientHeaderFulu, SignedBlindedBeaconBlock,
|
||||
};
|
||||
@@ -10,7 +11,6 @@ use derivative::Derivative;
|
||||
use safe_arith::ArithError;
|
||||
use safe_arith::SafeArith;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use serde_json::Value;
|
||||
use ssz::{Decode, Encode};
|
||||
use ssz_derive::Decode;
|
||||
use ssz_derive::Encode;
|
||||
@@ -117,11 +117,10 @@ impl From<milhouse::Error> for Error {
|
||||
),
|
||||
serde(bound = "E: EthSpec", deny_unknown_fields),
|
||||
arbitrary(bound = "E: EthSpec"),
|
||||
context_deserialize(ForkName),
|
||||
)
|
||||
)]
|
||||
#[derive(
|
||||
Debug, Clone, Serialize, Encode, TreeHash, Deserialize, arbitrary::Arbitrary, PartialEq,
|
||||
)]
|
||||
#[derive(Debug, Clone, Serialize, Encode, TreeHash, arbitrary::Arbitrary, PartialEq)]
|
||||
#[serde(untagged)]
|
||||
#[tree_hash(enum_behaviour = "transparent")]
|
||||
#[ssz(enum_behaviour = "transparent")]
|
||||
@@ -180,19 +179,37 @@ pub struct LightClientUpdate<E: EthSpec> {
|
||||
pub signature_slot: Slot,
|
||||
}
|
||||
|
||||
impl<E: EthSpec> ForkVersionDeserialize for LightClientUpdate<E> {
|
||||
fn deserialize_by_fork<'de, D: Deserializer<'de>>(
|
||||
value: Value,
|
||||
fork_name: ForkName,
|
||||
) -> Result<Self, D::Error> {
|
||||
match fork_name {
|
||||
ForkName::Base => Err(serde::de::Error::custom(format!(
|
||||
"LightClientUpdate failed to deserialize: unsupported fork '{}'",
|
||||
fork_name
|
||||
))),
|
||||
_ => Ok(serde_json::from_value::<LightClientUpdate<E>>(value)
|
||||
.map_err(serde::de::Error::custom))?,
|
||||
}
|
||||
impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for LightClientUpdate<E> {
|
||||
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let convert_err = |e| {
|
||||
serde::de::Error::custom(format!("LightClientUpdate failed to deserialize: {:?}", e))
|
||||
};
|
||||
Ok(match context {
|
||||
ForkName::Base => {
|
||||
return Err(serde::de::Error::custom(format!(
|
||||
"LightClientUpdate failed to deserialize: unsupported fork '{}'",
|
||||
context
|
||||
)))
|
||||
}
|
||||
ForkName::Altair | ForkName::Bellatrix => {
|
||||
Self::Altair(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Capella => {
|
||||
Self::Capella(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Deneb => {
|
||||
Self::Deneb(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Electra | ForkName::Eip7805 => {
|
||||
Self::Electra(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Fulu => {
|
||||
Self::Fulu(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +86,7 @@ pub trait AbstractExecPayload<E: EthSpec>:
|
||||
+ TryInto<Self::Electra>
|
||||
+ TryInto<Self::Eip7805>
|
||||
+ TryInto<Self::Fulu>
|
||||
+ Sync
|
||||
{
|
||||
type Ref<'a>: ExecPayload<E>
|
||||
+ Copy
|
||||
@@ -99,27 +100,33 @@ pub trait AbstractExecPayload<E: EthSpec>:
|
||||
type Bellatrix: OwnedExecPayload<E>
|
||||
+ Into<Self>
|
||||
+ for<'a> From<Cow<'a, ExecutionPayloadBellatrix<E>>>
|
||||
+ TryFrom<ExecutionPayloadHeaderBellatrix<E>>;
|
||||
+ TryFrom<ExecutionPayloadHeaderBellatrix<E>>
|
||||
+ Sync;
|
||||
type Capella: OwnedExecPayload<E>
|
||||
+ Into<Self>
|
||||
+ for<'a> From<Cow<'a, ExecutionPayloadCapella<E>>>
|
||||
+ TryFrom<ExecutionPayloadHeaderCapella<E>>;
|
||||
+ TryFrom<ExecutionPayloadHeaderCapella<E>>
|
||||
+ Sync;
|
||||
type Deneb: OwnedExecPayload<E>
|
||||
+ Into<Self>
|
||||
+ for<'a> From<Cow<'a, ExecutionPayloadDeneb<E>>>
|
||||
+ TryFrom<ExecutionPayloadHeaderDeneb<E>>;
|
||||
+ TryFrom<ExecutionPayloadHeaderDeneb<E>>
|
||||
+ Sync;
|
||||
type Electra: OwnedExecPayload<E>
|
||||
+ Into<Self>
|
||||
+ for<'a> From<Cow<'a, ExecutionPayloadElectra<E>>>
|
||||
+ TryFrom<ExecutionPayloadHeaderElectra<E>>;
|
||||
+ TryFrom<ExecutionPayloadHeaderElectra<E>>
|
||||
+ Sync;
|
||||
type Eip7805: OwnedExecPayload<E>
|
||||
+ Into<Self>
|
||||
+ for<'a> From<Cow<'a, ExecutionPayloadEip7805<E>>>
|
||||
+ TryFrom<ExecutionPayloadHeaderEip7805<E>>;
|
||||
+ TryFrom<ExecutionPayloadHeaderEip7805<E>>
|
||||
+ Sync;
|
||||
type Fulu: OwnedExecPayload<E>
|
||||
+ Into<Self>
|
||||
+ for<'a> From<Cow<'a, ExecutionPayloadFulu<E>>>
|
||||
+ TryFrom<ExecutionPayloadHeaderFulu<E>>;
|
||||
+ TryFrom<ExecutionPayloadHeaderFulu<E>>
|
||||
+ Sync;
|
||||
}
|
||||
|
||||
#[superstruct(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::context_deserialize;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::{AttestationData, BitList, EthSpec};
|
||||
|
||||
use crate::{AttestationData, BitList, EthSpec, ForkName};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use test_random_derive::TestRandom;
|
||||
@@ -22,6 +22,7 @@ use tree_hash_derive::TreeHash;
|
||||
arbitrary::Arbitrary,
|
||||
)]
|
||||
#[arbitrary(bound = "E: EthSpec")]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct PendingAttestation<E: EthSpec> {
|
||||
pub aggregation_bits: BitList<E::MaxValidatorsPerCommittee>,
|
||||
pub data: AttestationData,
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
use crate::context_deserialize;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::ForkName;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use test_random_derive::TestRandom;
|
||||
@@ -18,6 +20,7 @@ use tree_hash_derive::TreeHash;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct PendingConsolidation {
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub source_index: u64,
|
||||
|
||||
@@ -18,6 +18,7 @@ use tree_hash_derive::TreeHash;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct PendingDeposit {
|
||||
pub pubkey: PublicKeyBytes,
|
||||
pub withdrawal_credentials: Hash256,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::context_deserialize;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::Epoch;
|
||||
use crate::{Epoch, ForkName};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use test_random_derive::TestRandom;
|
||||
@@ -19,6 +20,7 @@ use tree_hash_derive::TreeHash;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct PendingPartialWithdrawal {
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub validator_index: u64,
|
||||
|
||||
@@ -227,28 +227,36 @@ pub struct ElectraPreset {
|
||||
pub min_activation_balance: u64,
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub max_effective_balance_electra: u64,
|
||||
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub min_slashing_penalty_quotient_electra: u64,
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub whistleblower_reward_quotient_electra: u64,
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub max_pending_partials_per_withdrawals_sweep: u64,
|
||||
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub pending_deposits_limit: u64,
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub pending_partial_withdrawals_limit: u64,
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub pending_consolidations_limit: u64,
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub max_consolidation_requests_per_payload: u64,
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub max_deposit_requests_per_payload: u64,
|
||||
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub max_attester_slashings_electra: u64,
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub max_attestations_electra: u64,
|
||||
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub max_deposit_requests_per_payload: u64,
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub max_withdrawal_requests_per_payload: u64,
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub max_consolidation_requests_per_payload: u64,
|
||||
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub max_pending_partials_per_withdrawals_sweep: u64,
|
||||
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub max_pending_deposits_per_epoch: u64,
|
||||
}
|
||||
|
||||
impl ElectraPreset {
|
||||
@@ -256,19 +264,26 @@ impl ElectraPreset {
|
||||
Self {
|
||||
min_activation_balance: spec.min_activation_balance,
|
||||
max_effective_balance_electra: spec.max_effective_balance_electra,
|
||||
|
||||
min_slashing_penalty_quotient_electra: spec.min_slashing_penalty_quotient_electra,
|
||||
whistleblower_reward_quotient_electra: spec.whistleblower_reward_quotient_electra,
|
||||
max_pending_partials_per_withdrawals_sweep: spec
|
||||
.max_pending_partials_per_withdrawals_sweep,
|
||||
|
||||
pending_deposits_limit: E::pending_deposits_limit() as u64,
|
||||
pending_partial_withdrawals_limit: E::pending_partial_withdrawals_limit() as u64,
|
||||
pending_consolidations_limit: E::pending_consolidations_limit() as u64,
|
||||
max_consolidation_requests_per_payload: E::max_consolidation_requests_per_payload()
|
||||
as u64,
|
||||
max_deposit_requests_per_payload: E::max_deposit_requests_per_payload() as u64,
|
||||
|
||||
max_attester_slashings_electra: E::max_attester_slashings_electra() as u64,
|
||||
max_attestations_electra: E::max_attestations_electra() as u64,
|
||||
|
||||
max_deposit_requests_per_payload: E::max_deposit_requests_per_payload() as u64,
|
||||
max_withdrawal_requests_per_payload: E::max_withdrawal_requests_per_payload() as u64,
|
||||
max_consolidation_requests_per_payload: E::max_consolidation_requests_per_payload()
|
||||
as u64,
|
||||
|
||||
max_pending_partials_per_withdrawals_sweep: spec
|
||||
.max_pending_partials_per_withdrawals_sweep,
|
||||
|
||||
max_pending_deposits_per_epoch: E::max_pending_deposits_per_epoch() as u64,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::context_deserialize;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::SignedBeaconBlockHeader;
|
||||
use crate::{ForkName, SignedBeaconBlockHeader};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
@@ -23,6 +24,7 @@ use tree_hash_derive::TreeHash;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct ProposerSlashing {
|
||||
pub signed_header_1: SignedBeaconBlockHeader,
|
||||
pub signed_header_2: SignedBeaconBlockHeader,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
use crate::ContextDeserialize;
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::de::Error as DeError;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use ssz::Decode;
|
||||
use ssz_types::Error;
|
||||
use std::ops::{Deref, Index, IndexMut};
|
||||
@@ -217,6 +219,28 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, C, T> ContextDeserialize<'de, (C, usize)> for RuntimeVariableList<T>
|
||||
where
|
||||
T: ContextDeserialize<'de, C>,
|
||||
C: Clone,
|
||||
{
|
||||
fn context_deserialize<D>(deserializer: D, context: (C, usize)) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
// first parse out a Vec<C> using the Vec<C> impl you already have
|
||||
let vec: Vec<T> = Vec::context_deserialize(deserializer, context.0)?;
|
||||
if vec.len() > context.1 {
|
||||
return Err(DeError::custom(format!(
|
||||
"RuntimeVariableList lengh {} exceeds max_len {}",
|
||||
vec.len(),
|
||||
context.1
|
||||
)));
|
||||
}
|
||||
Ok(RuntimeVariableList::from_vec(vec, context.1))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
@@ -2,11 +2,11 @@ use super::{
|
||||
AggregateAndProof, AggregateAndProofBase, AggregateAndProofElectra, AggregateAndProofRef,
|
||||
};
|
||||
use super::{
|
||||
AttestationRef, ChainSpec, Domain, EthSpec, Fork, Hash256, SecretKey, SelectionProof,
|
||||
Signature, SignedRoot,
|
||||
Attestation, AttestationRef, ChainSpec, Domain, EthSpec, Fork, ForkName, Hash256, SecretKey,
|
||||
SelectionProof, Signature, SignedRoot,
|
||||
};
|
||||
use crate::context_deserialize;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::Attestation;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use superstruct::superstruct;
|
||||
@@ -32,6 +32,7 @@ use tree_hash_derive::TreeHash;
|
||||
TestRandom,
|
||||
TreeHash,
|
||||
),
|
||||
context_deserialize(ForkName),
|
||||
serde(bound = "E: EthSpec"),
|
||||
arbitrary(bound = "E: EthSpec"),
|
||||
),
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
use crate::beacon_block_body::{format_kzg_commitments, BLOB_KZG_COMMITMENTS_INDEX};
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::*;
|
||||
use derivative::Derivative;
|
||||
use merkle_proof::MerkleTree;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use std::fmt;
|
||||
use superstruct::superstruct;
|
||||
use test_random_derive::TestRandom;
|
||||
use tree_hash::TreeHash;
|
||||
use tree_hash_derive::TreeHash;
|
||||
|
||||
@@ -49,7 +51,8 @@ impl From<SignedBeaconBlockHash> for Hash256 {
|
||||
Decode,
|
||||
TreeHash,
|
||||
Derivative,
|
||||
arbitrary::Arbitrary
|
||||
arbitrary::Arbitrary,
|
||||
TestRandom
|
||||
),
|
||||
derivative(PartialEq, Hash(bound = "E: EthSpec")),
|
||||
serde(bound = "E: EthSpec, Payload: AbstractExecPayload<E>"),
|
||||
@@ -767,20 +770,17 @@ impl<E: EthSpec> SignedBeaconBlock<E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec, Payload: AbstractExecPayload<E>> ForkVersionDeserialize
|
||||
impl<'de, E: EthSpec, Payload: AbstractExecPayload<E>> ContextDeserialize<'de, ForkName>
|
||||
for SignedBeaconBlock<E, Payload>
|
||||
{
|
||||
fn deserialize_by_fork<'de, D: serde::Deserializer<'de>>(
|
||||
value: serde_json::value::Value,
|
||||
fork_name: ForkName,
|
||||
) -> Result<Self, D::Error> {
|
||||
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
Ok(map_fork_name!(
|
||||
fork_name,
|
||||
context,
|
||||
Self,
|
||||
serde_json::from_value(value).map_err(|e| serde::de::Error::custom(format!(
|
||||
"SignedBeaconBlock failed to deserialize: {:?}",
|
||||
e
|
||||
)))?
|
||||
serde::Deserialize::deserialize(deserializer)?
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::context_deserialize;
|
||||
use crate::{
|
||||
test_utils::TestRandom, BeaconBlockHeader, ChainSpec, Domain, EthSpec, Fork, Hash256,
|
||||
test_utils::TestRandom, BeaconBlockHeader, ChainSpec, Domain, EthSpec, Fork, ForkName, Hash256,
|
||||
PublicKey, Signature, SignedRoot,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -24,6 +25,7 @@ use tree_hash_derive::TreeHash;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct SignedBeaconBlockHeader {
|
||||
pub message: BeaconBlockHeader,
|
||||
pub signature: Signature,
|
||||
|
||||
@@ -19,6 +19,7 @@ use tree_hash_derive::TreeHash;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct SignedBlsToExecutionChange {
|
||||
pub message: BlsToExecutionChange,
|
||||
pub signature: Signature,
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use super::{
|
||||
ChainSpec, ContributionAndProof, Domain, EthSpec, Fork, Hash256, SecretKey, Signature,
|
||||
SignedRoot, SyncCommitteeContribution, SyncSelectionProof,
|
||||
ChainSpec, ContributionAndProof, Domain, EthSpec, Fork, ForkName, Hash256, SecretKey,
|
||||
Signature, SignedRoot, SyncCommitteeContribution, SyncSelectionProof,
|
||||
};
|
||||
use crate::context_deserialize;
|
||||
use crate::test_utils::TestRandom;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
@@ -24,6 +25,7 @@ use tree_hash_derive::TreeHash;
|
||||
)]
|
||||
#[serde(bound = "E: EthSpec")]
|
||||
#[arbitrary(bound = "E: EthSpec")]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct SignedContributionAndProof<E: EthSpec> {
|
||||
/// The `ContributionAndProof` that was signed.
|
||||
pub message: ContributionAndProof<E>,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::{test_utils::TestRandom, VoluntaryExit};
|
||||
use crate::context_deserialize;
|
||||
use crate::{test_utils::TestRandom, ForkName, VoluntaryExit};
|
||||
use bls::Signature;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -22,6 +23,7 @@ use tree_hash_derive::TreeHash;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct SignedVoluntaryExit {
|
||||
pub message: VoluntaryExit,
|
||||
pub signature: Signature,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::context_deserialize;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::Hash256;
|
||||
use crate::{ForkName, Hash256};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
@@ -19,6 +20,7 @@ use tree_hash_derive::TreeHash;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct SigningData {
|
||||
pub object_root: Hash256,
|
||||
pub domain: Hash256,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::consts::altair::SYNC_COMMITTEE_SUBNET_COUNT;
|
||||
use crate::context_deserialize;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::{AggregateSignature, BitVector, EthSpec, SyncCommitteeContribution};
|
||||
use crate::{AggregateSignature, BitVector, EthSpec, ForkName, SyncCommitteeContribution};
|
||||
use derivative::Derivative;
|
||||
use safe_arith::{ArithError, SafeArith};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -36,6 +37,7 @@ impl From<ArithError> for Error {
|
||||
#[derivative(PartialEq, Hash(bound = "E: EthSpec"))]
|
||||
#[serde(bound = "E: EthSpec")]
|
||||
#[arbitrary(bound = "E: EthSpec")]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct SyncAggregate<E: EthSpec> {
|
||||
pub sync_committee_bits: BitVector<E::SyncCommitteeSize>,
|
||||
pub sync_committee_signature: AggregateSignature,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::context_deserialize;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::{SignedRoot, Slot};
|
||||
|
||||
use crate::{ForkName, SignedRoot, Slot};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use test_random_derive::TestRandom;
|
||||
@@ -19,6 +19,7 @@ use tree_hash_derive::TreeHash;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct SyncAggregatorSelectionData {
|
||||
pub slot: Slot,
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::context_deserialize;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::{EthSpec, FixedVector, SyncSubnetId};
|
||||
use crate::{EthSpec, FixedVector, ForkName, SyncSubnetId};
|
||||
use bls::PublicKeyBytes;
|
||||
use safe_arith::{ArithError, SafeArith};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -38,6 +39,7 @@ impl From<ArithError> for Error {
|
||||
)]
|
||||
#[serde(bound = "E: EthSpec")]
|
||||
#[arbitrary(bound = "E: EthSpec")]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct SyncCommittee<E: EthSpec> {
|
||||
pub pubkeys: FixedVector<PublicKeyBytes, E::SyncCommitteeSize>,
|
||||
pub aggregate_pubkey: PublicKeyBytes,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use super::{AggregateSignature, EthSpec, SignedRoot};
|
||||
use super::{AggregateSignature, EthSpec, ForkName, SignedRoot};
|
||||
use crate::context_deserialize;
|
||||
use crate::slot_data::SlotData;
|
||||
use crate::{test_utils::TestRandom, BitVector, Hash256, Slot, SyncCommitteeMessage};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -28,6 +29,7 @@ pub enum Error {
|
||||
)]
|
||||
#[serde(bound = "E: EthSpec")]
|
||||
#[arbitrary(bound = "E: EthSpec")]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct SyncCommitteeContribution<E: EthSpec> {
|
||||
pub slot: Slot,
|
||||
pub beacon_block_root: Hash256,
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::{ChainSpec, Domain, EthSpec, Fork, Hash256, SecretKey, Signature, SignedRoot, Slot};
|
||||
|
||||
use crate::context_deserialize;
|
||||
use crate::slot_data::SlotData;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::{
|
||||
ChainSpec, Domain, EthSpec, Fork, ForkName, Hash256, SecretKey, Signature, SignedRoot, Slot,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use test_random_derive::TestRandom;
|
||||
@@ -20,6 +22,7 @@ use tree_hash_derive::TreeHash;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct SyncCommitteeMessage {
|
||||
pub slot: Slot,
|
||||
pub beacon_block_root: Hash256,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::context_deserialize;
|
||||
use crate::{
|
||||
test_utils::TestRandom, Address, BeaconState, ChainSpec, Checkpoint, Epoch, EthSpec,
|
||||
FixedBytesExtended, ForkName, Hash256, PublicKeyBytes,
|
||||
@@ -23,6 +24,7 @@ use tree_hash_derive::TreeHash;
|
||||
TestRandom,
|
||||
TreeHash,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct Validator {
|
||||
pub pubkey: PublicKeyBytes,
|
||||
pub withdrawal_credentials: Hash256,
|
||||
@@ -249,7 +251,6 @@ impl Validator {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO(electra): refactor these functions and make it simpler.. this is a mess
|
||||
/// Returns `true` if the validator is partially withdrawable.
|
||||
fn is_partially_withdrawable_validator_capella(&self, balance: u64, spec: &ChainSpec) -> bool {
|
||||
self.has_eth1_withdrawal_credential(spec)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::context_deserialize;
|
||||
use crate::{
|
||||
test_utils::TestRandom, ChainSpec, Domain, Epoch, ForkName, Hash256, SecretKey, SignedRoot,
|
||||
SignedVoluntaryExit,
|
||||
@@ -24,6 +25,7 @@ use tree_hash_derive::TreeHash;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct VoluntaryExit {
|
||||
/// Earliest epoch when voluntary exit can be processed.
|
||||
pub epoch: Epoch,
|
||||
@@ -40,6 +42,16 @@ impl VoluntaryExit {
|
||||
genesis_validators_root: Hash256,
|
||||
spec: &ChainSpec,
|
||||
) -> SignedVoluntaryExit {
|
||||
let domain = self.get_domain(genesis_validators_root, spec);
|
||||
|
||||
let message = self.signing_root(domain);
|
||||
SignedVoluntaryExit {
|
||||
message: self,
|
||||
signature: secret_key.sign(message),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_domain(&self, genesis_validators_root: Hash256, spec: &ChainSpec) -> Hash256 {
|
||||
let fork_name = spec.fork_name_at_epoch(self.epoch);
|
||||
let fork_version = if fork_name.deneb_enabled() {
|
||||
// EIP-7044
|
||||
@@ -47,14 +59,7 @@ impl VoluntaryExit {
|
||||
} else {
|
||||
spec.fork_version_for_name(fork_name)
|
||||
};
|
||||
let domain =
|
||||
spec.compute_domain(Domain::VoluntaryExit, fork_version, genesis_validators_root);
|
||||
|
||||
let message = self.signing_root(domain);
|
||||
SignedVoluntaryExit {
|
||||
message: self,
|
||||
signature: secret_key.sign(message),
|
||||
}
|
||||
spec.compute_domain(Domain::VoluntaryExit, fork_version, genesis_validators_root)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ use tree_hash_derive::TreeHash;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct Withdrawal {
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub index: u64,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::context_deserialize;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::{Address, PublicKeyBytes};
|
||||
use crate::{Address, ForkName, PublicKeyBytes};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz::Encode;
|
||||
use ssz_derive::{Decode, Encode};
|
||||
@@ -20,6 +21,7 @@ use tree_hash_derive::TreeHash;
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[context_deserialize(ForkName)]
|
||||
pub struct WithdrawalRequest {
|
||||
#[serde(with = "serde_utils::address_hex")]
|
||||
pub source_address: Address,
|
||||
|
||||
Reference in New Issue
Block a user