diff --git a/common/eth2_network_config/built_in_network_configs/chiado/config.yaml b/common/eth2_network_config/built_in_network_configs/chiado/config.yaml index 6bc41113d6f..2e7ed7ef8c2 100644 --- a/common/eth2_network_config/built_in_network_configs/chiado/config.yaml +++ b/common/eth2_network_config/built_in_network_configs/chiado/config.yaml @@ -124,7 +124,7 @@ SUBNETS_PER_NODE: 2 # 2**8 (= 64) ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 -# ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS +# computed at runtime: ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 # Deneb diff --git a/common/eth2_network_config/built_in_network_configs/gnosis/config.yaml b/common/eth2_network_config/built_in_network_configs/gnosis/config.yaml index aa2dbb35d35..254a64de7f1 100644 --- a/common/eth2_network_config/built_in_network_configs/gnosis/config.yaml +++ b/common/eth2_network_config/built_in_network_configs/gnosis/config.yaml @@ -108,7 +108,8 @@ MESSAGE_DOMAIN_INVALID_SNAPPY: 0x00000000 MESSAGE_DOMAIN_VALID_SNAPPY: 0x01000000 ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 -ATTESTATION_SUBNET_PREFIX_BITS: 6 +# computed at runtime: ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS +ATTESTATION_SUBNET_PREFIX_BITS: 6 ATTESTATION_SUBNET_SHUFFLING_PREFIX_BITS: 3 # Deneb diff --git a/common/eth2_network_config/built_in_network_configs/holesky/config.yaml b/common/eth2_network_config/built_in_network_configs/holesky/config.yaml index b1e9faea1d6..fbbcd0e821b 100644 --- a/common/eth2_network_config/built_in_network_configs/holesky/config.yaml +++ b/common/eth2_network_config/built_in_network_configs/holesky/config.yaml @@ -126,7 +126,7 @@ SUBNETS_PER_NODE: 2 # 2**8 (= 64) ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 -# ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS +# computed at runtime: ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 ATTESTATION_SUBNET_SHUFFLING_PREFIX_BITS: 3 diff --git a/common/eth2_network_config/built_in_network_configs/hoodi/config.yaml b/common/eth2_network_config/built_in_network_configs/hoodi/config.yaml index 256957e1197..ae9bc67ff32 100644 --- a/common/eth2_network_config/built_in_network_configs/hoodi/config.yaml +++ b/common/eth2_network_config/built_in_network_configs/hoodi/config.yaml @@ -132,7 +132,7 @@ SUBNETS_PER_NODE: 2 # 2**8 (= 64) ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 -# ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS +# computed at runtime: ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 # Deneb diff --git a/common/eth2_network_config/built_in_network_configs/mainnet/config.yaml b/common/eth2_network_config/built_in_network_configs/mainnet/config.yaml index 49168018cbe..89a9c34f355 100644 --- a/common/eth2_network_config/built_in_network_configs/mainnet/config.yaml +++ b/common/eth2_network_config/built_in_network_configs/mainnet/config.yaml @@ -153,7 +153,7 @@ SUBNETS_PER_NODE: 2 ATTESTATION_SUBNET_COUNT: 64 # 0 bits ATTESTATION_SUBNET_EXTRA_BITS: 0 -# ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS (= 6 + 0) bits +# computed at runtime: ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 ATTESTATION_SUBNET_SHUFFLING_PREFIX_BITS: 3 diff --git a/common/eth2_network_config/built_in_network_configs/sepolia/config.yaml b/common/eth2_network_config/built_in_network_configs/sepolia/config.yaml index b1a01933d70..97f7615150f 100644 --- a/common/eth2_network_config/built_in_network_configs/sepolia/config.yaml +++ b/common/eth2_network_config/built_in_network_configs/sepolia/config.yaml @@ -132,7 +132,7 @@ SUBNETS_PER_NODE: 2 # 2**8 (= 64) ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 -# ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS +# computed at runtime: ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 ATTESTATION_SUBNET_SHUFFLING_PREFIX_BITS: 3 diff --git a/consensus/types/presets/gnosis/altair.yaml b/consensus/types/presets/gnosis/altair.yaml index ff6bd98a009..181f7fc8258 100644 --- a/consensus/types/presets/gnosis/altair.yaml +++ b/consensus/types/presets/gnosis/altair.yaml @@ -22,3 +22,5 @@ EPOCHS_PER_SYNC_COMMITTEE_PERIOD: 512 # --------------------------------------------------------------- # 1 MIN_SYNC_COMMITTEE_PARTICIPANTS: 1 +# SLOTS_PER_EPOCH * EPOCHS_PER_SYNC_COMMITTEE_PERIOD (= 16 * 512) +UPDATE_TIMEOUT: 8192 diff --git a/consensus/types/presets/minimal/altair.yaml b/consensus/types/presets/minimal/altair.yaml index 5e472c49cf3..49dc3ee3653 100644 --- a/consensus/types/presets/minimal/altair.yaml +++ b/consensus/types/presets/minimal/altair.yaml @@ -23,4 +23,4 @@ EPOCHS_PER_SYNC_COMMITTEE_PERIOD: 8 # 1 MIN_SYNC_COMMITTEE_PARTICIPANTS: 1 # SLOTS_PER_EPOCH * EPOCHS_PER_SYNC_COMMITTEE_PERIOD (= 8 * 8) -UPDATE_TIMEOUT: 64 +UPDATE_TIMEOUT: 8192 # hard-coded to mainnet value for testing given this config is not used in Lighthouse diff --git a/consensus/types/src/core/chain_spec.rs b/consensus/types/src/core/chain_spec.rs index da3f9b90ccc..c677d7ccc5d 100644 --- a/consensus/types/src/core/chain_spec.rs +++ b/consensus/types/src/core/chain_spec.rs @@ -252,7 +252,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: u64, pub attestation_subnet_prefix_bits: u8, /* @@ -1152,7 +1154,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 +1166,7 @@ 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(64, 0), max_request_blocks: default_max_request_blocks(), /* @@ -1517,7 +1521,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 +1534,7 @@ 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(64, 0), /* * Networking Deneb Specific @@ -1849,9 +1855,13 @@ 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(with = "serde_utils::quoted_u8")] - attestation_subnet_prefix_bits: u8, + #[serde(with = "serde_utils::quoted_u64")] + epochs_per_subnet_subscription: u64, + #[serde(with = "serde_utils::quoted_u64")] + attestation_subnet_count: u64, + #[serde(with = "serde_utils::quoted_u64")] + attestation_subnet_extra_bits: u64, + // attestation_subnet_prefix_bits is computed dynamically in ChainSpec, not serialized from config #[serde(default = "default_max_request_blocks_deneb")] #[serde(with = "serde_utils::quoted_u64")] max_request_blocks_deneb: u64, @@ -1966,8 +1976,27 @@ fn default_subnets_per_node() -> u8 { 2u8 } -fn default_attestation_subnet_prefix_bits() -> u8 { - 6 +/// Compute the minimum number of bits needed for n values, which means we need to represent [0 ... n-1]. +/// To find this, we simply need the minimum bits for n-1, which is found by finding the power of +/// the most significant bit of n-1 (which is floor(log2(n-1))) and adding 1 to account for the 2^0 bit. +/// Therefore, we get floor(log2(n-1)) + 1 = minimum number of bits needed for n values. +/// This is the same as ceiling(log2(n)), but Rust does not have this function. +fn compute_min_bits_for_n_values(n: u32) -> u32 { + + match n { + 0 => 0, + n => (n - 1).ilog2() + 1, // ilog2 = floor(log2(n)) + } +} + +/// 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: u64, +) -> u8 { + let min_bits = compute_min_bits_for_n_values(attestation_subnet_count as u32); + (min_bits + attestation_subnet_extra_bits as u32) as u8 } const fn default_max_per_epoch_activation_churn_limit() -> u64 { @@ -2252,7 +2281,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 +2374,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 +2449,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 +2472,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 +2645,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 +2731,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 +2883,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 +2995,12 @@ mod yaml_tests { MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT: 8 CHURN_LIMIT_QUOTIENT: 65536 PROPOSER_SCORE_BOOST: 40 + 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: 1 DEPOSIT_NETWORK_ID: 1 DEPOSIT_CONTRACT_ADDRESS: 0x00000000219ab540356cBB839Cbe05303d7705Fa @@ -2974,7 +3033,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); } diff --git a/consensus/types/src/core/config_and_preset.rs b/consensus/types/src/core/config_and_preset.rs index 08141c77311..5b8b27b02e2 100644 --- a/consensus/types/src/core/config_and_preset.rs +++ b/consensus/types/src/core/config_and_preset.rs @@ -114,6 +114,7 @@ pub fn get_extra_fields(spec: &ChainSpec) -> HashMap { 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 { "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::(&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::(&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); + } + } } diff --git a/consensus/types/src/core/preset.rs b/consensus/types/src/core/preset.rs index 75d2d8df6b3..43c5fdd8004 100644 --- a/consensus/types/src/core/preset.rs +++ b/consensus/types/src/core/preset.rs @@ -134,6 +134,8 @@ pub struct AltairPreset { pub epochs_per_sync_committee_period: Epoch, #[serde(with = "serde_utils::quoted_u64")] pub min_sync_committee_participants: u64, + #[serde(with = "serde_utils::quoted_u64")] + pub update_timeout: u64, } impl AltairPreset { @@ -145,6 +147,7 @@ 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: 8192, // light client constant (not used by Lighthouse) } } } diff --git a/lighthouse/environment/tests/testnet_dir/config.yaml b/lighthouse/environment/tests/testnet_dir/config.yaml index 24c4a67225b..2b701e71768 100644 --- a/lighthouse/environment/tests/testnet_dir/config.yaml +++ b/lighthouse/environment/tests/testnet_dir/config.yaml @@ -76,6 +76,9 @@ CHURN_LIMIT_QUOTIENT: 65536 # --------------------------------------------------------------- # 40% PROPOSER_SCORE_BOOST: 40 +REORG_HEAD_WEIGHT_THRESHOLD: 20 +REORG_PARENT_WEIGHT_THRESHOLD: 160 +REORG_MAX_EPOCHS_SINCE_FINALIZATION: 2 # Deposit contract # --------------------------------------------------------------- @@ -93,6 +96,7 @@ TTFB_TIMEOUT: 5 RESP_TIMEOUT: 10 MESSAGE_DOMAIN_INVALID_SNAPPY: 0x00000000 MESSAGE_DOMAIN_VALID_SNAPPY: 0x01000000 +EPOCHS_PER_SUBNET_SUBSCRIPTION: 256 ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 ATTESTATION_SUBNET_PREFIX_BITS: 6