mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-16 12:28:24 +00:00
Merge branch 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-engine-api
This commit is contained in:
@@ -36,8 +36,8 @@ fn get_state<E: EthSpec>(validator_count: usize) -> BeaconState<E> {
|
||||
slashed: false,
|
||||
activation_eligibility_epoch: Epoch::new(0),
|
||||
activation_epoch: Epoch::new(0),
|
||||
exit_epoch: Epoch::from(u64::max_value()),
|
||||
withdrawable_epoch: Epoch::from(u64::max_value()),
|
||||
exit_epoch: Epoch::from(u64::MAX),
|
||||
withdrawable_epoch: Epoch::from(u64::MAX),
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
|
||||
@@ -4,6 +4,7 @@ use super::{
|
||||
SignedRoot,
|
||||
};
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::Attestation;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use superstruct::superstruct;
|
||||
@@ -30,7 +31,7 @@ use tree_hash_derive::TreeHash;
|
||||
),
|
||||
ref_attributes(
|
||||
derive(Debug, PartialEq, TreeHash, Serialize,),
|
||||
serde(bound = "E: EthSpec"),
|
||||
serde(untagged, bound = "E: EthSpec"),
|
||||
tree_hash(enum_behaviour = "transparent")
|
||||
)
|
||||
)]
|
||||
@@ -88,28 +89,39 @@ impl<E: EthSpec> AggregateAndProof<E> {
|
||||
genesis_validators_root: Hash256,
|
||||
spec: &ChainSpec,
|
||||
) -> Self {
|
||||
let selection_proof = selection_proof
|
||||
.unwrap_or_else(|| {
|
||||
SelectionProof::new::<E>(
|
||||
aggregate.data().slot,
|
||||
secret_key,
|
||||
fork,
|
||||
genesis_validators_root,
|
||||
spec,
|
||||
)
|
||||
})
|
||||
.into();
|
||||
let selection_proof = selection_proof.unwrap_or_else(|| {
|
||||
SelectionProof::new::<E>(
|
||||
aggregate.data().slot,
|
||||
secret_key,
|
||||
fork,
|
||||
genesis_validators_root,
|
||||
spec,
|
||||
)
|
||||
});
|
||||
|
||||
Self::from_attestation(
|
||||
aggregator_index,
|
||||
aggregate.clone_as_attestation(),
|
||||
selection_proof,
|
||||
)
|
||||
}
|
||||
|
||||
/// Produces a new `AggregateAndProof` given a `selection_proof`
|
||||
pub fn from_attestation(
|
||||
aggregator_index: u64,
|
||||
aggregate: Attestation<E>,
|
||||
selection_proof: SelectionProof,
|
||||
) -> Self {
|
||||
match aggregate {
|
||||
AttestationRef::Base(attestation) => Self::Base(AggregateAndProofBase {
|
||||
Attestation::Base(aggregate) => Self::Base(AggregateAndProofBase {
|
||||
aggregator_index,
|
||||
aggregate: attestation.clone(),
|
||||
selection_proof,
|
||||
aggregate,
|
||||
selection_proof: selection_proof.into(),
|
||||
}),
|
||||
AttestationRef::Electra(attestation) => Self::Electra(AggregateAndProofElectra {
|
||||
Attestation::Electra(aggregate) => Self::Electra(AggregateAndProofElectra {
|
||||
aggregator_index,
|
||||
aggregate: attestation.clone(),
|
||||
selection_proof,
|
||||
aggregate,
|
||||
selection_proof: selection_proof.into(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::slot_data::SlotData;
|
||||
use crate::{test_utils::TestRandom, Hash256, Slot};
|
||||
use crate::{Checkpoint, ForkName};
|
||||
use derivative::Derivative;
|
||||
use rand::RngCore;
|
||||
use safe_arith::ArithError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
@@ -22,6 +22,8 @@ pub enum Error {
|
||||
AlreadySigned(usize),
|
||||
SubnetCountIsZero(ArithError),
|
||||
IncorrectStateVariant,
|
||||
InvalidCommitteeLength,
|
||||
InvalidCommitteeIndex,
|
||||
}
|
||||
|
||||
#[superstruct(
|
||||
@@ -74,23 +76,6 @@ pub struct Attestation<E: EthSpec> {
|
||||
pub signature: AggregateSignature,
|
||||
}
|
||||
|
||||
// TODO(electra): think about how to handle fork variants here
|
||||
impl<E: EthSpec> TestRandom for Attestation<E> {
|
||||
fn random_for_test(rng: &mut impl RngCore) -> Self {
|
||||
let aggregation_bits = BitList::random_for_test(rng);
|
||||
let data = AttestationData::random_for_test(rng);
|
||||
let signature = AggregateSignature::random_for_test(rng);
|
||||
let committee_bits = BitVector::random_for_test(rng);
|
||||
|
||||
Self::Electra(AttestationElectra {
|
||||
aggregation_bits,
|
||||
committee_bits,
|
||||
data,
|
||||
signature,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Hash for Attestation<E> {
|
||||
fn hash<H>(&self, state: &mut H)
|
||||
where
|
||||
@@ -104,6 +89,50 @@ impl<E: EthSpec> Hash for Attestation<E> {
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Attestation<E> {
|
||||
/// Produces an attestation with empty signature.
|
||||
pub fn empty_for_signing(
|
||||
committee_index: u64,
|
||||
committee_length: usize,
|
||||
slot: Slot,
|
||||
beacon_block_root: Hash256,
|
||||
source: Checkpoint,
|
||||
target: Checkpoint,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Self, Error> {
|
||||
if spec.fork_name_at_slot::<E>(slot) >= ForkName::Electra {
|
||||
let mut committee_bits: BitVector<E::MaxCommitteesPerSlot> = BitVector::default();
|
||||
committee_bits
|
||||
.set(committee_index as usize, true)
|
||||
.map_err(|_| Error::InvalidCommitteeIndex)?;
|
||||
Ok(Attestation::Electra(AttestationElectra {
|
||||
aggregation_bits: BitList::with_capacity(committee_length)
|
||||
.map_err(|_| Error::InvalidCommitteeLength)?,
|
||||
data: AttestationData {
|
||||
slot,
|
||||
index: 0u64,
|
||||
beacon_block_root,
|
||||
source,
|
||||
target,
|
||||
},
|
||||
committee_bits,
|
||||
signature: AggregateSignature::infinity(),
|
||||
}))
|
||||
} else {
|
||||
Ok(Attestation::Base(AttestationBase {
|
||||
aggregation_bits: BitList::with_capacity(committee_length)
|
||||
.map_err(|_| Error::InvalidCommitteeLength)?,
|
||||
data: AttestationData {
|
||||
slot,
|
||||
index: committee_index,
|
||||
beacon_block_root,
|
||||
source,
|
||||
target,
|
||||
},
|
||||
signature: AggregateSignature::infinity(),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
/// Aggregate another Attestation into this one.
|
||||
///
|
||||
/// The aggregation bitfields must be disjoint, and the data must be the same.
|
||||
|
||||
@@ -820,6 +820,11 @@ impl<E: EthSpec> From<BeaconBlockBody<E, FullPayload<E>>>
|
||||
}
|
||||
|
||||
impl<E: EthSpec> BeaconBlockBody<E> {
|
||||
/// Returns the name of the fork pertaining to `self`.
|
||||
pub fn fork_name(&self) -> ForkName {
|
||||
self.to_ref().fork_name()
|
||||
}
|
||||
|
||||
pub fn block_body_merkle_proof(&self, generalized_index: usize) -> Result<Vec<Hash256>, Error> {
|
||||
let field_index = match generalized_index {
|
||||
light_client_update::EXECUTION_PAYLOAD_INDEX => {
|
||||
@@ -834,22 +839,16 @@ impl<E: EthSpec> BeaconBlockBody<E> {
|
||||
_ => return Err(Error::IndexNotSupported(generalized_index)),
|
||||
};
|
||||
|
||||
let attestations_root = match self {
|
||||
BeaconBlockBody::Base(_)
|
||||
| BeaconBlockBody::Altair(_)
|
||||
| BeaconBlockBody::Bellatrix(_)
|
||||
| BeaconBlockBody::Capella(_)
|
||||
| BeaconBlockBody::Deneb(_) => self.attestations_base()?.tree_hash_root(),
|
||||
BeaconBlockBody::Electra(_) => self.attestations_electra()?.tree_hash_root(),
|
||||
let attestations_root = if self.fork_name() > ForkName::Electra {
|
||||
self.attestations_electra()?.tree_hash_root()
|
||||
} else {
|
||||
self.attestations_base()?.tree_hash_root()
|
||||
};
|
||||
|
||||
let attester_slashings_root = match self {
|
||||
BeaconBlockBody::Base(_)
|
||||
| BeaconBlockBody::Altair(_)
|
||||
| BeaconBlockBody::Bellatrix(_)
|
||||
| BeaconBlockBody::Capella(_)
|
||||
| BeaconBlockBody::Deneb(_) => self.attester_slashings_base()?.tree_hash_root(),
|
||||
BeaconBlockBody::Electra(_) => self.attester_slashings_electra()?.tree_hash_root(),
|
||||
let attester_slashings_root = if self.fork_name() > ForkName::Electra {
|
||||
self.attester_slashings_electra()?.tree_hash_root()
|
||||
} else {
|
||||
self.attester_slashings_base()?.tree_hash_root()
|
||||
};
|
||||
|
||||
let mut leaves = vec![
|
||||
|
||||
@@ -86,7 +86,7 @@ impl CommitteeCache {
|
||||
}
|
||||
|
||||
// The use of `NonZeroUsize` reduces the maximum number of possible validators by one.
|
||||
if state.validators().len() == usize::max_value() {
|
||||
if state.validators().len() == usize::MAX {
|
||||
return Err(Error::TooManyValidators);
|
||||
}
|
||||
|
||||
@@ -183,6 +183,8 @@ impl CommitteeCache {
|
||||
}
|
||||
|
||||
/// Get all the Beacon committees at a given `slot`.
|
||||
///
|
||||
/// Committees are sorted by ascending index order 0..committees_per_slot
|
||||
pub fn get_beacon_committees_at_slot(&self, slot: Slot) -> Result<Vec<BeaconCommittee>, Error> {
|
||||
if self.initialized_epoch.is_none() {
|
||||
return Err(Error::CommitteeCacheUninitialized(None));
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
use crate::test_utils::*;
|
||||
use beacon_chain::test_utils::{BeaconChainHarness, EphemeralHarnessType};
|
||||
use beacon_chain::types::*;
|
||||
use lazy_static::lazy_static;
|
||||
use swap_or_not_shuffle::shuffle_list;
|
||||
|
||||
pub const VALIDATOR_COUNT: usize = 16;
|
||||
|
||||
@@ -6,6 +6,7 @@ use beacon_chain::types::{
|
||||
ChainSpec, Domain, Epoch, EthSpec, Hash256, Keypair, MainnetEthSpec, MinimalEthSpec,
|
||||
RelativeEpoch, Slot, Vector,
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
use ssz::Encode;
|
||||
use std::ops::Mul;
|
||||
use swap_or_not_shuffle::compute_shuffled_index;
|
||||
|
||||
@@ -6,13 +6,10 @@ use crate::{
|
||||
use crate::{KzgProofs, SignedBeaconBlock};
|
||||
use bls::Signature;
|
||||
use derivative::Derivative;
|
||||
use kzg::{
|
||||
Blob as KzgBlob, Kzg, KzgCommitment, KzgProof, BYTES_PER_BLOB, BYTES_PER_FIELD_ELEMENT,
|
||||
FIELD_ELEMENTS_PER_BLOB,
|
||||
};
|
||||
use kzg::{Blob as KzgBlob, Kzg, KzgCommitment, KzgProof, BYTES_PER_BLOB, BYTES_PER_FIELD_ELEMENT};
|
||||
use merkle_proof::{merkle_root_from_branch, verify_merkle_proof, MerkleTreeError};
|
||||
use rand::Rng;
|
||||
use safe_arith::{ArithError, SafeArith};
|
||||
use safe_arith::ArithError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz::Encode;
|
||||
use ssz_derive::{Decode, Encode};
|
||||
@@ -190,33 +187,30 @@ impl<E: EthSpec> BlobSidecar<E> {
|
||||
}
|
||||
|
||||
/// Verifies the kzg commitment inclusion merkle proof.
|
||||
pub fn verify_blob_sidecar_inclusion_proof(&self) -> Result<bool, MerkleTreeError> {
|
||||
// Depth of the subtree rooted at `blob_kzg_commitments` in the `BeaconBlockBody`
|
||||
// is equal to depth of the ssz List max size + 1 for the length mixin
|
||||
let kzg_commitments_tree_depth = (E::max_blob_commitments_per_block()
|
||||
.next_power_of_two()
|
||||
.ilog2()
|
||||
.safe_add(1))? as usize;
|
||||
pub fn verify_blob_sidecar_inclusion_proof(&self) -> bool {
|
||||
let kzg_commitments_tree_depth = E::kzg_commitments_tree_depth();
|
||||
|
||||
// EthSpec asserts that kzg_commitments_tree_depth is less than KzgCommitmentInclusionProofDepth
|
||||
let (kzg_commitment_subtree_proof, kzg_commitments_proof) = self
|
||||
.kzg_commitment_inclusion_proof
|
||||
.split_at(kzg_commitments_tree_depth);
|
||||
|
||||
// Compute the `tree_hash_root` of the `blob_kzg_commitments` subtree using the
|
||||
// inclusion proof branches
|
||||
let blob_kzg_commitments_root = merkle_root_from_branch(
|
||||
self.kzg_commitment.tree_hash_root(),
|
||||
self.kzg_commitment_inclusion_proof
|
||||
.get(0..kzg_commitments_tree_depth)
|
||||
.ok_or(MerkleTreeError::PleaseNotifyTheDevs)?,
|
||||
kzg_commitment_subtree_proof,
|
||||
kzg_commitments_tree_depth,
|
||||
self.index as usize,
|
||||
);
|
||||
// The remaining inclusion proof branches are for the top level `BeaconBlockBody` tree
|
||||
Ok(verify_merkle_proof(
|
||||
verify_merkle_proof(
|
||||
blob_kzg_commitments_root,
|
||||
self.kzg_commitment_inclusion_proof
|
||||
.get(kzg_commitments_tree_depth..E::kzg_proof_inclusion_proof_depth())
|
||||
.ok_or(MerkleTreeError::PleaseNotifyTheDevs)?,
|
||||
E::kzg_proof_inclusion_proof_depth().safe_sub(kzg_commitments_tree_depth)?,
|
||||
kzg_commitments_proof,
|
||||
E::block_body_tree_depth(),
|
||||
BLOB_KZG_COMMITMENTS_INDEX,
|
||||
self.signed_block_header.message.body_root,
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
pub fn random_valid<R: Rng>(rng: &mut R, kzg: &Kzg) -> Result<Self, String> {
|
||||
@@ -224,13 +218,7 @@ impl<E: EthSpec> BlobSidecar<E> {
|
||||
rng.fill_bytes(&mut blob_bytes);
|
||||
// Ensure that the blob is canonical by ensuring that
|
||||
// each field element contained in the blob is < BLS_MODULUS
|
||||
for i in 0..FIELD_ELEMENTS_PER_BLOB {
|
||||
let Some(byte) = blob_bytes.get_mut(
|
||||
i.checked_mul(BYTES_PER_FIELD_ELEMENT)
|
||||
.ok_or("overflow".to_string())?,
|
||||
) else {
|
||||
return Err(format!("blob byte index out of bounds: {:?}", i));
|
||||
};
|
||||
for byte in blob_bytes.iter_mut().step_by(BYTES_PER_FIELD_ELEMENT) {
|
||||
*byte = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -376,7 +376,7 @@ impl ChainSpec {
|
||||
state: &BeaconState<E>,
|
||||
) -> u64 {
|
||||
let fork_name = state.fork_name_unchecked();
|
||||
if fork_name >= ForkName::Electra {
|
||||
if fork_name.electra_enabled() {
|
||||
self.min_slashing_penalty_quotient_electra
|
||||
} else if fork_name >= ForkName::Bellatrix {
|
||||
self.min_slashing_penalty_quotient_bellatrix
|
||||
|
||||
@@ -294,6 +294,22 @@ pub trait EthSpec:
|
||||
Self::KzgCommitmentInclusionProofDepth::to_usize()
|
||||
}
|
||||
|
||||
fn kzg_commitments_tree_depth() -> usize {
|
||||
// Depth of the subtree rooted at `blob_kzg_commitments` in the `BeaconBlockBody`
|
||||
// is equal to depth of the ssz List max size + 1 for the length mixin
|
||||
Self::max_blob_commitments_per_block()
|
||||
.next_power_of_two()
|
||||
.ilog2()
|
||||
.safe_add(1)
|
||||
.expect("The log of max_blob_commitments_per_block can not overflow") as usize
|
||||
}
|
||||
|
||||
fn block_body_tree_depth() -> usize {
|
||||
Self::kzg_proof_inclusion_proof_depth()
|
||||
.safe_sub(Self::kzg_commitments_tree_depth())
|
||||
.expect("Preset values are not configurable and never result in non-positive block body depth")
|
||||
}
|
||||
|
||||
/// Returns the `PENDING_BALANCE_DEPOSITS_LIMIT` constant for this specification.
|
||||
fn pending_balance_deposits_limit() -> usize {
|
||||
Self::PendingBalanceDepositsLimit::to_usize()
|
||||
@@ -525,3 +541,28 @@ impl EthSpec for GnosisEthSpec {
|
||||
EthSpecId::Gnosis
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::{EthSpec, GnosisEthSpec, MainnetEthSpec, MinimalEthSpec};
|
||||
use ssz_types::typenum::Unsigned;
|
||||
|
||||
fn assert_valid_spec<E: EthSpec>() {
|
||||
E::kzg_commitments_tree_depth();
|
||||
E::block_body_tree_depth();
|
||||
assert!(E::MaxValidatorsPerSlot::to_i32() >= E::MaxValidatorsPerCommittee::to_i32());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mainnet_spec() {
|
||||
assert_valid_spec::<MainnetEthSpec>();
|
||||
}
|
||||
#[test]
|
||||
fn minimal_spec() {
|
||||
assert_valid_spec::<MinimalEthSpec>();
|
||||
}
|
||||
#[test]
|
||||
fn gnosis_spec() {
|
||||
assert_valid_spec::<GnosisEthSpec>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,6 +119,10 @@ impl ForkName {
|
||||
ForkName::Electra => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn electra_enabled(self) -> bool {
|
||||
self >= ForkName::Electra
|
||||
}
|
||||
}
|
||||
|
||||
/// Map a fork name into a fork-versioned superstruct type like `BeaconBlock`.
|
||||
|
||||
@@ -37,9 +37,9 @@ impl From<[u8; GRAFFITI_BYTES_LEN]> for Graffiti {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<[u8; GRAFFITI_BYTES_LEN]> for Graffiti {
|
||||
fn into(self) -> [u8; GRAFFITI_BYTES_LEN] {
|
||||
self.0
|
||||
impl From<Graffiti> for [u8; GRAFFITI_BYTES_LEN] {
|
||||
fn from(from: Graffiti) -> [u8; GRAFFITI_BYTES_LEN] {
|
||||
from.0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,9 +77,9 @@ impl<'de> Deserialize<'de> for GraffitiString {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Graffiti> for GraffitiString {
|
||||
fn into(self) -> Graffiti {
|
||||
let graffiti_bytes = self.0.as_bytes();
|
||||
impl From<GraffitiString> for Graffiti {
|
||||
fn from(from: GraffitiString) -> Graffiti {
|
||||
let graffiti_bytes = from.0.as_bytes();
|
||||
let mut graffiti = [0; GRAFFITI_BYTES_LEN];
|
||||
|
||||
let graffiti_len = std::cmp::min(graffiti_bytes.len(), GRAFFITI_BYTES_LEN);
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
use crate::{test_utils::TestRandom, AggregateSignature, AttestationData, EthSpec, VariableList};
|
||||
use core::slice::Iter;
|
||||
use derivative::Derivative;
|
||||
use rand::RngCore;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz::Decode;
|
||||
use ssz::Encode;
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use std::hash::{Hash, Hasher};
|
||||
@@ -116,11 +114,14 @@ impl<E: EthSpec> IndexedAttestation<E> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_electra(self) -> Result<IndexedAttestationElectra<E>, ssz_types::Error> {
|
||||
Ok(match self {
|
||||
pub fn to_electra(self) -> IndexedAttestationElectra<E> {
|
||||
match self {
|
||||
Self::Base(att) => {
|
||||
let extended_attesting_indices: VariableList<u64, E::MaxValidatorsPerSlot> =
|
||||
VariableList::new(att.attesting_indices.to_vec())?;
|
||||
VariableList::new(att.attesting_indices.to_vec())
|
||||
.expect("MaxValidatorsPerSlot must be >= MaxValidatorsPerCommittee");
|
||||
// Note a unit test in consensus/types/src/eth_spec.rs asserts this invariant for
|
||||
// all known specs
|
||||
|
||||
IndexedAttestationElectra {
|
||||
attesting_indices: extended_attesting_indices,
|
||||
@@ -129,7 +130,7 @@ impl<E: EthSpec> IndexedAttestation<E> {
|
||||
}
|
||||
}
|
||||
Self::Electra(att) => att,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,43 +187,6 @@ impl<'a, E: EthSpec> IndexedAttestationRef<'a, E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Decode for IndexedAttestation<E> {
|
||||
fn is_ssz_fixed_len() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, ssz::DecodeError> {
|
||||
if let Ok(result) = IndexedAttestationBase::from_ssz_bytes(bytes) {
|
||||
return Ok(IndexedAttestation::Base(result));
|
||||
}
|
||||
|
||||
if let Ok(result) = IndexedAttestationElectra::from_ssz_bytes(bytes) {
|
||||
return Ok(IndexedAttestation::Electra(result));
|
||||
}
|
||||
|
||||
Err(ssz::DecodeError::BytesInvalid(String::from(
|
||||
"bytes not valid for any fork variant",
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(electra): think about how to handle fork variants here
|
||||
impl<E: EthSpec> TestRandom for IndexedAttestation<E> {
|
||||
fn random_for_test(rng: &mut impl RngCore) -> Self {
|
||||
let attesting_indices = VariableList::random_for_test(rng);
|
||||
// let committee_bits: BitList<E::MaxCommitteesPerSlot> = BitList::random_for_test(rng);
|
||||
let data = AttestationData::random_for_test(rng);
|
||||
let signature = AggregateSignature::random_for_test(rng);
|
||||
|
||||
Self::Base(IndexedAttestationBase {
|
||||
attesting_indices,
|
||||
// committee_bits,
|
||||
data,
|
||||
signature,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of non-crypto-secure `Hash`, for use with `HashMap` and `HashSet`.
|
||||
///
|
||||
/// Guarantees `att1 == att2 -> hash(att1) == hash(att2)`.
|
||||
@@ -276,6 +240,38 @@ 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::*;
|
||||
@@ -331,14 +327,22 @@ mod tests {
|
||||
assert!(!indexed_vote_first.is_surround_vote(&indexed_vote_second));
|
||||
}
|
||||
|
||||
ssz_and_tree_hash_tests!(IndexedAttestation<MainnetEthSpec>);
|
||||
mod base {
|
||||
use super::*;
|
||||
ssz_and_tree_hash_tests!(IndexedAttestationBase<MainnetEthSpec>);
|
||||
}
|
||||
mod electra {
|
||||
use super::*;
|
||||
ssz_and_tree_hash_tests!(IndexedAttestationElectra<MainnetEthSpec>);
|
||||
}
|
||||
|
||||
fn create_indexed_attestation(
|
||||
target_epoch: u64,
|
||||
source_epoch: u64,
|
||||
) -> IndexedAttestation<MainnetEthSpec> {
|
||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||
let mut indexed_vote = IndexedAttestation::random_for_test(&mut rng);
|
||||
let mut indexed_vote =
|
||||
IndexedAttestation::Base(IndexedAttestationBase::random_for_test(&mut rng));
|
||||
|
||||
indexed_vote.data_mut().source.epoch = Epoch::new(source_epoch);
|
||||
indexed_vote.data_mut().target.epoch = Epoch::new(target_epoch);
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
)
|
||||
)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
#[macro_use]
|
||||
pub mod test_utils;
|
||||
|
||||
@@ -178,7 +176,8 @@ 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, IndexedAttestationRef,
|
||||
IndexedAttestation, IndexedAttestationBase, IndexedAttestationElectra,
|
||||
IndexedAttestationOnDisk, IndexedAttestationRef, IndexedAttestationRefOnDisk,
|
||||
};
|
||||
pub use crate::light_client_bootstrap::{
|
||||
LightClientBootstrap, LightClientBootstrapAltair, LightClientBootstrapCapella,
|
||||
|
||||
@@ -77,9 +77,9 @@ impl SelectionProof {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Signature> for SelectionProof {
|
||||
fn into(self) -> Signature {
|
||||
self.0
|
||||
impl From<SelectionProof> for Signature {
|
||||
fn from(from: SelectionProof) -> Signature {
|
||||
from.0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ use super::{
|
||||
Signature, SignedRoot,
|
||||
};
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::Attestation;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use superstruct::superstruct;
|
||||
@@ -83,17 +84,19 @@ impl<E: EthSpec> SignedAggregateAndProof<E> {
|
||||
);
|
||||
let signing_message = message.signing_root(domain);
|
||||
|
||||
match message {
|
||||
Self::from_aggregate_and_proof(message, secret_key.sign(signing_message))
|
||||
}
|
||||
|
||||
/// Produces a new `SignedAggregateAndProof` given a `signature` of `aggregate`
|
||||
pub fn from_aggregate_and_proof(aggregate: AggregateAndProof<E>, signature: Signature) -> Self {
|
||||
match aggregate {
|
||||
AggregateAndProof::Base(message) => {
|
||||
SignedAggregateAndProof::Base(SignedAggregateAndProofBase {
|
||||
message,
|
||||
signature: secret_key.sign(signing_message),
|
||||
})
|
||||
SignedAggregateAndProof::Base(SignedAggregateAndProofBase { message, signature })
|
||||
}
|
||||
AggregateAndProof::Electra(message) => {
|
||||
SignedAggregateAndProof::Electra(SignedAggregateAndProofElectra {
|
||||
message,
|
||||
signature: secret_key.sign(signing_message),
|
||||
signature,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -107,4 +110,11 @@ impl<E: EthSpec> SignedAggregateAndProof<E> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ impl Slot {
|
||||
}
|
||||
|
||||
pub fn max_value() -> Slot {
|
||||
Slot(u64::max_value())
|
||||
Slot(u64::MAX)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ impl Epoch {
|
||||
}
|
||||
|
||||
pub fn max_value() -> Epoch {
|
||||
Epoch(u64::max_value())
|
||||
Epoch(u64::MAX)
|
||||
}
|
||||
|
||||
/// The first slot in the epoch.
|
||||
@@ -176,10 +176,10 @@ mod epoch_tests {
|
||||
let slots_per_epoch = 32;
|
||||
|
||||
// The last epoch which can be represented by u64.
|
||||
let epoch = Epoch::new(u64::max_value() / slots_per_epoch);
|
||||
let epoch = Epoch::new(u64::MAX / slots_per_epoch);
|
||||
|
||||
// A slot number on the epoch should be equal to u64::max_value.
|
||||
assert_eq!(epoch.end_slot(slots_per_epoch), Slot::new(u64::max_value()));
|
||||
assert_eq!(epoch.end_slot(slots_per_epoch), Slot::new(u64::MAX));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -6,9 +6,9 @@ macro_rules! impl_from_into_u64 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<u64> for $main {
|
||||
fn into(self) -> u64 {
|
||||
self.0
|
||||
impl From<$main> for u64 {
|
||||
fn from(from: $main) -> u64 {
|
||||
from.0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,9 +28,9 @@ macro_rules! impl_from_into_usize {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<usize> for $main {
|
||||
fn into(self) -> usize {
|
||||
self.0 as usize
|
||||
impl From<$main> for usize {
|
||||
fn from(from: $main) -> usize {
|
||||
from.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,7 +352,7 @@ macro_rules! new_tests {
|
||||
fn new() {
|
||||
assert_eq!($type(0), $type::new(0));
|
||||
assert_eq!($type(3), $type::new(3));
|
||||
assert_eq!($type(u64::max_value()), $type::new(u64::max_value()));
|
||||
assert_eq!($type(u64::MAX), $type::new(u64::MAX));
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -368,17 +368,17 @@ macro_rules! from_into_tests {
|
||||
let x: $other = $type(3).into();
|
||||
assert_eq!(x, 3);
|
||||
|
||||
let x: $other = $type(u64::max_value()).into();
|
||||
let x: $other = $type(u64::MAX).into();
|
||||
// Note: this will fail on 32 bit systems. This is expected as we don't have a proper
|
||||
// 32-bit system strategy in place.
|
||||
assert_eq!(x, $other::max_value());
|
||||
assert_eq!(x, $other::MAX);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from() {
|
||||
assert_eq!($type(0), $type::from(0_u64));
|
||||
assert_eq!($type(3), $type::from(3_u64));
|
||||
assert_eq!($type(u64::max_value()), $type::from($other::max_value()));
|
||||
assert_eq!($type(u64::MAX), $type::from($other::MAX));
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -396,8 +396,8 @@ macro_rules! math_between_tests {
|
||||
|
||||
assert_partial_ord(1, Ordering::Less, 2);
|
||||
assert_partial_ord(2, Ordering::Greater, 1);
|
||||
assert_partial_ord(0, Ordering::Less, u64::max_value());
|
||||
assert_partial_ord(u64::max_value(), Ordering::Greater, 0);
|
||||
assert_partial_ord(0, Ordering::Less, u64::MAX);
|
||||
assert_partial_ord(u64::MAX, Ordering::Greater, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -412,9 +412,9 @@ macro_rules! math_between_tests {
|
||||
assert_partial_eq(1, 0, false);
|
||||
assert_partial_eq(1, 1, true);
|
||||
|
||||
assert_partial_eq(u64::max_value(), u64::max_value(), true);
|
||||
assert_partial_eq(0, u64::max_value(), false);
|
||||
assert_partial_eq(u64::max_value(), 0, false);
|
||||
assert_partial_eq(u64::MAX, u64::MAX, true);
|
||||
assert_partial_eq(0, u64::MAX, false);
|
||||
assert_partial_eq(u64::MAX, 0, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -436,8 +436,8 @@ macro_rules! math_between_tests {
|
||||
assert_add(7, 7, 14);
|
||||
|
||||
// Addition should be saturating.
|
||||
assert_add(u64::max_value(), 1, u64::max_value());
|
||||
assert_add(u64::max_value(), u64::max_value(), u64::max_value());
|
||||
assert_add(u64::MAX, 1, u64::MAX);
|
||||
assert_add(u64::MAX, u64::MAX, u64::MAX);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -455,8 +455,8 @@ macro_rules! math_between_tests {
|
||||
assert_sub(1, 0, 1);
|
||||
assert_sub(2, 1, 1);
|
||||
assert_sub(14, 7, 7);
|
||||
assert_sub(u64::max_value(), 1, u64::max_value() - 1);
|
||||
assert_sub(u64::max_value(), u64::max_value(), 0);
|
||||
assert_sub(u64::MAX, 1, u64::MAX - 1);
|
||||
assert_sub(u64::MAX, u64::MAX, 0);
|
||||
|
||||
// Subtraction should be saturating
|
||||
assert_sub(0, 1, 0);
|
||||
@@ -480,7 +480,7 @@ macro_rules! math_between_tests {
|
||||
assert_mul(0, 2, 0);
|
||||
|
||||
// Multiplication should be saturating.
|
||||
assert_mul(u64::max_value(), 2, u64::max_value());
|
||||
assert_mul(u64::MAX, 2, u64::MAX);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -499,7 +499,7 @@ macro_rules! math_between_tests {
|
||||
assert_div(2, 2, 1);
|
||||
assert_div(100, 50, 2);
|
||||
assert_div(128, 2, 64);
|
||||
assert_div(u64::max_value(), 2, 2_u64.pow(63) - 1);
|
||||
assert_div(u64::MAX, 2, 2_u64.pow(63) - 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -544,8 +544,8 @@ macro_rules! math_tests {
|
||||
assert_saturating_sub(1, 0, 1);
|
||||
assert_saturating_sub(2, 1, 1);
|
||||
assert_saturating_sub(14, 7, 7);
|
||||
assert_saturating_sub(u64::max_value(), 1, u64::max_value() - 1);
|
||||
assert_saturating_sub(u64::max_value(), u64::max_value(), 0);
|
||||
assert_saturating_sub(u64::MAX, 1, u64::MAX - 1);
|
||||
assert_saturating_sub(u64::MAX, u64::MAX, 0);
|
||||
|
||||
// Subtraction should be saturating
|
||||
assert_saturating_sub(0, 1, 0);
|
||||
@@ -565,8 +565,8 @@ macro_rules! math_tests {
|
||||
assert_saturating_add(7, 7, 14);
|
||||
|
||||
// Addition should be saturating.
|
||||
assert_saturating_add(u64::max_value(), 1, u64::max_value());
|
||||
assert_saturating_add(u64::max_value(), u64::max_value(), u64::max_value());
|
||||
assert_saturating_add(u64::MAX, 1, u64::MAX);
|
||||
assert_saturating_add(u64::MAX, u64::MAX, u64::MAX);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -581,11 +581,11 @@ macro_rules! math_tests {
|
||||
assert_checked_div(2, 2, Some(1));
|
||||
assert_checked_div(100, 50, Some(2));
|
||||
assert_checked_div(128, 2, Some(64));
|
||||
assert_checked_div(u64::max_value(), 2, Some(2_u64.pow(63) - 1));
|
||||
assert_checked_div(u64::MAX, 2, Some(2_u64.pow(63) - 1));
|
||||
|
||||
assert_checked_div(2, 0, None);
|
||||
assert_checked_div(0, 0, None);
|
||||
assert_checked_div(u64::max_value(), 0, None);
|
||||
assert_checked_div(u64::MAX, 0, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -607,7 +607,7 @@ macro_rules! math_tests {
|
||||
assert_is_power_of_two(4, true);
|
||||
|
||||
assert_is_power_of_two(2_u64.pow(4), true);
|
||||
assert_is_power_of_two(u64::max_value(), false);
|
||||
assert_is_power_of_two(u64::MAX, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -619,8 +619,8 @@ macro_rules! math_tests {
|
||||
|
||||
assert_ord(1, Ordering::Less, 2);
|
||||
assert_ord(2, Ordering::Greater, 1);
|
||||
assert_ord(0, Ordering::Less, u64::max_value());
|
||||
assert_ord(u64::max_value(), Ordering::Greater, 0);
|
||||
assert_ord(0, Ordering::Less, u64::MAX);
|
||||
assert_ord(u64::MAX, Ordering::Greater, 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -647,8 +647,8 @@ macro_rules! all_tests {
|
||||
let x = $type(3).as_u64();
|
||||
assert_eq!(x, 3);
|
||||
|
||||
let x = $type(u64::max_value()).as_u64();
|
||||
assert_eq!(x, u64::max_value());
|
||||
let x = $type(u64::MAX).as_u64();
|
||||
assert_eq!(x, u64::MAX);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -665,8 +665,8 @@ macro_rules! all_tests {
|
||||
let x = $type(3).as_usize();
|
||||
assert_eq!(x, 3);
|
||||
|
||||
let x = $type(u64::max_value()).as_usize();
|
||||
assert_eq!(x, usize::max_value());
|
||||
let x = $type(u64::MAX).as_usize();
|
||||
assert_eq!(x, usize::MAX);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//! Identifies each shard by an integer identifier.
|
||||
use crate::{AttestationRef, ChainSpec, CommitteeIndex, Epoch, EthSpec, Slot};
|
||||
use lazy_static::lazy_static;
|
||||
use safe_arith::{ArithError, SafeArith};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
@@ -151,15 +152,15 @@ impl From<u64> for SubnetId {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<u64> for SubnetId {
|
||||
fn into(self) -> u64 {
|
||||
self.0
|
||||
impl From<SubnetId> for u64 {
|
||||
fn from(from: SubnetId) -> u64 {
|
||||
from.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<u64> for &SubnetId {
|
||||
fn into(self) -> u64 {
|
||||
self.0
|
||||
impl From<&SubnetId> for u64 {
|
||||
fn from(from: &SubnetId) -> u64 {
|
||||
from.0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -90,9 +90,9 @@ impl SyncSelectionProof {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Signature> for SyncSelectionProof {
|
||||
fn into(self) -> Signature {
|
||||
self.0
|
||||
impl From<SyncSelectionProof> for Signature {
|
||||
fn from(from: SyncSelectionProof) -> Signature {
|
||||
from.0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//! Identifies each sync committee subnet by an integer identifier.
|
||||
use crate::consts::altair::SYNC_COMMITTEE_SUBNET_COUNT;
|
||||
use crate::EthSpec;
|
||||
use lazy_static::lazy_static;
|
||||
use safe_arith::{ArithError, SafeArith};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_types::typenum::Unsigned;
|
||||
@@ -77,15 +78,15 @@ impl From<u64> for SyncSubnetId {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<u64> for SyncSubnetId {
|
||||
fn into(self) -> u64 {
|
||||
self.0
|
||||
impl From<SyncSubnetId> for u64 {
|
||||
fn from(from: SyncSubnetId) -> u64 {
|
||||
from.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<u64> for &SyncSubnetId {
|
||||
fn into(self) -> u64 {
|
||||
self.0
|
||||
impl From<&SyncSubnetId> for u64 {
|
||||
fn from(from: &SyncSubnetId) -> u64 {
|
||||
from.0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
use rand::Rng;
|
||||
|
||||
use kzg::{KzgCommitment, KzgProof};
|
||||
|
||||
use crate::beacon_block_body::KzgCommitments;
|
||||
use crate::*;
|
||||
|
||||
use super::*;
|
||||
|
||||
type BlobsBundle<E> = (KzgCommitments<E>, KzgProofs<E>, BlobsList<E>);
|
||||
|
||||
pub fn generate_rand_block_and_blobs<E: EthSpec>(
|
||||
fork_name: ForkName,
|
||||
num_blobs: usize,
|
||||
rng: &mut impl Rng,
|
||||
) -> (SignedBeaconBlock<E, FullPayload<E>>, Vec<BlobSidecar<E>>) {
|
||||
let inner = map_fork_name!(fork_name, BeaconBlock, <_>::random_for_test(rng));
|
||||
let mut block = SignedBeaconBlock::from_block(inner, Signature::random_for_test(rng));
|
||||
let mut blob_sidecars = vec![];
|
||||
|
||||
if block.fork_name_unchecked() < ForkName::Deneb {
|
||||
return (block, blob_sidecars);
|
||||
}
|
||||
|
||||
let (commitments, proofs, blobs) = generate_blobs::<E>(num_blobs).unwrap();
|
||||
*block
|
||||
.message_mut()
|
||||
.body_mut()
|
||||
.blob_kzg_commitments_mut()
|
||||
.expect("kzg commitment expected from Deneb") = commitments.clone();
|
||||
|
||||
for (index, ((blob, kzg_commitment), kzg_proof)) in blobs
|
||||
.into_iter()
|
||||
.zip(commitments.into_iter())
|
||||
.zip(proofs.into_iter())
|
||||
.enumerate()
|
||||
{
|
||||
blob_sidecars.push(BlobSidecar {
|
||||
index: index as u64,
|
||||
blob: blob.clone(),
|
||||
kzg_commitment,
|
||||
kzg_proof,
|
||||
signed_block_header: block.signed_block_header(),
|
||||
kzg_commitment_inclusion_proof: block
|
||||
.message()
|
||||
.body()
|
||||
.kzg_commitment_merkle_proof(index)
|
||||
.unwrap(),
|
||||
});
|
||||
}
|
||||
(block, blob_sidecars)
|
||||
}
|
||||
|
||||
pub fn generate_blobs<E: EthSpec>(n_blobs: usize) -> Result<BlobsBundle<E>, String> {
|
||||
let (mut commitments, mut proofs, mut blobs) = BlobsBundle::<E>::default();
|
||||
|
||||
for blob_index in 0..n_blobs {
|
||||
blobs
|
||||
.push(Blob::<E>::default())
|
||||
.map_err(|_| format!("blobs are full, blob index: {:?}", blob_index))?;
|
||||
commitments
|
||||
.push(KzgCommitment::empty_for_testing())
|
||||
.map_err(|_| format!("blobs are full, blob index: {:?}", blob_index))?;
|
||||
proofs
|
||||
.push(KzgProof::empty())
|
||||
.map_err(|_| format!("blobs are full, blob index: {:?}", blob_index))?;
|
||||
}
|
||||
|
||||
Ok((commitments, proofs, blobs))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use rand::thread_rng;
|
||||
|
||||
#[test]
|
||||
fn test_verify_blob_inclusion_proof() {
|
||||
let (_block, blobs) =
|
||||
generate_rand_block_and_blobs::<MainnetEthSpec>(ForkName::Deneb, 6, &mut thread_rng());
|
||||
for blob in blobs {
|
||||
assert!(blob.verify_blob_sidecar_inclusion_proof());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_verify_blob_inclusion_proof_invalid() {
|
||||
let (_block, blobs) =
|
||||
generate_rand_block_and_blobs::<MainnetEthSpec>(ForkName::Deneb, 6, &mut thread_rng());
|
||||
|
||||
for mut blob in blobs {
|
||||
blob.kzg_commitment_inclusion_proof = FixedVector::random_for_test(&mut thread_rng());
|
||||
assert!(!blob.verify_blob_sidecar_inclusion_proof());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,8 @@ use tree_hash::TreeHash;
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
mod generate_deterministic_keypairs;
|
||||
#[cfg(test)]
|
||||
mod generate_random_block_and_blobs;
|
||||
mod test_random;
|
||||
|
||||
pub fn test_ssz_tree_hash_pair<T, U>(v1: &T, v2: &U)
|
||||
|
||||
@@ -63,7 +63,7 @@ impl Validator {
|
||||
spec: &ChainSpec,
|
||||
current_fork: ForkName,
|
||||
) -> bool {
|
||||
if current_fork >= ForkName::Electra {
|
||||
if current_fork.electra_enabled() {
|
||||
self.is_eligible_for_activation_queue_electra(spec)
|
||||
} else {
|
||||
self.is_eligible_for_activation_queue_base(spec)
|
||||
@@ -172,7 +172,7 @@ impl Validator {
|
||||
spec: &ChainSpec,
|
||||
current_fork: ForkName,
|
||||
) -> bool {
|
||||
if current_fork >= ForkName::Electra {
|
||||
if current_fork.electra_enabled() {
|
||||
self.is_fully_withdrawable_at_electra(balance, epoch, spec)
|
||||
} else {
|
||||
self.is_fully_withdrawable_at_capella(balance, epoch, spec)
|
||||
@@ -212,7 +212,7 @@ impl Validator {
|
||||
spec: &ChainSpec,
|
||||
current_fork: ForkName,
|
||||
) -> bool {
|
||||
if current_fork >= ForkName::Electra {
|
||||
if current_fork.electra_enabled() {
|
||||
self.is_partially_withdrawable_validator_electra(balance, spec, current_fork)
|
||||
} else {
|
||||
self.is_partially_withdrawable_validator_capella(balance, spec)
|
||||
@@ -283,12 +283,12 @@ impl Default for Validator {
|
||||
Self {
|
||||
pubkey: PublicKeyBytes::empty(),
|
||||
withdrawal_credentials: Hash256::default(),
|
||||
activation_eligibility_epoch: Epoch::from(std::u64::MAX),
|
||||
activation_epoch: Epoch::from(std::u64::MAX),
|
||||
exit_epoch: Epoch::from(std::u64::MAX),
|
||||
withdrawable_epoch: Epoch::from(std::u64::MAX),
|
||||
activation_eligibility_epoch: Epoch::from(u64::MAX),
|
||||
activation_epoch: Epoch::from(u64::MAX),
|
||||
exit_epoch: Epoch::from(u64::MAX),
|
||||
withdrawable_epoch: Epoch::from(u64::MAX),
|
||||
slashed: false,
|
||||
effective_balance: std::u64::MAX,
|
||||
effective_balance: u64::MAX,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user