fix: 🔨 Update Snowbridge Ethereum network configuration with correct genesis hashes and fork versions (#310)

## 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 <noreply@anthropic.com>
Co-authored-by: undercover-cactus <lola@moonsonglabs.com>
This commit is contained in:
Steve Degosserie 2025-12-02 12:49:18 +01:00 committed by GitHub
parent 4d5716fdcb
commit 063773eb05
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 76 additions and 47 deletions

View file

@ -145,6 +145,10 @@ mod benchmarks {
version: hex!("05000000"),
epoch: 80000000000,
},
fulu: Fork {
version: hex!("06000000"),
epoch: 90000000000,
},
};
let finalized_root_gindex = EthereumBeaconClient::<T>::finalized_root_gindex_at_slot(
update.attested_header.slot,

View file

@ -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;
}

View file

@ -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)]

View file

@ -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
},
};
}

View file

@ -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.
/// <https://ethereum.org/en/developers/docs/apis/json-rpc/#net_version>
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<UniversalLocation, AccountId>
pub EthereumSovereignAccount: AccountId = AccountId::from(
hex_literal::hex!("d8030fb68aa5b447caec066f3c0bde23e6db0a05")
hex_literal::hex!("5300797dbea5b54078a4b3bf8230015ac47a55fa")
);
}

View file

@ -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,
},
};
}

View file

@ -1,5 +1,5 @@
{
"version": "0.1.0-autogenerated.11476932184186799098",
"version": "0.1.0-autogenerated.11512841249494289119",
"name": "@polkadot-api/descriptors",
"files": [
"dist"

Binary file not shown.