Skip to content
Merged
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
2 changes: 1 addition & 1 deletion config.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Some fields are optional and can be omitted, in which case the default value, if present, will be used.

# Chain spec ID. Supported values:
# A network ID. Supported values: Mainnet, Holesky, Sepolia, Helder.
# A network ID. Supported values: Mainnet, Holesky, Sepolia, Helder, Hoodi.
# A custom object, e.g., chain = { genesis_time_secs = 1695902400, path = "/path/to/spec.json" }, with a path to a chain spec file, either in .json format (e.g., as returned by the beacon endpoint /eth/v1/config/spec), or in .yml format (see examples in tests/data).
# A custom object, e.g., chain = { genesis_time_secs = 1695902400, slot_time_secs = 12, genesis_fork_version = "0x01017000" }.
chain = "Holesky"
Expand Down
4 changes: 4 additions & 0 deletions crates/common/src/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,5 +112,9 @@ mod tests {
compute_domain(Chain::Helder, APPLICATION_BUILDER_DOMAIN),
Chain::Helder.builder_domain()
);
assert_eq!(
compute_domain(Chain::Hoodi, APPLICATION_BUILDER_DOMAIN),
Chain::Hoodi.builder_domain()
);
}
}
48 changes: 46 additions & 2 deletions crates/common/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub enum Chain {
Holesky,
Sepolia,
Helder,
Hoodi,
Custom { genesis_time_secs: u64, slot_time_secs: u64, genesis_fork_version: ForkVersion },
}

Expand All @@ -31,7 +32,9 @@ pub type ForkVersion = [u8; 4];
impl std::fmt::Display for Chain {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Mainnet | Self::Holesky | Self::Sepolia | Self::Helder => write!(f, "{self:?}"),
Self::Mainnet | Self::Holesky | Self::Sepolia | Self::Helder | Self::Hoodi => {
write!(f, "{self:?}")
}
Self::Custom { .. } => write!(f, "Custom"),
}
}
Expand All @@ -44,6 +47,7 @@ impl std::fmt::Debug for Chain {
Self::Holesky => write!(f, "Holesky"),
Self::Sepolia => write!(f, "Sepolia"),
Self::Helder => write!(f, "Helder"),
Self::Hoodi => write!(f, "Hoodi"),
Self::Custom { genesis_time_secs, slot_time_secs, genesis_fork_version } => f
.debug_struct("Custom")
.field("genesis_time_secs", genesis_time_secs)
Expand All @@ -61,6 +65,7 @@ impl Chain {
Chain::Holesky => KnownChain::Holesky.id(),
Chain::Sepolia => KnownChain::Sepolia.id(),
Chain::Helder => KnownChain::Helder.id(),
Chain::Hoodi => KnownChain::Hoodi.id(),
Chain::Custom { .. } => {
unimplemented!("chain id is not supported on custom chains, please file an issue")
}
Expand All @@ -73,6 +78,7 @@ impl Chain {
Chain::Holesky => KnownChain::Holesky.builder_domain(),
Chain::Sepolia => KnownChain::Sepolia.builder_domain(),
Chain::Helder => KnownChain::Helder.builder_domain(),
Chain::Hoodi => KnownChain::Hoodi.builder_domain(),
Chain::Custom { .. } => compute_domain(*self, APPLICATION_BUILDER_DOMAIN),
}
}
Expand All @@ -83,6 +89,7 @@ impl Chain {
Chain::Holesky => KnownChain::Holesky.genesis_fork_version(),
Chain::Sepolia => KnownChain::Sepolia.genesis_fork_version(),
Chain::Helder => KnownChain::Helder.genesis_fork_version(),
Chain::Hoodi => KnownChain::Hoodi.genesis_fork_version(),
Chain::Custom { genesis_fork_version, .. } => *genesis_fork_version,
}
}
Expand All @@ -93,6 +100,7 @@ impl Chain {
Chain::Holesky => KnownChain::Holesky.genesis_time_sec(),
Chain::Sepolia => KnownChain::Sepolia.genesis_time_sec(),
Chain::Helder => KnownChain::Helder.genesis_time_sec(),
Chain::Hoodi => KnownChain::Hoodi.genesis_time_sec(),
Chain::Custom { genesis_time_secs, .. } => *genesis_time_secs,
}
}
Expand All @@ -103,6 +111,7 @@ impl Chain {
Chain::Holesky => KnownChain::Holesky.slot_time_sec(),
Chain::Sepolia => KnownChain::Sepolia.slot_time_sec(),
Chain::Helder => KnownChain::Helder.slot_time_sec(),
Chain::Hoodi => KnownChain::Hoodi.slot_time_sec(),
Chain::Custom { slot_time_secs, .. } => *slot_time_secs,
}
}
Expand All @@ -118,6 +127,8 @@ pub enum KnownChain {
Sepolia,
#[serde(alias = "helder")]
Helder,
#[serde(alias = "hoodi")]
Hoodi,
}

