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 @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 2 additions & 0 deletions consensus/types/presets/gnosis/altair.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion consensus/types/presets/minimal/altair.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
80 changes: 69 additions & 11 deletions consensus/types/src/core/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,

/*
Expand Down Expand Up @@ -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,
Expand All @@ -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(),

/*
Expand Down Expand Up @@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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)]
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
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);
}
}
}
3 changes: 3 additions & 0 deletions consensus/types/src/core/preset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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)
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions lighthouse/environment/tests/testnet_dir/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
# ---------------------------------------------------------------
Expand All @@ -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
Expand Down