mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-20 21:34:46 +00:00
Merge branch 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-engine-api
This commit is contained in:
@@ -33,7 +33,8 @@ use tree_hash_derive::TreeHash;
|
||||
derive(Debug, PartialEq, TreeHash, Serialize,),
|
||||
serde(untagged, bound = "E: EthSpec"),
|
||||
tree_hash(enum_behaviour = "transparent")
|
||||
)
|
||||
),
|
||||
map_ref_into(AttestationRef)
|
||||
)]
|
||||
#[derive(
|
||||
arbitrary::Arbitrary, Debug, Clone, PartialEq, Serialize, Deserialize, Encode, TreeHash,
|
||||
@@ -59,19 +60,17 @@ pub struct AggregateAndProof<E: EthSpec> {
|
||||
impl<'a, E: EthSpec> AggregateAndProofRef<'a, E> {
|
||||
/// Returns `true` if `validator_pubkey` signed over `self.aggregate.data.slot`.
|
||||
pub fn aggregate(self) -> AttestationRef<'a, E> {
|
||||
match self {
|
||||
AggregateAndProofRef::Base(a) => AttestationRef::Base(&a.aggregate),
|
||||
AggregateAndProofRef::Electra(a) => AttestationRef::Electra(&a.aggregate),
|
||||
}
|
||||
map_aggregate_and_proof_ref_into_attestation_ref!(&'a _, self, |inner, cons| {
|
||||
cons(&inner.aggregate)
|
||||
})
|
||||
}
|
||||
}
|
||||
impl<E: EthSpec> AggregateAndProof<E> {
|
||||
/// Returns `true` if `validator_pubkey` signed over `self.aggregate.data.slot`.
|
||||
pub fn aggregate(&self) -> AttestationRef<E> {
|
||||
match self {
|
||||
AggregateAndProof::Base(a) => AttestationRef::Base(&a.aggregate),
|
||||
AggregateAndProof::Electra(a) => AttestationRef::Electra(&a.aggregate),
|
||||
}
|
||||
pub fn aggregate<'a>(&'a self) -> AttestationRef<'a, E> {
|
||||
map_aggregate_and_proof_ref_into_attestation_ref!(&'a _, self.to_ref(), |inner, cons| {
|
||||
cons(&inner.aggregate)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::slot_data::SlotData;
|
||||
use crate::Checkpoint;
|
||||
use crate::{test_utils::TestRandom, Hash256, Slot};
|
||||
use crate::{Checkpoint, ForkName};
|
||||
use derivative::Derivative;
|
||||
use safe_arith::ArithError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -99,7 +99,7 @@ impl<E: EthSpec> Attestation<E> {
|
||||
target: Checkpoint,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Self, Error> {
|
||||
if spec.fork_name_at_slot::<E>(slot) >= ForkName::Electra {
|
||||
if spec.fork_name_at_slot::<E>(slot).electra_enabled() {
|
||||
let mut committee_bits: BitVector<E::MaxCommitteesPerSlot> = BitVector::default();
|
||||
committee_bits
|
||||
.set(committee_index as usize, true)
|
||||
@@ -277,16 +277,6 @@ impl<'a, E: EthSpec> AttestationRef<'a, E> {
|
||||
}
|
||||
|
||||
impl<E: EthSpec> AttestationElectra<E> {
|
||||
/// Are the aggregation bitfields of these attestations disjoint?
|
||||
// TODO(electra): check whether the definition from CompactIndexedAttestation::should_aggregate
|
||||
// is useful where this is used, i.e. only consider attestations disjoint when their committees
|
||||
// match AND their aggregation bits do not intersect.
|
||||
pub fn signers_disjoint_from(&self, other: &Self) -> bool {
|
||||
self.aggregation_bits
|
||||
.intersection(&other.aggregation_bits)
|
||||
.is_zero()
|
||||
}
|
||||
|
||||
pub fn committee_index(&self) -> Option<u64> {
|
||||
self.get_committee_indices().first().cloned()
|
||||
}
|
||||
@@ -304,7 +294,6 @@ impl<E: EthSpec> AttestationElectra<E> {
|
||||
/// The aggregation bitfields must be disjoint, and the data must be the same.
|
||||
pub fn aggregate(&mut self, other: &Self) {
|
||||
debug_assert_eq!(self.data, other.data);
|
||||
debug_assert!(self.signers_disjoint_from(other));
|
||||
self.aggregation_bits = self.aggregation_bits.union(&other.aggregation_bits);
|
||||
self.signature.add_assign_aggregate(&other.signature);
|
||||
}
|
||||
@@ -358,19 +347,11 @@ impl<E: EthSpec> AttestationElectra<E> {
|
||||
}
|
||||
|
||||
impl<E: EthSpec> AttestationBase<E> {
|
||||
/// Are the aggregation bitfields of these attestations disjoint?
|
||||
pub fn signers_disjoint_from(&self, other: &Self) -> bool {
|
||||
self.aggregation_bits
|
||||
.intersection(&other.aggregation_bits)
|
||||
.is_zero()
|
||||
}
|
||||
|
||||
/// Aggregate another Attestation into this one.
|
||||
///
|
||||
/// The aggregation bitfields must be disjoint, and the data must be the same.
|
||||
pub fn aggregate(&mut self, other: &Self) {
|
||||
debug_assert_eq!(self.data, other.data);
|
||||
debug_assert!(self.signers_disjoint_from(other));
|
||||
self.aggregation_bits = self.aggregation_bits.union(&other.aggregation_bits);
|
||||
self.signature.add_assign_aggregate(&other.signature);
|
||||
}
|
||||
|
||||
@@ -118,12 +118,8 @@ impl<E: EthSpec> ExecutionPayloadHeader<E> {
|
||||
pub fn ssz_max_var_len_for_fork(fork_name: ForkName) -> usize {
|
||||
// Matching here in case variable fields are added in future forks.
|
||||
match fork_name {
|
||||
ForkName::Base
|
||||
| ForkName::Altair
|
||||
| ForkName::Bellatrix
|
||||
| ForkName::Capella
|
||||
| ForkName::Deneb
|
||||
| ForkName::Electra => {
|
||||
ForkName::Base | ForkName::Altair => 0,
|
||||
ForkName::Bellatrix | ForkName::Capella | ForkName::Deneb | ForkName::Electra => {
|
||||
// Max size of variable length `extra_data` field
|
||||
E::max_extra_data_bytes() * <u8 as Encode>::ssz_fixed_len()
|
||||
}
|
||||
|
||||
@@ -120,6 +120,10 @@ impl ForkName {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deneb_enabled(self) -> bool {
|
||||
self >= ForkName::Deneb
|
||||
}
|
||||
|
||||
pub fn electra_enabled(self) -> bool {
|
||||
self >= ForkName::Electra
|
||||
}
|
||||
|
||||
@@ -240,38 +240,6 @@ mod quoted_variable_list_u64 {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Encode, Decode, PartialEq)]
|
||||
#[ssz(enum_behaviour = "union")]
|
||||
pub enum IndexedAttestationOnDisk<E: EthSpec> {
|
||||
Base(IndexedAttestationBase<E>),
|
||||
Electra(IndexedAttestationElectra<E>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Encode, PartialEq)]
|
||||
#[ssz(enum_behaviour = "union")]
|
||||
pub enum IndexedAttestationRefOnDisk<'a, E: EthSpec> {
|
||||
Base(&'a IndexedAttestationBase<E>),
|
||||
Electra(&'a IndexedAttestationElectra<E>),
|
||||
}
|
||||
|
||||
impl<'a, E: EthSpec> From<&'a IndexedAttestation<E>> for IndexedAttestationRefOnDisk<'a, E> {
|
||||
fn from(attestation: &'a IndexedAttestation<E>) -> Self {
|
||||
match attestation {
|
||||
IndexedAttestation::Base(attestation) => Self::Base(attestation),
|
||||
IndexedAttestation::Electra(attestation) => Self::Electra(attestation),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<IndexedAttestationOnDisk<E>> for IndexedAttestation<E> {
|
||||
fn from(attestation: IndexedAttestationOnDisk<E>) -> Self {
|
||||
match attestation {
|
||||
IndexedAttestationOnDisk::Base(attestation) => Self::Base(attestation),
|
||||
IndexedAttestationOnDisk::Electra(attestation) => Self::Electra(attestation),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -176,27 +176,28 @@ pub use crate::fork_versioned_response::{ForkVersionDeserialize, ForkVersionedRe
|
||||
pub use crate::graffiti::{Graffiti, GRAFFITI_BYTES_LEN};
|
||||
pub use crate::historical_batch::HistoricalBatch;
|
||||
pub use crate::indexed_attestation::{
|
||||
IndexedAttestation, IndexedAttestationBase, IndexedAttestationElectra,
|
||||
IndexedAttestationOnDisk, IndexedAttestationRef, IndexedAttestationRefOnDisk,
|
||||
IndexedAttestation, IndexedAttestationBase, IndexedAttestationElectra, IndexedAttestationRef,
|
||||
};
|
||||
pub use crate::light_client_bootstrap::{
|
||||
LightClientBootstrap, LightClientBootstrapAltair, LightClientBootstrapCapella,
|
||||
LightClientBootstrapDeneb,
|
||||
LightClientBootstrapDeneb, LightClientBootstrapElectra,
|
||||
};
|
||||
pub use crate::light_client_finality_update::{
|
||||
LightClientFinalityUpdate, LightClientFinalityUpdateAltair, LightClientFinalityUpdateCapella,
|
||||
LightClientFinalityUpdateDeneb,
|
||||
LightClientFinalityUpdateDeneb, LightClientFinalityUpdateElectra,
|
||||
};
|
||||
pub use crate::light_client_header::{
|
||||
LightClientHeader, LightClientHeaderAltair, LightClientHeaderCapella, LightClientHeaderDeneb,
|
||||
LightClientHeaderElectra,
|
||||
};
|
||||
pub use crate::light_client_optimistic_update::{
|
||||
LightClientOptimisticUpdate, LightClientOptimisticUpdateAltair,
|
||||
LightClientOptimisticUpdateCapella, LightClientOptimisticUpdateDeneb,
|
||||
LightClientOptimisticUpdateElectra,
|
||||
};
|
||||
pub use crate::light_client_update::{
|
||||
Error as LightClientError, LightClientUpdate, LightClientUpdateAltair,
|
||||
LightClientUpdateCapella, LightClientUpdateDeneb,
|
||||
LightClientUpdateCapella, LightClientUpdateDeneb, LightClientUpdateElectra,
|
||||
};
|
||||
pub use crate::participation_flags::ParticipationFlags;
|
||||
pub use crate::participation_list::ParticipationList;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use crate::{
|
||||
light_client_update::*, test_utils::TestRandom, BeaconState, ChainSpec, EthSpec, FixedVector,
|
||||
ForkName, ForkVersionDeserialize, Hash256, LightClientHeader, LightClientHeaderAltair,
|
||||
LightClientHeaderCapella, LightClientHeaderDeneb, SignedBeaconBlock, Slot, SyncCommittee,
|
||||
LightClientHeaderCapella, LightClientHeaderDeneb, LightClientHeaderElectra, SignedBeaconBlock,
|
||||
Slot, SyncCommittee,
|
||||
};
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
@@ -16,7 +17,7 @@ use tree_hash_derive::TreeHash;
|
||||
/// A LightClientBootstrap is the initializer we send over to light_client nodes
|
||||
/// that are trying to generate their basic storage when booting up.
|
||||
#[superstruct(
|
||||
variants(Altair, Capella, Deneb),
|
||||
variants(Altair, Capella, Deneb, Electra),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Debug,
|
||||
@@ -51,6 +52,8 @@ pub struct LightClientBootstrap<E: EthSpec> {
|
||||
pub header: LightClientHeaderCapella<E>,
|
||||
#[superstruct(only(Deneb), partial_getter(rename = "header_deneb"))]
|
||||
pub header: LightClientHeaderDeneb<E>,
|
||||
#[superstruct(only(Electra), partial_getter(rename = "header_electra"))]
|
||||
pub header: LightClientHeaderElectra<E>,
|
||||
/// The `SyncCommittee` used in the requested period.
|
||||
pub current_sync_committee: Arc<SyncCommittee<E>>,
|
||||
/// Merkle proof for sync committee
|
||||
@@ -66,6 +69,7 @@ impl<E: EthSpec> LightClientBootstrap<E> {
|
||||
Self::Altair(_) => func(ForkName::Altair),
|
||||
Self::Capella(_) => func(ForkName::Capella),
|
||||
Self::Deneb(_) => func(ForkName::Deneb),
|
||||
Self::Electra(_) => func(ForkName::Electra),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,9 +86,8 @@ impl<E: EthSpec> LightClientBootstrap<E> {
|
||||
Self::Altair(LightClientBootstrapAltair::from_ssz_bytes(bytes)?)
|
||||
}
|
||||
ForkName::Capella => Self::Capella(LightClientBootstrapCapella::from_ssz_bytes(bytes)?),
|
||||
ForkName::Deneb | ForkName::Electra => {
|
||||
Self::Deneb(LightClientBootstrapDeneb::from_ssz_bytes(bytes)?)
|
||||
}
|
||||
ForkName::Deneb => Self::Deneb(LightClientBootstrapDeneb::from_ssz_bytes(bytes)?),
|
||||
ForkName::Electra => Self::Electra(LightClientBootstrapElectra::from_ssz_bytes(bytes)?),
|
||||
ForkName::Base => {
|
||||
return Err(ssz::DecodeError::BytesInvalid(format!(
|
||||
"LightClientBootstrap decoding for {fork_name} not implemented"
|
||||
@@ -97,18 +100,16 @@ impl<E: EthSpec> LightClientBootstrap<E> {
|
||||
|
||||
#[allow(clippy::arithmetic_side_effects)]
|
||||
pub fn ssz_max_len_for_fork(fork_name: ForkName) -> usize {
|
||||
// TODO(electra): review electra changes
|
||||
match fork_name {
|
||||
let fixed_len = match fork_name {
|
||||
ForkName::Base => 0,
|
||||
ForkName::Altair
|
||||
| ForkName::Bellatrix
|
||||
| ForkName::Capella
|
||||
| ForkName::Deneb
|
||||
| ForkName::Electra => {
|
||||
ForkName::Altair | ForkName::Bellatrix => {
|
||||
<LightClientBootstrapAltair<E> as Encode>::ssz_fixed_len()
|
||||
+ LightClientHeader::<E>::ssz_max_var_len_for_fork(fork_name)
|
||||
}
|
||||
}
|
||||
ForkName::Capella => <LightClientBootstrapCapella<E> as Encode>::ssz_fixed_len(),
|
||||
ForkName::Deneb => <LightClientBootstrapDeneb<E> as Encode>::ssz_fixed_len(),
|
||||
ForkName::Electra => <LightClientBootstrapElectra<E> as Encode>::ssz_fixed_len(),
|
||||
};
|
||||
fixed_len + LightClientHeader::<E>::ssz_max_var_len_for_fork(fork_name)
|
||||
}
|
||||
|
||||
pub fn from_beacon_state(
|
||||
@@ -138,11 +139,16 @@ impl<E: EthSpec> LightClientBootstrap<E> {
|
||||
current_sync_committee,
|
||||
current_sync_committee_branch,
|
||||
}),
|
||||
ForkName::Deneb | ForkName::Electra => Self::Deneb(LightClientBootstrapDeneb {
|
||||
ForkName::Deneb => Self::Deneb(LightClientBootstrapDeneb {
|
||||
header: LightClientHeaderDeneb::block_to_light_client_header(block)?,
|
||||
current_sync_committee,
|
||||
current_sync_committee_branch,
|
||||
}),
|
||||
ForkName::Electra => Self::Electra(LightClientBootstrapElectra {
|
||||
header: LightClientHeaderElectra::block_to_light_client_header(block)?,
|
||||
current_sync_committee,
|
||||
current_sync_committee_branch,
|
||||
}),
|
||||
};
|
||||
|
||||
Ok(light_client_bootstrap)
|
||||
|
||||
@@ -2,7 +2,8 @@ use super::{EthSpec, FixedVector, Hash256, LightClientHeader, Slot, SyncAggregat
|
||||
use crate::ChainSpec;
|
||||
use crate::{
|
||||
light_client_update::*, test_utils::TestRandom, ForkName, ForkVersionDeserialize,
|
||||
LightClientHeaderAltair, LightClientHeaderCapella, LightClientHeaderDeneb, SignedBeaconBlock,
|
||||
LightClientHeaderAltair, LightClientHeaderCapella, LightClientHeaderDeneb,
|
||||
LightClientHeaderElectra, SignedBeaconBlock,
|
||||
};
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
@@ -15,7 +16,7 @@ use test_random_derive::TestRandom;
|
||||
use tree_hash_derive::TreeHash;
|
||||
|
||||
#[superstruct(
|
||||
variants(Altair, Capella, Deneb),
|
||||
variants(Altair, Capella, Deneb, Electra),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Debug,
|
||||
@@ -50,6 +51,8 @@ pub struct LightClientFinalityUpdate<E: EthSpec> {
|
||||
pub attested_header: LightClientHeaderCapella<E>,
|
||||
#[superstruct(only(Deneb), partial_getter(rename = "attested_header_deneb"))]
|
||||
pub attested_header: LightClientHeaderDeneb<E>,
|
||||
#[superstruct(only(Electra), partial_getter(rename = "attested_header_electra"))]
|
||||
pub attested_header: LightClientHeaderElectra<E>,
|
||||
/// The last `BeaconBlockHeader` from the last attested finalized block (end of epoch).
|
||||
#[superstruct(only(Altair), partial_getter(rename = "finalized_header_altair"))]
|
||||
pub finalized_header: LightClientHeaderAltair<E>,
|
||||
@@ -57,6 +60,8 @@ pub struct LightClientFinalityUpdate<E: EthSpec> {
|
||||
pub finalized_header: LightClientHeaderCapella<E>,
|
||||
#[superstruct(only(Deneb), partial_getter(rename = "finalized_header_deneb"))]
|
||||
pub finalized_header: LightClientHeaderDeneb<E>,
|
||||
#[superstruct(only(Electra), partial_getter(rename = "finalized_header_electra"))]
|
||||
pub finalized_header: LightClientHeaderElectra<E>,
|
||||
/// Merkle proof attesting finalized header.
|
||||
#[test_random(default)]
|
||||
pub finality_branch: FixedVector<Hash256, FinalizedRootProofLen>,
|
||||
@@ -80,7 +85,7 @@ impl<E: EthSpec> LightClientFinalityUpdate<E> {
|
||||
.map_err(|_| Error::InconsistentFork)?
|
||||
{
|
||||
ForkName::Altair | ForkName::Bellatrix => {
|
||||
let finality_update = LightClientFinalityUpdateAltair {
|
||||
Self::Altair(LightClientFinalityUpdateAltair {
|
||||
attested_header: LightClientHeaderAltair::block_to_light_client_header(
|
||||
attested_block,
|
||||
)?,
|
||||
@@ -90,37 +95,42 @@ impl<E: EthSpec> LightClientFinalityUpdate<E> {
|
||||
finality_branch,
|
||||
sync_aggregate,
|
||||
signature_slot,
|
||||
};
|
||||
Self::Altair(finality_update)
|
||||
}
|
||||
ForkName::Capella => {
|
||||
let finality_update = LightClientFinalityUpdateCapella {
|
||||
attested_header: LightClientHeaderCapella::block_to_light_client_header(
|
||||
attested_block,
|
||||
)?,
|
||||
finalized_header: LightClientHeaderCapella::block_to_light_client_header(
|
||||
finalized_block,
|
||||
)?,
|
||||
finality_branch,
|
||||
sync_aggregate,
|
||||
signature_slot,
|
||||
};
|
||||
Self::Capella(finality_update)
|
||||
}
|
||||
ForkName::Deneb | ForkName::Electra => {
|
||||
let finality_update = LightClientFinalityUpdateDeneb {
|
||||
attested_header: LightClientHeaderDeneb::block_to_light_client_header(
|
||||
attested_block,
|
||||
)?,
|
||||
finalized_header: LightClientHeaderDeneb::block_to_light_client_header(
|
||||
finalized_block,
|
||||
)?,
|
||||
finality_branch,
|
||||
sync_aggregate,
|
||||
signature_slot,
|
||||
};
|
||||
Self::Deneb(finality_update)
|
||||
})
|
||||
}
|
||||
ForkName::Capella => Self::Capella(LightClientFinalityUpdateCapella {
|
||||
attested_header: LightClientHeaderCapella::block_to_light_client_header(
|
||||
attested_block,
|
||||
)?,
|
||||
finalized_header: LightClientHeaderCapella::block_to_light_client_header(
|
||||
finalized_block,
|
||||
)?,
|
||||
finality_branch,
|
||||
sync_aggregate,
|
||||
signature_slot,
|
||||
}),
|
||||
ForkName::Deneb => Self::Deneb(LightClientFinalityUpdateDeneb {
|
||||
attested_header: LightClientHeaderDeneb::block_to_light_client_header(
|
||||
attested_block,
|
||||
)?,
|
||||
finalized_header: LightClientHeaderDeneb::block_to_light_client_header(
|
||||
finalized_block,
|
||||
)?,
|
||||
finality_branch,
|
||||
sync_aggregate,
|
||||
signature_slot,
|
||||
}),
|
||||
ForkName::Electra => Self::Electra(LightClientFinalityUpdateElectra {
|
||||
attested_header: LightClientHeaderElectra::block_to_light_client_header(
|
||||
attested_block,
|
||||
)?,
|
||||
finalized_header: LightClientHeaderElectra::block_to_light_client_header(
|
||||
finalized_block,
|
||||
)?,
|
||||
finality_branch,
|
||||
sync_aggregate,
|
||||
signature_slot,
|
||||
}),
|
||||
|
||||
ForkName::Base => return Err(Error::AltairForkNotActive),
|
||||
};
|
||||
|
||||
@@ -135,6 +145,7 @@ impl<E: EthSpec> LightClientFinalityUpdate<E> {
|
||||
Self::Altair(_) => func(ForkName::Altair),
|
||||
Self::Capella(_) => func(ForkName::Capella),
|
||||
Self::Deneb(_) => func(ForkName::Deneb),
|
||||
Self::Electra(_) => func(ForkName::Electra),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,8 +164,9 @@ impl<E: EthSpec> LightClientFinalityUpdate<E> {
|
||||
ForkName::Capella => {
|
||||
Self::Capella(LightClientFinalityUpdateCapella::from_ssz_bytes(bytes)?)
|
||||
}
|
||||
ForkName::Deneb | ForkName::Electra => {
|
||||
Self::Deneb(LightClientFinalityUpdateDeneb::from_ssz_bytes(bytes)?)
|
||||
ForkName::Deneb => Self::Deneb(LightClientFinalityUpdateDeneb::from_ssz_bytes(bytes)?),
|
||||
ForkName::Electra => {
|
||||
Self::Electra(LightClientFinalityUpdateElectra::from_ssz_bytes(bytes)?)
|
||||
}
|
||||
ForkName::Base => {
|
||||
return Err(ssz::DecodeError::BytesInvalid(format!(
|
||||
@@ -168,18 +180,17 @@ impl<E: EthSpec> LightClientFinalityUpdate<E> {
|
||||
|
||||
#[allow(clippy::arithmetic_side_effects)]
|
||||
pub fn ssz_max_len_for_fork(fork_name: ForkName) -> usize {
|
||||
// TODO(electra): review electra changes
|
||||
match fork_name {
|
||||
let fixed_size = match fork_name {
|
||||
ForkName::Base => 0,
|
||||
ForkName::Altair
|
||||
| ForkName::Bellatrix
|
||||
| ForkName::Capella
|
||||
| ForkName::Deneb
|
||||
| ForkName::Electra => {
|
||||
ForkName::Altair | ForkName::Bellatrix => {
|
||||
<LightClientFinalityUpdateAltair<E> as Encode>::ssz_fixed_len()
|
||||
+ 2 * LightClientHeader::<E>::ssz_max_var_len_for_fork(fork_name)
|
||||
}
|
||||
}
|
||||
ForkName::Capella => <LightClientFinalityUpdateCapella<E> as Encode>::ssz_fixed_len(),
|
||||
ForkName::Deneb => <LightClientFinalityUpdateDeneb<E> as Encode>::ssz_fixed_len(),
|
||||
ForkName::Electra => <LightClientFinalityUpdateElectra<E> as Encode>::ssz_fixed_len(),
|
||||
};
|
||||
// `2 *` because there are two headers in the update
|
||||
fixed_size + 2 * LightClientHeader::<E>::ssz_max_var_len_for_fork(fork_name)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::ForkVersionDeserialize;
|
||||
use crate::{light_client_update::*, BeaconBlockBody};
|
||||
use crate::{
|
||||
test_utils::TestRandom, EthSpec, ExecutionPayloadHeaderCapella, ExecutionPayloadHeaderDeneb,
|
||||
FixedVector, Hash256, SignedBeaconBlock,
|
||||
ExecutionPayloadHeaderElectra, FixedVector, Hash256, SignedBeaconBlock,
|
||||
};
|
||||
use crate::{BeaconBlockHeader, ExecutionPayloadHeader};
|
||||
use derivative::Derivative;
|
||||
@@ -17,7 +17,7 @@ use test_random_derive::TestRandom;
|
||||
use tree_hash_derive::TreeHash;
|
||||
|
||||
#[superstruct(
|
||||
variants(Altair, Capella, Deneb),
|
||||
variants(Altair, Capella, Deneb, Electra),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Debug,
|
||||
@@ -54,8 +54,13 @@ pub struct LightClientHeader<E: EthSpec> {
|
||||
pub execution: ExecutionPayloadHeaderCapella<E>,
|
||||
#[superstruct(only(Deneb), partial_getter(rename = "execution_payload_header_deneb"))]
|
||||
pub execution: ExecutionPayloadHeaderDeneb<E>,
|
||||
#[superstruct(
|
||||
only(Electra),
|
||||
partial_getter(rename = "execution_payload_header_electra")
|
||||
)]
|
||||
pub execution: ExecutionPayloadHeaderElectra<E>,
|
||||
|
||||
#[superstruct(only(Capella, Deneb))]
|
||||
#[superstruct(only(Capella, Deneb, Electra))]
|
||||
pub execution_branch: FixedVector<Hash256, ExecutionPayloadProofLen>,
|
||||
|
||||
#[ssz(skip_serializing, skip_deserializing)]
|
||||
@@ -81,9 +86,12 @@ impl<E: EthSpec> LightClientHeader<E> {
|
||||
ForkName::Capella => LightClientHeader::Capella(
|
||||
LightClientHeaderCapella::block_to_light_client_header(block)?,
|
||||
),
|
||||
ForkName::Deneb | ForkName::Electra => LightClientHeader::Deneb(
|
||||
ForkName::Deneb => LightClientHeader::Deneb(
|
||||
LightClientHeaderDeneb::block_to_light_client_header(block)?,
|
||||
),
|
||||
ForkName::Electra => LightClientHeader::Electra(
|
||||
LightClientHeaderElectra::block_to_light_client_header(block)?,
|
||||
),
|
||||
};
|
||||
Ok(header)
|
||||
}
|
||||
@@ -96,9 +104,12 @@ impl<E: EthSpec> LightClientHeader<E> {
|
||||
ForkName::Capella => {
|
||||
LightClientHeader::Capella(LightClientHeaderCapella::from_ssz_bytes(bytes)?)
|
||||
}
|
||||
ForkName::Deneb | ForkName::Electra => {
|
||||
ForkName::Deneb => {
|
||||
LightClientHeader::Deneb(LightClientHeaderDeneb::from_ssz_bytes(bytes)?)
|
||||
}
|
||||
ForkName::Electra => {
|
||||
LightClientHeader::Electra(LightClientHeaderElectra::from_ssz_bytes(bytes)?)
|
||||
}
|
||||
ForkName::Base => {
|
||||
return Err(ssz::DecodeError::BytesInvalid(format!(
|
||||
"LightClientHeader decoding for {fork_name} not implemented"
|
||||
@@ -192,6 +203,34 @@ impl<E: EthSpec> LightClientHeaderDeneb<E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> LightClientHeaderElectra<E> {
|
||||
pub fn block_to_light_client_header(block: &SignedBeaconBlock<E>) -> Result<Self, Error> {
|
||||
let payload = block
|
||||
.message()
|
||||
.execution_payload()?
|
||||
.execution_payload_electra()?;
|
||||
|
||||
let header = ExecutionPayloadHeaderElectra::from(payload);
|
||||
let beacon_block_body = BeaconBlockBody::from(
|
||||
block
|
||||
.message()
|
||||
.body_electra()
|
||||
.map_err(|_| Error::BeaconBlockBodyError)?
|
||||
.to_owned(),
|
||||
);
|
||||
|
||||
let execution_branch =
|
||||
beacon_block_body.block_body_merkle_proof(EXECUTION_PAYLOAD_INDEX)?;
|
||||
|
||||
Ok(LightClientHeaderElectra {
|
||||
beacon: block.message().block_header(),
|
||||
execution: header,
|
||||
execution_branch: FixedVector::new(execution_branch)?,
|
||||
_phantom_data: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> ForkVersionDeserialize for LightClientHeader<E> {
|
||||
fn deserialize_by_fork<'de, D: serde::Deserializer<'de>>(
|
||||
value: serde_json::value::Value,
|
||||
@@ -204,9 +243,12 @@ impl<E: EthSpec> ForkVersionDeserialize for LightClientHeader<E> {
|
||||
ForkName::Capella => serde_json::from_value(value)
|
||||
.map(|light_client_header| Self::Capella(light_client_header))
|
||||
.map_err(serde::de::Error::custom),
|
||||
ForkName::Deneb | ForkName::Electra => serde_json::from_value(value)
|
||||
ForkName::Deneb => serde_json::from_value(value)
|
||||
.map(|light_client_header| Self::Deneb(light_client_header))
|
||||
.map_err(serde::de::Error::custom),
|
||||
ForkName::Electra => serde_json::from_value(value)
|
||||
.map(|light_client_header| Self::Electra(light_client_header))
|
||||
.map_err(serde::de::Error::custom),
|
||||
ForkName::Base => Err(serde::de::Error::custom(format!(
|
||||
"LightClientHeader deserialization for {fork_name} not implemented"
|
||||
))),
|
||||
|
||||
@@ -2,7 +2,7 @@ use super::{EthSpec, ForkName, ForkVersionDeserialize, LightClientHeader, Slot,
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::{
|
||||
light_client_update::*, ChainSpec, LightClientHeaderAltair, LightClientHeaderCapella,
|
||||
LightClientHeaderDeneb, SignedBeaconBlock,
|
||||
LightClientHeaderDeneb, LightClientHeaderElectra, SignedBeaconBlock,
|
||||
};
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
@@ -18,7 +18,7 @@ use tree_hash_derive::TreeHash;
|
||||
/// A LightClientOptimisticUpdate is the update we send on each slot,
|
||||
/// it is based off the current unfinalized epoch is verified only against BLS signature.
|
||||
#[superstruct(
|
||||
variants(Altair, Capella, Deneb),
|
||||
variants(Altair, Capella, Deneb, Electra),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Debug,
|
||||
@@ -53,6 +53,8 @@ pub struct LightClientOptimisticUpdate<E: EthSpec> {
|
||||
pub attested_header: LightClientHeaderCapella<E>,
|
||||
#[superstruct(only(Deneb), partial_getter(rename = "attested_header_deneb"))]
|
||||
pub attested_header: LightClientHeaderDeneb<E>,
|
||||
#[superstruct(only(Electra), partial_getter(rename = "attested_header_electra"))]
|
||||
pub attested_header: LightClientHeaderElectra<E>,
|
||||
/// current sync aggregate
|
||||
pub sync_aggregate: SyncAggregate<E>,
|
||||
/// Slot of the sync aggregated signature
|
||||
@@ -86,13 +88,20 @@ impl<E: EthSpec> LightClientOptimisticUpdate<E> {
|
||||
sync_aggregate,
|
||||
signature_slot,
|
||||
}),
|
||||
ForkName::Deneb | ForkName::Electra => Self::Deneb(LightClientOptimisticUpdateDeneb {
|
||||
ForkName::Deneb => Self::Deneb(LightClientOptimisticUpdateDeneb {
|
||||
attested_header: LightClientHeaderDeneb::block_to_light_client_header(
|
||||
attested_block,
|
||||
)?,
|
||||
sync_aggregate,
|
||||
signature_slot,
|
||||
}),
|
||||
ForkName::Electra => Self::Electra(LightClientOptimisticUpdateElectra {
|
||||
attested_header: LightClientHeaderElectra::block_to_light_client_header(
|
||||
attested_block,
|
||||
)?,
|
||||
sync_aggregate,
|
||||
signature_slot,
|
||||
}),
|
||||
ForkName::Base => return Err(Error::AltairForkNotActive),
|
||||
};
|
||||
|
||||
@@ -107,6 +116,7 @@ impl<E: EthSpec> LightClientOptimisticUpdate<E> {
|
||||
Self::Altair(_) => func(ForkName::Altair),
|
||||
Self::Capella(_) => func(ForkName::Capella),
|
||||
Self::Deneb(_) => func(ForkName::Deneb),
|
||||
Self::Electra(_) => func(ForkName::Electra),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,9 +149,12 @@ impl<E: EthSpec> LightClientOptimisticUpdate<E> {
|
||||
ForkName::Capella => {
|
||||
Self::Capella(LightClientOptimisticUpdateCapella::from_ssz_bytes(bytes)?)
|
||||
}
|
||||
ForkName::Deneb | ForkName::Electra => {
|
||||
ForkName::Deneb => {
|
||||
Self::Deneb(LightClientOptimisticUpdateDeneb::from_ssz_bytes(bytes)?)
|
||||
}
|
||||
ForkName::Electra => {
|
||||
Self::Electra(LightClientOptimisticUpdateElectra::from_ssz_bytes(bytes)?)
|
||||
}
|
||||
ForkName::Base => {
|
||||
return Err(ssz::DecodeError::BytesInvalid(format!(
|
||||
"LightClientOptimisticUpdate decoding for {fork_name} not implemented"
|
||||
@@ -154,18 +167,16 @@ impl<E: EthSpec> LightClientOptimisticUpdate<E> {
|
||||
|
||||
#[allow(clippy::arithmetic_side_effects)]
|
||||
pub fn ssz_max_len_for_fork(fork_name: ForkName) -> usize {
|
||||
// TODO(electra): review electra changes
|
||||
match fork_name {
|
||||
let fixed_len = match fork_name {
|
||||
ForkName::Base => 0,
|
||||
ForkName::Altair
|
||||
| ForkName::Bellatrix
|
||||
| ForkName::Capella
|
||||
| ForkName::Deneb
|
||||
| ForkName::Electra => {
|
||||
ForkName::Altair | ForkName::Bellatrix => {
|
||||
<LightClientOptimisticUpdateAltair<E> as Encode>::ssz_fixed_len()
|
||||
+ LightClientHeader::<E>::ssz_max_var_len_for_fork(fork_name)
|
||||
}
|
||||
}
|
||||
ForkName::Capella => <LightClientOptimisticUpdateCapella<E> as Encode>::ssz_fixed_len(),
|
||||
ForkName::Deneb => <LightClientOptimisticUpdateDeneb<E> as Encode>::ssz_fixed_len(),
|
||||
ForkName::Electra => <LightClientOptimisticUpdateElectra<E> as Encode>::ssz_fixed_len(),
|
||||
};
|
||||
fixed_len + LightClientHeader::<E>::ssz_max_var_len_for_fork(fork_name)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use super::{EthSpec, FixedVector, Hash256, Slot, SyncAggregate, SyncCommittee};
|
||||
use crate::light_client_header::LightClientHeaderElectra;
|
||||
use crate::{
|
||||
beacon_state, test_utils::TestRandom, BeaconBlock, BeaconBlockHeader, BeaconState, ChainSpec,
|
||||
ForkName, ForkVersionDeserialize, LightClientHeaderAltair, LightClientHeaderCapella,
|
||||
@@ -76,7 +77,7 @@ impl From<milhouse::Error> for Error {
|
||||
/// or to sync up to the last committee period, we need to have one ready for each ALTAIR period
|
||||
/// we go over, note: there is no need to keep all of the updates from [ALTAIR_PERIOD, CURRENT_PERIOD].
|
||||
#[superstruct(
|
||||
variants(Altair, Capella, Deneb),
|
||||
variants(Altair, Capella, Deneb, Electra),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Debug,
|
||||
@@ -111,6 +112,8 @@ pub struct LightClientUpdate<E: EthSpec> {
|
||||
pub attested_header: LightClientHeaderCapella<E>,
|
||||
#[superstruct(only(Deneb), partial_getter(rename = "attested_header_deneb"))]
|
||||
pub attested_header: LightClientHeaderDeneb<E>,
|
||||
#[superstruct(only(Electra), partial_getter(rename = "attested_header_electra"))]
|
||||
pub attested_header: LightClientHeaderElectra<E>,
|
||||
/// The `SyncCommittee` used in the next period.
|
||||
pub next_sync_committee: Arc<SyncCommittee<E>>,
|
||||
/// Merkle proof for next sync committee
|
||||
@@ -122,6 +125,8 @@ pub struct LightClientUpdate<E: EthSpec> {
|
||||
pub finalized_header: LightClientHeaderCapella<E>,
|
||||
#[superstruct(only(Deneb), partial_getter(rename = "finalized_header_deneb"))]
|
||||
pub finalized_header: LightClientHeaderDeneb<E>,
|
||||
#[superstruct(only(Electra), partial_getter(rename = "finalized_header_electra"))]
|
||||
pub finalized_header: LightClientHeaderElectra<E>,
|
||||
/// Merkle proof attesting finalized header.
|
||||
pub finality_branch: FixedVector<Hash256, FinalizedRootProofLen>,
|
||||
/// current sync aggreggate
|
||||
@@ -221,7 +226,7 @@ impl<E: EthSpec> LightClientUpdate<E> {
|
||||
signature_slot: block.slot(),
|
||||
})
|
||||
}
|
||||
ForkName::Deneb | ForkName::Electra => {
|
||||
ForkName::Deneb => {
|
||||
let attested_header =
|
||||
LightClientHeaderDeneb::block_to_light_client_header(attested_block)?;
|
||||
let finalized_header =
|
||||
@@ -236,6 +241,23 @@ impl<E: EthSpec> LightClientUpdate<E> {
|
||||
signature_slot: block.slot(),
|
||||
})
|
||||
}
|
||||
ForkName::Electra => {
|
||||
let attested_header =
|
||||
LightClientHeaderElectra::block_to_light_client_header(attested_block)?;
|
||||
let finalized_header =
|
||||
LightClientHeaderElectra::block_to_light_client_header(finalized_block)?;
|
||||
Self::Electra(LightClientUpdateElectra {
|
||||
attested_header,
|
||||
next_sync_committee: attested_state.next_sync_committee()?.clone(),
|
||||
next_sync_committee_branch: FixedVector::new(next_sync_committee_branch)?,
|
||||
finalized_header,
|
||||
finality_branch: FixedVector::new(finality_branch)?,
|
||||
sync_aggregate: sync_aggregate.clone(),
|
||||
signature_slot: block.slot(),
|
||||
})
|
||||
} // To add a new fork, just append the new fork variant on the latest fork. Forks that
|
||||
// have a distinct execution header will need a new LightClientUdpate variant only
|
||||
// if you need to test or support lightclient usages
|
||||
};
|
||||
|
||||
Ok(light_client_update)
|
||||
@@ -247,9 +269,8 @@ impl<E: EthSpec> LightClientUpdate<E> {
|
||||
Self::Altair(LightClientUpdateAltair::from_ssz_bytes(bytes)?)
|
||||
}
|
||||
ForkName::Capella => Self::Capella(LightClientUpdateCapella::from_ssz_bytes(bytes)?),
|
||||
ForkName::Deneb | ForkName::Electra => {
|
||||
Self::Deneb(LightClientUpdateDeneb::from_ssz_bytes(bytes)?)
|
||||
}
|
||||
ForkName::Deneb => Self::Deneb(LightClientUpdateDeneb::from_ssz_bytes(bytes)?),
|
||||
ForkName::Electra => Self::Electra(LightClientUpdateElectra::from_ssz_bytes(bytes)?),
|
||||
ForkName::Base => {
|
||||
return Err(ssz::DecodeError::BytesInvalid(format!(
|
||||
"LightClientUpdate decoding for {fork_name} not implemented"
|
||||
|
||||
@@ -34,7 +34,9 @@ use tree_hash_derive::TreeHash;
|
||||
),
|
||||
serde(bound = "E: EthSpec"),
|
||||
arbitrary(bound = "E: EthSpec"),
|
||||
)
|
||||
),
|
||||
map_into(Attestation),
|
||||
map_ref_into(AggregateAndProofRef)
|
||||
)]
|
||||
#[derive(
|
||||
arbitrary::Arbitrary, Debug, Clone, PartialEq, Serialize, Deserialize, Encode, TreeHash,
|
||||
@@ -102,19 +104,17 @@ impl<E: EthSpec> SignedAggregateAndProof<E> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn message(&self) -> AggregateAndProofRef<E> {
|
||||
match self {
|
||||
SignedAggregateAndProof::Base(message) => AggregateAndProofRef::Base(&message.message),
|
||||
SignedAggregateAndProof::Electra(message) => {
|
||||
AggregateAndProofRef::Electra(&message.message)
|
||||
}
|
||||
}
|
||||
pub fn message<'a>(&'a self) -> AggregateAndProofRef<'a, E> {
|
||||
map_signed_aggregate_and_proof_ref_into_aggregate_and_proof_ref!(
|
||||
&'a _,
|
||||
self.to_ref(),
|
||||
|inner, cons| { cons(&inner.message) }
|
||||
)
|
||||
}
|
||||
|
||||
pub fn into_attestation(self) -> Attestation<E> {
|
||||
match self {
|
||||
Self::Base(att) => Attestation::Base(att.message.aggregate),
|
||||
Self::Electra(att) => Attestation::Electra(att.message.aggregate),
|
||||
}
|
||||
map_signed_aggregate_and_proof_into_attestation!(self, |inner, cons| {
|
||||
cons(inner.message.aggregate)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,13 +63,6 @@ impl<E: EthSpec> SyncCommitteeContribution<E> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Are the aggregation bitfields of these sync contribution disjoint?
|
||||
pub fn signers_disjoint_from(&self, other: &Self) -> bool {
|
||||
self.aggregation_bits
|
||||
.intersection(&other.aggregation_bits)
|
||||
.is_zero()
|
||||
}
|
||||
|
||||
/// Aggregate another `SyncCommitteeContribution` into this one.
|
||||
///
|
||||
/// The aggregation bitfields must be disjoint, and the data must be the same.
|
||||
@@ -77,7 +70,6 @@ impl<E: EthSpec> SyncCommitteeContribution<E> {
|
||||
debug_assert_eq!(self.slot, other.slot);
|
||||
debug_assert_eq!(self.beacon_block_root, other.beacon_block_root);
|
||||
debug_assert_eq!(self.subcommittee_index, other.subcommittee_index);
|
||||
debug_assert!(self.signers_disjoint_from(other));
|
||||
|
||||
self.aggregation_bits = self.aggregation_bits.union(&other.aggregation_bits);
|
||||
self.signature.add_assign_aggregate(&other.signature);
|
||||
|
||||
Reference in New Issue
Block a user