// Constants
Expand All @@ -128,6 +139,7 @@ impl KnownChain {
KnownChain::Holesky => 17000,
KnownChain::Sepolia => 11155111,
KnownChain::Helder => 167000,
KnownChain::Hoodi => 560048,
}
}

Expand All @@ -149,6 +161,10 @@ impl KnownChain {
0, 0, 0, 1, 148, 196, 26, 244, 132, 255, 247, 150, 73, 105, 224, 189, 217, 34, 248,
45, 255, 15, 75, 232, 122, 96, 208, 102, 76, 201, 209, 255,
],
KnownChain::Hoodi => [
0, 0, 0, 1, 113, 145, 3, 81, 30, 250, 79, 19, 98, 255, 42, 80, 153, 108, 204, 243,
41, 204, 132, 203, 65, 12, 94, 92, 125, 53, 29, 3,
],
}
}

Expand All @@ -158,6 +174,7 @@ impl KnownChain {
KnownChain::Holesky => hex!("01017000"),
KnownChain::Sepolia => hex!("90000069"),
KnownChain::Helder => hex!("10000000"),
KnownChain::Hoodi => hex!("10000910"),
}
}

Expand All @@ -167,6 +184,7 @@ impl KnownChain {
KnownChain::Holesky => 1695902400,
KnownChain::Sepolia => 1655733600,
KnownChain::Helder => 1718967660,
KnownChain::Hoodi => 1742213400,
}
}

