-
Notifications
You must be signed in to change notification settings - Fork 787
/
superchain.go
101 lines (91 loc) · 3.07 KB
/
superchain.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package core
import (
"fmt"
"math/big"
"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"
)
func LoadOPStackGenesis(chainID uint64) (*Genesis, error) {
chConfig, ok := superchain.OPChains[chainID]
if !ok {
return nil, fmt.Errorf("unknown chain ID: %d", chainID)
}
cfg, err := params.LoadOPStackChainConfig(chainID)
if err != nil {
return nil, fmt.Errorf("failed to load params.ChainConfig for chain %d: %w", chainID, err)
}
gen, err := superchain.LoadGenesis(chainID)
if err != nil {
return nil, fmt.Errorf("failed to load genesis definition for chain %d: %w", chainID, err)
}
genesis := &Genesis{
Config: cfg,
Nonce: gen.Nonce,
Timestamp: gen.Timestamp,
ExtraData: gen.ExtraData,
GasLimit: gen.GasLimit,
Difficulty: (*big.Int)(gen.Difficulty),
Mixhash: common.Hash(gen.Mixhash),
Coinbase: common.Address(gen.Coinbase),
Alloc: make(types.GenesisAlloc),
Number: gen.Number,
GasUsed: gen.GasUsed,
ParentHash: common.Hash(gen.ParentHash),
BaseFee: (*big.Int)(gen.BaseFee),
ExcessBlobGas: gen.ExcessBlobGas,
BlobGasUsed: gen.BlobGasUsed,
}
for addr, acc := range gen.Alloc {
var code []byte
if acc.CodeHash != ([32]byte{}) {
dat, err := superchain.LoadContractBytecode(acc.CodeHash)
if err != nil {
return nil, fmt.Errorf("failed to load bytecode %s of address %s in chain %d: %w", acc.CodeHash, addr, chainID, err)
}
code = dat
}
var storage map[common.Hash]common.Hash
if len(acc.Storage) > 0 {
storage = make(map[common.Hash]common.Hash)
for k, v := range acc.Storage {
storage[common.Hash(k)] = common.Hash(v)
}
}
bal := common.Big0
if acc.Balance != nil {
bal = (*big.Int)(acc.Balance)
}
genesis.Alloc[common.Address(addr)] = GenesisAccount{
Code: code,
Storage: storage,
Balance: bal,
Nonce: acc.Nonce,
}
}
if gen.StateHash != nil {
if len(gen.Alloc) > 0 {
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()
genesisBlockHash := genesisBlock.Hash()
expectedHash := common.Hash([32]byte(chConfig.Genesis.L2.Hash))
// Verify we correctly produced the genesis config by recomputing the genesis-block-hash,
// and check the genesis matches the chain genesis definition.
if chConfig.Genesis.L2.Number != genesisBlock.NumberU64() {
switch chainID {
case params.OPMainnetChainID:
expectedHash = common.HexToHash("0x7ca38a1916c42007829c55e69d3e9a73265554b586a499015373241b8a3fa48b")
default:
return nil, fmt.Errorf("unknown stateless genesis definition for chain %d", chainID)
}
}
if expectedHash != genesisBlockHash {
return nil, fmt.Errorf("chainID=%d: produced genesis with hash %s but expected %s", chainID, genesisBlockHash, expectedHash)
}
return genesis, nil
}