@ -145,13 +145,12 @@ func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) {
return statedb . Commit ( 0 , false )
}
// flushAlloc is very similar with hash, 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 flushAlloc ( ga * types . GenesisAlloc , db ethdb . Database , triedb * triedb . Database , blockhash common . Hash ) error {
// flushAlloc is very similar with hash, but the main difference is all the
// generated states will be persisted into the given database.
func flushAlloc ( ga * types . GenesisAlloc , db ethdb . Database , triedb * triedb . Database ) ( common . Hash , error ) {
statedb , err := state . New ( types . EmptyRootHash , state . NewDatabaseWithNodeDB ( db , triedb ) , nil )
if err != nil {
return err
return common . Hash { } , err
}
for addr , account := range * ga {
if account . Balance != nil {
@ -167,21 +166,15 @@ func flushAlloc(ga *types.GenesisAlloc, db ethdb.Database, triedb *triedb.Databa
}
root , err := statedb . Commit ( 0 , false )
if err != nil {
return err
return common . Hash { } , err
}
// Commit newly generated states into disk if it's not empty.
if root != types . EmptyRootHash {
if err := triedb . Commit ( root , true ) ; err != nil {
return err
return common . Hash { } , err
}
}
// Marshal the genesis state specification and persist.
blob , err := json . Marshal ( ga )
if err != nil {
return err
}
rawdb . WriteGenesisStateSpec ( db , blockhash , blob )
return nil
return root , nil
}
func getGenesisState ( db ethdb . Database , blockhash common . Hash ) ( alloc types . GenesisAlloc , err error ) {
@ -426,6 +419,11 @@ func (g *Genesis) ToBlock() *types.Block {
if err != nil {
panic ( err )
}
return g . toBlockWithRoot ( root )
}
// toBlockWithRoot constructs the genesis block with the given genesis state root.
func ( g * Genesis ) toBlockWithRoot ( root common . Hash ) * types . Block {
head := & types . Header {
Number : new ( big . Int ) . SetUint64 ( g . Number ) ,
Nonce : types . EncodeNonce ( g . Nonce ) ,
@ -482,8 +480,7 @@ func (g *Genesis) ToBlock() *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 , triedb * triedb . Database ) ( * types . Block , error ) {
block := g . ToBlock ( )
if block . Number ( ) . Sign ( ) != 0 {
if g . Number != 0 {
return nil , errors . New ( "can't commit genesis block with number > 0" )
}
config := g . Config
@ -493,15 +490,22 @@ func (g *Genesis) Commit(db ethdb.Database, triedb *triedb.Database) (*types.Blo
if err := config . CheckConfigForkOrder ( ) ; err != nil {
return nil , err
}
if config . Clique != nil && len ( block . Extra ( ) ) < 32 + crypto . SignatureLength {
if config . Clique != nil && len ( g . ExtraData ) < 32 + crypto . SignatureLength {
return nil , errors . New ( "can't start clique chain without signers" )
}
// All the checks has passed, flushAlloc the states derived from the genesis
// specification as well as the specification itself into the provided
// database.
if err := flushAlloc ( & g . Alloc , db , triedb , block . Hash ( ) ) ; err != nil {
// flush the data to disk and compute the state root
root , err := flushAlloc ( & g . Alloc , db , triedb )
if err != nil {
return nil , err
}
block := g . toBlockWithRoot ( root )
// Marshal the genesis state specification and persist.
blob , err := json . Marshal ( g . Alloc )
if err != nil {
return nil , err
}
rawdb . WriteGenesisStateSpec ( db , block . Hash ( ) , blob )
rawdb . WriteTd ( db , block . Hash ( ) , block . NumberU64 ( ) , block . Difficulty ( ) )
rawdb . WriteBlock ( db , block )
rawdb . WriteReceipts ( db , block . Hash ( ) , block . NumberU64 ( ) , nil )