Merge remote-tracking branch 'origin/unstable' into gloas-envelope-processing

This commit is contained in:
Michael Sproul
2026-01-19 12:05:38 +11:00
145 changed files with 1414 additions and 1701 deletions

View File

@@ -28,7 +28,7 @@ pub fn get_base_reward(
validator_effective_balance: u64,
base_reward_per_increment: BaseRewardPerIncrement,
spec: &ChainSpec,
) -> Result<u64, Error> {
) -> Result<u64, BeaconStateError> {
validator_effective_balance
.safe_div(spec.effective_balance_increment)?
.safe_mul(base_reward_per_increment.as_u64())

View File

@@ -107,7 +107,7 @@ pub mod attesting_indices_electra {
for committee_index in committee_indices {
let beacon_committee = committees
.get(committee_index as usize)
.ok_or(Error::NoCommitteeFound(committee_index))?;
.ok_or(BeaconStateError::NoCommitteeFound(committee_index))?;
// This check is new to the spec's `process_attestation` in Electra.
if committee_index >= committee_count_per_slot {

View File

@@ -42,8 +42,7 @@ pub fn slash_validator<E: EthSpec>(
decrease_balance(
state,
slashed_index,
validator_effective_balance
.safe_div(spec.min_slashing_penalty_quotient_for_state(state))?,
validator_effective_balance.safe_div(state.get_min_slashing_penalty_quotient(spec))?,
)?;
update_progressive_balances_on_slashing(state, slashed_index, validator_effective_balance)?;
@@ -54,8 +53,8 @@ pub fn slash_validator<E: EthSpec>(
// Apply proposer and whistleblower rewards
let proposer_index = ctxt.get_proposer_index(state, spec)? as usize;
let whistleblower_index = opt_whistleblower_index.unwrap_or(proposer_index);
let whistleblower_reward = validator_effective_balance
.safe_div(spec.whistleblower_reward_quotient_for_state(state))?;
let whistleblower_reward =
validator_effective_balance.safe_div(state.get_whistleblower_reward_quotient(spec))?;
let proposer_reward = if state.fork_name_unchecked().altair_enabled() {
whistleblower_reward
.safe_mul(PROPOSER_WEIGHT)?

View File

@@ -5,7 +5,7 @@ use crate::metrics;
use fixed_bytes::FixedBytesExtended;
use safe_arith::SafeArith;
use tracing::instrument;
use types::epoch_cache::{EpochCache, EpochCacheError, EpochCacheKey};
use types::state::{EpochCache, EpochCacheError, EpochCacheKey};
use types::{ActivationQueue, BeaconState, ChainSpec, EthSpec, ForkName, Hash256};
/// Precursor to an `EpochCache`.

View File

@@ -195,7 +195,7 @@ pub fn is_valid_genesis_state<E: EthSpec>(state: &BeaconState<E>, spec: &ChainSp
pub fn process_activations<E: EthSpec>(
state: &mut BeaconState<E>,
spec: &ChainSpec,
) -> Result<(), Error> {
) -> Result<(), BeaconStateError> {
let (validators, balances, _) = state.validators_and_balances_and_progressive_balances_mut();
let mut validators_iter = validators.iter_cow();
while let Some((index, validator)) = validators_iter.next_cow() {
@@ -203,7 +203,7 @@ pub fn process_activations<E: EthSpec>(
let balance = balances
.get(index)
.copied()
.ok_or(Error::BalancesOutOfBounds(index))?;
.ok_or(BeaconStateError::BalancesOutOfBounds(index))?;
validator.effective_balance = std::cmp::min(
balance.safe_sub(balance.safe_rem(spec.effective_balance_increment)?)?,
spec.max_effective_balance,

View File

@@ -334,7 +334,7 @@ pub fn process_randao<E: EthSpec, Payload: AbstractExecPayload<E>>(
pub fn process_eth1_data<E: EthSpec>(
state: &mut BeaconState<E>,
eth1_data: &Eth1Data,
) -> Result<(), Error> {
) -> Result<(), BeaconStateError> {
if let Some(new_eth1_data) = get_new_eth1_data(state, eth1_data)? {
*state.eth1_data_mut() = new_eth1_data;
}

View File

@@ -1,5 +1,5 @@
use ethereum_hashing::hash_fixed;
use types::{KzgCommitment, VERSIONED_HASH_VERSION_KZG, VersionedHash};
use types::{VersionedHash, kzg_ext::KzgCommitment, kzg_ext::consts::VERSIONED_HASH_VERSION_KZG};
pub fn kzg_commitment_to_versioned_hash(kzg_commitment: &KzgCommitment) -> VersionedHash {
let mut hashed_commitment = hash_fixed(&kzg_commitment.0);

View File

@@ -1,8 +1,7 @@
use crate::EpochProcessingError;
use crate::per_epoch_processing::single_pass::{SinglePassConfig, process_epoch_single_pass};
use types::beacon_state::BeaconState;
use types::chain_spec::ChainSpec;
use types::eth_spec::EthSpec;
use types::core::{ChainSpec, EthSpec};
use types::state::BeaconState;
/// Slow version of `process_inactivity_updates` that runs a subset of single-pass processing.
///

View File

@@ -1,8 +1,8 @@
use crate::EpochProcessingError;
use milhouse::List;
use types::beacon_state::BeaconState;
use types::eth_spec::EthSpec;
use types::participation_flags::ParticipationFlags;
use types::attestation::ParticipationFlags;
use types::core::EthSpec;
use types::state::BeaconState;
pub fn process_participation_flag_updates<E: EthSpec>(
state: &mut BeaconState<E>,

View File

@@ -1,9 +1,8 @@
use crate::EpochProcessingError;
use safe_arith::SafeArith;
use std::sync::Arc;
use types::beacon_state::BeaconState;
use types::chain_spec::ChainSpec;
use types::eth_spec::EthSpec;
use types::core::{ChainSpec, EthSpec};
use types::state::BeaconState;
pub fn process_sync_committee_updates<E: EthSpec>(
state: &mut BeaconState<E>,

View File

@@ -1,6 +1,6 @@
use crate::EpochProcessingError;
use types::beacon_state::BeaconState;
use types::eth_spec::EthSpec;
use types::core::EthSpec;
use types::state::BeaconState;
pub fn process_participation_record_updates<E: EthSpec>(
state: &mut BeaconState<E>,

View File

@@ -1,6 +1,6 @@
use crate::EpochProcessingError;
use safe_arith::SafeArith;
use types::historical_summary::HistoricalSummary;
use types::state::HistoricalSummary;
use types::{BeaconState, EthSpec};
pub fn process_historical_summaries_update<E: EthSpec>(

View File

@@ -1,8 +1,8 @@
use super::errors::EpochProcessingError;
use crate::per_epoch_processing::single_pass::{SinglePassConfig, process_epoch_single_pass};
use safe_arith::SafeArith;
use types::beacon_state::BeaconState;
use types::chain_spec::ChainSpec;
use types::core::ChainSpec;
use types::state::BeaconState;
use types::{BeaconStateError, EthSpec};
/// This implementation is now only used in phase0. Later hard forks use single-pass.

View File

@@ -2,8 +2,8 @@ use super::errors::EpochProcessingError;
use safe_arith::SafeArith;
use tree_hash::TreeHash;
use typenum::Unsigned;
use types::beacon_state::BeaconState;
use types::eth_spec::EthSpec;
use types::core::EthSpec;
use types::state::BeaconState;
pub fn process_historical_roots_update<E: EthSpec>(
state: &mut BeaconState<E>,

View File

@@ -2,8 +2,8 @@ use super::errors::EpochProcessingError;
use milhouse::List;
use safe_arith::SafeArith;
use typenum::Unsigned;
use types::beacon_state::BeaconState;
use types::eth_spec::EthSpec;
use types::core::EthSpec;
use types::state::BeaconState;
pub fn process_eth1_data_reset<E: EthSpec>(
state: &mut BeaconState<E>,

View File

@@ -957,7 +957,7 @@ impl SlashingsContext {
) -> Result<Self, Error> {
let sum_slashings = state.get_all_slashings().iter().copied().safe_sum()?;
let adjusted_total_slashing_balance = min(
sum_slashings.safe_mul(spec.proportional_slashing_multiplier_for_state(state))?,
sum_slashings.safe_mul(state.get_proportional_slashing_multiplier(spec))?,
state_ctxt.total_active_balance,
);

View File

@@ -17,7 +17,7 @@ pub fn process_slashings<E: EthSpec>(
let sum_slashings = state.get_all_slashings().iter().copied().safe_sum()?;
let adjusted_total_slashing_balance = std::cmp::min(
sum_slashings.safe_mul(spec.proportional_slashing_multiplier_for_state(state))?,
sum_slashings.safe_mul(state.get_proportional_slashing_multiplier(spec))?,
total_balance,
);

View File

@@ -6,6 +6,7 @@
use crate::*;
use fixed_bytes::FixedBytesExtended;
use tracing::instrument;
use types::{BeaconState, ChainSpec, EthSpec, Hash256, Slot};
#[derive(Debug, PartialEq)]
@@ -59,6 +60,7 @@ pub fn complete_state_advance<E: EthSpec>(
///
/// - If `state.slot > target_slot`, an error will be returned.
/// - If `state_root_opt.is_none()` but the latest block header requires a state root.
#[instrument(skip_all, level = "debug")]
pub fn partial_state_advance<E: EthSpec>(
state: &mut BeaconState<E>,
state_root_opt: Option<Hash256>,

View File

@@ -70,7 +70,10 @@ pub fn upgrade_state_to_gloas<E: EthSpec>(
current_sync_committee: pre.current_sync_committee.clone(),
next_sync_committee: pre.next_sync_committee.clone(),
// Execution Bid
latest_execution_payload_bid: ExecutionPayloadBid::default(),
latest_execution_payload_bid: ExecutionPayloadBid {
block_hash: pre.latest_execution_payload_header.block_hash,
..Default::default()
},
// Capella
next_withdrawal_index: pre.next_withdrawal_index,
next_withdrawal_validator_index: pre.next_withdrawal_validator_index,

View File

@@ -13,10 +13,11 @@ use test_random_derive::TestRandom;
use tree_hash::{BYTES_PER_CHUNK, TreeHash};
use tree_hash_derive::TreeHash;
use crate::payload_attestation::PayloadAttestation;
use crate::{
SignedExecutionPayloadBid,
attestation::{AttestationBase, AttestationElectra, AttestationRef, AttestationRefMut},
attestation::{
AttestationBase, AttestationElectra, AttestationRef, AttestationRefMut, PayloadAttestation,
},
core::{EthSpec, Graffiti, Hash256},
deposit::Deposit,
execution::{

View File

@@ -14,12 +14,10 @@ use tree_hash::TreeHash;
use crate::{
core::{
APPLICATION_DOMAIN_BUILDER, Address, ApplicationDomain, EnrForkId, Epoch, EthSpec,
EthSpecId, Hash256, MainnetEthSpec, Slot, Uint256,
EthSpecId, ExecutionBlockHash, Hash256, MainnetEthSpec, Slot, Uint256,
},
data::{BlobIdentifier, DataColumnSubnetId, DataColumnsByRootIdentifier},
execution::ExecutionBlockHash,
fork::{Fork, ForkData, ForkName},
state::BeaconState,
};
/// Each of the BLS signature domains.
@@ -164,6 +162,7 @@ pub struct ChainSpec {
pub inactivity_score_bias: u64,
pub inactivity_score_recovery_rate: u64,
pub min_sync_committee_participants: u64,
pub update_timeout: u64,
pub(crate) domain_sync_committee: u32,
pub(crate) domain_sync_committee_selection_proof: u32,
pub(crate) domain_contribution_and_proof: u32,
@@ -252,7 +251,9 @@ pub struct ChainSpec {
pub message_domain_invalid_snappy: [u8; 4],
pub message_domain_valid_snappy: [u8; 4],
pub subnets_per_node: u8,
pub epochs_per_subnet_subscription: u64,
pub attestation_subnet_count: u64,
pub attestation_subnet_extra_bits: u8,
pub attestation_subnet_prefix_bits: u8,
/*
@@ -418,51 +419,6 @@ impl ChainSpec {
}
}
/// For a given `BeaconState`, return the proportional slashing multiplier associated with its variant.
pub fn proportional_slashing_multiplier_for_state<E: EthSpec>(
&self,
state: &BeaconState<E>,
) -> u64 {
let fork_name = state.fork_name_unchecked();
if fork_name >= ForkName::Bellatrix {
self.proportional_slashing_multiplier_bellatrix
} else if fork_name >= ForkName::Altair {
self.proportional_slashing_multiplier_altair
} else {
self.proportional_slashing_multiplier
}
}
/// For a given `BeaconState`, return the minimum slashing penalty quotient associated with its variant.
pub fn min_slashing_penalty_quotient_for_state<E: EthSpec>(
&self,
state: &BeaconState<E>,
) -> u64 {
let fork_name = state.fork_name_unchecked();
if fork_name.electra_enabled() {
self.min_slashing_penalty_quotient_electra
} else if fork_name >= ForkName::Bellatrix {
self.min_slashing_penalty_quotient_bellatrix
} else if fork_name >= ForkName::Altair {
self.min_slashing_penalty_quotient_altair
} else {
self.min_slashing_penalty_quotient
}
}
/// For a given `BeaconState`, return the whistleblower reward quotient associated with its variant.
pub fn whistleblower_reward_quotient_for_state<E: EthSpec>(
&self,
state: &BeaconState<E>,
) -> u64 {
let fork_name = state.fork_name_unchecked();
if fork_name.electra_enabled() {
self.whistleblower_reward_quotient_electra
} else {
self.whistleblower_reward_quotient
}
}
pub fn max_effective_balance_for_fork(&self, fork_name: ForkName) -> u64 {
if fork_name.electra_enabled() {
self.max_effective_balance_electra
@@ -1060,6 +1016,7 @@ impl ChainSpec {
inactivity_score_bias: 4,
inactivity_score_recovery_rate: 16,
min_sync_committee_participants: 1,
update_timeout: 8192,
epochs_per_sync_committee_period: Epoch::new(256),
domain_sync_committee: 7,
domain_sync_committee_selection_proof: 8,
@@ -1152,7 +1109,9 @@ impl ChainSpec {
boot_nodes: vec![],
network_id: 1, // mainnet network id
attestation_propagation_slot_range: default_attestation_propagation_slot_range(),
epochs_per_subnet_subscription: 256,
attestation_subnet_count: 64,
attestation_subnet_extra_bits: 0,
subnets_per_node: 2,
maximum_gossip_clock_disparity: default_maximum_gossip_clock_disparity(),
target_aggregators_per_committee: 16,
@@ -1162,7 +1121,10 @@ impl ChainSpec {
resp_timeout: default_resp_timeout(),
message_domain_invalid_snappy: default_message_domain_invalid_snappy(),
message_domain_valid_snappy: default_message_domain_valid_snappy(),
attestation_subnet_prefix_bits: default_attestation_subnet_prefix_bits(),
attestation_subnet_prefix_bits: compute_attestation_subnet_prefix_bits(
default_attestation_subnet_count(),
default_attestation_subnet_extra_bits(),
),
max_request_blocks: default_max_request_blocks(),
/*
@@ -1243,6 +1205,7 @@ impl ChainSpec {
proportional_slashing_multiplier: 2,
// Altair
epochs_per_sync_committee_period: Epoch::new(8),
update_timeout: 64,
altair_fork_version: [0x01, 0x00, 0x00, 0x01],
altair_fork_epoch: None,
// Bellatrix
@@ -1426,6 +1389,7 @@ impl ChainSpec {
inactivity_score_bias: 4,
inactivity_score_recovery_rate: 16,
min_sync_committee_participants: 1,
update_timeout: 8192,
epochs_per_sync_committee_period: Epoch::new(512),
domain_sync_committee: 7,
domain_sync_committee_selection_proof: 8,
@@ -1517,7 +1481,9 @@ impl ChainSpec {
boot_nodes: vec![],
network_id: 100, // Gnosis Chain network id
attestation_propagation_slot_range: default_attestation_propagation_slot_range(),
epochs_per_subnet_subscription: 256,
attestation_subnet_count: 64,
attestation_subnet_extra_bits: 0,
subnets_per_node: 4, // Make this larger than usual to avoid network damage
maximum_gossip_clock_disparity: default_maximum_gossip_clock_disparity(),
target_aggregators_per_committee: 16,
@@ -1528,7 +1494,10 @@ impl ChainSpec {
message_domain_invalid_snappy: default_message_domain_invalid_snappy(),
message_domain_valid_snappy: default_message_domain_valid_snappy(),
max_request_blocks: default_max_request_blocks(),
attestation_subnet_prefix_bits: default_attestation_subnet_prefix_bits(),
attestation_subnet_prefix_bits: compute_attestation_subnet_prefix_bits(
default_attestation_subnet_count(),
default_attestation_subnet_extra_bits(),
),
/*
* Networking Deneb Specific
@@ -1849,9 +1818,15 @@ pub struct Config {
#[serde(default = "default_message_domain_valid_snappy")]
#[serde(with = "serde_utils::bytes_4_hex")]
message_domain_valid_snappy: [u8; 4],
#[serde(default = "default_attestation_subnet_prefix_bits")]
#[serde(default = "default_epochs_per_subnet_subscription")]
#[serde(with = "serde_utils::quoted_u64")]
epochs_per_subnet_subscription: u64,
#[serde(default = "default_attestation_subnet_count")]
#[serde(with = "serde_utils::quoted_u64")]
attestation_subnet_count: u64,
#[serde(default = "default_attestation_subnet_extra_bits")]
#[serde(with = "serde_utils::quoted_u8")]
attestation_subnet_prefix_bits: u8,
attestation_subnet_extra_bits: u8,
#[serde(default = "default_max_request_blocks_deneb")]
#[serde(with = "serde_utils::quoted_u64")]
max_request_blocks_deneb: u64,
@@ -1966,8 +1941,36 @@ fn default_subnets_per_node() -> u8 {
2u8
}
fn default_attestation_subnet_prefix_bits() -> u8 {
6
const fn default_epochs_per_subnet_subscription() -> u64 {
256
}
const fn default_attestation_subnet_count() -> u64 {
64
}
const fn default_attestation_subnet_extra_bits() -> u8 {
0
}
/// Compute attestation_subnet_prefix_bits dynamically as:
/// ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS
fn compute_attestation_subnet_prefix_bits(
attestation_subnet_count: u64,
attestation_subnet_extra_bits: u8,
) -> u8 {
let default_attestation_subnet_prefix_bits = 6u8;
// ceillog2() = next_power_of_two().ilog2()
// casting to u8 is fine given ilog2(u64::MAX) = 63
let min_bits_needed = attestation_subnet_count
.checked_next_power_of_two()
.and_then(|x| x.checked_ilog2())
.unwrap_or(default_attestation_subnet_prefix_bits as u32) as u8;
min_bits_needed
.safe_add(attestation_subnet_extra_bits)
.unwrap_or(default_attestation_subnet_prefix_bits)
}
const fn default_max_per_epoch_activation_churn_limit() -> u64 {
@@ -2252,7 +2255,9 @@ impl Config {
shard_committee_period: spec.shard_committee_period,
eth1_follow_distance: spec.eth1_follow_distance,
subnets_per_node: spec.subnets_per_node,
attestation_subnet_prefix_bits: spec.attestation_subnet_prefix_bits,
epochs_per_subnet_subscription: spec.epochs_per_subnet_subscription,
attestation_subnet_count: spec.attestation_subnet_count,
attestation_subnet_extra_bits: spec.attestation_subnet_extra_bits,
inactivity_score_bias: spec.inactivity_score_bias,
inactivity_score_recovery_rate: spec.inactivity_score_recovery_rate,
@@ -2343,7 +2348,9 @@ impl Config {
shard_committee_period,
eth1_follow_distance,
subnets_per_node,
attestation_subnet_prefix_bits,
epochs_per_subnet_subscription,
attestation_subnet_count,
attestation_subnet_extra_bits,
inactivity_score_bias,
inactivity_score_recovery_rate,
ejection_balance,
@@ -2416,6 +2423,9 @@ impl Config {
shard_committee_period,
eth1_follow_distance,
subnets_per_node,
epochs_per_subnet_subscription,
attestation_subnet_count,
attestation_subnet_extra_bits,
inactivity_score_bias,
inactivity_score_recovery_rate,
ejection_balance,
@@ -2436,7 +2446,11 @@ impl Config {
resp_timeout,
message_domain_invalid_snappy,
message_domain_valid_snappy,
attestation_subnet_prefix_bits,
// Compute attestation_subnet_prefix_bits dynamically
attestation_subnet_prefix_bits: compute_attestation_subnet_prefix_bits(
attestation_subnet_count,
attestation_subnet_extra_bits,
),
max_request_blocks,
attestation_propagation_slot_range,
maximum_gossip_clock_disparity,
@@ -2605,6 +2619,13 @@ mod tests {
}
}
}
#[test]
fn test_compute_min_bits_for_n_values_edge_cases() {
assert_eq!(compute_attestation_subnet_prefix_bits(64, 0), 6);
assert_eq!(compute_attestation_subnet_prefix_bits(65, 0), 7);
assert_eq!(compute_attestation_subnet_prefix_bits(0, 1), 1);
}
}
#[cfg(test)]
@@ -2684,6 +2705,9 @@ mod yaml_tests {
REORG_HEAD_WEIGHT_THRESHOLD: 20
REORG_PARENT_WEIGHT_THRESHOLD: 160
REORG_MAX_EPOCHS_SINCE_FINALIZATION: 2
EPOCHS_PER_SUBNET_SUBSCRIPTION: 256
ATTESTATION_SUBNET_COUNT: 64
ATTESTATION_SUBNET_EXTRA_BITS: 0
DEPOSIT_CHAIN_ID: 7042643276
DEPOSIT_NETWORK_ID: 7042643276
DEPOSIT_CONTRACT_ADDRESS: 0x00000000219ab540356cBB839Cbe05303d7705Fa
@@ -2833,6 +2857,9 @@ mod yaml_tests {
REORG_HEAD_WEIGHT_THRESHOLD: 20
REORG_PARENT_WEIGHT_THRESHOLD: 160
REORG_MAX_EPOCHS_SINCE_FINALIZATION: 2
EPOCHS_PER_SUBNET_SUBSCRIPTION: 256
ATTESTATION_SUBNET_COUNT: 64
ATTESTATION_SUBNET_EXTRA_BITS: 0
DEPOSIT_CHAIN_ID: 7042643276
DEPOSIT_NETWORK_ID: 7042643276
DEPOSIT_CONTRACT_ADDRESS: 0x00000000219ab540356cBB839Cbe05303d7705Fa
@@ -2942,6 +2969,9 @@ mod yaml_tests {
MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT: 8
CHURN_LIMIT_QUOTIENT: 65536
PROPOSER_SCORE_BOOST: 40
EPOCHS_PER_SUBNET_SUBSCRIPTION: 256
ATTESTATION_SUBNET_COUNT: 64
ATTESTATION_SUBNET_EXTRA_BITS: 0
DEPOSIT_CHAIN_ID: 1
DEPOSIT_NETWORK_ID: 1
DEPOSIT_CONTRACT_ADDRESS: 0x00000000219ab540356cBB839Cbe05303d7705Fa
@@ -2974,7 +3004,6 @@ mod yaml_tests {
check_default!(resp_timeout);
check_default!(message_domain_invalid_snappy);
check_default!(message_domain_valid_snappy);
check_default!(attestation_subnet_prefix_bits);
assert_eq!(chain_spec.bellatrix_fork_epoch, None);
}

View File

@@ -114,6 +114,7 @@ pub fn get_extra_fields(spec: &ChainSpec) -> HashMap<String, Value> {
let u32_hex = |v: u32| hex_string(&v.to_le_bytes());
let u8_hex = |v: u8| hex_string(&v.to_le_bytes());
hashmap! {
"attestation_subnet_prefix_bits".to_uppercase() => spec.attestation_subnet_prefix_bits.to_string().into(),
"bls_withdrawal_prefix".to_uppercase() => u8_hex(spec.bls_withdrawal_prefix_byte),
"eth1_address_withdrawal_prefix".to_uppercase() => u8_hex(spec.eth1_address_withdrawal_prefix_byte),
"domain_beacon_proposer".to_uppercase() => u32_hex(spec.domain_beacon_proposer),
@@ -131,6 +132,7 @@ pub fn get_extra_fields(spec: &ChainSpec) -> HashMap<String, Value> {
"domain_sync_committee".to_uppercase() => u32_hex(spec.domain_sync_committee),
"domain_sync_committee_selection_proof".to_uppercase() =>
u32_hex(spec.domain_sync_committee_selection_proof),
"domain_bls_to_execution_change".to_uppercase() => u32_hex(spec.domain_bls_to_execution_change),
"sync_committee_subnet_count".to_uppercase() =>
consts::altair::SYNC_COMMITTEE_SUBNET_COUNT.to_string().into(),
"target_aggregators_per_sync_subcommittee".to_uppercase() =>
@@ -183,4 +185,38 @@ mod test {
serde_yaml::from_reader(reader).expect("error while deserializing");
assert_eq!(ConfigAndPreset::Gloas(from), yamlconfig);
}
#[test]
fn test_attestation_subnet_prefix_bits_in_extra_fields() {
let mainnet_spec = ChainSpec::mainnet();
let config = ConfigAndPreset::from_chain_spec::<MainnetEthSpec>(&mainnet_spec);
let extra_fields = config.extra_fields();
assert!(extra_fields.contains_key("ATTESTATION_SUBNET_PREFIX_BITS"));
// For mainnet: 64 subnets, 0 extra bits -> ceil(log2(64)) + 0 = 6
assert_eq!(
extra_fields.get("ATTESTATION_SUBNET_PREFIX_BITS"),
Some(&Value::String("6".to_string()))
);
}
// This is not exhaustive, but it can be extended as new fields are added to the spec.
#[test]
fn test_required_spec_fields_exist() {
let mainnet_spec = ChainSpec::mainnet();
let config = ConfigAndPreset::from_chain_spec::<MainnetEthSpec>(&mainnet_spec);
let json = serde_json::to_value(&config).expect("should serialize");
let obj = json.as_object().expect("should be an object");
let required_fields = [
"EPOCHS_PER_SUBNET_SUBSCRIPTION",
"ATTESTATION_SUBNET_COUNT",
"ATTESTATION_SUBNET_EXTRA_BITS",
"ATTESTATION_SUBNET_PREFIX_BITS",
"UPDATE_TIMEOUT",
"DOMAIN_BLS_TO_EXECUTION_CHANGE",
];
for field in required_fields {
assert!(obj.contains_key(field), "Missing required field: {}", field);
}
}
}

View File

@@ -3,7 +3,7 @@ use std::{
str::FromStr,
};
use safe_arith::SafeArith;
use safe_arith::{ArithError, SafeArith};
use serde::{Deserialize, Serialize};
use typenum::{
U0, U1, U2, U4, U8, U16, U17, U32, U64, U128, U256, U512, U625, U1024, U2048, U4096, U8192,
@@ -11,10 +11,7 @@ use typenum::{
U1099511627776, UInt, Unsigned, bit::B0,
};
use crate::{
core::{ChainSpec, Epoch},
state::BeaconStateError,
};
use crate::core::{ChainSpec, Epoch};
type U5000 = UInt<UInt<UInt<U625, B0>, B0>, B0>; // 625 * 8 = 5000
@@ -196,7 +193,7 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq +
fn get_committee_count_per_slot(
active_validator_count: usize,
spec: &ChainSpec,
) -> Result<usize, BeaconStateError> {
) -> Result<usize, ArithError> {
Self::get_committee_count_per_slot_with(
active_validator_count,
spec.max_committees_per_slot,
@@ -208,7 +205,7 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq +
active_validator_count: usize,
max_committees_per_slot: usize,
target_committee_size: usize,
) -> Result<usize, BeaconStateError> {
) -> Result<usize, ArithError> {
let slots_per_epoch = Self::SlotsPerEpoch::to_usize();
Ok(std::cmp::max(

View File

@@ -5,6 +5,7 @@ mod chain_spec;
mod config_and_preset;
mod enr_fork_id;
mod eth_spec;
mod execution_block_hash;
mod graffiti;
mod non_zero_usize;
mod preset;
@@ -25,6 +26,7 @@ pub use config_and_preset::{
};
pub use enr_fork_id::EnrForkId;
pub use eth_spec::{EthSpec, EthSpecId, GNOSIS, GnosisEthSpec, MainnetEthSpec, MinimalEthSpec};
pub use execution_block_hash::ExecutionBlockHash;
pub use graffiti::{GRAFFITI_BYTES_LEN, Graffiti, GraffitiString};
pub use non_zero_usize::new_non_zero_usize;
pub use preset::{

View File

@@ -134,6 +134,9 @@ pub struct AltairPreset {
pub epochs_per_sync_committee_period: Epoch,
#[serde(with = "serde_utils::quoted_u64")]
pub min_sync_committee_participants: u64,
#[serde(default = "default_update_timeout")]
#[serde(with = "serde_utils::quoted_u64")]
pub update_timeout: u64,
}
impl AltairPreset {
@@ -145,10 +148,15 @@ impl AltairPreset {
sync_committee_size: E::SyncCommitteeSize::to_u64(),
epochs_per_sync_committee_period: spec.epochs_per_sync_committee_period,
min_sync_committee_participants: spec.min_sync_committee_participants,
update_timeout: spec.update_timeout,
}
}
}
const fn default_update_timeout() -> u64 {
8192
}
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub struct BellatrixPreset {

View File

@@ -10,8 +10,7 @@ use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;
use crate::{
core::{Address, EthSpec, Hash256},
execution::ExecutionBlockHash,
core::{Address, EthSpec, ExecutionBlockHash, Hash256},
fork::{ForkName, ForkVersionDecode},
state::BeaconStateError,
test_utils::TestRandom,

View File

@@ -18,6 +18,7 @@ pub struct ExecutionPayloadBid {
pub parent_block_hash: ExecutionBlockHash,
pub parent_block_root: Hash256,
pub block_hash: ExecutionBlockHash,
pub prev_randao: Hash256,
#[serde(with = "serde_utils::address_hex")]
pub fee_recipient: Address,
#[serde(with = "serde_utils::quoted_u64")]
@@ -27,6 +28,8 @@ pub struct ExecutionPayloadBid {
pub slot: Slot,
#[serde(with = "serde_utils::quoted_u64")]
pub value: u64,
#[serde(with = "serde_utils::quoted_u64")]
pub execution_payment: u64,
pub blob_kzg_commitments_root: Hash256,
}

View File

@@ -11,11 +11,10 @@ use tree_hash::TreeHash;
use tree_hash_derive::TreeHash;
use crate::{
core::{Address, EthSpec, Hash256, Uint256},
core::{Address, EthSpec, ExecutionBlockHash, Hash256, Uint256},
execution::{
ExecutionBlockHash, ExecutionPayloadBellatrix, ExecutionPayloadCapella,
ExecutionPayloadDeneb, ExecutionPayloadElectra, ExecutionPayloadFulu, ExecutionPayloadRef,
Transactions,
ExecutionPayloadBellatrix, ExecutionPayloadCapella, ExecutionPayloadDeneb,
ExecutionPayloadElectra, ExecutionPayloadFulu, ExecutionPayloadRef, Transactions,
},
fork::ForkName,
map_execution_payload_ref_into_execution_payload_header,

View File

@@ -1,5 +1,4 @@
mod eth1_data;
mod execution_block_hash;
mod execution_block_header;
#[macro_use]
mod execution_payload;
@@ -16,7 +15,6 @@ mod signed_execution_payload_envelope;
pub use bls_to_execution_change::BlsToExecutionChange;
pub use eth1_data::Eth1Data;
pub use execution_block_hash::ExecutionBlockHash;
pub use execution_block_header::{EncodableExecutionBlockHeader, ExecutionBlockHeader};
pub use execution_payload::{
ExecutionPayload, ExecutionPayloadBellatrix, ExecutionPayloadCapella, ExecutionPayloadDeneb,

View File

@@ -11,9 +11,9 @@ use tree_hash::TreeHash;
use tree_hash_derive::TreeHash;
use crate::{
core::{Address, EthSpec, Hash256},
core::{Address, EthSpec, ExecutionBlockHash, Hash256},
execution::{
ExecutionBlockHash, ExecutionPayload, ExecutionPayloadBellatrix, ExecutionPayloadCapella,
ExecutionPayload, ExecutionPayloadBellatrix, ExecutionPayloadCapella,
ExecutionPayloadDeneb, ExecutionPayloadElectra, ExecutionPayloadFulu,
ExecutionPayloadHeader, ExecutionPayloadHeaderBellatrix, ExecutionPayloadHeaderCapella,
ExecutionPayloadHeaderDeneb, ExecutionPayloadHeaderElectra, ExecutionPayloadHeaderFulu,

View File

@@ -49,129 +49,6 @@ pub use sync_committee::*;
pub use validator::*;
pub use withdrawal::*;
// Temporary facade modules to maintain backwards compatibility for Lighthouse.
pub mod eth_spec {
pub use crate::core::EthSpec;
}
pub mod chain_spec {
pub use crate::core::ChainSpec;
}
pub mod beacon_block {
pub use crate::block::{BlindedBeaconBlock, BlockImportSource};
}
pub mod beacon_block_body {
pub use crate::kzg_ext::{KzgCommitments, format_kzg_commitments};
}
pub mod beacon_state {
pub use crate::state::{
BeaconState, BeaconStateBase, CommitteeCache, compute_committee_index_in_epoch,
compute_committee_range_in_epoch, epoch_committee_count,
};
}
pub mod graffiti {
pub use crate::core::GraffitiString;
pub use crate::core::{GRAFFITI_BYTES_LEN, Graffiti, GraffitiString};
}
pub mod indexed_attestation {
pub use crate::attestation::{IndexedAttestationBase, IndexedAttestationElectra};
}
pub mod historical_summary {
pub use crate::state::HistoricalSummary;
}
pub mod participation_flags {
pub use crate::attestation::ParticipationFlags;
}
pub mod epoch_cache {
pub use crate::state::{EpochCache, EpochCacheError, EpochCacheKey};
}
pub mod non_zero_usize {
pub use crate::core::new_non_zero_usize;
}
pub mod data_column_sidecar {
pub use crate::data::{
Cell, ColumnIndex, DataColumn, DataColumnSidecar, DataColumnSidecarError,
DataColumnSidecarList,
};
}
pub mod builder_bid {
pub use crate::builder::*;
}
pub mod blob_sidecar {
pub use crate::data::{
BlobIdentifier, BlobSidecar, BlobSidecarError, BlobsList, FixedBlobSidecarList,
};
}
pub mod payload {
pub use crate::execution::BlockProductionVersion;
}
pub mod execution_requests {
pub use crate::execution::{
ConsolidationRequests, DepositRequests, ExecutionRequests, RequestType, WithdrawalRequests,
};
}
pub mod execution_payload_envelope {
pub use crate::execution::{ExecutionPayloadEnvelope, SignedExecutionPayloadEnvelope};
}
pub mod data_column_custody_group {
pub use crate::data::{
CustodyIndex, compute_columns_for_custody_group, compute_ordered_custody_column_indices,
compute_subnets_for_node, compute_subnets_from_custody_group, get_custody_groups,
};
}
pub mod sync_aggregate {
pub use crate::sync_committee::SyncAggregateError as Error;
}
pub mod light_client_update {
pub use crate::light_client::consts::{
CURRENT_SYNC_COMMITTEE_INDEX, CURRENT_SYNC_COMMITTEE_INDEX_ELECTRA, FINALIZED_ROOT_INDEX,
FINALIZED_ROOT_INDEX_ELECTRA, MAX_REQUEST_LIGHT_CLIENT_UPDATES, NEXT_SYNC_COMMITTEE_INDEX,
NEXT_SYNC_COMMITTEE_INDEX_ELECTRA,
};
}
pub mod sync_committee_contribution {
pub use crate::sync_committee::{
SyncCommitteeContributionError as Error, SyncContributionData,
};
}
pub mod slot_data {
pub use crate::core::SlotData;
}
pub mod signed_aggregate_and_proof {
pub use crate::attestation::SignedAggregateAndProofRefMut;
}
pub mod payload_attestation {
pub use crate::attestation::{
PayloadAttestation, PayloadAttestationData, PayloadAttestationMessage,
};
}
pub mod application_domain {
pub use crate::core::ApplicationDomain;
}
// Temporary re-exports to maintain backwards compatibility for Lighthouse.
pub use crate::kzg_ext::consts::VERSIONED_HASH_VERSION_KZG;
pub use crate::light_client::LightClientError as LightClientUpdateError;
pub use crate::state::BeaconStateError as Error;

View File

@@ -2552,6 +2552,42 @@ impl<E: EthSpec> BeaconState<E> {
self.epoch_cache().get_base_reward(validator_index)
}
/// Get the proportional slashing multiplier for the current fork.
pub fn get_proportional_slashing_multiplier(&self, spec: &ChainSpec) -> u64 {
let fork_name = self.fork_name_unchecked();
if fork_name >= ForkName::Bellatrix {
spec.proportional_slashing_multiplier_bellatrix
} else if fork_name >= ForkName::Altair {
spec.proportional_slashing_multiplier_altair
} else {
spec.proportional_slashing_multiplier
}
}
/// Get the minimum slashing penalty quotient for the current fork.
pub fn get_min_slashing_penalty_quotient(&self, spec: &ChainSpec) -> u64 {
let fork_name = self.fork_name_unchecked();
if fork_name.electra_enabled() {
spec.min_slashing_penalty_quotient_electra
} else if fork_name >= ForkName::Bellatrix {
spec.min_slashing_penalty_quotient_bellatrix
} else if fork_name >= ForkName::Altair {
spec.min_slashing_penalty_quotient_altair
} else {
spec.min_slashing_penalty_quotient
}
}
/// Get the whistleblower reward quotient for the current fork.
pub fn get_whistleblower_reward_quotient(&self, spec: &ChainSpec) -> u64 {
let fork_name = self.fork_name_unchecked();
if fork_name.electra_enabled() {
spec.whistleblower_reward_quotient_electra
} else {
spec.whistleblower_reward_quotient
}
}
// ******* Electra accessors *******
/// Return the churn limit for the current epoch.

View File

@@ -100,7 +100,8 @@ impl CommitteeCache {
}
let committees_per_slot =
E::get_committee_count_per_slot(active_validator_indices.len(), spec)? as u64;
E::get_committee_count_per_slot(active_validator_indices.len(), spec)
.map_err(BeaconStateError::ArithError)? as u64;
let seed = state.get_seed(epoch, Domain::BeaconAttester, spec)?;