mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-20 13:24:44 +00:00
superstruct the AttesterSlashing (#5636)
* `superstruct` Attester Fork Variants * Push a little further * Deal with Encode / Decode of AttesterSlashing * not so sure about this.. * Stop Encode/Decode Bounds from Propagating Out * Tons of Changes.. * More Conversions to AttestationRef * Add AsReference trait (#15) * Add AsReference trait * Fix some snafus * Got it Compiling! :D * Got Tests Building * Get beacon chain tests compiling --------- Co-authored-by: Michael Sproul <micsproul@gmail.com>
This commit is contained in:
@@ -212,6 +212,15 @@ impl<E: EthSpec> Attestation<E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: EthSpec> AttestationRef<'a, E> {
|
||||
pub fn clone_as_attestation(self) -> Attestation<E> {
|
||||
match self {
|
||||
AttestationRef::Base(att) => Attestation::Base(att.clone()),
|
||||
AttestationRef::Electra(att) => Attestation::Electra(att.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> AttestationElectra<E> {
|
||||
/// Are the aggregation bitfields of these attestations disjoint?
|
||||
pub fn signers_disjoint_from(&self, other: &Self) -> bool {
|
||||
@@ -363,6 +372,12 @@ impl<E: EthSpec> SlotData for Attestation<E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: EthSpec> SlotData for AttestationRef<'a, E> {
|
||||
fn get_slot(&self) -> Slot {
|
||||
self.data().slot
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -394,5 +409,6 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
ssz_and_tree_hash_tests!(Attestation<MainnetEthSpec>);
|
||||
// TODO(electra): can we do this with both variants or should we?
|
||||
ssz_and_tree_hash_tests!(AttestationBase<MainnetEthSpec>);
|
||||
}
|
||||
|
||||
@@ -1,32 +1,168 @@
|
||||
use crate::{test_utils::TestRandom, EthSpec, IndexedAttestation};
|
||||
|
||||
use crate::indexed_attestation::{
|
||||
IndexedAttestationBase, IndexedAttestationElectra, IndexedAttestationRef,
|
||||
};
|
||||
use crate::{test_utils::TestRandom, EthSpec};
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use superstruct::superstruct;
|
||||
use test_random_derive::TestRandom;
|
||||
use tree_hash_derive::TreeHash;
|
||||
|
||||
/// Two conflicting attestations.
|
||||
///
|
||||
/// Spec v0.12.1
|
||||
#[superstruct(
|
||||
variants(Base, Electra),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Derivative,
|
||||
Debug,
|
||||
Clone,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Encode,
|
||||
Decode,
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
arbitrary::Arbitrary
|
||||
),
|
||||
derivative(PartialEq, Eq, Hash(bound = "E: EthSpec")),
|
||||
serde(bound = "E: EthSpec"),
|
||||
arbitrary(bound = "E: EthSpec")
|
||||
),
|
||||
ref_attributes(derive(Debug))
|
||||
)]
|
||||
#[derive(
|
||||
Derivative,
|
||||
Debug,
|
||||
Clone,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Encode,
|
||||
Decode,
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
arbitrary::Arbitrary,
|
||||
Debug, Clone, Serialize, Encode, Deserialize, TreeHash, Derivative, arbitrary::Arbitrary,
|
||||
)]
|
||||
#[derivative(PartialEq, Eq, Hash(bound = "E: EthSpec"))]
|
||||
#[serde(bound = "E: EthSpec")]
|
||||
#[serde(bound = "E: EthSpec", untagged)]
|
||||
#[arbitrary(bound = "E: EthSpec")]
|
||||
#[ssz(enum_behaviour = "transparent")]
|
||||
#[tree_hash(enum_behaviour = "transparent")]
|
||||
pub struct AttesterSlashing<E: EthSpec> {
|
||||
pub attestation_1: IndexedAttestation<E>,
|
||||
pub attestation_2: IndexedAttestation<E>,
|
||||
// TODO(electra) change this to `#[superstruct(flatten)]` when 0.8 is out..
|
||||
#[superstruct(only(Base), partial_getter(rename = "attestation_1_base"))]
|
||||
pub attestation_1: IndexedAttestationBase<E>,
|
||||
#[superstruct(only(Electra), partial_getter(rename = "attestation_1_electra"))]
|
||||
pub attestation_1: IndexedAttestationElectra<E>,
|
||||
#[superstruct(only(Base), partial_getter(rename = "attestation_2_base"))]
|
||||
pub attestation_2: IndexedAttestationBase<E>,
|
||||
#[superstruct(only(Electra), partial_getter(rename = "attestation_2_electra"))]
|
||||
pub attestation_2: IndexedAttestationElectra<E>,
|
||||
}
|
||||
|
||||
/// This is a copy of the `AttesterSlashing` enum but with `Encode` and `Decode` derived
|
||||
/// using the `union` behavior for the purposes of persistence on disk. We use a separate
|
||||
/// type so that we don't accidentally use this non-spec encoding in consensus objects.
|
||||
#[derive(Debug, Clone, Encode, Decode, Derivative)]
|
||||
#[derivative(PartialEq, Eq, Hash(bound = "E: EthSpec"))]
|
||||
#[ssz(enum_behaviour = "union")]
|
||||
pub enum AttesterSlashingOnDisk<E: EthSpec> {
|
||||
Base(AttesterSlashingBase<E>),
|
||||
Electra(AttesterSlashingElectra<E>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Encode)]
|
||||
#[ssz(enum_behaviour = "union")]
|
||||
pub enum AttesterSlashingRefOnDisk<'a, E: EthSpec> {
|
||||
Base(&'a AttesterSlashingBase<E>),
|
||||
Electra(&'a AttesterSlashingElectra<E>),
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<AttesterSlashing<E>> for AttesterSlashingOnDisk<E> {
|
||||
fn from(attester_slashing: AttesterSlashing<E>) -> Self {
|
||||
match attester_slashing {
|
||||
AttesterSlashing::Base(attester_slashing) => Self::Base(attester_slashing),
|
||||
AttesterSlashing::Electra(attester_slashing) => Self::Electra(attester_slashing),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<AttesterSlashingOnDisk<E>> for AttesterSlashing<E> {
|
||||
fn from(attester_slashing: AttesterSlashingOnDisk<E>) -> Self {
|
||||
match attester_slashing {
|
||||
AttesterSlashingOnDisk::Base(attester_slashing) => Self::Base(attester_slashing),
|
||||
AttesterSlashingOnDisk::Electra(attester_slashing) => Self::Electra(attester_slashing),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: EthSpec> From<AttesterSlashingRefOnDisk<'a, E>> for AttesterSlashingRef<'a, E> {
|
||||
fn from(attester_slashing: AttesterSlashingRefOnDisk<'a, E>) -> Self {
|
||||
match attester_slashing {
|
||||
AttesterSlashingRefOnDisk::Base(attester_slashing) => Self::Base(attester_slashing),
|
||||
AttesterSlashingRefOnDisk::Electra(attester_slashing) => {
|
||||
Self::Electra(attester_slashing)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: EthSpec> From<AttesterSlashingRef<'a, E>> for AttesterSlashingRefOnDisk<'a, E> {
|
||||
fn from(attester_slashing: AttesterSlashingRef<'a, E>) -> Self {
|
||||
match attester_slashing {
|
||||
AttesterSlashingRef::Base(attester_slashing) => Self::Base(attester_slashing),
|
||||
AttesterSlashingRef::Electra(attester_slashing) => Self::Electra(attester_slashing),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: EthSpec> AttesterSlashingRef<'a, E> {
|
||||
pub fn clone_as_attester_slashing(self) -> AttesterSlashing<E> {
|
||||
match self {
|
||||
AttesterSlashingRef::Base(attester_slashing) => {
|
||||
AttesterSlashing::Base(attester_slashing.clone())
|
||||
}
|
||||
AttesterSlashingRef::Electra(attester_slashing) => {
|
||||
AttesterSlashing::Electra(attester_slashing.clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attestation_1(&self) -> IndexedAttestationRef<'a, E> {
|
||||
match self {
|
||||
AttesterSlashingRef::Base(attester_slashing) => {
|
||||
IndexedAttestationRef::Base(&attester_slashing.attestation_1)
|
||||
}
|
||||
AttesterSlashingRef::Electra(attester_slashing) => {
|
||||
IndexedAttestationRef::Electra(&attester_slashing.attestation_1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attestation_2(&self) -> IndexedAttestationRef<'a, E> {
|
||||
match self {
|
||||
AttesterSlashingRef::Base(attester_slashing) => {
|
||||
IndexedAttestationRef::Base(&attester_slashing.attestation_2)
|
||||
}
|
||||
AttesterSlashingRef::Electra(attester_slashing) => {
|
||||
IndexedAttestationRef::Electra(&attester_slashing.attestation_2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> AttesterSlashing<E> {
|
||||
pub fn attestation_1(&self) -> IndexedAttestationRef<E> {
|
||||
match self {
|
||||
AttesterSlashing::Base(attester_slashing) => {
|
||||
IndexedAttestationRef::Base(&attester_slashing.attestation_1)
|
||||
}
|
||||
AttesterSlashing::Electra(attester_slashing) => {
|
||||
IndexedAttestationRef::Electra(&attester_slashing.attestation_1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attestation_2(&self) -> IndexedAttestationRef<E> {
|
||||
match self {
|
||||
AttesterSlashing::Base(attester_slashing) => {
|
||||
IndexedAttestationRef::Base(&attester_slashing.attestation_2)
|
||||
}
|
||||
AttesterSlashing::Electra(attester_slashing) => {
|
||||
IndexedAttestationRef::Electra(&attester_slashing.attestation_2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -34,5 +170,6 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::*;
|
||||
|
||||
ssz_and_tree_hash_tests!(AttesterSlashing<MainnetEthSpec>);
|
||||
// TODO(electra): should this be done for both variants?
|
||||
ssz_and_tree_hash_tests!(AttesterSlashingBase<MainnetEthSpec>);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ use test_random_derive::TestRandom;
|
||||
use tree_hash::TreeHash;
|
||||
use tree_hash_derive::TreeHash;
|
||||
|
||||
use self::indexed_attestation::IndexedAttestationBase;
|
||||
use self::indexed_attestation::{IndexedAttestationBase, IndexedAttestationElectra};
|
||||
|
||||
/// A block of the `BeaconChain`.
|
||||
#[superstruct(
|
||||
@@ -327,16 +327,15 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBase<E, Payload> {
|
||||
message: header,
|
||||
signature: Signature::empty(),
|
||||
};
|
||||
let indexed_attestation: IndexedAttestation<E> =
|
||||
IndexedAttestation::Base(IndexedAttestationBase {
|
||||
attesting_indices: VariableList::new(vec![
|
||||
0_u64;
|
||||
E::MaxValidatorsPerCommittee::to_usize()
|
||||
])
|
||||
.unwrap(),
|
||||
data: AttestationData::default(),
|
||||
signature: AggregateSignature::empty(),
|
||||
});
|
||||
let indexed_attestation = IndexedAttestationBase {
|
||||
attesting_indices: VariableList::new(vec![
|
||||
0_u64;
|
||||
E::MaxValidatorsPerCommittee::to_usize()
|
||||
])
|
||||
.unwrap(),
|
||||
data: AttestationData::default(),
|
||||
signature: AggregateSignature::empty(),
|
||||
};
|
||||
|
||||
let deposit_data = DepositData {
|
||||
pubkey: PublicKeyBytes::empty(),
|
||||
@@ -349,17 +348,17 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBase<E, Payload> {
|
||||
signed_header_2: signed_header,
|
||||
};
|
||||
|
||||
let attester_slashing = AttesterSlashing {
|
||||
let attester_slashing = AttesterSlashingBase {
|
||||
attestation_1: indexed_attestation.clone(),
|
||||
attestation_2: indexed_attestation,
|
||||
};
|
||||
|
||||
let attestation: Attestation<E> = Attestation::Base(AttestationBase {
|
||||
let attestation = AttestationBase {
|
||||
aggregation_bits: BitList::with_capacity(E::MaxValidatorsPerCommittee::to_usize())
|
||||
.unwrap(),
|
||||
data: AttestationData::default(),
|
||||
signature: AggregateSignature::empty(),
|
||||
});
|
||||
};
|
||||
|
||||
let deposit = Deposit {
|
||||
proof: FixedVector::from_elem(Hash256::zero()),
|
||||
@@ -607,6 +606,42 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockElectra<E, Payload>
|
||||
/// Return a Electra block where the block has maximum size.
|
||||
pub fn full(spec: &ChainSpec) -> Self {
|
||||
let base_block: BeaconBlockBase<_, Payload> = BeaconBlockBase::full(spec);
|
||||
// TODO(electra): check this
|
||||
let indexed_attestation: IndexedAttestationElectra<E> = IndexedAttestationElectra {
|
||||
attesting_indices: VariableList::new(vec![
|
||||
0_u64;
|
||||
E::MaxValidatorsPerCommitteePerSlot::to_usize(
|
||||
)
|
||||
])
|
||||
.unwrap(),
|
||||
data: AttestationData::default(),
|
||||
signature: AggregateSignature::empty(),
|
||||
};
|
||||
// TODO(electra): fix this so we calculate this size correctly
|
||||
let attester_slashings = vec![
|
||||
AttesterSlashingElectra {
|
||||
attestation_1: indexed_attestation.clone(),
|
||||
attestation_2: indexed_attestation,
|
||||
};
|
||||
E::max_attester_slashings_electra()
|
||||
]
|
||||
.into();
|
||||
// TODO(electra): check this
|
||||
let attestation = AttestationElectra {
|
||||
aggregation_bits: BitList::with_capacity(
|
||||
E::MaxValidatorsPerCommitteePerSlot::to_usize(),
|
||||
)
|
||||
.unwrap(),
|
||||
data: AttestationData::default(),
|
||||
signature: AggregateSignature::empty(),
|
||||
// TODO(electra): does this actually allocate the size correctly?
|
||||
committee_bits: BitVector::new(),
|
||||
};
|
||||
let mut attestations_electra = vec![];
|
||||
for _ in 0..E::MaxAttestationsElectra::to_usize() {
|
||||
attestations_electra.push(attestation.clone());
|
||||
}
|
||||
|
||||
let bls_to_execution_changes = vec![
|
||||
SignedBlsToExecutionChange {
|
||||
message: BlsToExecutionChange {
|
||||
@@ -630,8 +665,8 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockElectra<E, Payload>
|
||||
state_root: Hash256::zero(),
|
||||
body: BeaconBlockBodyElectra {
|
||||
proposer_slashings: base_block.body.proposer_slashings,
|
||||
attester_slashings: base_block.body.attester_slashings,
|
||||
attestations: base_block.body.attestations,
|
||||
attester_slashings,
|
||||
attestations: attestations_electra.into(),
|
||||
deposits: base_block.body.deposits,
|
||||
voluntary_exits: base_block.body.voluntary_exits,
|
||||
bls_to_execution_changes,
|
||||
@@ -645,6 +680,7 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockElectra<E, Payload>
|
||||
graffiti: Graffiti::default(),
|
||||
execution_payload: Payload::Electra::default(),
|
||||
blob_kzg_commitments: VariableList::empty(),
|
||||
consolidations: VariableList::empty(),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -675,6 +711,7 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> EmptyBlock for BeaconBlockElec
|
||||
execution_payload: Payload::Electra::default(),
|
||||
bls_to_execution_changes: VariableList::empty(),
|
||||
blob_kzg_commitments: VariableList::empty(),
|
||||
consolidations: VariableList::empty(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,8 +63,21 @@ pub struct BeaconBlockBody<E: EthSpec, Payload: AbstractExecPayload<E> = FullPay
|
||||
pub eth1_data: Eth1Data,
|
||||
pub graffiti: Graffiti,
|
||||
pub proposer_slashings: VariableList<ProposerSlashing, E::MaxProposerSlashings>,
|
||||
pub attester_slashings: VariableList<AttesterSlashing<E>, E::MaxAttesterSlashings>,
|
||||
pub attestations: VariableList<Attestation<E>, E::MaxAttestations>,
|
||||
#[superstruct(
|
||||
only(Base, Altair, Merge, Capella, Deneb),
|
||||
partial_getter(rename = "attester_slashings_base")
|
||||
)]
|
||||
pub attester_slashings: VariableList<AttesterSlashingBase<E>, E::MaxAttesterSlashings>,
|
||||
#[superstruct(only(Electra), partial_getter(rename = "attester_slashings_electra"))]
|
||||
pub attester_slashings:
|
||||
VariableList<AttesterSlashingElectra<E>, E::MaxAttesterSlashingsElectra>,
|
||||
#[superstruct(
|
||||
only(Base, Altair, Merge, Capella, Deneb),
|
||||
partial_getter(rename = "attestations_base")
|
||||
)]
|
||||
pub attestations: VariableList<AttestationBase<E>, E::MaxAttestations>,
|
||||
#[superstruct(only(Electra), partial_getter(rename = "attestations_electra"))]
|
||||
pub attestations: VariableList<AttestationElectra<E>, E::MaxAttestationsElectra>,
|
||||
pub deposits: VariableList<Deposit, E::MaxDeposits>,
|
||||
pub voluntary_exits: VariableList<SignedVoluntaryExit, E::MaxVoluntaryExits>,
|
||||
#[superstruct(only(Altair, Merge, Capella, Deneb, Electra))]
|
||||
@@ -89,6 +102,8 @@ pub struct BeaconBlockBody<E: EthSpec, Payload: AbstractExecPayload<E> = FullPay
|
||||
VariableList<SignedBlsToExecutionChange, E::MaxBlsToExecutionChanges>,
|
||||
#[superstruct(only(Deneb, Electra))]
|
||||
pub blob_kzg_commitments: KzgCommitments<E>,
|
||||
#[superstruct(only(Electra))]
|
||||
pub consolidations: VariableList<SignedConsolidation, E::MaxConsolidations>,
|
||||
#[superstruct(only(Base, Altair))]
|
||||
#[ssz(skip_serializing, skip_deserializing)]
|
||||
#[tree_hash(skip_hashing)]
|
||||
@@ -253,6 +268,99 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'a, E,
|
||||
self.blob_kzg_commitments()
|
||||
.map_or(false, |blobs| !blobs.is_empty())
|
||||
}
|
||||
|
||||
pub fn attestations_len(&self) -> usize {
|
||||
match self {
|
||||
Self::Base(body) => body.attestations.len(),
|
||||
Self::Altair(body) => body.attestations.len(),
|
||||
Self::Merge(body) => body.attestations.len(),
|
||||
Self::Capella(body) => body.attestations.len(),
|
||||
Self::Deneb(body) => body.attestations.len(),
|
||||
Self::Electra(body) => body.attestations.len(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attester_slashings_len(&self) -> usize {
|
||||
match self {
|
||||
Self::Base(body) => body.attester_slashings.len(),
|
||||
Self::Altair(body) => body.attester_slashings.len(),
|
||||
Self::Merge(body) => body.attester_slashings.len(),
|
||||
Self::Capella(body) => body.attester_slashings.len(),
|
||||
Self::Deneb(body) => body.attester_slashings.len(),
|
||||
Self::Electra(body) => body.attester_slashings.len(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attestations(&self) -> Box<dyn Iterator<Item = AttestationRef<'a, E>> + 'a> {
|
||||
match self {
|
||||
Self::Base(body) => Box::new(body.attestations.iter().map(AttestationRef::Base)),
|
||||
Self::Altair(body) => Box::new(body.attestations.iter().map(AttestationRef::Base)),
|
||||
Self::Merge(body) => Box::new(body.attestations.iter().map(AttestationRef::Base)),
|
||||
Self::Capella(body) => Box::new(body.attestations.iter().map(AttestationRef::Base)),
|
||||
Self::Deneb(body) => Box::new(body.attestations.iter().map(AttestationRef::Base)),
|
||||
Self::Electra(body) => Box::new(body.attestations.iter().map(AttestationRef::Electra)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attester_slashings(&self) -> Box<dyn Iterator<Item = AttesterSlashingRef<'a, E>> + 'a> {
|
||||
match self {
|
||||
Self::Base(body) => Box::new(
|
||||
body.attester_slashings
|
||||
.iter()
|
||||
.map(AttesterSlashingRef::Base),
|
||||
),
|
||||
Self::Altair(body) => Box::new(
|
||||
body.attester_slashings
|
||||
.iter()
|
||||
.map(AttesterSlashingRef::Base),
|
||||
),
|
||||
Self::Merge(body) => Box::new(
|
||||
body.attester_slashings
|
||||
.iter()
|
||||
.map(AttesterSlashingRef::Base),
|
||||
),
|
||||
Self::Capella(body) => Box::new(
|
||||
body.attester_slashings
|
||||
.iter()
|
||||
.map(AttesterSlashingRef::Base),
|
||||
),
|
||||
Self::Deneb(body) => Box::new(
|
||||
body.attester_slashings
|
||||
.iter()
|
||||
.map(AttesterSlashingRef::Base),
|
||||
),
|
||||
Self::Electra(body) => Box::new(
|
||||
body.attester_slashings
|
||||
.iter()
|
||||
.map(AttesterSlashingRef::Electra),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRefMut<'a, E, Payload> {
|
||||
pub fn attestations_mut(
|
||||
&'a mut self,
|
||||
) -> Box<dyn Iterator<Item = AttestationRefMut<'a, E>> + 'a> {
|
||||
match self {
|
||||
Self::Base(body) => Box::new(body.attestations.iter_mut().map(AttestationRefMut::Base)),
|
||||
Self::Altair(body) => {
|
||||
Box::new(body.attestations.iter_mut().map(AttestationRefMut::Base))
|
||||
}
|
||||
Self::Merge(body) => {
|
||||
Box::new(body.attestations.iter_mut().map(AttestationRefMut::Base))
|
||||
}
|
||||
Self::Capella(body) => {
|
||||
Box::new(body.attestations.iter_mut().map(AttestationRefMut::Base))
|
||||
}
|
||||
Self::Deneb(body) => {
|
||||
Box::new(body.attestations.iter_mut().map(AttestationRefMut::Base))
|
||||
}
|
||||
Self::Electra(body) => {
|
||||
Box::new(body.attestations.iter_mut().map(AttestationRefMut::Electra))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'a, E, Payload> {
|
||||
@@ -553,6 +661,7 @@ impl<E: EthSpec> From<BeaconBlockBodyElectra<E, FullPayload<E>>>
|
||||
execution_payload: FullPayloadElectra { execution_payload },
|
||||
bls_to_execution_changes,
|
||||
blob_kzg_commitments,
|
||||
consolidations,
|
||||
} = body;
|
||||
|
||||
(
|
||||
@@ -571,6 +680,7 @@ impl<E: EthSpec> From<BeaconBlockBodyElectra<E, FullPayload<E>>>
|
||||
},
|
||||
bls_to_execution_changes,
|
||||
blob_kzg_commitments: blob_kzg_commitments.clone(),
|
||||
consolidations,
|
||||
},
|
||||
Some(execution_payload),
|
||||
)
|
||||
@@ -709,6 +819,7 @@ impl<E: EthSpec> BeaconBlockBodyElectra<E, FullPayload<E>> {
|
||||
execution_payload: FullPayloadElectra { execution_payload },
|
||||
bls_to_execution_changes,
|
||||
blob_kzg_commitments,
|
||||
consolidations,
|
||||
} = self;
|
||||
|
||||
BeaconBlockBodyElectra {
|
||||
@@ -726,6 +837,7 @@ impl<E: EthSpec> BeaconBlockBodyElectra<E, FullPayload<E>> {
|
||||
},
|
||||
bls_to_execution_changes: bls_to_execution_changes.clone(),
|
||||
blob_kzg_commitments: blob_kzg_commitments.clone(),
|
||||
consolidations: consolidations.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -759,13 +871,31 @@ impl<E: EthSpec> BeaconBlockBody<E> {
|
||||
_ => return Err(Error::IndexNotSupported(generalized_index)),
|
||||
};
|
||||
|
||||
let attestations_root = match self {
|
||||
BeaconBlockBody::Base(_)
|
||||
| BeaconBlockBody::Altair(_)
|
||||
| BeaconBlockBody::Merge(_)
|
||||
| BeaconBlockBody::Capella(_)
|
||||
| BeaconBlockBody::Deneb(_) => self.attestations_base()?.tree_hash_root(),
|
||||
BeaconBlockBody::Electra(_) => self.attestations_electra()?.tree_hash_root(),
|
||||
};
|
||||
|
||||
let attester_slashings_root = match self {
|
||||
BeaconBlockBody::Base(_)
|
||||
| BeaconBlockBody::Altair(_)
|
||||
| BeaconBlockBody::Merge(_)
|
||||
| BeaconBlockBody::Capella(_)
|
||||
| BeaconBlockBody::Deneb(_) => self.attester_slashings_base()?.tree_hash_root(),
|
||||
BeaconBlockBody::Electra(_) => self.attester_slashings_electra()?.tree_hash_root(),
|
||||
};
|
||||
|
||||
let mut leaves = vec![
|
||||
self.randao_reveal().tree_hash_root(),
|
||||
self.eth1_data().tree_hash_root(),
|
||||
self.graffiti().tree_hash_root(),
|
||||
self.proposer_slashings().tree_hash_root(),
|
||||
self.attester_slashings().tree_hash_root(),
|
||||
self.attestations().tree_hash_root(),
|
||||
attester_slashings_root,
|
||||
attestations_root,
|
||||
self.deposits().tree_hash_root(),
|
||||
self.voluntary_exits().tree_hash_root(),
|
||||
];
|
||||
|
||||
@@ -69,15 +69,16 @@ impl<E: EthSpec> IndexedAttestation<E> {
|
||||
///
|
||||
/// Spec v0.12.1
|
||||
pub fn is_double_vote(&self, other: &Self) -> bool {
|
||||
self.data().target.epoch == other.data().target.epoch && self.data() != other.data()
|
||||
// reuse the ref implementation to ensure logic is the same
|
||||
self.to_ref().is_double_vote(other.to_ref())
|
||||
}
|
||||
|
||||
/// Check if ``attestation_data_1`` surrounds ``attestation_data_2``.
|
||||
///
|
||||
/// Spec v0.12.1
|
||||
pub fn is_surround_vote(&self, other: &Self) -> bool {
|
||||
self.data().source.epoch < other.data().source.epoch
|
||||
&& other.data().target.epoch < self.data().target.epoch
|
||||
// reuse the ref implementation to ensure logic is the same
|
||||
self.to_ref().is_surround_vote(other.to_ref())
|
||||
}
|
||||
|
||||
pub fn attesting_indices_len(&self) -> usize {
|
||||
@@ -116,6 +117,59 @@ impl<E: EthSpec> IndexedAttestation<E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: EthSpec> IndexedAttestationRef<'a, E> {
|
||||
pub fn is_double_vote(&self, other: Self) -> bool {
|
||||
self.data().target.epoch == other.data().target.epoch && self.data() != other.data()
|
||||
}
|
||||
|
||||
pub fn is_surround_vote(&self, other: Self) -> bool {
|
||||
self.data().source.epoch < other.data().source.epoch
|
||||
&& other.data().target.epoch < self.data().target.epoch
|
||||
}
|
||||
|
||||
pub fn attesting_indices_len(&self) -> usize {
|
||||
match self {
|
||||
IndexedAttestationRef::Base(att) => att.attesting_indices.len(),
|
||||
IndexedAttestationRef::Electra(att) => att.attesting_indices.len(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attesting_indices_to_vec(&self) -> Vec<u64> {
|
||||
match self {
|
||||
IndexedAttestationRef::Base(att) => att.attesting_indices.to_vec(),
|
||||
IndexedAttestationRef::Electra(att) => att.attesting_indices.to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attesting_indices_is_empty(&self) -> bool {
|
||||
match self {
|
||||
IndexedAttestationRef::Base(att) => att.attesting_indices.is_empty(),
|
||||
IndexedAttestationRef::Electra(att) => att.attesting_indices.is_empty(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attesting_indices_iter(&self) -> Iter<'_, u64> {
|
||||
match self {
|
||||
IndexedAttestationRef::Base(att) => att.attesting_indices.iter(),
|
||||
IndexedAttestationRef::Electra(att) => att.attesting_indices.iter(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attesting_indices_first(&self) -> Option<&u64> {
|
||||
match self {
|
||||
IndexedAttestationRef::Base(att) => att.attesting_indices.first(),
|
||||
IndexedAttestationRef::Electra(att) => att.attesting_indices.first(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clone_as_indexed_attestation(self) -> IndexedAttestation<E> {
|
||||
match self {
|
||||
IndexedAttestationRef::Base(att) => IndexedAttestation::Base(att.clone()),
|
||||
IndexedAttestationRef::Electra(att) => IndexedAttestation::Electra(att.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Decode for IndexedAttestation<E> {
|
||||
fn is_ssz_fixed_len() -> bool {
|
||||
false
|
||||
|
||||
@@ -115,10 +115,16 @@ use ethereum_types::{H160, H256};
|
||||
|
||||
pub use crate::activation_queue::ActivationQueue;
|
||||
pub use crate::aggregate_and_proof::AggregateAndProof;
|
||||
pub use crate::attestation::{Attestation, Error as AttestationError};
|
||||
pub use crate::attestation::{
|
||||
Attestation, AttestationBase, AttestationElectra, AttestationRef, AttestationRefMut,
|
||||
Error as AttestationError,
|
||||
};
|
||||
pub use crate::attestation_data::AttestationData;
|
||||
pub use crate::attestation_duty::AttestationDuty;
|
||||
pub use crate::attester_slashing::AttesterSlashing;
|
||||
pub use crate::attester_slashing::{
|
||||
AttesterSlashing, AttesterSlashingBase, AttesterSlashingElectra, AttesterSlashingOnDisk,
|
||||
AttesterSlashingRef, AttesterSlashingRefOnDisk,
|
||||
};
|
||||
pub use crate::beacon_block::{
|
||||
BeaconBlock, BeaconBlockAltair, BeaconBlockBase, BeaconBlockCapella, BeaconBlockDeneb,
|
||||
BeaconBlockElectra, BeaconBlockMerge, BeaconBlockRef, BeaconBlockRefMut, BlindedBeaconBlock,
|
||||
@@ -169,7 +175,9 @@ pub use crate::fork_name::{ForkName, InconsistentFork};
|
||||
pub use crate::fork_versioned_response::{ForkVersionDeserialize, ForkVersionedResponse};
|
||||
pub use crate::graffiti::{Graffiti, GRAFFITI_BYTES_LEN};
|
||||
pub use crate::historical_batch::HistoricalBatch;
|
||||
pub use crate::indexed_attestation::IndexedAttestation;
|
||||
pub use crate::indexed_attestation::{
|
||||
IndexedAttestation, IndexedAttestationBase, IndexedAttestationElectra, IndexedAttestationRef,
|
||||
};
|
||||
pub use crate::light_client_bootstrap::{
|
||||
LightClientBootstrap, LightClientBootstrapAltair, LightClientBootstrapCapella,
|
||||
LightClientBootstrapDeneb,
|
||||
|
||||
@@ -498,6 +498,7 @@ impl<E: EthSpec> SignedBeaconBlockElectra<E, BlindedPayload<E>> {
|
||||
execution_payload: BlindedPayloadElectra { .. },
|
||||
bls_to_execution_changes,
|
||||
blob_kzg_commitments,
|
||||
consolidations,
|
||||
},
|
||||
},
|
||||
signature,
|
||||
@@ -521,6 +522,7 @@ impl<E: EthSpec> SignedBeaconBlockElectra<E, BlindedPayload<E>> {
|
||||
execution_payload: FullPayloadElectra { execution_payload },
|
||||
bls_to_execution_changes,
|
||||
blob_kzg_commitments,
|
||||
consolidations,
|
||||
},
|
||||
},
|
||||
signature,
|
||||
|
||||
@@ -110,6 +110,12 @@ impl<E: EthSpec> SlotData for SyncCommitteeContribution<E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> SlotData for &SyncCommitteeContribution<E> {
|
||||
fn get_slot(&self) -> Slot {
|
||||
self.slot
|
||||
}
|
||||
}
|
||||
|
||||
impl SlotData for SyncContributionData {
|
||||
fn get_slot(&self) -> Slot {
|
||||
self.slot
|
||||
|
||||
Reference in New Issue
Block a user