1
0
Fork 0
forked from forks/go-ethereum

params: add hoodi testnet definition (#31406)

Adds support for the new hoodi testnet. Hoodi is meant for stakers to test
their setup. For more info please refer to https://hoodi.ethpandaops.io/.
This commit is contained in:
Marius van der Wijden 2025-03-18 12:07:49 +01:00 committed by GitHub
parent 40ad6bedf6
commit 668118bfe1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 140 additions and 2 deletions

View file

@ -55,4 +55,17 @@ var (
AddFork("CAPELLA", 256, []byte{4, 1, 112, 0}).
AddFork("DENEB", 29696, []byte{5, 1, 112, 0}).
AddFork("ELECTRA", 115968, []byte{6, 1, 112, 0})
HoodiLightConfig = (&ChainConfig{
GenesisValidatorsRoot: common.HexToHash("0x212f13fc4df078b6cb7db228f1c8307566dcecf900867401a92023d7ba99cb5f"),
GenesisTime: 1742212800,
Checkpoint: common.HexToHash(""),
}).
AddFork("GENESIS", 0, common.FromHex("0x10000910")).
AddFork("ALTAIR", 0, common.FromHex("0x20000910")).
AddFork("BELLATRIX", 0, common.FromHex("0x30000910")).
AddFork("CAPELLA", 0, common.FromHex("0x40000910")).
AddFork("DENEB", 0, common.FromHex("0x50000910")).
AddFork("ELECTRA", 2048, common.FromHex("0x60000910")).
AddFork("FULU", 18446744073709551615, common.FromHex("0x70000910"))
)

View file

@ -47,6 +47,7 @@ func main() {
utils.MainnetFlag,
utils.SepoliaFlag,
utils.HoleskyFlag,
utils.HoodiFlag,
utils.BlsyncApiFlag,
utils.BlsyncJWTSecretFlag,
},

View file

@ -234,6 +234,8 @@ func ethFilter(args []string) (nodeFilter, error) {
filter = forkid.NewStaticFilter(params.SepoliaChainConfig, core.DefaultSepoliaGenesisBlock().ToBlock())
case "holesky":
filter = forkid.NewStaticFilter(params.HoleskyChainConfig, core.DefaultHoleskyGenesisBlock().ToBlock())
case "hoodi":
filter = forkid.NewStaticFilter(params.HoodiChainConfig, core.DefaultHoodiGenesisBlock().ToBlock())
default:
return nil, fmt.Errorf("unknown network %q", args[0])
}

View file

@ -296,6 +296,9 @@ func prepare(ctx *cli.Context) {
case ctx.IsSet(utils.HoleskyFlag.Name):
log.Info("Starting Geth on Holesky testnet...")
case ctx.IsSet(utils.HoodiFlag.Name):
log.Info("Starting Geth on Hoodi testnet...")
case ctx.IsSet(utils.DeveloperFlag.Name):
log.Info("Starting Geth in ephemeral dev mode...")
log.Warn(`You are running Geth in --dev mode. Please note the following:
@ -322,6 +325,7 @@ func prepare(ctx *cli.Context) {
// Make sure we're not on any supported preconfigured testnet either
if !ctx.IsSet(utils.HoleskyFlag.Name) &&
!ctx.IsSet(utils.SepoliaFlag.Name) &&
!ctx.IsSet(utils.HoodiFlag.Name) &&
!ctx.IsSet(utils.DeveloperFlag.Name) {
// Nope, we're really on mainnet. Bump that cache up!
log.Info("Bumping default cache on mainnet", "provided", ctx.Int(utils.CacheFlag.Name), "updated", 4096)

View file

@ -134,7 +134,7 @@ var (
}
NetworkIdFlag = &cli.Uint64Flag{
Name: "networkid",
Usage: "Explicitly set network id (integer)(For testnets: use --sepolia, --holesky instead)",
Usage: "Explicitly set network id (integer)(For testnets: use --sepolia, --holesky, --hoodi instead)",
Value: ethconfig.Defaults.NetworkId,
Category: flags.EthCategory,
}
@ -153,6 +153,11 @@ var (
Usage: "Holesky network: pre-configured proof-of-stake test network",
Category: flags.EthCategory,
}
HoodiFlag = &cli.BoolFlag{
Name: "hoodi",
Usage: "Hoodi network: pre-configured proof-of-stake test network",
Category: flags.EthCategory,
}
// Dev mode
DeveloperFlag = &cli.BoolFlag{
Name: "dev",
@ -958,6 +963,7 @@ var (
TestnetFlags = []cli.Flag{
SepoliaFlag,
HoleskyFlag,
HoodiFlag,
}
// NetworkFlags is the flag group of all built-in supported networks.
NetworkFlags = append([]cli.Flag{MainnetFlag}, TestnetFlags...)
@ -984,6 +990,9 @@ func MakeDataDir(ctx *cli.Context) string {
if ctx.Bool(HoleskyFlag.Name) {
return filepath.Join(path, "holesky")
}
if ctx.Bool(HoodiFlag.Name) {
return filepath.Join(path, "hoodi")
}
return path
}
Fatalf("Cannot determine default data directory, please set manually (--datadir)")
@ -1044,6 +1053,8 @@ func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
urls = params.HoleskyBootnodes
case ctx.Bool(SepoliaFlag.Name):
urls = params.SepoliaBootnodes
case ctx.Bool(HoodiFlag.Name):
urls = params.HoodiBootnodes
}
}
cfg.BootstrapNodes = mustParseBootnodes(urls)
@ -1428,6 +1439,8 @@ func SetDataDir(ctx *cli.Context, cfg *node.Config) {
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "sepolia")
case ctx.Bool(HoleskyFlag.Name) && cfg.DataDir == node.DefaultDataDir():
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "holesky")
case ctx.Bool(HoodiFlag.Name) && cfg.DataDir == node.DefaultDataDir():
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "hoodi")
}
}
@ -1554,7 +1567,7 @@ func setRequiredBlocks(ctx *cli.Context, cfg *ethconfig.Config) {
// SetEthConfig applies eth-related command line flags to the config.
func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
// Avoid conflicting network flags
flags.CheckExclusive(ctx, MainnetFlag, DeveloperFlag, SepoliaFlag, HoleskyFlag)
flags.CheckExclusive(ctx, MainnetFlag, DeveloperFlag, SepoliaFlag, HoleskyFlag, HoodiFlag)
flags.CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer
// Set configurations from CLI flags
@ -1738,6 +1751,12 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
}
cfg.Genesis = core.DefaultSepoliaGenesisBlock()
SetDNSDiscoveryDefaults(cfg, params.SepoliaGenesisHash)
case ctx.Bool(HoodiFlag.Name):
if !ctx.IsSet(NetworkIdFlag.Name) {
cfg.NetworkId = 560048
}
cfg.Genesis = core.DefaultHoodiGenesisBlock()
SetDNSDiscoveryDefaults(cfg, params.HoodiGenesisHash)
case ctx.Bool(DeveloperFlag.Name):
if !ctx.IsSet(NetworkIdFlag.Name) {
cfg.NetworkId = 1337
@ -1852,6 +1871,8 @@ func MakeBeaconLightConfig(ctx *cli.Context) bparams.ClientConfig {
config.ChainConfig = *bparams.SepoliaLightConfig
case ctx.Bool(HoleskyFlag.Name):
config.ChainConfig = *bparams.HoleskyLightConfig
case ctx.Bool(HoodiFlag.Name):
config.ChainConfig = *bparams.HoodiLightConfig
default:
if !customConfig {
config.ChainConfig = *bparams.MainnetLightConfig
@ -2118,6 +2139,8 @@ func MakeGenesis(ctx *cli.Context) *core.Genesis {
genesis = core.DefaultHoleskyGenesisBlock()
case ctx.Bool(SepoliaFlag.Name):
genesis = core.DefaultSepoliaGenesisBlock()
case ctx.Bool(HoodiFlag.Name):
genesis = core.DefaultHoodiGenesisBlock()
case ctx.Bool(DeveloperFlag.Name):
Fatalf("Developer chains are ephemeral")
}

View file

@ -46,6 +46,9 @@ var checkpointsSepoliaJSON []byte
//go:embed checkpoints_holesky.json
var checkpointsHoleskyJSON []byte
//go:embed checkpoints_hoodi.json
var checkpointsHoodiJSON []byte
// checkpoints lists sets of checkpoints for multiple chains. The matching
// checkpoint set is autodetected by the indexer once the canonical chain is
// known.
@ -53,6 +56,7 @@ var checkpoints = []checkpointList{
decodeCheckpoints(checkpointsMainnetJSON),
decodeCheckpoints(checkpointsSepoliaJSON),
decodeCheckpoints(checkpointsHoleskyJSON),
decodeCheckpoints(checkpointsHoodiJSON),
}
func decodeCheckpoints(encoded []byte) (result checkpointList) {

View file

@ -0,0 +1 @@
[]

View file

@ -112,6 +112,17 @@ func TestCreation(t *testing.T) {
{123, 2740434112, ID{Hash: checksumToBytes(0xdfbd9bed), Next: 0}}, // Future Prague block
},
},
// Hoodi test cases
{
params.HoodiChainConfig,
core.DefaultHoodiGenesisBlock().ToBlock(),
[]testcase{
{0, 0, ID{Hash: checksumToBytes(0xbef71d30), Next: 1742999832}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople, Petersburg, Istanbul, Berlin, London, Paris, Shanghai, Cancun block
{123, 1742999831, ID{Hash: checksumToBytes(0xbef71d30), Next: 1742999832}}, // Last Cancun block
{123, 1742999832, ID{Hash: checksumToBytes(0x0929e24e), Next: 0}}, // First Prague block
{123, 2740434112, ID{Hash: checksumToBytes(0x0929e24e), Next: 0}}, // Future Prague block
},
},
}
for i, tt := range tests {
for j, ttt := range tt.cases {

View file

@ -221,6 +221,8 @@ func getGenesisState(db ethdb.Database, blockhash common.Hash) (alloc types.Gene
genesis = DefaultSepoliaGenesisBlock()
case params.HoleskyGenesisHash:
genesis = DefaultHoleskyGenesisBlock()
case params.HoodiGenesisHash:
genesis = DefaultHoodiGenesisBlock()
}
if genesis != nil {
return genesis.Alloc, nil
@ -431,6 +433,8 @@ func (g *Genesis) chainConfigOrDefault(ghash common.Hash, stored *params.ChainCo
return params.HoleskyChainConfig
case ghash == params.SepoliaGenesisHash:
return params.SepoliaChainConfig
case ghash == params.HoodiGenesisHash:
return params.HoodiChainConfig
default:
return stored
}
@ -625,6 +629,18 @@ func DefaultHoleskyGenesisBlock() *Genesis {
}
}
// DefaultHoodiGenesisBlock returns the Hoodi network genesis block.
func DefaultHoodiGenesisBlock() *Genesis {
return &Genesis{
Config: params.HoodiChainConfig,
Nonce: 0x1234,
GasLimit: 0x2255100,
Difficulty: big.NewInt(0x01),
Timestamp: 1742212800,
Alloc: decodePrealloc(hoodiAllocData),
}
}
// DeveloperGenesisBlock returns the 'geth --dev' genesis block.
func DeveloperGenesisBlock(gasLimit uint64, faucet *common.Address) *Genesis {
// Override the default period to the user requested one

File diff suppressed because one or more lines are too long

View file

@ -104,6 +104,15 @@ func testSetupGenesis(t *testing.T, scheme string) {
},
wantErr: &GenesisMismatchError{Stored: customghash, New: params.SepoliaGenesisHash},
},
{
name: "custom block in DB, genesis == hoodi",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
tdb := triedb.NewDatabase(db, newDbConfig(scheme))
customg.Commit(db, tdb)
return SetupGenesisBlock(db, tdb, DefaultHoodiGenesisBlock())
},
wantErr: &GenesisMismatchError{Stored: customghash, New: params.HoodiGenesisHash},
},
{
name: "compatible config in DB",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
@ -178,6 +187,8 @@ func TestGenesisHashes(t *testing.T) {
}{
{DefaultGenesisBlock(), params.MainnetGenesisHash},
{DefaultSepoliaGenesisBlock(), params.SepoliaGenesisHash},
{DefaultHoleskyGenesisBlock(), params.HoleskyGenesisHash},
{DefaultHoodiGenesisBlock(), params.HoodiGenesisHash},
} {
// Test via MustCommit
db := rawdb.NewMemoryDatabase()

View file

@ -119,6 +119,7 @@ func TestDeleteBloomBits(t *testing.T) {
for s := uint64(0); s < 2; s++ {
WriteBloomBits(db, i, s, params.MainnetGenesisHash, []byte{0x01, 0x02})
WriteBloomBits(db, i, s, params.SepoliaGenesisHash, []byte{0x01, 0x02})
WriteBloomBits(db, i, s, params.HoodiGenesisHash, []byte{0x01, 0x02})
}
}
check := func(bit uint, section uint64, head common.Hash, exist bool) {
@ -133,24 +134,31 @@ func TestDeleteBloomBits(t *testing.T) {
// Check the existence of written data.
check(0, 0, params.MainnetGenesisHash, true)
check(0, 0, params.SepoliaGenesisHash, true)
check(0, 0, params.HoodiGenesisHash, true)
// Check the existence of deleted data.
DeleteBloombits(db, 0, 0, 1)
check(0, 0, params.MainnetGenesisHash, false)
check(0, 0, params.SepoliaGenesisHash, false)
check(0, 0, params.HoodiGenesisHash, false)
check(0, 1, params.MainnetGenesisHash, true)
check(0, 1, params.SepoliaGenesisHash, true)
check(0, 1, params.HoodiGenesisHash, true)
// Check the existence of deleted data.
DeleteBloombits(db, 0, 0, 2)
check(0, 0, params.MainnetGenesisHash, false)
check(0, 0, params.SepoliaGenesisHash, false)
check(0, 0, params.HoodiGenesisHash, false)
check(0, 1, params.MainnetGenesisHash, false)
check(0, 1, params.SepoliaGenesisHash, false)
check(0, 1, params.HoodiGenesisHash, false)
// Bit1 shouldn't be affect.
check(1, 0, params.MainnetGenesisHash, true)
check(1, 0, params.SepoliaGenesisHash, true)
check(1, 0, params.HoodiGenesisHash, true)
check(1, 1, params.MainnetGenesisHash, true)
check(1, 1, params.SepoliaGenesisHash, true)
check(1, 1, params.HoodiGenesisHash, true)
}

View file

@ -28,6 +28,15 @@ var MainnetBootnodes = []string{
"enode://4aeb4ab6c14b23e2c4cfdce879c04b0748a20d8e9b59e25ded2a08143e265c6c25936e74cbc8e641e3312ca288673d91f2f93f8e277de3cfa444ecdaaf982052@157.90.35.166:30303", // bootnode-hetzner-fsn
}
// HoodiBootnodes are the enode URLs of the P2P bootstrap nodes running on the
// Hoodi test network.
var HoodiBootnodes = []string{
// EF DevOps
"enode://2112dd3839dd752813d4df7f40936f06829fc54c0e051a93967c26e5f5d27d99d886b57b4ffcc3c475e930ec9e79c56ef1dbb7d86ca5ee83a9d2ccf36e5c240c@134.209.138.84:30303",
"enode://60203fcb3524e07c5df60a14ae1c9c5b24023ea5d47463dfae051d2c9f3219f309657537576090ca0ae641f73d419f53d8e8000d7a464319d4784acd7d2abc41@209.38.124.160:30303",
"enode://8ae4a48101b2299597341263da0deb47cc38aa4d3ef4b7430b897d49bfa10eb1ccfe1655679b1ed46928ef177fbf21b86837bd724400196c508427a6f41602cd@134.199.184.23:30303",
}
// HoleskyBootnodes are the enode URLs of the P2P bootstrap nodes running on the
// Holesky test network.
var HoleskyBootnodes = []string{
@ -84,6 +93,8 @@ func KnownDNSNetwork(genesis common.Hash, protocol string) string {
net = "sepolia"
case HoleskyGenesisHash:
net = "holesky"
case HoodiGenesisHash:
net = "hoodi"
default:
return ""
}

View file

@ -31,6 +31,7 @@ var (
MainnetGenesisHash = common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
HoleskyGenesisHash = common.HexToHash("0xb5f7f912443c940f21fd611f12828d75b534364ed9e95ca4e307729a4661bde4")
SepoliaGenesisHash = common.HexToHash("0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9")
HoodiGenesisHash = common.HexToHash("0xbbe312868b376a3001692a646dd2d7d1e4406380dfd86b98aa8a34d1557c971b")
)
func newUint64(val uint64) *uint64 { return &val }
@ -125,6 +126,36 @@ var (
Prague: DefaultPragueBlobConfig,
},
}
// HoodiChainConfig contains the chain parameters to run a node on the Hoodi test network.
HoodiChainConfig = &ChainConfig{
ChainID: big.NewInt(560048),
HomesteadBlock: big.NewInt(0),
DAOForkBlock: nil,
DAOForkSupport: true,
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
ArrowGlacierBlock: nil,
GrayGlacierBlock: nil,
TerminalTotalDifficulty: big.NewInt(0),
MergeNetsplitBlock: big.NewInt(0),
ShanghaiTime: newUint64(0),
CancunTime: newUint64(0),
PragueTime: newUint64(1742999832),
DepositContractAddress: common.HexToAddress("0x00000000219ab540356cBB839Cbe05303d7705Fa"),
Ethash: new(EthashConfig),
BlobScheduleConfig: &BlobScheduleConfig{
Cancun: DefaultCancunBlobConfig,
Prague: DefaultPragueBlobConfig,
},
}
// AllEthashProtocolChanges contains every protocol change (EIPs) introduced
// and accepted by the Ethereum core developers into the Ethash consensus.
AllEthashProtocolChanges = &ChainConfig{
@ -338,6 +369,7 @@ var NetworkNames = map[string]string{
MainnetChainConfig.ChainID.String(): "mainnet",
SepoliaChainConfig.ChainID.String(): "sepolia",
HoleskyChainConfig.ChainID.String(): "holesky",
HoodiChainConfig.ChainID.String(): "hoodi",
}
// ChainConfig is the core config which determines the blockchain settings.