Skip to content

Commit

Permalink
core: fix op-mainnet-genesis hash (#405)
Browse files Browse the repository at this point in the history
- fix genesis-spec-from-DB export
- fix OP-Mainnet genesis Commit() of canonical block hash
  • Loading branch information
protolambda authored Oct 21, 2024
1 parent 82dd9eb commit 7e9a329
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 8 deletions.
27 changes: 20 additions & 7 deletions core/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,11 @@ func ReadGenesis(db ethdb.Database) (*Genesis, error) {
genesis.BaseFee = genesisHeader.BaseFee
genesis.ExcessBlobGas = genesisHeader.ExcessBlobGas
genesis.BlobGasUsed = genesisHeader.BlobGasUsed
if genesis.Alloc == nil {
h := genesisHeader.Hash()
// A nil or empty alloc, with a non-matching state-root in the block header, intents to override the state-root.
if genesis.Alloc == nil || (len(genesis.Alloc) == 0 && genesisHeader.Root != types.EmptyRootHash) {
h := genesisHeader.Root // the genesis block is encoded as RLP in the DB and will contain the state-root
genesis.StateHash = &h
genesis.Alloc = nil
}

return &genesis, nil
Expand Down Expand Up @@ -567,12 +569,23 @@ func (g *Genesis) Commit(db ethdb.Database, triedb *triedb.Database) (*types.Blo
if config.Clique != nil && len(g.ExtraData) < 32+crypto.SignatureLength {
return nil, errors.New("can't start clique chain without signers")
}
// flush the data to disk and compute the state root
root, err := flushAlloc(&g.Alloc, triedb)
if err != nil {
return nil, err
var stateHash common.Hash
if len(g.Alloc) == 0 {
if g.StateHash == nil {
log.Warn("Empty genesis alloc, and no 'stateHash' override was set")
stateHash = types.EmptyRootHash // default to the hash of the empty state. Some unit-tests rely on this.
} else {
stateHash = *g.StateHash
}
} else {
// flush the data to disk and compute the state root
root, err := flushAlloc(&g.Alloc, triedb)
if err != nil {
return nil, err
}
stateHash = root
}
block := g.toBlockWithRoot(root)
block := g.toBlockWithRoot(stateHash)

// Marshal the genesis state specification and persist.
blob, err := json.Marshal(g.Alloc)
Expand Down
4 changes: 3 additions & 1 deletion core/superchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/ethereum-optimism/superchain-registry/superchain"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
)

Expand Down Expand Up @@ -35,7 +36,7 @@ func LoadOPStackGenesis(chainID uint64) (*Genesis, error) {
Difficulty: (*big.Int)(gen.Difficulty),
Mixhash: common.Hash(gen.Mixhash),
Coinbase: common.Address(gen.Coinbase),
Alloc: make(GenesisAlloc),
Alloc: make(types.GenesisAlloc),
Number: gen.Number,
GasUsed: gen.GasUsed,
ParentHash: common.Hash(gen.ParentHash),
Expand Down Expand Up @@ -76,6 +77,7 @@ func LoadOPStackGenesis(chainID uint64) (*Genesis, error) {
return nil, fmt.Errorf("chain definition unexpectedly contains both allocation (%d) and state-hash %s", len(gen.Alloc), *gen.StateHash)
}
genesis.StateHash = (*common.Hash)(gen.StateHash)
genesis.Alloc = nil
}

genesisBlock := genesis.ToBlock()
Expand Down
21 changes: 21 additions & 0 deletions core/superchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

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

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/triedb"
)
Expand Down Expand Up @@ -102,3 +103,23 @@ func TestRegistryChainConfigOverride(t *testing.T) {
})
}
}

func TestOPMainnetGenesisDB(t *testing.T) {
db := rawdb.NewMemoryDatabase()
genesis, err := LoadOPStackGenesis(10)
if err != nil {
t.Fatal(err)
}
tdb := triedb.NewDatabase(db, newDbConfig(rawdb.PathScheme))
genesis.MustCommit(db, tdb)
bl := genesis.ToBlock()
expected := common.HexToHash("0x7ca38a1916c42007829c55e69d3e9a73265554b586a499015373241b8a3fa48b")
if blockHash := bl.Hash(); blockHash != expected {
t.Fatalf("block hash mismatch: %s <> %s", blockHash, expected)
}
// This is written separately to the DB by Commit() and is thus tested explicitly here
canonicalHash := rawdb.ReadCanonicalHash(db, 0)
if canonicalHash != expected {
t.Fatalf("canonical hash mismatch: %s <> %s", canonicalHash, expected)
}
}

0 comments on commit 7e9a329

Please sign in to comment.