|
|
|
@ -80,10 +80,12 @@ 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) |
|
|
|
|
// deriveHash computes the state root according to the genesis specification.
|
|
|
|
|
func (ga *GenesisAlloc) deriveHash() (common.Hash, error) { |
|
|
|
|
// Create an ephemeral in-memory database for computing hash,
|
|
|
|
|
// all the derived states will be discarded to not pollute disk.
|
|
|
|
|
db := state.NewDatabase(rawdb.NewMemoryDatabase()) |
|
|
|
|
statedb, err := state.New(common.Hash{}, db, nil) |
|
|
|
|
if err != nil { |
|
|
|
|
return common.Hash{}, err |
|
|
|
|
} |
|
|
|
@ -95,25 +97,39 @@ func (ga *GenesisAlloc) flush(db ethdb.Database) (common.Hash, error) { |
|
|
|
|
statedb.SetState(addr, key, value) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return statedb.Commit(false) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// flush is very similar with deriveHash, but the main difference is
|
|
|
|
|
// all the generated states will be persisted into the given database.
|
|
|
|
|
// Also, the genesis state specification will be flushed as well.
|
|
|
|
|
func (ga *GenesisAlloc) flush(db ethdb.Database) error { |
|
|
|
|
statedb, err := state.New(common.Hash{}, state.NewDatabase(db), nil) |
|
|
|
|
if err != nil { |
|
|
|
|
return 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 |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
err = statedb.Database().TrieDB().Commit(root, true, nil) |
|
|
|
|
if err != nil { |
|
|
|
|
return common.Hash{}, err |
|
|
|
|
return 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 { |
|
|
|
|
// Marshal the genesis state specification and persist.
|
|
|
|
|
blob, err := json.Marshal(ga) |
|
|
|
|
if err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
rawdb.WriteGenesisState(db, hash, blob) |
|
|
|
|
rawdb.WriteGenesisStateSpec(db, root, blob) |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -121,7 +137,7 @@ func (ga *GenesisAlloc) write(db ethdb.KeyValueWriter, hash common.Hash) error { |
|
|
|
|
// 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) |
|
|
|
|
blob := rawdb.ReadGenesisStateSpec(db, hash) |
|
|
|
|
if len(blob) != 0 { |
|
|
|
|
if err := alloc.UnmarshalJSON(blob); err != nil { |
|
|
|
|
return err |
|
|
|
@ -151,8 +167,7 @@ func CommitGenesisState(db ethdb.Database, hash common.Hash) error { |
|
|
|
|
return errors.New("not found") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
_, err := alloc.flush(db) |
|
|
|
|
return err |
|
|
|
|
return alloc.flush(db) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// GenesisAccount is an account in the state of the genesis block.
|
|
|
|
@ -273,7 +288,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, override |
|
|
|
|
genesis = DefaultGenesisBlock() |
|
|
|
|
} |
|
|
|
|
// Ensure the stored genesis matches with the given one.
|
|
|
|
|
hash := genesis.ToBlock(nil).Hash() |
|
|
|
|
hash := genesis.ToBlock().Hash() |
|
|
|
|
if hash != stored { |
|
|
|
|
return genesis.Config, hash, &GenesisMismatchError{stored, hash} |
|
|
|
|
} |
|
|
|
@ -286,7 +301,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, override |
|
|
|
|
} |
|
|
|
|
// Check whether the genesis block is already written.
|
|
|
|
|
if genesis != nil { |
|
|
|
|
hash := genesis.ToBlock(nil).Hash() |
|
|
|
|
hash := genesis.ToBlock().Hash() |
|
|
|
|
if hash != stored { |
|
|
|
|
return genesis.Config, hash, &GenesisMismatchError{stored, hash} |
|
|
|
|
} |
|
|
|
@ -347,13 +362,9 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ToBlock creates the genesis block and writes state of a genesis specification
|
|
|
|
|
// to the given database (or discards it if nil).
|
|
|
|
|
func (g *Genesis) ToBlock(db ethdb.Database) *types.Block { |
|
|
|
|
if db == nil { |
|
|
|
|
db = rawdb.NewMemoryDatabase() |
|
|
|
|
} |
|
|
|
|
root, err := g.Alloc.flush(db) |
|
|
|
|
// ToBlock returns the genesis block according to genesis specification.
|
|
|
|
|
func (g *Genesis) ToBlock() *types.Block { |
|
|
|
|
root, err := g.Alloc.deriveHash() |
|
|
|
|
if err != nil { |
|
|
|
|
panic(err) |
|
|
|
|
} |
|
|
|
@ -390,7 +401,7 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block { |
|
|
|
|
// Commit writes the block and state of a genesis specification to the database.
|
|
|
|
|
// The block is committed as the canonical head block.
|
|
|
|
|
func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) { |
|
|
|
|
block := g.ToBlock(db) |
|
|
|
|
block := g.ToBlock() |
|
|
|
|
if block.Number().Sign() != 0 { |
|
|
|
|
return nil, errors.New("can't commit genesis block with number > 0") |
|
|
|
|
} |
|
|
|
@ -404,7 +415,10 @@ func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) { |
|
|
|
|
if config.Clique != nil && len(block.Extra()) < 32+crypto.SignatureLength { |
|
|
|
|
return nil, errors.New("can't start clique chain without signers") |
|
|
|
|
} |
|
|
|
|
if err := g.Alloc.write(db, block.Hash()); err != nil { |
|
|
|
|
// All the checks has passed, flush the states derived from the genesis
|
|
|
|
|
// specification as well as the specification itself into the provided
|
|
|
|
|
// database.
|
|
|
|
|
if err := g.Alloc.flush(db); err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
rawdb.WriteTd(db, block.Hash(), block.NumberU64(), block.Difficulty()) |
|
|
|
@ -428,15 +442,6 @@ func (g *Genesis) MustCommit(db ethdb.Database) *types.Block { |
|
|
|
|
return block |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// GenesisBlockForTesting creates and writes a block in which addr has the given wei balance.
|
|
|
|
|
func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big.Int) *types.Block { |
|
|
|
|
g := Genesis{ |
|
|
|
|
Alloc: GenesisAlloc{addr: {Balance: balance}}, |
|
|
|
|
BaseFee: big.NewInt(params.InitialBaseFee), |
|
|
|
|
} |
|
|
|
|
return g.MustCommit(db) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// DefaultGenesisBlock returns the Ethereum main net genesis block.
|
|
|
|
|
func DefaultGenesisBlock() *Genesis { |
|
|
|
|
return &Genesis{ |
|
|
|
@ -498,6 +503,7 @@ func DefaultSepoliaGenesisBlock() *Genesis { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// DefaultKilnGenesisBlock returns the kiln network genesis block.
|
|
|
|
|
func DefaultKilnGenesisBlock() *Genesis { |
|
|
|
|
g := new(Genesis) |
|
|
|
|
reader := strings.NewReader(KilnAllocData) |
|
|
|
|