From 063773eb05a74d9b725e14a4cfcbf66e4973fbdb Mon Sep 17 00:00:00 2001 From: Steve Degosserie <723552+stiiifff@users.noreply.github.com> Date: Tue, 2 Dec 2025 12:49:18 +0100 Subject: [PATCH] =?UTF-8?q?fix:=20=F0=9F=94=A8=20Update=20Snowbridge=20Eth?= =?UTF-8?q?ereum=20network=20configuration=20with=20correct=20genesis=20ha?= =?UTF-8?q?shes=20and=20fork=20versions=20(#310)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary This PR fixes the Snowbridge Ethereum network configuration across all three runtimes (Mainnet, Stagenet, and Testnet) by replacing placeholder genesis hashes with correct values and updating fork versions to match the target Ethereum networks. ### Changes Made #### **Stagenet Runtime** - ✅ Updated genesis hash from `[3u8; 32]` to Hoodi testnet genesis: `0xbbe312868b376a3001692a646dd2d7d1e4406380dfd86b98aa8a34d1557c971b` - ✅ Fixed chain ID from `3151908` to `560048` (Hoodi testnet) - ✅ Updated fork versions to Hoodi testnet configuration (0x10000910 series) - ✅ Added Fulu fork at epoch 50688 (activated Oct 28, 2025) #### **Testnet Runtime** - ✅ Updated genesis hash from `[2u8; 32]` to Hoodi testnet genesis: `0xbbe312868b376a3001692a646dd2d7d1e4406380dfd86b98aa8a34d1557c971b` - ✅ Updated fork versions from Holesky to Hoodi testnet configuration - ✅ Added Fulu fork at epoch 50688 #### **Mainnet Runtime** - ✅ Updated genesis hash from `[1u8; 32]` to Ethereum mainnet genesis: `0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3` - ✅ Updated fork versions from Holesky to Ethereum mainnet configuration (0x00000000 series) - ✅ Added Fulu fork at epoch 411392 (scheduled for Dec 3, 2025) #### **Core Updates** - ✅ Added `fulu` field to `ForkVersions` struct in `snowbridge-beacon-primitives` - ✅ Updated `select_fork_version` function in ethereum-client pallet to handle Fulu fork ### Technical Details **Hoodi Testnet (Stagenet & Testnet):** - Chain ID: 560048 - Genesis: `0xbbe312868b376a3001692a646dd2d7d1e4406380dfd86b98aa8a34d1557c971b` - Fork versions: Genesis (0x10000910) → Altair → Bellatrix → Capella → Deneb → Electra (epoch 2048) → Fulu (epoch 50688) - Source: https://github.com/eth-clients/hoodi **Ethereum Mainnet:** - Chain ID: 1 - Genesis: `0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3` - Fork versions: Genesis (0x00000000) → Altair (epoch 74240) → Bellatrix (144896) → Capella (194048) → Deneb (269568) → Electra (364032) → Fulu (411392) - Source: https://github.com/ethereum/consensus-specs ### Why This Matters The Snowbridge light client relies on accurate Ethereum network parameters to verify consensus proofs. Incorrect genesis hashes or fork versions would cause signature verification failures and prevent the bridge from functioning correctly. ### Fulu Fork Support The Fulu fork (part of Fusaka upgrade) adds a `proposer_lookahead` field to BeaconState but does **not** change generalized indices for sync committees or finalized roots, so it reuses Electra's configuration constants. --------- Co-authored-by: Claude Co-authored-by: undercover-cactus --- .../ethereum-client/src/benchmarking/mod.rs | 4 ++ operator/pallets/ethereum-client/src/lib.rs | 3 ++ .../primitives/snowbridge/beacon/src/types.rs | 1 + operator/runtime/mainnet/src/configs/mod.rs | 38 +++++++++------- operator/runtime/stagenet/src/configs/mod.rs | 41 ++++++++++-------- operator/runtime/testnet/src/configs/mod.rs | 34 +++++++++------ test/.papi/descriptors/package.json | 2 +- test/.papi/metadata/datahaven.scale | Bin 623425 -> 623452 bytes 8 files changed, 76 insertions(+), 47 deletions(-) diff --git a/operator/pallets/ethereum-client/src/benchmarking/mod.rs b/operator/pallets/ethereum-client/src/benchmarking/mod.rs index 56e23289..34114bc4 100644 --- a/operator/pallets/ethereum-client/src/benchmarking/mod.rs +++ b/operator/pallets/ethereum-client/src/benchmarking/mod.rs @@ -145,6 +145,10 @@ mod benchmarks { version: hex!("05000000"), epoch: 80000000000, }, + fulu: Fork { + version: hex!("06000000"), + epoch: 90000000000, + }, }; let finalized_root_gindex = EthereumBeaconClient::::finalized_root_gindex_at_slot( update.attested_header.slot, diff --git a/operator/pallets/ethereum-client/src/lib.rs b/operator/pallets/ethereum-client/src/lib.rs index 668e311f..dfe9c131 100644 --- a/operator/pallets/ethereum-client/src/lib.rs +++ b/operator/pallets/ethereum-client/src/lib.rs @@ -648,6 +648,9 @@ pub mod pallet { /// Returns the fork version based on the current epoch. pub(super) fn select_fork_version(fork_versions: &ForkVersions, epoch: u64) -> ForkVersion { + if epoch >= fork_versions.fulu.epoch { + return fork_versions.fulu.version; + } if epoch >= fork_versions.electra.epoch { return fork_versions.electra.version; } diff --git a/operator/primitives/snowbridge/beacon/src/types.rs b/operator/primitives/snowbridge/beacon/src/types.rs index 9c74b089..062eb218 100644 --- a/operator/primitives/snowbridge/beacon/src/types.rs +++ b/operator/primitives/snowbridge/beacon/src/types.rs @@ -37,6 +37,7 @@ pub struct ForkVersions { pub capella: Fork, pub deneb: Fork, pub electra: Fork, + pub fulu: Fork, } #[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] diff --git a/operator/runtime/mainnet/src/configs/mod.rs b/operator/runtime/mainnet/src/configs/mod.rs index 57e73af9..45bc321a 100644 --- a/operator/runtime/mainnet/src/configs/mod.rs +++ b/operator/runtime/mainnet/src/configs/mod.rs @@ -1043,8 +1043,8 @@ impl pallet_evm_chain_id::Config for Runtime {} // --- Snowbridge Config Constants & Parameter Types --- parameter_types! { - // TODO: Update with real genesis hash once mainnet is deployed - pub const MainnetGenesisHash: [u8; 32] = [1u8; 32]; + // Ethereum mainnet genesis hash + pub const MainnetGenesisHash: [u8; 32] = hex_literal::hex!("d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"); pub UniversalLocation: InteriorLocation = [ GlobalConsensus(ByGenesis(MainnetGenesisHash::get())) ].into(); @@ -1143,11 +1143,15 @@ parameter_types! { version: hex_literal::hex!("60000038"), epoch: 0, }, + fulu: Fork { + version: hex_literal::hex!("70000038"), + epoch: 0, + }, }; } -// Holesky: https://github.com/eth-clients/holesky -// Fork versions: https://github.com/eth-clients/holesky/blob/main/metadata/config.yaml +// Ethereum mainnet fork versions +// Source: https://github.com/ethereum/consensus-specs/blob/dev/configs/mainnet.yaml #[cfg(not(any( feature = "std", feature = "fast-runtime", @@ -1157,28 +1161,32 @@ parameter_types! { parameter_types! { pub const ChainForkVersions: ForkVersions = ForkVersions { genesis: Fork { - version: hex_literal::hex!("01017000"), // 0x01017000 + version: hex_literal::hex!("00000000"), // 0x00000000 epoch: 0, }, altair: Fork { - version: hex_literal::hex!("02017000"), // 0x02017000 - epoch: 0, + version: hex_literal::hex!("01000000"), // 0x01000000 + epoch: 74240, }, bellatrix: Fork { - version: hex_literal::hex!("03017000"), // 0x03017000 - epoch: 0, + version: hex_literal::hex!("02000000"), // 0x02000000 + epoch: 144896, }, capella: Fork { - version: hex_literal::hex!("04017000"), // 0x04017000 - epoch: 256, + version: hex_literal::hex!("03000000"), // 0x03000000 + epoch: 194048, }, deneb: Fork { - version: hex_literal::hex!("05017000"), // 0x05017000 - epoch: 29696, + version: hex_literal::hex!("04000000"), // 0x04000000 + epoch: 269568, }, electra: Fork { - version: hex_literal::hex!("06017000"), // 0x06017000 - epoch: 115968, + version: hex_literal::hex!("05000000"), // 0x05000000 + epoch: 364032, + }, + fulu: Fork { + version: hex_literal::hex!("06000000"), // 0x06000000 + epoch: 411392, // Fusaka upgrade on December 3, 2025 }, }; } diff --git a/operator/runtime/stagenet/src/configs/mod.rs b/operator/runtime/stagenet/src/configs/mod.rs index 3a0bde15..353c5856 100644 --- a/operator/runtime/stagenet/src/configs/mod.rs +++ b/operator/runtime/stagenet/src/configs/mod.rs @@ -1040,8 +1040,8 @@ impl pallet_evm_chain_id::Config for Runtime {} // --- Snowbridge Config Constants & Parameter Types --- parameter_types! { - // TODO: Update with real genesis hash once stagenet is deployed - pub const StagenetGenesisHash: [u8; 32] = [3u8; 32]; + // Hoodi testnet genesis hash + pub const StagenetGenesisHash: [u8; 32] = hex_literal::hex!("bbe312868b376a3001692a646dd2d7d1e4406380dfd86b98aa8a34d1557c971b"); pub UniversalLocation: InteriorLocation = [ GlobalConsensus(ByGenesis(StagenetGenesisHash::get())) ].into(); @@ -1140,13 +1140,15 @@ parameter_types! { version: hex_literal::hex!("60000038"), epoch: 0, }, + fulu: Fork { + version: hex_literal::hex!("70000038"), + epoch: 0, + }, }; } -// For production runtime, use Kurtosis-specific fork versions -// The version numbers are taken from looking at the Dora explorer when launching the -// kurtosis Ethereum network. Hovering over the fork names, shows the version numbers. -// These version numbers need to match, otherwise the aggregated signature verification will fail. +// Hoodi testnet fork versions +// Source: https://github.com/eth-clients/hoodi/blob/main/metadata/config.yaml #[cfg(not(any( feature = "std", feature = "fast-runtime", @@ -1156,28 +1158,32 @@ parameter_types! { parameter_types! { pub const ChainForkVersions: ForkVersions = ForkVersions { genesis: Fork { - version: [16, 0, 0, 56], // 0x10000038 + version: hex_literal::hex!("10000910"), // 0x10000910 epoch: 0, }, altair: Fork { - version: [32, 0, 0, 56], // 0x20000038 + version: hex_literal::hex!("20000910"), // 0x20000910 epoch: 0, }, bellatrix: Fork { - version: [48, 0, 0, 56], // 0x30000038 + version: hex_literal::hex!("30000910"), // 0x30000910 epoch: 0, }, capella: Fork { - version: [64, 0, 0, 56], // 0x40000038 + version: hex_literal::hex!("40000910"), // 0x40000910 epoch: 0, }, deneb: Fork { - version: [80, 0, 0, 56], // 0x50000038 + version: hex_literal::hex!("50000910"), // 0x50000910 epoch: 0, }, electra: Fork { - version: [96, 0, 0, 56], // 0x60000038 - epoch: 0, + version: hex_literal::hex!("60000910"), // 0x60000910 + epoch: 2048, + }, + fulu: Fork { + version: hex_literal::hex!("70000910"), // 0x70000910 + epoch: 50688, }, }; } @@ -1251,10 +1257,9 @@ impl snowbridge_pallet_inbound_queue_v2::Config for Runtime { parameter_types! { /// Network and location for the Ethereum chain. - /// Using the local test network, with chain ID 3151908. - /// This matches the chain ID used in the local test environment. + /// Using Hoodi testnet, with chain ID 560048. /// - pub EthereumNetwork: NetworkId = NetworkId::Ethereum { chain_id: 3151908 }; + pub EthereumNetwork: NetworkId = NetworkId::Ethereum { chain_id: 560048 }; } pub struct CommitmentHandler; @@ -1540,10 +1545,10 @@ impl pallet_external_validators_rewards::Config for Runtime { parameter_types! { /// The Ethereum sovereign account derived from its XCM location /// This is a hardcoded value for performance, computed from: - /// Location::new(1, [GlobalConsensus(NetworkId::Ethereum { chain_id: 3151908 })]) + /// Location::new(1, [GlobalConsensus(NetworkId::Ethereum { chain_id: 560048 })]) /// using GlobalConsensusConvertsFor pub EthereumSovereignAccount: AccountId = AccountId::from( - hex_literal::hex!("d8030fb68aa5b447caec066f3c0bde23e6db0a05") + hex_literal::hex!("5300797dbea5b54078a4b3bf8230015ac47a55fa") ); } diff --git a/operator/runtime/testnet/src/configs/mod.rs b/operator/runtime/testnet/src/configs/mod.rs index 57f40fb0..b35c4cb6 100644 --- a/operator/runtime/testnet/src/configs/mod.rs +++ b/operator/runtime/testnet/src/configs/mod.rs @@ -1043,8 +1043,8 @@ impl pallet_evm_chain_id::Config for Runtime {} // --- Snowbridge Config Constants & Parameter Types --- parameter_types! { - // TODO: Update with real genesis hash once testnet is deployed - pub const TestnetGenesisHash: [u8; 32] = [2u8; 32]; + // Hoodi testnet genesis hash + pub const TestnetGenesisHash: [u8; 32] = hex_literal::hex!("bbe312868b376a3001692a646dd2d7d1e4406380dfd86b98aa8a34d1557c971b"); pub UniversalLocation: InteriorLocation = [ GlobalConsensus(ByGenesis(TestnetGenesisHash::get())) ].into(); @@ -1143,11 +1143,15 @@ parameter_types! { version: hex_literal::hex!("60000038"), epoch: 0, }, + fulu: Fork { + version: hex_literal::hex!("70000038"), + epoch: 0, + }, }; } -// Holesky: https://github.com/eth-clients/holesky -// Fork versions: https://github.com/eth-clients/holesky/blob/main/metadata/config.yaml +// Hoodi testnet fork versions +// Source: https://github.com/eth-clients/hoodi/blob/main/metadata/config.yaml #[cfg(not(any( feature = "std", feature = "fast-runtime", @@ -1157,28 +1161,32 @@ parameter_types! { parameter_types! { pub const ChainForkVersions: ForkVersions = ForkVersions { genesis: Fork { - version: hex_literal::hex!("01017000"), // 0x01017000 + version: hex_literal::hex!("10000910"), // 0x10000910 epoch: 0, }, altair: Fork { - version: hex_literal::hex!("02017000"), // 0x02017000 + version: hex_literal::hex!("20000910"), // 0x20000910 epoch: 0, }, bellatrix: Fork { - version: hex_literal::hex!("03017000"), // 0x03017000 + version: hex_literal::hex!("30000910"), // 0x30000910 epoch: 0, }, capella: Fork { - version: hex_literal::hex!("04017000"), // 0x04017000 - epoch: 256, + version: hex_literal::hex!("40000910"), // 0x40000910 + epoch: 0, }, deneb: Fork { - version: hex_literal::hex!("05017000"), // 0x05017000 - epoch: 29696, + version: hex_literal::hex!("50000910"), // 0x50000910 + epoch: 0, }, electra: Fork { - version: hex_literal::hex!("06017000"), // 0x06017000 - epoch: 115968, + version: hex_literal::hex!("60000910"), // 0x60000910 + epoch: 2048, + }, + fulu: Fork { + version: hex_literal::hex!("70000910"), // 0x70000910 + epoch: 50688, }, }; } diff --git a/test/.papi/descriptors/package.json b/test/.papi/descriptors/package.json index d077482a..09f51162 100644 --- a/test/.papi/descriptors/package.json +++ b/test/.papi/descriptors/package.json @@ -1,5 +1,5 @@ { - "version": "0.1.0-autogenerated.11476932184186799098", + "version": "0.1.0-autogenerated.11512841249494289119", "name": "@polkadot-api/descriptors", "files": [ "dist" diff --git a/test/.papi/metadata/datahaven.scale b/test/.papi/metadata/datahaven.scale index 4cc20d1d63277fe9d75508ffcd9a8e062f54c723..d61037e000293c4cf8d8360d7b65088984d6efdd 100644 GIT binary patch delta 72 zcmX@urgo=It)Ydng{g&k3(GDWMw#imZCJ9|7zNTwb4uG~ZCQYr6^Pk@n0>pfEk~6( YW8m}|B^;iN1?|^LIJRFa;mqa(09l6@8UO$Q delta 63 zcmcc9rgpGRt)Ydng{g&k3(GDWMv3XWZCJ9~O>J3#m=%cGfS7%|sVzsLIiuqA