@@ -83,6 +83,81 @@ func (ga *GenesisAlloc) UnmarshalJSON(data []byte) error {
8383 return nil
8484}
8585
86+ // flush adds allocated genesis accounts into a fresh new statedb and
87+ // commit the state changes into the given database handler.
88+ func (ga * GenesisAlloc ) flush (db ethdb.Database ) (common.Hash , error ) {
89+ statedb , err := state .New (common.Hash {}, state .NewDatabase (db ), nil )
90+ if err != nil {
91+ return common.Hash {}, err
92+ }
93+ for addr , account := range * ga {
94+ statedb .AddBalance (addr , account .Balance )
95+ statedb .SetCode (addr , account .Code )
96+ statedb .SetNonce (addr , account .Nonce )
97+ for key , value := range account .Storage {
98+ statedb .SetState (addr , key , value )
99+ }
100+ }
101+ root , err := statedb .Commit (false )
102+ if err != nil {
103+ return common.Hash {}, err
104+ }
105+ err = statedb .Database ().TrieDB ().Commit (root , true , nil )
106+ if err != nil {
107+ return common.Hash {}, err
108+ }
109+ return root , nil
110+ }
111+
112+ // write writes the json marshaled genesis state into database
113+ // with the given block hash as the unique identifier.
114+ func (ga * GenesisAlloc ) write (db ethdb.KeyValueWriter , hash common.Hash ) error {
115+ blob , err := json .Marshal (ga )
116+ if err != nil {
117+ return err
118+ }
119+ rawdb .WriteGenesisState (db , hash , blob )
120+ return nil
121+ }
122+
123+ // CommitGenesisState loads the stored genesis state with the given block
124+ // hash and commits them into the given database handler.
125+ func CommitGenesisState (db ethdb.Database , hash common.Hash ) error {
126+ var alloc GenesisAlloc
127+ blob := rawdb .ReadGenesisState (db , hash )
128+ if len (blob ) != 0 {
129+ if err := alloc .UnmarshalJSON (blob ); err != nil {
130+ return err
131+ }
132+ } else {
133+ // Genesis allocation is missing and there are several possibilities:
134+ // the node is legacy which doesn't persist the genesis allocation or
135+ // the persisted allocation is just lost.
136+ // - supported networks(mainnet, testnets), recover with defined allocations
137+ // - private network, can't recover
138+ var genesis * Genesis
139+ switch hash {
140+ case params .MainnetGenesisHash :
141+ genesis = DefaultGenesisBlock ()
142+ case params .RopstenGenesisHash :
143+ genesis = DefaultRopstenGenesisBlock ()
144+ case params .RinkebyGenesisHash :
145+ genesis = DefaultRinkebyGenesisBlock ()
146+ case params .GoerliGenesisHash :
147+ genesis = DefaultGoerliGenesisBlock ()
148+ case params .SepoliaGenesisHash :
149+ genesis = DefaultSepoliaGenesisBlock ()
150+ }
151+ if genesis != nil {
152+ alloc = genesis .Alloc
153+ } else {
154+ return errors .New ("not found" )
155+ }
156+ }
157+ _ , err := alloc .flush (db )
158+ return err
159+ }
160+
86161// GenesisAccount is an account in the state of the genesis block.
87162type GenesisAccount struct {
88163 Code []byte `json:"code,omitempty"`
@@ -274,19 +349,10 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
274349 if db == nil {
275350 db = rawdb .NewMemoryDatabase ()
276351 }
277- statedb , err := state . New (common. Hash {}, state . NewDatabase (db ), nil )
352+ root , err := g . Alloc . flush (db )
278353 if err != nil {
279354 panic (err )
280355 }
281- for addr , account := range g .Alloc {
282- statedb .AddBalance (addr , account .Balance )
283- statedb .SetCode (addr , account .Code )
284- statedb .SetNonce (addr , account .Nonce )
285- for key , value := range account .Storage {
286- statedb .SetState (addr , key , value )
287- }
288- }
289- root := statedb .IntermediateRoot (false )
290356 head := & types.Header {
291357 Number : new (big.Int ).SetUint64 (g .Number ),
292358 Nonce : types .EncodeNonce (g .Nonce ),
@@ -314,9 +380,6 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
314380 head .BaseFee = new (big.Int ).SetUint64 (params .InitialBaseFee )
315381 }
316382 }
317- statedb .Commit (false )
318- statedb .Database ().TrieDB ().Commit (root , true , nil )
319-
320383 return types .NewBlock (head , nil , nil , nil , trie .NewStackTrie (nil ))
321384}
322385
@@ -337,6 +400,9 @@ func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) {
337400 if config .Clique != nil && len (block .Extra ()) == 0 {
338401 return nil , errors .New ("can't start clique chain without signers" )
339402 }
403+ if err := g .Alloc .write (db , block .Hash ()); err != nil {
404+ return nil , err
405+ }
340406 rawdb .WriteTd (db , block .Hash (), block .NumberU64 (), block .Difficulty ())
341407 rawdb .WriteBlock (db , block )
342408 rawdb .WriteReceipts (db , block .Hash (), block .NumberU64 (), nil )
0 commit comments