gitlab.com/flarenetwork/coreth@v0.1.1/core/genesis.go (about) 1 // (c) 2019-2020, Ava Labs, Inc. 2 // 3 // This file is a derived work, based on the go-ethereum library whose original 4 // notices appear below. 5 // 6 // It is distributed under a license compatible with the licensing terms of the 7 // original code from which it is derived. 8 // 9 // Much love to the original authors for their work. 10 // ********** 11 // Copyright 2014 The go-ethereum Authors 12 // This file is part of the go-ethereum library. 13 // 14 // The go-ethereum library is free software: you can redistribute it and/or modify 15 // it under the terms of the GNU Lesser General Public License as published by 16 // the Free Software Foundation, either version 3 of the License, or 17 // (at your option) any later version. 18 // 19 // The go-ethereum library is distributed in the hope that it will be useful, 20 // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 // GNU Lesser General Public License for more details. 23 // 24 // You should have received a copy of the GNU Lesser General Public License 25 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 26 27 package core 28 29 import ( 30 "bytes" 31 "encoding/hex" 32 "encoding/json" 33 "errors" 34 "fmt" 35 "math/big" 36 37 "github.com/ethereum/go-ethereum/common" 38 "github.com/ethereum/go-ethereum/common/hexutil" 39 "github.com/ethereum/go-ethereum/common/math" 40 "github.com/ethereum/go-ethereum/ethdb" 41 "github.com/ethereum/go-ethereum/log" 42 "github.com/ethereum/go-ethereum/trie" 43 "gitlab.com/flarenetwork/coreth/core/rawdb" 44 "gitlab.com/flarenetwork/coreth/core/state" 45 "gitlab.com/flarenetwork/coreth/core/types" 46 "gitlab.com/flarenetwork/coreth/params" 47 ) 48 49 //go:generate gencodec -type Genesis -field-override genesisSpecMarshaling -out gen_genesis.go 50 //go:generate gencodec -type GenesisAccount -field-override genesisAccountMarshaling -out gen_genesis_account.go 51 52 var errGenesisNoConfig = errors.New("genesis has no chain configuration") 53 54 // Genesis specifies the header fields, state of a genesis block. It also defines hard 55 // fork switch-over blocks through the chain configuration. 56 type Genesis struct { 57 Config *params.ChainConfig `json:"config"` 58 Nonce uint64 `json:"nonce"` 59 Timestamp uint64 `json:"timestamp"` 60 ExtraData []byte `json:"extraData"` 61 GasLimit uint64 `json:"gasLimit" gencodec:"required"` 62 Difficulty *big.Int `json:"difficulty" gencodec:"required"` 63 Mixhash common.Hash `json:"mixHash"` 64 Coinbase common.Address `json:"coinbase"` 65 Alloc GenesisAlloc `json:"alloc" gencodec:"required"` 66 67 // These fields are used for consensus tests. Please don't use them 68 // in actual genesis blocks. 69 Number uint64 `json:"number"` 70 GasUsed uint64 `json:"gasUsed"` 71 ParentHash common.Hash `json:"parentHash"` 72 BaseFee *big.Int `json:"baseFeePerGas"` 73 } 74 75 // GenesisAlloc specifies the initial state that is part of the genesis block. 76 type GenesisAlloc map[common.Address]GenesisAccount 77 78 func (ga *GenesisAlloc) UnmarshalJSON(data []byte) error { 79 m := make(map[common.UnprefixedAddress]GenesisAccount) 80 if err := json.Unmarshal(data, &m); err != nil { 81 return err 82 } 83 *ga = make(GenesisAlloc) 84 for addr, a := range m { 85 (*ga)[common.Address(addr)] = a 86 } 87 return nil 88 } 89 90 type GenesisMultiCoinBalance map[common.Hash]*big.Int 91 92 // GenesisAccount is an account in the state of the genesis block. 93 type GenesisAccount struct { 94 Code []byte `json:"code,omitempty"` 95 Storage map[common.Hash]common.Hash `json:"storage,omitempty"` 96 Balance *big.Int `json:"balance" gencodec:"required"` 97 MCBalance GenesisMultiCoinBalance `json:"mcbalance,omitempty"` 98 Nonce uint64 `json:"nonce,omitempty"` 99 PrivateKey []byte `json:"secretKey,omitempty"` // for tests 100 } 101 102 // field type overrides for gencodec 103 type genesisSpecMarshaling struct { 104 Nonce math.HexOrDecimal64 105 Timestamp math.HexOrDecimal64 106 ExtraData hexutil.Bytes 107 GasLimit math.HexOrDecimal64 108 GasUsed math.HexOrDecimal64 109 Number math.HexOrDecimal64 110 Difficulty *math.HexOrDecimal256 111 BaseFee *math.HexOrDecimal256 112 Alloc map[common.UnprefixedAddress]GenesisAccount 113 } 114 115 type genesisAccountMarshaling struct { 116 Code hexutil.Bytes 117 Balance *math.HexOrDecimal256 118 Nonce math.HexOrDecimal64 119 Storage map[storageJSON]storageJSON 120 PrivateKey hexutil.Bytes 121 } 122 123 // storageJSON represents a 256 bit byte array, but allows less than 256 bits when 124 // unmarshaling from hex. 125 type storageJSON common.Hash 126 127 func (h *storageJSON) UnmarshalText(text []byte) error { 128 text = bytes.TrimPrefix(text, []byte("0x")) 129 if len(text) > 64 { 130 return fmt.Errorf("too many hex characters in storage key/value %q", text) 131 } 132 offset := len(h) - len(text)/2 // pad on the left 133 if _, err := hex.Decode(h[offset:], text); err != nil { 134 fmt.Println(err) 135 return fmt.Errorf("invalid hex storage key/value %q", text) 136 } 137 return nil 138 } 139 140 func (h storageJSON) MarshalText() ([]byte, error) { 141 return hexutil.Bytes(h[:]).MarshalText() 142 } 143 144 // GenesisMismatchError is raised when trying to overwrite an existing 145 // genesis block with an incompatible one. 146 type GenesisMismatchError struct { 147 Stored, New common.Hash 148 } 149 150 func (e *GenesisMismatchError) Error() string { 151 return fmt.Sprintf("database contains incompatible genesis (have %x, new %x)", e.Stored, e.New) 152 } 153 154 // SetupGenesisBlock writes or updates the genesis block in db. 155 // The block that will be used is: 156 // 157 // genesis == nil genesis != nil 158 // +------------------------------------------ 159 // db has no genesis | main-net default | genesis 160 // db has genesis | from DB | genesis (if compatible) 161 // 162 // The stored chain configuration will be updated if it is compatible (i.e. does not 163 // specify a fork block below the local head block). In case of a conflict, the 164 // error is a *params.ConfigCompatError and the new, unwritten config is returned. 165 func SetupGenesisBlock(db ethdb.Database, genesis *Genesis) (*params.ChainConfig, error) { 166 if genesis == nil { 167 return nil, ErrNoGenesis 168 } 169 if genesis.Config == nil { 170 return nil, errGenesisNoConfig 171 } 172 // Just commit the new block if there is no stored genesis block. 173 stored := rawdb.ReadCanonicalHash(db, 0) 174 if (stored == common.Hash{}) { 175 log.Info("Writing genesis to database") 176 _, err := genesis.Commit(db) 177 if err != nil { 178 return genesis.Config, err 179 } 180 return genesis.Config, nil 181 } 182 // We have the genesis block in database(perhaps in ancient database) 183 // but the corresponding state is missing. 184 header := rawdb.ReadHeader(db, stored, 0) 185 if _, err := state.New(header.Root, state.NewDatabase(db), nil); err != nil { 186 // Ensure the stored genesis matches with the given one. 187 hash := genesis.ToBlock(nil).Hash() 188 if hash != stored { 189 return genesis.Config, &GenesisMismatchError{stored, hash} 190 } 191 _, err := genesis.Commit(db) 192 return genesis.Config, err 193 } 194 // Check whether the genesis block is already written. 195 hash := genesis.ToBlock(nil).Hash() 196 if hash != stored { 197 return genesis.Config, &GenesisMismatchError{stored, hash} 198 } 199 // Get the existing chain configuration. 200 newcfg := genesis.Config 201 if err := newcfg.CheckConfigForkOrder(); err != nil { 202 return newcfg, err 203 } 204 storedcfg := rawdb.ReadChainConfig(db, stored) 205 if storedcfg == nil { 206 log.Warn("Found genesis block without chain config") 207 rawdb.WriteChainConfig(db, stored, newcfg) 208 return newcfg, nil 209 } 210 211 // Check config compatibility and write the config. Compatibility errors 212 // are returned to the caller unless we're already at block zero. 213 height := rawdb.ReadHeaderNumber(db, rawdb.ReadHeadHeaderHash(db)) 214 if height == nil { 215 return newcfg, fmt.Errorf("missing block number for head header hash") 216 } 217 compatErr := storedcfg.CheckCompatible(newcfg, *height) 218 if compatErr != nil && *height != 0 && compatErr.RewindTo != 0 { 219 return newcfg, compatErr 220 } 221 rawdb.WriteChainConfig(db, stored, newcfg) 222 return newcfg, nil 223 } 224 225 // ToBlock creates the genesis block and writes state of a genesis specification 226 // to the given database (or discards it if nil). 227 func (g *Genesis) ToBlock(db ethdb.Database) *types.Block { 228 if db == nil { 229 db = rawdb.NewMemoryDatabase() 230 } 231 statedb, err := state.New(common.Hash{}, state.NewDatabase(db), nil) 232 if err != nil { 233 panic(err) 234 } 235 for addr, account := range g.Alloc { 236 statedb.AddBalance(addr, account.Balance) 237 statedb.SetCode(addr, account.Code) 238 statedb.SetNonce(addr, account.Nonce) 239 for key, value := range account.Storage { 240 statedb.SetState(addr, key, value) 241 } 242 if account.MCBalance != nil { 243 for coinID, value := range account.MCBalance { 244 statedb.AddBalanceMultiCoin(addr, coinID, value) 245 } 246 } 247 } 248 root := statedb.IntermediateRoot(false) 249 head := &types.Header{ 250 Number: new(big.Int).SetUint64(g.Number), 251 Nonce: types.EncodeNonce(g.Nonce), 252 Time: g.Timestamp, 253 ParentHash: g.ParentHash, 254 Extra: g.ExtraData, 255 GasLimit: g.GasLimit, 256 GasUsed: g.GasUsed, 257 BaseFee: g.BaseFee, 258 Difficulty: g.Difficulty, 259 MixDigest: g.Mixhash, 260 Coinbase: g.Coinbase, 261 Root: root, 262 } 263 if g.GasLimit == 0 { 264 head.GasLimit = params.GenesisGasLimit 265 } 266 if g.Difficulty == nil { 267 head.Difficulty = params.GenesisDifficulty 268 } 269 if g.Config != nil && g.Config.IsApricotPhase3(common.Big0) { 270 if g.BaseFee != nil { 271 head.BaseFee = g.BaseFee 272 } else { 273 head.BaseFee = big.NewInt(params.ApricotPhase3InitialBaseFee) 274 } 275 } 276 statedb.Commit(false) 277 statedb.Database().TrieDB().Commit(root, true, nil) 278 279 return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil), nil, false) 280 } 281 282 // Commit writes the block and state of a genesis specification to the database. 283 // The block is committed as the canonical head block. 284 func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) { 285 block := g.ToBlock(db) 286 if block.Number().Sign() != 0 { 287 return nil, fmt.Errorf("can't commit genesis block with number > 0") 288 } 289 config := g.Config 290 if config == nil { 291 return nil, errGenesisNoConfig 292 } 293 if err := config.CheckConfigForkOrder(); err != nil { 294 return nil, err 295 } 296 rawdb.WriteTd(db, block.Hash(), block.NumberU64(), g.Difficulty) 297 rawdb.WriteBlock(db, block) 298 rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), nil) 299 rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64()) 300 rawdb.WriteHeadBlockHash(db, block.Hash()) 301 rawdb.WriteHeadFastBlockHash(db, block.Hash()) 302 rawdb.WriteHeadHeaderHash(db, block.Hash()) 303 rawdb.WriteChainConfig(db, block.Hash(), config) 304 return block, nil 305 } 306 307 // MustCommit writes the genesis block and state to db, panicking on error. 308 // The block is committed as the canonical head block. 309 func (g *Genesis) MustCommit(db ethdb.Database) *types.Block { 310 block, err := g.Commit(db) 311 if err != nil { 312 panic(err) 313 } 314 return block 315 } 316 317 // GenesisBlockForTesting creates and writes a block in which addr has the given wei balance. 318 func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big.Int) *types.Block { 319 g := Genesis{ 320 Alloc: GenesisAlloc{addr: {Balance: balance}}, 321 BaseFee: big.NewInt(params.ApricotPhase3InitialBaseFee), 322 } 323 return g.MustCommit(db) 324 }