mirror of
https://github.com/sigp/lighthouse.git
synced 2026-07-05 05:44:30 +00:00
Updated consensus types for Gloas 1.7.0-alpha.1 (#8688)
Pulling out consensus type changes from #8677. This PR covers all type changes for spec 1.7.0-alpha.1 (except for `DataColumnSidecar` changes, which is covered in @eserilev's PR #8682) Co-Authored-By: Jimmy Chen <jchen.tc@gmail.com> Co-Authored-By: Michael Sproul <michael@sigmaprime.io>
This commit is contained in:
@@ -1364,6 +1364,7 @@ async fn proposer_shuffling_root_consistency_at_fork_boundary() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
#[allow(clippy::large_stack_frames)]
|
||||||
async fn proposer_shuffling_changing_with_lookahead() {
|
async fn proposer_shuffling_changing_with_lookahead() {
|
||||||
let initial_blocks = E::slots_per_epoch() * 4 - 1;
|
let initial_blocks = E::slots_per_epoch() * 4 - 1;
|
||||||
|
|
||||||
|
|||||||
@@ -22,13 +22,13 @@ TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH: 18446744073709551615
|
|||||||
|
|
||||||
# Genesis
|
# Genesis
|
||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
# `2**14` (= 16,384)
|
# 2**14 (= 16,384) validators
|
||||||
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 16384
|
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 16384
|
||||||
# Dec 1, 2020, 12pm UTC
|
# Dec 1, 2020, 12pm UTC
|
||||||
MIN_GENESIS_TIME: 1606824000
|
MIN_GENESIS_TIME: 1606824000
|
||||||
# Mainnet initial fork version, recommend altering for testnets
|
# Initial fork version for mainnet
|
||||||
GENESIS_FORK_VERSION: 0x00000000
|
GENESIS_FORK_VERSION: 0x00000000
|
||||||
# 604800 seconds (7 days)
|
# 7 * 24 * 3,600 (= 604,800) seconds, 7 days
|
||||||
GENESIS_DELAY: 604800
|
GENESIS_DELAY: 604800
|
||||||
|
|
||||||
# Forking
|
# Forking
|
||||||
@@ -39,25 +39,34 @@ GENESIS_DELAY: 604800
|
|||||||
|
|
||||||
# Altair
|
# Altair
|
||||||
ALTAIR_FORK_VERSION: 0x01000000
|
ALTAIR_FORK_VERSION: 0x01000000
|
||||||
ALTAIR_FORK_EPOCH: 74240 # Oct 27, 2021, 10:56:23am UTC
|
ALTAIR_FORK_EPOCH: 74240 # Oct 27, 2021, 10:56:23am UTC
|
||||||
# Bellatrix
|
# Bellatrix
|
||||||
BELLATRIX_FORK_VERSION: 0x02000000
|
BELLATRIX_FORK_VERSION: 0x02000000
|
||||||
BELLATRIX_FORK_EPOCH: 144896 # Sept 6, 2022, 11:34:47am UTC
|
BELLATRIX_FORK_EPOCH: 144896 # Sept 6, 2022, 11:34:47am UTC
|
||||||
# Capella
|
# Capella
|
||||||
CAPELLA_FORK_VERSION: 0x03000000
|
CAPELLA_FORK_VERSION: 0x03000000
|
||||||
CAPELLA_FORK_EPOCH: 194048 # April 12, 2023, 10:27:35pm UTC
|
CAPELLA_FORK_EPOCH: 194048 # April 12, 2023, 10:27:35pm UTC
|
||||||
# Deneb
|
# Deneb
|
||||||
DENEB_FORK_VERSION: 0x04000000
|
DENEB_FORK_VERSION: 0x04000000
|
||||||
DENEB_FORK_EPOCH: 269568 # March 13, 2024, 01:55:35pm UTC
|
DENEB_FORK_EPOCH: 269568 # March 13, 2024, 01:55:35pm UTC
|
||||||
# Electra
|
# Electra
|
||||||
ELECTRA_FORK_VERSION: 0x05000000
|
ELECTRA_FORK_VERSION: 0x05000000
|
||||||
ELECTRA_FORK_EPOCH: 364032 # May 7, 2025, 10:05:11am UTC
|
ELECTRA_FORK_EPOCH: 364032 # May 7, 2025, 10:05:11am UTC
|
||||||
# Fulu
|
# Fulu
|
||||||
FULU_FORK_VERSION: 0x06000000
|
FULU_FORK_VERSION: 0x06000000
|
||||||
FULU_FORK_EPOCH: 411392 # December 3, 2025, 09:49:11pm UTC
|
FULU_FORK_EPOCH: 411392 # December 3, 2025, 09:49:11pm UTC
|
||||||
# Gloas
|
# Gloas
|
||||||
GLOAS_FORK_VERSION: 0x07000000
|
GLOAS_FORK_VERSION: 0x07000000 # temporary stub
|
||||||
GLOAS_FORK_EPOCH: 18446744073709551615
|
GLOAS_FORK_EPOCH: 18446744073709551615
|
||||||
|
# EIP7441
|
||||||
|
EIP7441_FORK_VERSION: 0x08000000 # temporary stub
|
||||||
|
EIP7441_FORK_EPOCH: 18446744073709551615
|
||||||
|
# EIP7805
|
||||||
|
EIP7805_FORK_VERSION: 0x0a000000 # temporary stub
|
||||||
|
EIP7805_FORK_EPOCH: 18446744073709551615
|
||||||
|
# EIP7928
|
||||||
|
EIP7928_FORK_VERSION: 0x0b000000 # temporary stub
|
||||||
|
EIP7928_FORK_EPOCH: 18446744073709551615
|
||||||
|
|
||||||
# Time parameters
|
# Time parameters
|
||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
@@ -86,6 +95,28 @@ SYNC_MESSAGE_DUE_BPS: 3333
|
|||||||
# 6667 basis points, ~67% of SLOT_DURATION_MS
|
# 6667 basis points, ~67% of SLOT_DURATION_MS
|
||||||
CONTRIBUTION_DUE_BPS: 6667
|
CONTRIBUTION_DUE_BPS: 6667
|
||||||
|
|
||||||
|
# Gloas
|
||||||
|
# 2**12 (= 4,096) epochs
|
||||||
|
MIN_BUILDER_WITHDRAWABILITY_DELAY: 4096
|
||||||
|
# 2500 basis points, 25% of SLOT_DURATION_MS
|
||||||
|
ATTESTATION_DUE_BPS_GLOAS: 2500
|
||||||
|
# 5000 basis points, 50% of SLOT_DURATION_MS
|
||||||
|
AGGREGATE_DUE_BPS_GLOAS: 5000
|
||||||
|
# 2500 basis points, 25% of SLOT_DURATION_MS
|
||||||
|
SYNC_MESSAGE_DUE_BPS_GLOAS: 2500
|
||||||
|
# 5000 basis points, 50% of SLOT_DURATION_MS
|
||||||
|
CONTRIBUTION_DUE_BPS_GLOAS: 5000
|
||||||
|
# 7500 basis points, 75% of SLOT_DURATION_MS
|
||||||
|
PAYLOAD_ATTESTATION_DUE_BPS: 7500
|
||||||
|
|
||||||
|
# EIP7805
|
||||||
|
# 7500 basis points, 75% of SLOT_DURATION_MS
|
||||||
|
VIEW_FREEZE_CUTOFF_BPS: 7500
|
||||||
|
# 6667 basis points, ~67% of SLOT_DURATION_MS
|
||||||
|
INCLUSION_LIST_SUBMISSION_DUE_BPS: 6667
|
||||||
|
# 9167 basis points, ~92% of SLOT_DURATION_MS
|
||||||
|
PROPOSER_INCLUSION_LIST_CUTOFF_BPS: 9167
|
||||||
|
|
||||||
# Validator cycle
|
# Validator cycle
|
||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
# 2**2 (= 4)
|
# 2**2 (= 4)
|
||||||
@@ -137,10 +168,6 @@ MAX_REQUEST_BLOCKS: 1024
|
|||||||
EPOCHS_PER_SUBNET_SUBSCRIPTION: 256
|
EPOCHS_PER_SUBNET_SUBSCRIPTION: 256
|
||||||
# MIN_VALIDATOR_WITHDRAWABILITY_DELAY + CHURN_LIMIT_QUOTIENT // 2 (= 33,024) epochs
|
# MIN_VALIDATOR_WITHDRAWABILITY_DELAY + CHURN_LIMIT_QUOTIENT // 2 (= 33,024) epochs
|
||||||
MIN_EPOCHS_FOR_BLOCK_REQUESTS: 33024
|
MIN_EPOCHS_FOR_BLOCK_REQUESTS: 33024
|
||||||
# 5s
|
|
||||||
TTFB_TIMEOUT: 5
|
|
||||||
# 10s
|
|
||||||
RESP_TIMEOUT: 10
|
|
||||||
# 2**5 (= 32) slots
|
# 2**5 (= 32) slots
|
||||||
ATTESTATION_PROPAGATION_SLOT_RANGE: 32
|
ATTESTATION_PROPAGATION_SLOT_RANGE: 32
|
||||||
# 500ms
|
# 500ms
|
||||||
@@ -154,9 +181,7 @@ ATTESTATION_SUBNET_COUNT: 64
|
|||||||
# 0 bits
|
# 0 bits
|
||||||
ATTESTATION_SUBNET_EXTRA_BITS: 0
|
ATTESTATION_SUBNET_EXTRA_BITS: 0
|
||||||
# ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS (= 6 + 0) bits
|
# ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS (= 6 + 0) bits
|
||||||
# computed at runtime
|
|
||||||
ATTESTATION_SUBNET_PREFIX_BITS: 6
|
ATTESTATION_SUBNET_PREFIX_BITS: 6
|
||||||
ATTESTATION_SUBNET_SHUFFLING_PREFIX_BITS: 3
|
|
||||||
|
|
||||||
# Deneb
|
# Deneb
|
||||||
# 2**7 (= 128) blocks
|
# 2**7 (= 128) blocks
|
||||||
@@ -196,6 +221,22 @@ BALANCE_PER_ADDITIONAL_CUSTODY_GROUP: 32000000000
|
|||||||
# 2**12 (= 4,096) epochs
|
# 2**12 (= 4,096) epochs
|
||||||
MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS: 4096
|
MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS: 4096
|
||||||
|
|
||||||
|
# Gloas
|
||||||
|
# 2**7 (= 128) payloads
|
||||||
|
MAX_REQUEST_PAYLOADS: 128
|
||||||
|
|
||||||
|
# EIP7441
|
||||||
|
# 2**8 (= 256) epochs
|
||||||
|
EPOCHS_PER_SHUFFLING_PHASE: 256
|
||||||
|
# 2**1 (= 2) epochs
|
||||||
|
PROPOSER_SELECTION_GAP: 2
|
||||||
|
|
||||||
|
# EIP7805
|
||||||
|
# 2**4 (= 16) inclusion lists
|
||||||
|
MAX_REQUEST_INCLUSION_LIST: 16
|
||||||
|
# 2**13 (= 8,192) bytes
|
||||||
|
MAX_BYTES_PER_INCLUSION_LIST: 8192
|
||||||
|
|
||||||
# Blob Scheduling
|
# Blob Scheduling
|
||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
|
|
||||||
@@ -204,5 +245,3 @@ BLOB_SCHEDULE:
|
|||||||
MAX_BLOBS_PER_BLOCK: 15
|
MAX_BLOBS_PER_BLOCK: 15
|
||||||
- EPOCH: 419072 # January 7, 2026, 01:01:11am UTC
|
- EPOCH: 419072 # January 7, 2026, 01:01:11am UTC
|
||||||
MAX_BLOBS_PER_BLOCK: 21
|
MAX_BLOBS_PER_BLOCK: 21
|
||||||
|
|
||||||
# Gloas
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use bls::Hash256;
|
|
||||||
use milhouse::{List, Vector};
|
use milhouse::{List, Vector};
|
||||||
use ssz_types::BitVector;
|
use ssz_types::BitVector;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use typenum::Unsigned;
|
||||||
use types::{
|
use types::{
|
||||||
BeaconState, BeaconStateError as Error, BeaconStateGloas, BuilderPendingPayment, ChainSpec,
|
BeaconState, BeaconStateError as Error, BeaconStateGloas, BuilderPendingPayment, ChainSpec,
|
||||||
EthSpec, ExecutionPayloadBid, Fork,
|
EthSpec, ExecutionPayloadBid, Fork,
|
||||||
@@ -88,15 +88,23 @@ pub fn upgrade_state_to_gloas<E: EthSpec>(
|
|||||||
pending_deposits: pre.pending_deposits.clone(),
|
pending_deposits: pre.pending_deposits.clone(),
|
||||||
pending_partial_withdrawals: pre.pending_partial_withdrawals.clone(),
|
pending_partial_withdrawals: pre.pending_partial_withdrawals.clone(),
|
||||||
pending_consolidations: pre.pending_consolidations.clone(),
|
pending_consolidations: pre.pending_consolidations.clone(),
|
||||||
|
proposer_lookahead: mem::take(&mut pre.proposer_lookahead),
|
||||||
// Gloas
|
// Gloas
|
||||||
execution_payload_availability: BitVector::default(), // All bits set to false initially
|
builders: List::default(),
|
||||||
|
next_withdrawal_builder_index: 0,
|
||||||
|
// All bits set to true per spec:
|
||||||
|
// execution_payload_availability = [0b1 for _ in range(SLOTS_PER_HISTORICAL_ROOT)]
|
||||||
|
execution_payload_availability: BitVector::from_bytes(
|
||||||
|
vec![0xFFu8; E::SlotsPerHistoricalRoot::to_usize() / 8].into(),
|
||||||
|
)
|
||||||
|
.map_err(|_| Error::InvalidBitfield)?,
|
||||||
builder_pending_payments: Vector::new(vec![
|
builder_pending_payments: Vector::new(vec![
|
||||||
BuilderPendingPayment::default();
|
BuilderPendingPayment::default();
|
||||||
E::builder_pending_payments_limit()
|
E::builder_pending_payments_limit()
|
||||||
])?,
|
])?,
|
||||||
builder_pending_withdrawals: List::default(), // Empty list initially,
|
builder_pending_withdrawals: List::default(), // Empty list initially,
|
||||||
latest_block_hash: pre.latest_execution_payload_header.block_hash,
|
latest_block_hash: pre.latest_execution_payload_header.block_hash,
|
||||||
latest_withdrawals_root: Hash256::default(),
|
payload_expected_withdrawals: List::default(),
|
||||||
// Caches
|
// Caches
|
||||||
total_active_balance: pre.total_active_balance,
|
total_active_balance: pre.total_active_balance,
|
||||||
progressive_balances_cache: mem::take(&mut pre.progressive_balances_cache),
|
progressive_balances_cache: mem::take(&mut pre.progressive_balances_cache),
|
||||||
@@ -105,7 +113,6 @@ pub fn upgrade_state_to_gloas<E: EthSpec>(
|
|||||||
exit_cache: mem::take(&mut pre.exit_cache),
|
exit_cache: mem::take(&mut pre.exit_cache),
|
||||||
slashings_cache: mem::take(&mut pre.slashings_cache),
|
slashings_cache: mem::take(&mut pre.slashings_cache),
|
||||||
epoch_cache: mem::take(&mut pre.epoch_cache),
|
epoch_cache: mem::take(&mut pre.epoch_cache),
|
||||||
proposer_lookahead: mem::take(&mut pre.proposer_lookahead),
|
|
||||||
});
|
});
|
||||||
Ok(post)
|
Ok(post)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1,23 @@
|
|||||||
# Mainnet preset - Gloas
|
# Mainnet preset - Gloas
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
# 2**9 (= 512) validators
|
||||||
|
PTC_SIZE: 512
|
||||||
|
|
||||||
|
# Max operations per block
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
# 2**2 (= 4) attestations
|
||||||
|
MAX_PAYLOAD_ATTESTATIONS: 4
|
||||||
|
|
||||||
|
# State list lengths
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
# 2**40 (= 1,099,511,627,776) builder spots
|
||||||
|
BUILDER_REGISTRY_LIMIT: 1099511627776
|
||||||
|
# 2**20 (= 1,048,576) builder pending withdrawals
|
||||||
|
BUILDER_PENDING_WITHDRAWALS_LIMIT: 1048576
|
||||||
|
|
||||||
|
# Withdrawals processing
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
# 2**14 (= 16,384) builders
|
||||||
|
MAX_BUILDERS_PER_WITHDRAWALS_SWEEP: 16384
|
||||||
@@ -1 +1,23 @@
|
|||||||
# Minimal preset - Gloas
|
# Minimal preset - Gloas
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
# [customized] 2**1 (= 2) validators
|
||||||
|
PTC_SIZE: 2
|
||||||
|
|
||||||
|
# Max operations per block
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
# 2**2 (= 4) attestations
|
||||||
|
MAX_PAYLOAD_ATTESTATIONS: 4
|
||||||
|
|
||||||
|
# State list lengths
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
# 2**40 (= 1,099,511,627,776) builder spots
|
||||||
|
BUILDER_REGISTRY_LIMIT: 1099511627776
|
||||||
|
# 2**20 (= 1,048,576) builder pending withdrawals
|
||||||
|
BUILDER_PENDING_WITHDRAWALS_LIMIT: 1048576
|
||||||
|
|
||||||
|
# Withdrawals processing
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
# [customized] 2**4 (= 16) builders
|
||||||
|
MAX_BUILDERS_PER_WITHDRAWALS_SWEEP: 16
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ mod payload_attestation;
|
|||||||
mod payload_attestation_data;
|
mod payload_attestation_data;
|
||||||
mod payload_attestation_message;
|
mod payload_attestation_message;
|
||||||
mod pending_attestation;
|
mod pending_attestation;
|
||||||
|
mod ptc;
|
||||||
mod selection_proof;
|
mod selection_proof;
|
||||||
mod shuffling_id;
|
mod shuffling_id;
|
||||||
mod signed_aggregate_and_proof;
|
mod signed_aggregate_and_proof;
|
||||||
@@ -36,6 +37,7 @@ pub use payload_attestation::PayloadAttestation;
|
|||||||
pub use payload_attestation_data::PayloadAttestationData;
|
pub use payload_attestation_data::PayloadAttestationData;
|
||||||
pub use payload_attestation_message::PayloadAttestationMessage;
|
pub use payload_attestation_message::PayloadAttestationMessage;
|
||||||
pub use pending_attestation::PendingAttestation;
|
pub use pending_attestation::PendingAttestation;
|
||||||
|
pub use ptc::PTC;
|
||||||
pub use selection_proof::SelectionProof;
|
pub use selection_proof::SelectionProof;
|
||||||
pub use shuffling_id::AttestationShufflingId;
|
pub use shuffling_id::AttestationShufflingId;
|
||||||
pub use signed_aggregate_and_proof::{
|
pub use signed_aggregate_and_proof::{
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use bls::AggregateSignature;
|
|||||||
use context_deserialize::context_deserialize;
|
use context_deserialize::context_deserialize;
|
||||||
use educe::Educe;
|
use educe::Educe;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use ssz::BitList;
|
use ssz::BitVector;
|
||||||
use ssz_derive::{Decode, Encode};
|
use ssz_derive::{Decode, Encode};
|
||||||
use test_random_derive::TestRandom;
|
use test_random_derive::TestRandom;
|
||||||
use tree_hash_derive::TreeHash;
|
use tree_hash_derive::TreeHash;
|
||||||
@@ -17,7 +17,7 @@ use tree_hash_derive::TreeHash;
|
|||||||
#[educe(PartialEq, Hash)]
|
#[educe(PartialEq, Hash)]
|
||||||
#[context_deserialize(ForkName)]
|
#[context_deserialize(ForkName)]
|
||||||
pub struct PayloadAttestation<E: EthSpec> {
|
pub struct PayloadAttestation<E: EthSpec> {
|
||||||
pub aggregation_bits: BitList<E::PTCSize>,
|
pub aggregation_bits: BitVector<E::PTCSize>,
|
||||||
pub data: PayloadAttestationData,
|
pub data: PayloadAttestationData,
|
||||||
pub signature: AggregateSignature,
|
pub signature: AggregateSignature,
|
||||||
}
|
}
|
||||||
|
|||||||
23
consensus/types/src/attestation/ptc.rs
Normal file
23
consensus/types/src/attestation/ptc.rs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
use crate::EthSpec;
|
||||||
|
use ssz_types::FixedVector;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub struct PTC<E: EthSpec>(pub FixedVector<usize, E::PTCSize>);
|
||||||
|
|
||||||
|
impl<'a, E: EthSpec> IntoIterator for &'a PTC<E> {
|
||||||
|
type Item = &'a usize;
|
||||||
|
type IntoIter = std::slice::Iter<'a, usize>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.0.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: EthSpec> IntoIterator for PTC<E> {
|
||||||
|
type Item = usize;
|
||||||
|
type IntoIter = std::vec::IntoIter<usize>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.0.into_iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
24
consensus/types/src/builder/builder.rs
Normal file
24
consensus/types/src/builder/builder.rs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
use crate::test_utils::TestRandom;
|
||||||
|
use crate::{Address, Epoch};
|
||||||
|
use bls::PublicKeyBytes;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use ssz_derive::{Decode, Encode};
|
||||||
|
use test_random_derive::TestRandom;
|
||||||
|
use tree_hash_derive::TreeHash;
|
||||||
|
|
||||||
|
pub type BuilderIndex = u64;
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
||||||
|
#[derive(
|
||||||
|
Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Encode, Decode, TestRandom, TreeHash,
|
||||||
|
)]
|
||||||
|
pub struct Builder {
|
||||||
|
pub pubkey: PublicKeyBytes,
|
||||||
|
#[serde(with = "serde_utils::quoted_u8")]
|
||||||
|
pub version: u8,
|
||||||
|
pub execution_address: Address,
|
||||||
|
#[serde(with = "serde_utils::quoted_u64")]
|
||||||
|
pub balance: u64,
|
||||||
|
pub deposit_epoch: Epoch,
|
||||||
|
pub withdrawable_epoch: Epoch,
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
use crate::{Address, Epoch, ForkName};
|
use crate::{Address, ForkName};
|
||||||
use context_deserialize::context_deserialize;
|
use context_deserialize::context_deserialize;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use ssz_derive::{Decode, Encode};
|
use ssz_derive::{Decode, Encode};
|
||||||
@@ -29,7 +29,6 @@ pub struct BuilderPendingWithdrawal {
|
|||||||
pub amount: u64,
|
pub amount: u64,
|
||||||
#[serde(with = "serde_utils::quoted_u64")]
|
#[serde(with = "serde_utils::quoted_u64")]
|
||||||
pub builder_index: u64,
|
pub builder_index: u64,
|
||||||
pub withdrawable_epoch: Epoch,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
mod builder;
|
||||||
mod builder_bid;
|
mod builder_bid;
|
||||||
mod builder_pending_payment;
|
mod builder_pending_payment;
|
||||||
mod builder_pending_withdrawal;
|
mod builder_pending_withdrawal;
|
||||||
|
|
||||||
|
pub use builder::{Builder, BuilderIndex};
|
||||||
pub use builder_bid::{
|
pub use builder_bid::{
|
||||||
BuilderBid, BuilderBidBellatrix, BuilderBidCapella, BuilderBidDeneb, BuilderBidElectra,
|
BuilderBid, BuilderBidBellatrix, BuilderBidCapella, BuilderBidDeneb, BuilderBidElectra,
|
||||||
BuilderBidFulu, SignedBuilderBid,
|
BuilderBidFulu, SignedBuilderBid,
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ pub enum Domain {
|
|||||||
SyncCommitteeSelectionProof,
|
SyncCommitteeSelectionProof,
|
||||||
BeaconBuilder,
|
BeaconBuilder,
|
||||||
PTCAttester,
|
PTCAttester,
|
||||||
|
ProposerPreferences,
|
||||||
ApplicationMask(ApplicationDomain),
|
ApplicationMask(ApplicationDomain),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,6 +131,7 @@ pub struct ChainSpec {
|
|||||||
pub(crate) domain_aggregate_and_proof: u32,
|
pub(crate) domain_aggregate_and_proof: u32,
|
||||||
pub(crate) domain_beacon_builder: u32,
|
pub(crate) domain_beacon_builder: u32,
|
||||||
pub(crate) domain_ptc_attester: u32,
|
pub(crate) domain_ptc_attester: u32,
|
||||||
|
pub(crate) domain_proposer_preferences: u32,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fork choice
|
* Fork choice
|
||||||
@@ -234,6 +236,7 @@ pub struct ChainSpec {
|
|||||||
pub gloas_fork_epoch: Option<Epoch>,
|
pub gloas_fork_epoch: Option<Epoch>,
|
||||||
pub builder_payment_threshold_numerator: u64,
|
pub builder_payment_threshold_numerator: u64,
|
||||||
pub builder_payment_threshold_denominator: u64,
|
pub builder_payment_threshold_denominator: u64,
|
||||||
|
pub min_builder_withdrawability_delay: Epoch,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Networking
|
* Networking
|
||||||
@@ -500,6 +503,7 @@ impl ChainSpec {
|
|||||||
Domain::AggregateAndProof => self.domain_aggregate_and_proof,
|
Domain::AggregateAndProof => self.domain_aggregate_and_proof,
|
||||||
Domain::BeaconBuilder => self.domain_beacon_builder,
|
Domain::BeaconBuilder => self.domain_beacon_builder,
|
||||||
Domain::PTCAttester => self.domain_ptc_attester,
|
Domain::PTCAttester => self.domain_ptc_attester,
|
||||||
|
Domain::ProposerPreferences => self.domain_proposer_preferences,
|
||||||
Domain::SyncCommittee => self.domain_sync_committee,
|
Domain::SyncCommittee => self.domain_sync_committee,
|
||||||
Domain::ContributionAndProof => self.domain_contribution_and_proof,
|
Domain::ContributionAndProof => self.domain_contribution_and_proof,
|
||||||
Domain::SyncCommitteeSelectionProof => self.domain_sync_committee_selection_proof,
|
Domain::SyncCommitteeSelectionProof => self.domain_sync_committee_selection_proof,
|
||||||
@@ -977,8 +981,9 @@ impl ChainSpec {
|
|||||||
domain_voluntary_exit: 4,
|
domain_voluntary_exit: 4,
|
||||||
domain_selection_proof: 5,
|
domain_selection_proof: 5,
|
||||||
domain_aggregate_and_proof: 6,
|
domain_aggregate_and_proof: 6,
|
||||||
domain_beacon_builder: 0x1B,
|
domain_beacon_builder: 0x0B,
|
||||||
domain_ptc_attester: 0x0C,
|
domain_ptc_attester: 0x0C,
|
||||||
|
domain_proposer_preferences: 0x0D,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fork choice
|
* Fork choice
|
||||||
@@ -1102,6 +1107,7 @@ impl ChainSpec {
|
|||||||
gloas_fork_epoch: None,
|
gloas_fork_epoch: None,
|
||||||
builder_payment_threshold_numerator: 6,
|
builder_payment_threshold_numerator: 6,
|
||||||
builder_payment_threshold_denominator: 10,
|
builder_payment_threshold_denominator: 10,
|
||||||
|
min_builder_withdrawability_delay: Epoch::new(4096),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Network specific
|
* Network specific
|
||||||
@@ -1242,7 +1248,7 @@ impl ChainSpec {
|
|||||||
fulu_fork_version: [0x06, 0x00, 0x00, 0x01],
|
fulu_fork_version: [0x06, 0x00, 0x00, 0x01],
|
||||||
fulu_fork_epoch: None,
|
fulu_fork_epoch: None,
|
||||||
// Gloas
|
// Gloas
|
||||||
gloas_fork_version: [0x07, 0x00, 0x00, 0x00],
|
gloas_fork_version: [0x07, 0x00, 0x00, 0x01],
|
||||||
gloas_fork_epoch: None,
|
gloas_fork_epoch: None,
|
||||||
// Other
|
// Other
|
||||||
network_id: 2, // lighthouse testnet network id
|
network_id: 2, // lighthouse testnet network id
|
||||||
@@ -1350,8 +1356,9 @@ impl ChainSpec {
|
|||||||
domain_voluntary_exit: 4,
|
domain_voluntary_exit: 4,
|
||||||
domain_selection_proof: 5,
|
domain_selection_proof: 5,
|
||||||
domain_aggregate_and_proof: 6,
|
domain_aggregate_and_proof: 6,
|
||||||
domain_beacon_builder: 0x1B,
|
domain_beacon_builder: 0x0B,
|
||||||
domain_ptc_attester: 0x0C,
|
domain_ptc_attester: 0x0C,
|
||||||
|
domain_proposer_preferences: 0x0D,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fork choice
|
* Fork choice
|
||||||
@@ -1474,6 +1481,7 @@ impl ChainSpec {
|
|||||||
gloas_fork_epoch: None,
|
gloas_fork_epoch: None,
|
||||||
builder_payment_threshold_numerator: 6,
|
builder_payment_threshold_numerator: 6,
|
||||||
builder_payment_threshold_denominator: 10,
|
builder_payment_threshold_denominator: 10,
|
||||||
|
min_builder_withdrawability_delay: Epoch::new(4096),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Network specific
|
* Network specific
|
||||||
|
|||||||
@@ -25,3 +25,17 @@ pub mod bellatrix {
|
|||||||
pub mod deneb {
|
pub mod deneb {
|
||||||
pub use kzg::VERSIONED_HASH_VERSION_KZG;
|
pub use kzg::VERSIONED_HASH_VERSION_KZG;
|
||||||
}
|
}
|
||||||
|
pub mod gloas {
|
||||||
|
pub const BUILDER_INDEX_SELF_BUILD: u64 = u64::MAX;
|
||||||
|
pub const BUILDER_INDEX_FLAG: u64 = 1 << 40;
|
||||||
|
|
||||||
|
// Fork choice constants
|
||||||
|
pub type PayloadStatus = u8;
|
||||||
|
pub const PAYLOAD_STATUS_PENDING: PayloadStatus = 0;
|
||||||
|
pub const PAYLOAD_STATUS_EMPTY: PayloadStatus = 1;
|
||||||
|
pub const PAYLOAD_STATUS_FULL: PayloadStatus = 2;
|
||||||
|
|
||||||
|
pub const ATTESTATION_TIMELINESS_INDEX: usize = 0;
|
||||||
|
pub const PTC_TIMELINESS_INDEX: usize = 1;
|
||||||
|
pub const NUM_BLOCK_TIMELINESS_DEADLINES: usize = 2;
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use safe_arith::{ArithError, SafeArith};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use typenum::{
|
use typenum::{
|
||||||
U0, U1, U2, U4, U8, U16, U17, U32, U64, U128, U256, U512, U625, U1024, U2048, U4096, U8192,
|
U0, U1, U2, U4, U8, U16, U17, U32, U64, U128, U256, U512, U625, U1024, U2048, U4096, U8192,
|
||||||
U65536, U131072, U262144, U1048576, U16777216, U33554432, U134217728, U1073741824,
|
U16384, U65536, U131072, U262144, U1048576, U16777216, U33554432, U134217728, U1073741824,
|
||||||
U1099511627776, UInt, Unsigned, bit::B0,
|
U1099511627776, UInt, Unsigned, bit::B0,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -122,6 +122,10 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq +
|
|||||||
type CellsPerExtBlob: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
type CellsPerExtBlob: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
||||||
type NumberOfColumns: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
type NumberOfColumns: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
||||||
type ProposerLookaheadSlots: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
type ProposerLookaheadSlots: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
||||||
|
/*
|
||||||
|
* New in Gloas
|
||||||
|
*/
|
||||||
|
type BuilderRegistryLimit: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
||||||
/*
|
/*
|
||||||
* Derived values (set these CAREFULLY)
|
* Derived values (set these CAREFULLY)
|
||||||
*/
|
*/
|
||||||
@@ -175,6 +179,7 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq +
|
|||||||
type MaxPayloadAttestations: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
type MaxPayloadAttestations: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
||||||
type BuilderPendingPaymentsLimit: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
type BuilderPendingPaymentsLimit: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
||||||
type BuilderPendingWithdrawalsLimit: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
type BuilderPendingWithdrawalsLimit: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
||||||
|
type MaxBuildersPerWithdrawalsSweep: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
||||||
|
|
||||||
fn default_spec() -> ChainSpec;
|
fn default_spec() -> ChainSpec;
|
||||||
|
|
||||||
@@ -427,6 +432,16 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq +
|
|||||||
fn max_payload_attestations() -> usize {
|
fn max_payload_attestations() -> usize {
|
||||||
Self::MaxPayloadAttestations::to_usize()
|
Self::MaxPayloadAttestations::to_usize()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the `MaxBuildersPerWithdrawalsSweep` constant for this specification.
|
||||||
|
fn max_builders_per_withdrawals_sweep() -> usize {
|
||||||
|
Self::MaxBuildersPerWithdrawalsSweep::to_usize()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the `PAYLOAD_TIMELY_THRESHOLD` constant (PTC_SIZE / 2).
|
||||||
|
fn payload_timely_threshold() -> usize {
|
||||||
|
Self::PTCSize::to_usize() / 2
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Macro to inherit some type values from another EthSpec.
|
/// Macro to inherit some type values from another EthSpec.
|
||||||
@@ -484,6 +499,7 @@ impl EthSpec for MainnetEthSpec {
|
|||||||
type CellsPerExtBlob = U128;
|
type CellsPerExtBlob = U128;
|
||||||
type NumberOfColumns = U128;
|
type NumberOfColumns = U128;
|
||||||
type ProposerLookaheadSlots = U64; // Derived from (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH
|
type ProposerLookaheadSlots = U64; // Derived from (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH
|
||||||
|
type BuilderRegistryLimit = U1099511627776;
|
||||||
type SyncSubcommitteeSize = U128; // 512 committee size / 4 sync committee subnet count
|
type SyncSubcommitteeSize = U128; // 512 committee size / 4 sync committee subnet count
|
||||||
type MaxPendingAttestations = U4096; // 128 max attestations * 32 slots per epoch
|
type MaxPendingAttestations = U4096; // 128 max attestations * 32 slots per epoch
|
||||||
type SlotsPerEth1VotingPeriod = U2048; // 64 epochs * 32 slots per epoch
|
type SlotsPerEth1VotingPeriod = U2048; // 64 epochs * 32 slots per epoch
|
||||||
@@ -500,6 +516,7 @@ impl EthSpec for MainnetEthSpec {
|
|||||||
type MaxPendingDepositsPerEpoch = U16;
|
type MaxPendingDepositsPerEpoch = U16;
|
||||||
type PTCSize = U512;
|
type PTCSize = U512;
|
||||||
type MaxPayloadAttestations = U4;
|
type MaxPayloadAttestations = U4;
|
||||||
|
type MaxBuildersPerWithdrawalsSweep = U16384;
|
||||||
|
|
||||||
fn default_spec() -> ChainSpec {
|
fn default_spec() -> ChainSpec {
|
||||||
ChainSpec::mainnet()
|
ChainSpec::mainnet()
|
||||||
@@ -543,6 +560,8 @@ impl EthSpec for MinimalEthSpec {
|
|||||||
type NumberOfColumns = U128;
|
type NumberOfColumns = U128;
|
||||||
type ProposerLookaheadSlots = U16; // Derived from (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH
|
type ProposerLookaheadSlots = U16; // Derived from (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH
|
||||||
type BuilderPendingPaymentsLimit = U16; // 2 * SLOTS_PER_EPOCH = 2 * 8 = 16
|
type BuilderPendingPaymentsLimit = U16; // 2 * SLOTS_PER_EPOCH = 2 * 8 = 16
|
||||||
|
type PTCSize = U2;
|
||||||
|
type MaxBuildersPerWithdrawalsSweep = U16;
|
||||||
|
|
||||||
params_from_eth_spec!(MainnetEthSpec {
|
params_from_eth_spec!(MainnetEthSpec {
|
||||||
JustificationBitsLength,
|
JustificationBitsLength,
|
||||||
@@ -573,8 +592,8 @@ impl EthSpec for MinimalEthSpec {
|
|||||||
MaxAttestationsElectra,
|
MaxAttestationsElectra,
|
||||||
MaxDepositRequestsPerPayload,
|
MaxDepositRequestsPerPayload,
|
||||||
MaxWithdrawalRequestsPerPayload,
|
MaxWithdrawalRequestsPerPayload,
|
||||||
PTCSize,
|
MaxPayloadAttestations,
|
||||||
MaxPayloadAttestations
|
BuilderRegistryLimit
|
||||||
});
|
});
|
||||||
|
|
||||||
fn default_spec() -> ChainSpec {
|
fn default_spec() -> ChainSpec {
|
||||||
@@ -647,8 +666,10 @@ impl EthSpec for GnosisEthSpec {
|
|||||||
type CellsPerExtBlob = U128;
|
type CellsPerExtBlob = U128;
|
||||||
type NumberOfColumns = U128;
|
type NumberOfColumns = U128;
|
||||||
type ProposerLookaheadSlots = U32; // Derived from (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH
|
type ProposerLookaheadSlots = U32; // Derived from (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH
|
||||||
|
type BuilderRegistryLimit = U1099511627776;
|
||||||
type PTCSize = U512;
|
type PTCSize = U512;
|
||||||
type MaxPayloadAttestations = U2;
|
type MaxPayloadAttestations = U2;
|
||||||
|
type MaxBuildersPerWithdrawalsSweep = U16384;
|
||||||
|
|
||||||
fn default_spec() -> ChainSpec {
|
fn default_spec() -> ChainSpec {
|
||||||
ChainSpec::gnosis()
|
ChainSpec::gnosis()
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
use crate::{EthSpec, ExecutionPayloadEnvelope};
|
use crate::{
|
||||||
use bls::Signature;
|
ChainSpec, Domain, Epoch, EthSpec, ExecutionBlockHash, ExecutionPayloadEnvelope, Fork, Hash256,
|
||||||
|
SignedRoot, Slot,
|
||||||
|
};
|
||||||
|
use bls::{PublicKey, Signature};
|
||||||
use educe::Educe;
|
use educe::Educe;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use ssz_derive::{Decode, Encode};
|
use ssz_derive::{Decode, Encode};
|
||||||
@@ -15,6 +18,46 @@ pub struct SignedExecutionPayloadEnvelope<E: EthSpec> {
|
|||||||
pub signature: Signature,
|
pub signature: Signature,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<E: EthSpec> SignedExecutionPayloadEnvelope<E> {
|
||||||
|
pub fn slot(&self) -> Slot {
|
||||||
|
self.message.slot
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn epoch(&self) -> Epoch {
|
||||||
|
self.slot().epoch(E::slots_per_epoch())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn beacon_block_root(&self) -> Hash256 {
|
||||||
|
self.message.beacon_block_root
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn block_hash(&self) -> ExecutionBlockHash {
|
||||||
|
self.message.payload.block_hash
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Verify `self.signature`.
|
||||||
|
pub fn verify_signature(
|
||||||
|
&self,
|
||||||
|
pubkey: &PublicKey,
|
||||||
|
fork: &Fork,
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
) -> bool {
|
||||||
|
// Signed envelopes using the new BeaconBuilder domain per the spec:
|
||||||
|
// https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.1/specs/gloas/beacon-chain.md#new-verify_execution_payload_envelope_signature
|
||||||
|
let domain = spec.get_domain(
|
||||||
|
self.epoch(),
|
||||||
|
Domain::BeaconBuilder,
|
||||||
|
fork,
|
||||||
|
genesis_validators_root,
|
||||||
|
);
|
||||||
|
|
||||||
|
let message = self.message.signing_root(domain);
|
||||||
|
|
||||||
|
self.signature.verify(pubkey, message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
@@ -23,10 +23,11 @@ use tree_hash_derive::TreeHash;
|
|||||||
use typenum::Unsigned;
|
use typenum::Unsigned;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
BuilderPendingPayment, BuilderPendingWithdrawal, ExecutionBlockHash, ExecutionPayloadBid,
|
Builder, BuilderIndex, BuilderPendingPayment, BuilderPendingWithdrawal, ExecutionBlockHash,
|
||||||
|
ExecutionPayloadBid, Withdrawal,
|
||||||
attestation::{
|
attestation::{
|
||||||
AttestationDuty, BeaconCommittee, Checkpoint, CommitteeIndex, ParticipationFlags,
|
AttestationData, AttestationDuty, BeaconCommittee, Checkpoint, CommitteeIndex, PTC,
|
||||||
PendingAttestation,
|
ParticipationFlags, PendingAttestation,
|
||||||
},
|
},
|
||||||
block::{BeaconBlock, BeaconBlockHeader, SignedBeaconBlockHash},
|
block::{BeaconBlock, BeaconBlockHeader, SignedBeaconBlockHash},
|
||||||
consolidation::PendingConsolidation,
|
consolidation::PendingConsolidation,
|
||||||
@@ -195,6 +196,7 @@ pub enum BeaconStateError {
|
|||||||
ProposerLookaheadOutOfBounds {
|
ProposerLookaheadOutOfBounds {
|
||||||
i: usize,
|
i: usize,
|
||||||
},
|
},
|
||||||
|
InvalidIndicesCount,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Control whether an epoch-indexed field can be indexed at the next epoch or not.
|
/// Control whether an epoch-indexed field can be indexed at the next epoch or not.
|
||||||
@@ -602,8 +604,17 @@ where
|
|||||||
#[superstruct(only(Fulu, Gloas))]
|
#[superstruct(only(Fulu, Gloas))]
|
||||||
#[serde(with = "ssz_types::serde_utils::quoted_u64_fixed_vec")]
|
#[serde(with = "ssz_types::serde_utils::quoted_u64_fixed_vec")]
|
||||||
pub proposer_lookahead: Vector<u64, E::ProposerLookaheadSlots>,
|
pub proposer_lookahead: Vector<u64, E::ProposerLookaheadSlots>,
|
||||||
|
|
||||||
// Gloas
|
// Gloas
|
||||||
|
#[compare_fields(as_iter)]
|
||||||
|
#[test_random(default)]
|
||||||
|
#[superstruct(only(Gloas))]
|
||||||
|
pub builders: List<Builder, E::BuilderRegistryLimit>,
|
||||||
|
|
||||||
|
#[metastruct(exclude_from(tree_lists))]
|
||||||
|
#[serde(with = "serde_utils::quoted_u64")]
|
||||||
|
#[superstruct(only(Gloas), partial_getter(copy))]
|
||||||
|
pub next_withdrawal_builder_index: BuilderIndex,
|
||||||
|
|
||||||
#[test_random(default)]
|
#[test_random(default)]
|
||||||
#[superstruct(only(Gloas))]
|
#[superstruct(only(Gloas))]
|
||||||
#[metastruct(exclude_from(tree_lists))]
|
#[metastruct(exclude_from(tree_lists))]
|
||||||
@@ -625,10 +636,10 @@ where
|
|||||||
#[metastruct(exclude_from(tree_lists))]
|
#[metastruct(exclude_from(tree_lists))]
|
||||||
pub latest_block_hash: ExecutionBlockHash,
|
pub latest_block_hash: ExecutionBlockHash,
|
||||||
|
|
||||||
|
#[compare_fields(as_iter)]
|
||||||
#[test_random(default)]
|
#[test_random(default)]
|
||||||
#[superstruct(only(Gloas))]
|
#[superstruct(only(Gloas))]
|
||||||
#[metastruct(exclude_from(tree_lists))]
|
pub payload_expected_withdrawals: List<Withdrawal, E::MaxWithdrawalsPerPayload>,
|
||||||
pub latest_withdrawals_root: Hash256,
|
|
||||||
|
|
||||||
// Caching (not in the spec)
|
// Caching (not in the spec)
|
||||||
#[serde(skip_serializing, skip_deserializing)]
|
#[serde(skip_serializing, skip_deserializing)]
|
||||||
@@ -1115,13 +1126,22 @@ impl<E: EthSpec> BeaconState<E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let gloas_enabled = self.fork_name_unchecked().gloas_enabled();
|
||||||
epoch
|
epoch
|
||||||
.slot_iter(E::slots_per_epoch())
|
.slot_iter(E::slots_per_epoch())
|
||||||
.map(|slot| {
|
.map(|slot| {
|
||||||
let mut preimage = seed.to_vec();
|
let mut preimage = seed.to_vec();
|
||||||
preimage.append(&mut int_to_bytes8(slot.as_u64()));
|
preimage.append(&mut int_to_bytes8(slot.as_u64()));
|
||||||
let seed = hash(&preimage);
|
let seed = hash(&preimage);
|
||||||
self.compute_proposer_index(indices, &seed, spec)
|
|
||||||
|
if gloas_enabled {
|
||||||
|
self.compute_balance_weighted_selection(indices, &seed, 1, true, spec)?
|
||||||
|
.first()
|
||||||
|
.copied()
|
||||||
|
.ok_or(BeaconStateError::InsufficientValidators)
|
||||||
|
} else {
|
||||||
|
self.compute_proposer_index(indices, &seed, spec)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
@@ -1378,39 +1398,50 @@ impl<E: EthSpec> BeaconState<E> {
|
|||||||
let epoch = self.current_epoch().safe_add(1)?;
|
let epoch = self.current_epoch().safe_add(1)?;
|
||||||
|
|
||||||
let active_validator_indices = self.get_active_validator_indices(epoch, spec)?;
|
let active_validator_indices = self.get_active_validator_indices(epoch, spec)?;
|
||||||
let active_validator_count = active_validator_indices.len();
|
|
||||||
|
|
||||||
let seed = self.get_seed(epoch, Domain::SyncCommittee, spec)?;
|
let seed = self.get_seed(epoch, Domain::SyncCommittee, spec)?;
|
||||||
let max_effective_balance = spec.max_effective_balance_for_fork(self.fork_name_unchecked());
|
|
||||||
let max_random_value = if self.fork_name_unchecked().electra_enabled() {
|
|
||||||
MAX_RANDOM_VALUE
|
|
||||||
} else {
|
|
||||||
MAX_RANDOM_BYTE
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut i = 0;
|
if self.fork_name_unchecked().gloas_enabled() {
|
||||||
let mut sync_committee_indices = Vec::with_capacity(E::SyncCommitteeSize::to_usize());
|
self.compute_balance_weighted_selection(
|
||||||
while sync_committee_indices.len() < E::SyncCommitteeSize::to_usize() {
|
&active_validator_indices,
|
||||||
let shuffled_index = compute_shuffled_index(
|
|
||||||
i.safe_rem(active_validator_count)?,
|
|
||||||
active_validator_count,
|
|
||||||
seed.as_slice(),
|
seed.as_slice(),
|
||||||
spec.shuffle_round_count,
|
E::SyncCommitteeSize::to_usize(),
|
||||||
|
true,
|
||||||
|
spec,
|
||||||
)
|
)
|
||||||
.ok_or(BeaconStateError::UnableToShuffle)?;
|
} else {
|
||||||
let candidate_index = *active_validator_indices
|
let active_validator_count = active_validator_indices.len();
|
||||||
.get(shuffled_index)
|
let max_effective_balance =
|
||||||
.ok_or(BeaconStateError::ShuffleIndexOutOfBounds(shuffled_index))?;
|
spec.max_effective_balance_for_fork(self.fork_name_unchecked());
|
||||||
let random_value = self.shuffling_random_value(i, seed.as_slice())?;
|
let max_random_value = if self.fork_name_unchecked().electra_enabled() {
|
||||||
let effective_balance = self.get_validator(candidate_index)?.effective_balance;
|
MAX_RANDOM_VALUE
|
||||||
if effective_balance.safe_mul(max_random_value)?
|
} else {
|
||||||
>= max_effective_balance.safe_mul(random_value)?
|
MAX_RANDOM_BYTE
|
||||||
{
|
};
|
||||||
sync_committee_indices.push(candidate_index);
|
|
||||||
|
let mut i = 0;
|
||||||
|
let mut sync_committee_indices = Vec::with_capacity(E::SyncCommitteeSize::to_usize());
|
||||||
|
while sync_committee_indices.len() < E::SyncCommitteeSize::to_usize() {
|
||||||
|
let shuffled_index = compute_shuffled_index(
|
||||||
|
i.safe_rem(active_validator_count)?,
|
||||||
|
active_validator_count,
|
||||||
|
seed.as_slice(),
|
||||||
|
spec.shuffle_round_count,
|
||||||
|
)
|
||||||
|
.ok_or(BeaconStateError::UnableToShuffle)?;
|
||||||
|
let candidate_index = *active_validator_indices
|
||||||
|
.get(shuffled_index)
|
||||||
|
.ok_or(BeaconStateError::ShuffleIndexOutOfBounds(shuffled_index))?;
|
||||||
|
let random_value = self.shuffling_random_value(i, seed.as_slice())?;
|
||||||
|
let effective_balance = self.get_validator(candidate_index)?.effective_balance;
|
||||||
|
if effective_balance.safe_mul(max_random_value)?
|
||||||
|
>= max_effective_balance.safe_mul(random_value)?
|
||||||
|
{
|
||||||
|
sync_committee_indices.push(candidate_index);
|
||||||
|
}
|
||||||
|
i.safe_add_assign(1)?;
|
||||||
}
|
}
|
||||||
i.safe_add_assign(1)?;
|
Ok(sync_committee_indices)
|
||||||
}
|
}
|
||||||
Ok(sync_committee_indices)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the next sync committee.
|
/// Compute the next sync committee.
|
||||||
@@ -2032,6 +2063,25 @@ impl<E: EthSpec> BeaconState<E> {
|
|||||||
Ok(cache.get_attestation_duties(validator_index))
|
Ok(cache.get_attestation_duties(validator_index))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if the attestation is for the block proposed at the attestation slot.
|
||||||
|
///
|
||||||
|
/// Returns `true` if the attestation's block root matches the block root at the
|
||||||
|
/// attestation's slot, and the block root differs from the previous slot's root.
|
||||||
|
pub fn is_attestation_same_slot(
|
||||||
|
&self,
|
||||||
|
data: &AttestationData,
|
||||||
|
) -> Result<bool, BeaconStateError> {
|
||||||
|
if data.slot == 0 {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
let block_root = data.beacon_block_root;
|
||||||
|
let slot_block_root = *self.get_block_root(data.slot)?;
|
||||||
|
let prev_block_root = *self.get_block_root(data.slot.safe_sub(1)?)?;
|
||||||
|
|
||||||
|
Ok(block_root == slot_block_root && block_root != prev_block_root)
|
||||||
|
}
|
||||||
|
|
||||||
/// Compute the total active balance cache from scratch.
|
/// Compute the total active balance cache from scratch.
|
||||||
///
|
///
|
||||||
/// This method should rarely be invoked because single-pass epoch processing keeps the total
|
/// This method should rarely be invoked because single-pass epoch processing keeps the total
|
||||||
@@ -2292,6 +2342,7 @@ impl<E: EthSpec> BeaconState<E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return true if the parent block was full (both beacon block and execution payload were present).
|
||||||
pub fn is_parent_block_full(&self) -> bool {
|
pub fn is_parent_block_full(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
BeaconState::Base(_) | BeaconState::Altair(_) => false,
|
BeaconState::Base(_) | BeaconState::Altair(_) => false,
|
||||||
@@ -2878,6 +2929,111 @@ impl<E: EthSpec> BeaconState<E> {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the payload timeliness committee for the given `slot`.
|
||||||
|
///
|
||||||
|
/// Requires the committee cache to be initialized.
|
||||||
|
/// TODO(EIP-7732): definitely gonna have to cache this..
|
||||||
|
pub fn get_ptc(&self, slot: Slot, spec: &ChainSpec) -> Result<PTC<E>, BeaconStateError> {
|
||||||
|
let committee_cache = self.committee_cache_at_slot(slot)?;
|
||||||
|
let committees = committee_cache.get_beacon_committees_at_slot(slot)?;
|
||||||
|
|
||||||
|
let seed = self.get_ptc_attester_seed(slot, spec)?;
|
||||||
|
|
||||||
|
let committee_indices: Vec<usize> = committees
|
||||||
|
.iter()
|
||||||
|
.flat_map(|committee| committee.committee.iter().copied())
|
||||||
|
.collect();
|
||||||
|
let selected_indices = self.compute_balance_weighted_selection(
|
||||||
|
&committee_indices,
|
||||||
|
&seed,
|
||||||
|
E::ptc_size(),
|
||||||
|
false,
|
||||||
|
spec,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(PTC(FixedVector::new(selected_indices)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compute the seed to use for the ptc attester selection at the given `slot`.
|
||||||
|
pub fn get_ptc_attester_seed(
|
||||||
|
&self,
|
||||||
|
slot: Slot,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
) -> Result<Vec<u8>, BeaconStateError> {
|
||||||
|
let epoch = slot.epoch(E::slots_per_epoch());
|
||||||
|
let mut preimage = self
|
||||||
|
.get_seed(epoch, Domain::PTCAttester, spec)?
|
||||||
|
.as_slice()
|
||||||
|
.to_vec();
|
||||||
|
preimage.append(&mut int_to_bytes8(slot.as_u64()));
|
||||||
|
Ok(hash(&preimage))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return size indices sampled by effective balance, using indices as candidates.
|
||||||
|
///
|
||||||
|
/// If shuffle_indices is True, candidate indices are themselves sampled from indices
|
||||||
|
/// by shuffling it, otherwise indices is traversed in order.
|
||||||
|
fn compute_balance_weighted_selection(
|
||||||
|
&self,
|
||||||
|
indices: &[usize],
|
||||||
|
seed: &[u8],
|
||||||
|
size: usize,
|
||||||
|
shuffle_indices: bool,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
) -> Result<Vec<usize>, BeaconStateError> {
|
||||||
|
let total = indices.len();
|
||||||
|
if total == 0 {
|
||||||
|
return Err(BeaconStateError::InvalidIndicesCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut selected = Vec::with_capacity(size);
|
||||||
|
let mut i = 0usize;
|
||||||
|
|
||||||
|
while selected.len() < size {
|
||||||
|
let mut next_index = i.safe_rem(total)?;
|
||||||
|
|
||||||
|
if shuffle_indices {
|
||||||
|
next_index =
|
||||||
|
compute_shuffled_index(next_index, total, seed, spec.shuffle_round_count)
|
||||||
|
.ok_or(BeaconStateError::UnableToShuffle)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let candidate_index = indices
|
||||||
|
.get(next_index)
|
||||||
|
.ok_or(BeaconStateError::InvalidIndicesCount)?;
|
||||||
|
|
||||||
|
if self.compute_balance_weighted_acceptance(*candidate_index, seed, i, spec)? {
|
||||||
|
selected.push(*candidate_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
i.safe_add_assign(1)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(selected)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return whether to accept the selection of the validator `index`, with probability
|
||||||
|
/// proportional to its `effective_balance`, and randomness given by `seed` and `iteration`.
|
||||||
|
fn compute_balance_weighted_acceptance(
|
||||||
|
&self,
|
||||||
|
index: usize,
|
||||||
|
seed: &[u8],
|
||||||
|
iteration: usize,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
) -> Result<bool, BeaconStateError> {
|
||||||
|
// TODO(EIP-7732): Consider grabbing effective balances from the epoch cache here.
|
||||||
|
// Note that this function will be used in a loop, so using cached values could be nice for performance.
|
||||||
|
// However, post-gloas, this function will be used in `compute_proposer_indices`, `get_next_sync_committee_indices`, and `get_ptc`, which has ~15 call sites in total
|
||||||
|
// so we will need to check each one to ensure epoch cache is initialized first, if we deem a good idea.
|
||||||
|
// Currently, we can't test if making the change would work since the test suite is not ready for gloas.
|
||||||
|
let effective_balance = self.get_effective_balance(index)?;
|
||||||
|
let max_effective_balance = spec.max_effective_balance_for_fork(self.fork_name_unchecked());
|
||||||
|
let random_value = self.shuffling_random_value(iteration, seed)?;
|
||||||
|
|
||||||
|
Ok(effective_balance.safe_mul(MAX_RANDOM_VALUE)?
|
||||||
|
>= max_effective_balance.safe_mul(random_value)?)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: EthSpec> ForkVersionDecode for BeaconState<E> {
|
impl<E: EthSpec> ForkVersionDecode for BeaconState<E> {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# To download/extract nightly tests, run:
|
# To download/extract nightly tests, run:
|
||||||
# CONSENSUS_SPECS_TEST_VERSION=nightly make
|
# CONSENSUS_SPECS_TEST_VERSION=nightly make
|
||||||
CONSENSUS_SPECS_TEST_VERSION ?= v1.6.0-beta.1
|
CONSENSUS_SPECS_TEST_VERSION ?= v1.7.0-alpha.1
|
||||||
REPO_NAME := consensus-spec-tests
|
REPO_NAME := consensus-spec-tests
|
||||||
OUTPUT_DIR := ./$(REPO_NAME)
|
OUTPUT_DIR := ./$(REPO_NAME)
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ excluded_paths = [
|
|||||||
# Ignore KZG tests that target internal kzg library functions
|
# Ignore KZG tests that target internal kzg library functions
|
||||||
"tests/.*/compute_verify_cell_kzg_proof_batch_challenge/.*",
|
"tests/.*/compute_verify_cell_kzg_proof_batch_challenge/.*",
|
||||||
"tests/.*/compute_challenge/.*",
|
"tests/.*/compute_challenge/.*",
|
||||||
|
# We don't need these manifest files at the moment.
|
||||||
|
"tests/.*/manifest.yaml"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -297,6 +297,15 @@ impl<E: EthSpec> Case for ForkChoiceTest<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn result(&self, _case_index: usize, fork_name: ForkName) -> Result<(), Error> {
|
fn result(&self, _case_index: usize, fork_name: ForkName) -> Result<(), Error> {
|
||||||
|
// TODO(gloas): We have not implemented this change to fork choice/proposer boost yet.
|
||||||
|
// https://github.com/sigp/lighthouse/issues/8689
|
||||||
|
if self.description == "voting_source_beyond_two_epoch"
|
||||||
|
|| self.description == "justified_update_not_realized_finality"
|
||||||
|
|| self.description == "justified_update_always_if_better"
|
||||||
|
{
|
||||||
|
return Err(Error::SkippedKnownFailure);
|
||||||
|
}
|
||||||
|
|
||||||
let tester = Tester::new(self, testing_spec::<E>(fork_name))?;
|
let tester = Tester::new(self, testing_spec::<E>(fork_name))?;
|
||||||
|
|
||||||
for step in &self.steps {
|
for step in &self.steps {
|
||||||
|
|||||||
@@ -387,8 +387,16 @@ where
|
|||||||
T::name().into()
|
T::name().into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn disabled_forks(&self) -> Vec<ForkName> {
|
||||||
|
// TODO(gloas): Can be removed once we enable Gloas on all tests
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
|
||||||
fn is_enabled_for_fork(&self, fork_name: ForkName) -> bool {
|
fn is_enabled_for_fork(&self, fork_name: ForkName) -> bool {
|
||||||
|
// TODO(gloas): DataColumnSidecar tests are disabled until we update the DataColumnSidecar
|
||||||
|
// type.
|
||||||
self.supported_forks.contains(&fork_name)
|
self.supported_forks.contains(&fork_name)
|
||||||
|
&& !(fork_name == ForkName::Gloas && T::name() == "DataColumnSidecar")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user