|
|
|
@ -80,6 +80,81 @@ func (ga *GenesisAlloc) UnmarshalJSON(data []byte) error { |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// flush adds allocated genesis accounts into a fresh new statedb and
|
|
|
|
|
// commit the state changes into the given database handler.
|
|
|
|
|
func (ga *GenesisAlloc) flush(db ethdb.Database) (common.Hash, error) { |
|
|
|
|
statedb, err := state.New(common.Hash{}, state.NewDatabase(db), nil) |
|
|
|
|
if err != nil { |
|
|
|
|
return common.Hash{}, err |
|
|
|
|
} |
|
|
|
|
for addr, account := range *ga { |
|
|
|
|
statedb.AddBalance(addr, account.Balance) |
|
|
|
|
statedb.SetCode(addr, account.Code) |
|
|
|
|
statedb.SetNonce(addr, account.Nonce) |
|
|
|
|
for key, value := range account.Storage { |
|
|
|
|
statedb.SetState(addr, key, value) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
root, err := statedb.Commit(false) |
|
|
|
|
if err != nil { |
|
|
|
|
return common.Hash{}, err |
|
|
|
|
} |
|
|
|
|
err = statedb.Database().TrieDB().Commit(root, true, nil) |
|
|
|
|
if err != nil { |
|
|
|
|
return common.Hash{}, err |
|
|
|
|
} |
|
|
|
|
return root, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// write writes the json marshaled genesis state into database
|
|
|
|
|
// with the given block hash as the unique identifier.
|
|
|
|
|
func (ga *GenesisAlloc) write(db ethdb.KeyValueWriter, hash common.Hash) error { |
|
|
|
|
blob, err := json.Marshal(ga) |
|
|
|
|
if err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
rawdb.WriteGenesisState(db, hash, blob) |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// CommitGenesisState loads the stored genesis state with the given block
|
|
|
|
|
// hash and commits them into the given database handler.
|
|
|
|
|
func CommitGenesisState(db ethdb.Database, hash common.Hash) error { |
|
|
|
|
var alloc GenesisAlloc |
|
|
|
|
blob := rawdb.ReadGenesisState(db, hash) |
|
|
|
|
if len(blob) != 0 { |
|
|
|
|
if err := alloc.UnmarshalJSON(blob); err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
// Genesis allocation is missing and there are several possibilities:
|
|
|
|
|
// the node is legacy which doesn't persist the genesis allocation or
|
|
|
|
|
// the persisted allocation is just lost.
|
|
|
|
|
// - supported networks(mainnet, testnets), recover with defined allocations
|
|
|
|
|
// - private network, can't recover
|
|
|
|
|
var genesis *Genesis |
|
|
|
|
switch hash { |
|
|
|
|
case params.MainnetGenesisHash: |
|
|
|
|
genesis = DefaultGenesisBlock() |
|
|
|
|
case params.RopstenGenesisHash: |
|
|
|
|
genesis = DefaultRopstenGenesisBlock() |
|
|
|
|
case params.RinkebyGenesisHash: |
|
|
|
|
genesis = DefaultRinkebyGenesisBlock() |
|
|
|
|
case params.GoerliGenesisHash: |
|
|
|
|
genesis = DefaultGoerliGenesisBlock() |
|
|
|
|
case params.SepoliaGenesisHash: |
|
|
|
|
genesis = DefaultSepoliaGenesisBlock() |
|
|
|
|
} |
|
|
|
|
if genesis != nil { |
|
|
|
|
alloc = genesis.Alloc |
|
|
|
|
} else { |
|
|
|
|
return errors.New("not found") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
_, err := alloc.flush(db) |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// GenesisAccount is an account in the state of the genesis block.
|
|
|
|
|
type GenesisAccount struct { |
|
|
|
|
Code []byte `json:"code,omitempty"` |
|
|
|
@ -267,19 +342,10 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block { |
|
|
|
|
if db == nil { |
|
|
|
|
db = rawdb.NewMemoryDatabase() |
|
|
|
|
} |
|
|
|
|
statedb, err := state.New(common.Hash{}, state.NewDatabase(db), nil) |
|
|
|
|
root, err := g.Alloc.flush(db) |
|
|
|
|
if err != nil { |
|
|
|
|
panic(err) |
|
|
|
|
} |
|
|
|
|
for addr, account := range g.Alloc { |
|
|
|
|
statedb.AddBalance(addr, account.Balance) |
|
|
|
|
statedb.SetCode(addr, account.Code) |
|
|
|
|
statedb.SetNonce(addr, account.Nonce) |
|
|
|
|
for key, value := range account.Storage { |
|
|
|
|
statedb.SetState(addr, key, value) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
root := statedb.IntermediateRoot(false) |
|
|
|
|
head := &types.Header{ |
|
|
|
|
Number: new(big.Int).SetUint64(g.Number), |
|
|
|
|
Nonce: types.EncodeNonce(g.Nonce), |
|
|
|
@ -307,9 +373,6 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block { |
|
|
|
|
head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
statedb.Commit(false) |
|
|
|
|
statedb.Database().TrieDB().Commit(root, true, nil) |
|
|
|
|
|
|
|
|
|
return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -330,6 +393,9 @@ func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) { |
|
|
|
|
if config.Clique != nil && len(block.Extra()) == 0 { |
|
|
|
|
return nil, errors.New("can't start clique chain without signers") |
|
|
|
|
} |
|
|
|
|
if err := g.Alloc.write(db, block.Hash()); err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
rawdb.WriteTd(db, block.Hash(), block.NumberU64(), block.Difficulty()) |
|
|
|
|
rawdb.WriteBlock(db, block) |
|
|
|
|
rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), nil) |
|
|
|
|