Skip to content

Commit 7e9a329

Browse files
authored
core: fix op-mainnet-genesis hash (ethereum-optimism#405)
- fix genesis-spec-from-DB export - fix OP-Mainnet genesis Commit() of canonical block hash
1 parent 82dd9eb commit 7e9a329

File tree

3 files changed

+44
-8
lines changed

3 files changed

+44
-8
lines changed

core/genesis.go

+20-7
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,11 @@ func ReadGenesis(db ethdb.Database) (*Genesis, error) {
116116
genesis.BaseFee = genesisHeader.BaseFee
117117
genesis.ExcessBlobGas = genesisHeader.ExcessBlobGas
118118
genesis.BlobGasUsed = genesisHeader.BlobGasUsed
119-
if genesis.Alloc == nil {
120-
h := genesisHeader.Hash()
119+
// A nil or empty alloc, with a non-matching state-root in the block header, intents to override the state-root.
120+
if genesis.Alloc == nil || (len(genesis.Alloc) == 0 && genesisHeader.Root != types.EmptyRootHash) {
121+
h := genesisHeader.Root // the genesis block is encoded as RLP in the DB and will contain the state-root
121122
genesis.StateHash = &h
123+
genesis.Alloc = nil
122124
}
123125

124126
return &genesis, nil
@@ -567,12 +569,23 @@ func (g *Genesis) Commit(db ethdb.Database, triedb *triedb.Database) (*types.Blo
567569
if config.Clique != nil && len(g.ExtraData) < 32+crypto.SignatureLength {
568570
return nil, errors.New("can't start clique chain without signers")
569571
}
570-
// flush the data to disk and compute the state root
571-
root, err := flushAlloc(&g.Alloc, triedb)
572-
if err != nil {
573-
return nil, err
572+
var stateHash common.Hash
573+
if len(g.Alloc) == 0 {
574+
if g.StateHash == nil {
575+
log.Warn("Empty genesis alloc, and no 'stateHash' override was set")
576+
stateHash = types.EmptyRootHash // default to the hash of the empty state. Some unit-tests rely on this.
577+
} else {
578+
stateHash = *g.StateHash
579+
}
580+
} else {
581+
// flush the data to disk and compute the state root
582+
root, err := flushAlloc(&g.Alloc, triedb)
583+
if err != nil {
584+
return nil, err
585+
}
586+
stateHash = root
574587
}
575-
block := g.toBlockWithRoot(root)
588+
block := g.toBlockWithRoot(stateHash)
576589

577590
// Marshal the genesis state specification and persist.
578591
blob, err := json.Marshal(g.Alloc)

core/superchain.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"github.com/ethereum-optimism/superchain-registry/superchain"
88

99
"github.com/ethereum/go-ethereum/common"
10+
"github.com/ethereum/go-ethereum/core/types"
1011
"github.com/ethereum/go-ethereum/params"
1112
)
1213

@@ -35,7 +36,7 @@ func LoadOPStackGenesis(chainID uint64) (*Genesis, error) {
3536
Difficulty: (*big.Int)(gen.Difficulty),
3637
Mixhash: common.Hash(gen.Mixhash),
3738
Coinbase: common.Address(gen.Coinbase),
38-
Alloc: make(GenesisAlloc),
39+
Alloc: make(types.GenesisAlloc),
3940
Number: gen.Number,
4041
GasUsed: gen.GasUsed,
4142
ParentHash: common.Hash(gen.ParentHash),
@@ -76,6 +77,7 @@ func LoadOPStackGenesis(chainID uint64) (*Genesis, error) {
7677
return nil, fmt.Errorf("chain definition unexpectedly contains both allocation (%d) and state-hash %s", len(gen.Alloc), *gen.StateHash)
7778
}
7879
genesis.StateHash = (*common.Hash)(gen.StateHash)
80+
genesis.Alloc = nil
7981
}
8082

8183
genesisBlock := genesis.ToBlock()

core/superchain_test.go

+21
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"github.com/ethereum-optimism/superchain-registry/superchain"
77

8+
"github.com/ethereum/go-ethereum/common"
89
"github.com/ethereum/go-ethereum/core/rawdb"
910
"github.com/ethereum/go-ethereum/triedb"
1011
)
@@ -102,3 +103,23 @@ func TestRegistryChainConfigOverride(t *testing.T) {
102103
})
103104
}
104105
}
106+
107+
func TestOPMainnetGenesisDB(t *testing.T) {
108+
db := rawdb.NewMemoryDatabase()
109+
genesis, err := LoadOPStackGenesis(10)
110+
if err != nil {
111+
t.Fatal(err)
112+
}
113+
tdb := triedb.NewDatabase(db, newDbConfig(rawdb.PathScheme))
114+
genesis.MustCommit(db, tdb)
115+
bl := genesis.ToBlock()
116+
expected := common.HexToHash("0x7ca38a1916c42007829c55e69d3e9a73265554b586a499015373241b8a3fa48b")
117+
if blockHash := bl.Hash(); blockHash != expected {
118+
t.Fatalf("block hash mismatch: %s <> %s", blockHash, expected)
119+
}
120+
// This is written separately to the DB by Commit() and is thus tested explicitly here
121+
canonicalHash := rawdb.ReadCanonicalHash(db, 0)
122+
if canonicalHash != expected {
123+
t.Fatalf("canonical hash mismatch: %s <> %s", canonicalHash, expected)
124+
}
125+
}

0 commit comments

Comments
 (0)