Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ SUBNETS_PER_NODE: 2
ATTESTATION_SUBNET_COUNT: 64
ATTESTATION_SUBNET_EXTRA_BITS: 0
# ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS
# computed at runtime
ATTESTATION_SUBNET_PREFIX_BITS: 6

# Deneb
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ MESSAGE_DOMAIN_INVALID_SNAPPY: 0x00000000
MESSAGE_DOMAIN_VALID_SNAPPY: 0x01000000
ATTESTATION_SUBNET_COUNT: 64
ATTESTATION_SUBNET_EXTRA_BITS: 0
# ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS
# computed at runtime
ATTESTATION_SUBNET_PREFIX_BITS: 6
ATTESTATION_SUBNET_SHUFFLING_PREFIX_BITS: 3

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ SUBNETS_PER_NODE: 2
ATTESTATION_SUBNET_COUNT: 64
ATTESTATION_SUBNET_EXTRA_BITS: 0
# ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS
# computed at runtime
ATTESTATION_SUBNET_PREFIX_BITS: 6
ATTESTATION_SUBNET_SHUFFLING_PREFIX_BITS: 3

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ SUBNETS_PER_NODE: 2
ATTESTATION_SUBNET_COUNT: 64
ATTESTATION_SUBNET_EXTRA_BITS: 0
# ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS
# computed at runtime
ATTESTATION_SUBNET_PREFIX_BITS: 6

# Deneb
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ 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
ATTESTATION_SUBNET_PREFIX_BITS: 6
ATTESTATION_SUBNET_SHUFFLING_PREFIX_BITS: 3

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ SUBNETS_PER_NODE: 2
ATTESTATION_SUBNET_COUNT: 64
ATTESTATION_SUBNET_EXTRA_BITS: 0
# ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS
# computed at runtime
ATTESTATION_SUBNET_PREFIX_BITS: 6
ATTESTATION_SUBNET_SHUFFLING_PREFIX_BITS: 3

Expand Down
96 changes: 86 additions & 10 deletions consensus/types/src/core/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,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,
Expand Down Expand Up @@ -252,7 +253,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,

/*
Expand Down Expand Up @@ -1060,6 +1063,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,
Expand Down Expand Up @@ -1152,7 +1156,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,
Expand All @@ -1162,7 +1168,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(),

/*
Expand Down Expand Up @@ -1243,6 +1252,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
Expand Down Expand Up @@ -1426,6 +1436,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,
Expand Down Expand Up @@ -1517,7 +1528,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,
Expand All @@ -1528,7 +1541,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
Expand Down Expand Up @@ -1849,9 +1865,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,
Expand Down Expand Up @@ -1966,8 +1988,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 {
Expand Down Expand Up @@ -2252,7 +2302,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,
Expand Down Expand Up @@ -2343,7 +2395,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,
Expand Down Expand Up @@ -2416,6 +2470,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,
Expand All @@ -2436,7 +2493,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,
Expand Down Expand Up @@ -2605,6 +2666,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)]
Expand Down Expand Up @@ -2684,6 +2752,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
Expand Down Expand Up @@ -2833,6 +2904,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
Expand Down Expand Up @@ -2942,6 +3016,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
Expand Down Expand Up @@ -2974,7 +3051,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);
}
Expand Down
36 changes: 36 additions & 0 deletions consensus/types/src/core/config_and_preset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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() =>
Expand Down Expand Up @@ -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);
}
}
}
8 changes: 8 additions & 0 deletions consensus/types/src/core/preset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions lighthouse/environment/tests/testnet_dir/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,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
Expand Down