Expand All @@ -175,7 +193,8 @@ impl KnownChain {
KnownChain::Mainnet |
KnownChain::Holesky |
KnownChain::Sepolia |
KnownChain::Helder => 12,
KnownChain::Helder |
KnownChain::Hoodi => 12,
}
}
}
Expand All @@ -187,6 +206,7 @@ impl From<KnownChain> for Chain {
KnownChain::Holesky => Chain::Holesky,
KnownChain::Sepolia => Chain::Sepolia,
KnownChain::Helder => Chain::Helder,
KnownChain::Hoodi => Chain::Hoodi,
}
}
}
Expand Down Expand Up @@ -220,6 +240,7 @@ impl Serialize for Chain {
Chain::Holesky => ChainLoader::Known(KnownChain::Holesky),
Chain::Sepolia => ChainLoader::Known(KnownChain::Sepolia),
Chain::Helder => ChainLoader::Known(KnownChain::Helder),
Chain::Hoodi => ChainLoader::Known(KnownChain::Hoodi),
Chain::Custom { genesis_time_secs, slot_time_secs, genesis_fork_version } => {
ChainLoader::Custom {
genesis_time_secs: *genesis_time_secs,
Expand Down Expand Up @@ -372,6 +393,7 @@ mod tests {
let s = format!("chain = {{ genesis_time_secs = 1, path = {path:?}}}");

let decoded: MockConfig = toml::from_str(&s).unwrap();
assert_eq!(decoded.chain.slot_time_sec(), KnownChain::Holesky.slot_time_sec());
assert_eq!(decoded.chain, Chain::Custom {
genesis_time_secs: 1,
slot_time_secs: KnownChain::Holesky.slot_time_sec(),
Expand All @@ -391,13 +413,34 @@ mod tests {
let s = format!("chain = {{ genesis_time_secs = 1, path = {path:?}}}");

let decoded: MockConfig = toml::from_str(&s).unwrap();
assert_eq!(decoded.chain.slot_time_sec(), KnownChain::Helder.slot_time_sec());
assert_eq!(decoded.chain, Chain::Custom {
genesis_time_secs: 1,
slot_time_secs: KnownChain::Sepolia.slot_time_sec(),
genesis_fork_version: KnownChain::Sepolia.genesis_fork_version()
})
}

#[test]
fn test_spec_hoodi_data_json() {
let a = env!("CARGO_MANIFEST_DIR");
let mut path = PathBuf::from(a);

path.pop();
path.pop();
path.push("tests/data/hoodi_spec.json");

let s = format!("chain = {{ genesis_time_secs = 1, path = {path:?}}}");

let decoded: MockConfig = toml::from_str(&s).unwrap();
assert_eq!(decoded.chain.slot_time_sec(), KnownChain::Hoodi.slot_time_sec());
assert_eq!(decoded.chain, Chain::Custom {
genesis_time_secs: 1,
slot_time_secs: KnownChain::Hoodi.slot_time_sec(),
genesis_fork_version: KnownChain::Hoodi.genesis_fork_version()
})
}

#[test]
fn test_spec_helder_yml() {
let a = env!("CARGO_MANIFEST_DIR");
Expand All @@ -410,6 +453,7 @@ mod tests {
let s = format!("chain = {{ genesis_time_secs = 1, path = {path:?}}}");

let decoded: MockConfig = toml::from_str(&s).unwrap();
assert_eq!(decoded.chain.slot_time_sec(), KnownChain::Helder.slot_time_sec());
assert_eq!(decoded.chain, Chain::Custom {
genesis_time_secs: 1,
slot_time_secs: KnownChain::Helder.slot_time_sec(),
Expand Down
155 changes: 155 additions & 0 deletions tests/data/hoodi_spec.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
{
"data": {
"CONFIG_NAME": "hoodi",
"PRESET_BASE": "mainnet",
"TERMINAL_TOTAL_DIFFICULTY": "0",
"TERMINAL_BLOCK_HASH": "0x0000000000000000000000000000000000000000000000000000000000000000",
"TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH": "18446744073709551615",
"MIN_GENESIS_ACTIVE_VALIDATOR_COUNT": "16384",
"MIN_GENESIS_TIME": "1742212800",
"GENESIS_FORK_VERSION": "0x10000910",
"GENESIS_DELAY": "600",
"ALTAIR_FORK_VERSION": "0x20000910",
"ALTAIR_FORK_EPOCH": "0",
"BELLATRIX_FORK_VERSION": "0x30000910",
"BELLATRIX_FORK_EPOCH": "0",
"CAPELLA_FORK_VERSION": "0x40000910",
"CAPELLA_FORK_EPOCH": "0",
"DENEB_FORK_VERSION": "0x50000910",
"DENEB_FORK_EPOCH": "0",
"ELECTRA_FORK_VERSION": "0x60000910",
"ELECTRA_FORK_EPOCH": "2048",
"FULU_FORK_VERSION": "0x70000910",
"FULU_FORK_EPOCH": "18446744073709551615",
"SECONDS_PER_SLOT": "12",
"SECONDS_PER_ETH1_BLOCK": "12",
"MIN_VALIDATOR_WITHDRAWABILITY_DELAY": "256",
"SHARD_COMMITTEE_PERIOD": "256",
"ETH1_FOLLOW_DISTANCE": "2048",
"SUBNETS_PER_NODE": "2",
"INACTIVITY_SCORE_BIAS": "4",
"INACTIVITY_SCORE_RECOVERY_RATE": "16",
"EJECTION_BALANCE": "16000000000",
"MIN_PER_EPOCH_CHURN_LIMIT": "4",
"MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT": "8",
"CHURN_LIMIT_QUOTIENT": "65536",
"PROPOSER_SCORE_BOOST": "40",
"DEPOSIT_CHAIN_ID": "560048",
"DEPOSIT_NETWORK_ID": "560048",
"DEPOSIT_CONTRACT_ADDRESS": "0x00000000219ab540356cbb839cbe05303d7705fa",
"GAS_LIMIT_ADJUSTMENT_FACTOR": "1024",
"GOSSIP_MAX_SIZE": "10485760",
"MAX_REQUEST_BLOCKS": "1024",
"MIN_EPOCHS_FOR_BLOCK_REQUESTS": "33024",
"MAX_CHUNK_SIZE": "10485760",
"TTFB_TIMEOUT": "5",
"RESP_TIMEOUT": "10",
"ATTESTATION_PROPAGATION_SLOT_RANGE": "32",
"MAXIMUM_GOSSIP_CLOCK_DISPARITY_MILLIS": "500",
"MESSAGE_DOMAIN_INVALID_SNAPPY": "0x00000000",
"MESSAGE_DOMAIN_VALID_SNAPPY": "0x01000000",
"ATTESTATION_SUBNET_PREFIX_BITS": "6",
"MAX_REQUEST_BLOCKS_DENEB": "128",
"MAX_REQUEST_BLOB_SIDECARS": "768",
"MAX_REQUEST_DATA_COLUMN_SIDECARS": "16384",
"MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS": "4096",
"BLOB_SIDECAR_SUBNET_COUNT": "6",
"MAX_BLOBS_PER_BLOCK": "6",
"MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA": "128000000000",
"MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT": "256000000000",
"MAX_BLOBS_PER_BLOCK_ELECTRA": "9",
"BLOB_SIDECAR_SUBNET_COUNT_ELECTRA": "9",
"MAX_REQUEST_BLOB_SIDECARS_ELECTRA": "1152",
"NUMBER_OF_COLUMNS": "128",
"NUMBER_OF_CUSTODY_GROUPS": "128",
"DATA_COLUMN_SIDECAR_SUBNET_COUNT": "128",
"SAMPLES_PER_SLOT": "8",
"CUSTODY_REQUIREMENT": "4",
"MAX_COMMITTEES_PER_SLOT": "64",
"TARGET_COMMITTEE_SIZE": "128",
"MAX_VALIDATORS_PER_COMMITTEE": "2048",
"SHUFFLE_ROUND_COUNT": "90",
"HYSTERESIS_QUOTIENT": "4",
"HYSTERESIS_DOWNWARD_MULTIPLIER": "1",
"HYSTERESIS_UPWARD_MULTIPLIER": "5",
"MIN_DEPOSIT_AMOUNT": "1000000000",
"MAX_EFFECTIVE_BALANCE": "32000000000",
"EFFECTIVE_BALANCE_INCREMENT": "1000000000",
"MIN_ATTESTATION_INCLUSION_DELAY": "1",
"SLOTS_PER_EPOCH": "32",
"MIN_SEED_LOOKAHEAD": "1",
"MAX_SEED_LOOKAHEAD": "4",
"EPOCHS_PER_ETH1_VOTING_PERIOD": "64",
"SLOTS_PER_HISTORICAL_ROOT": "8192",
"MIN_EPOCHS_TO_INACTIVITY_PENALTY": "4",
"EPOCHS_PER_HISTORICAL_VECTOR": "65536",
"EPOCHS_PER_SLASHINGS_VECTOR": "8192",
"HISTORICAL_ROOTS_LIMIT": "16777216",
"VALIDATOR_REGISTRY_LIMIT": "1099511627776",
"BASE_REWARD_FACTOR": "64",
"WHISTLEBLOWER_REWARD_QUOTIENT": "512",
"PROPOSER_REWARD_QUOTIENT": "8",
"INACTIVITY_PENALTY_QUOTIENT": "67108864",
"MIN_SLASHING_PENALTY_QUOTIENT": "128",
"PROPORTIONAL_SLASHING_MULTIPLIER": "1",
"MAX_PROPOSER_SLASHINGS": "16",
"MAX_ATTESTER_SLASHINGS": "2",
"MAX_ATTESTATIONS": "128",
"MAX_DEPOSITS": "16",
"MAX_VOLUNTARY_EXITS": "16",
"INACTIVITY_PENALTY_QUOTIENT_ALTAIR": "50331648",
"MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR": "64",
"PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR": "2",
"SYNC_COMMITTEE_SIZE": "512",
"EPOCHS_PER_SYNC_COMMITTEE_PERIOD": "256",
"MIN_SYNC_COMMITTEE_PARTICIPANTS": "1",
"INACTIVITY_PENALTY_QUOTIENT_BELLATRIX": "16777216",
"MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX": "32",
"PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX": "3",
"MAX_BYTES_PER_TRANSACTION": "1073741824",
"MAX_TRANSACTIONS_PER_PAYLOAD": "1048576",
"BYTES_PER_LOGS_BLOOM": "256",
"MAX_EXTRA_DATA_BYTES": "32",
"MAX_BLS_TO_EXECUTION_CHANGES": "16",
"MAX_WITHDRAWALS_PER_PAYLOAD": "16",
"MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP": "16384",
"MAX_BLOB_COMMITMENTS_PER_BLOCK": "4096",
"FIELD_ELEMENTS_PER_BLOB": "4096",
"MIN_ACTIVATION_BALANCE": "32000000000",
"MAX_EFFECTIVE_BALANCE_ELECTRA": "2048000000000",
"MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA": "4096",
"WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA": "4096",
"MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP": "8",
"PENDING_DEPOSITS_LIMIT": "134217728",
"PENDING_PARTIAL_WITHDRAWALS_LIMIT": "134217728",
"PENDING_CONSOLIDATIONS_LIMIT": "262144",
"MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD": "2",
"MAX_DEPOSIT_REQUESTS_PER_PAYLOAD": "8192",
"MAX_ATTESTER_SLASHINGS_ELECTRA": "1",
"MAX_ATTESTATIONS_ELECTRA": "8",
"MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD": "16",
"FIELD_ELEMENTS_PER_CELL": "64",
"FIELD_ELEMENTS_PER_EXT_BLOB": "8192",
"KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH": "4",
"VERSIONED_HASH_VERSION_KZG": "1",
"DOMAIN_SYNC_COMMITTEE": "0x07000000",
"DOMAIN_VOLUNTARY_EXIT": "0x04000000",
"TARGET_AGGREGATORS_PER_COMMITTEE": "16",
"SYNC_COMMITTEE_SUBNET_COUNT": "4",
"DOMAIN_BEACON_ATTESTER": "0x01000000",
"FULL_EXIT_REQUEST_AMOUNT": "0",
"BLS_WITHDRAWAL_PREFIX": "0x00",
"DOMAIN_SELECTION_PROOF": "0x05000000",
"DOMAIN_AGGREGATE_AND_PROOF": "0x06000000",
"DOMAIN_DEPOSIT": "0x03000000",
"DOMAIN_CONTRIBUTION_AND_PROOF": "0x09000000",
"DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF": "0x08000000",
"COMPOUNDING_WITHDRAWAL_PREFIX": "0x02",
"DOMAIN_APPLICATION_MASK": "0x00000001",
"DOMAIN_RANDAO": "0x02000000",
"UNSET_DEPOSIT_REQUESTS_START_INDEX": "18446744073709551615",
"TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE": "16",
"DOMAIN_BEACON_PROPOSER": "0x00000000",
"ETH1_ADDRESS_WITHDRAWAL_PREFIX": "0x01"
}
}
Loading