@@ -174,6 +174,10 @@ type Tree struct {
174174
175175 // Test hooks
176176 onFlatten func () // Hook invoked when the bottom most diff layers are flattened
177+
178+ // XXX
179+ children map [common.Hash ][]common.Hash
180+ initiallyLoaded map [common.Hash ]struct {}
177181}
178182
179183// New attempts to load an already existing snapshot from a persistent key-value
@@ -195,10 +199,12 @@ type Tree struct {
195199func New (config Config , diskdb ethdb.KeyValueStore , triedb * triedb.Database , root common.Hash ) (* Tree , error ) {
196200 // Create a new, empty snapshot tree
197201 snap := & Tree {
198- config : config ,
199- diskdb : diskdb ,
200- triedb : triedb ,
201- layers : make (map [common.Hash ]snapshot ),
202+ config : config ,
203+ diskdb : diskdb ,
204+ triedb : triedb ,
205+ layers : make (map [common.Hash ]snapshot ),
206+ children : make (map [common.Hash ][]common.Hash ),
207+ initiallyLoaded : map [common.Hash ]struct {}{root : {}},
202208 }
203209 // Attempt to load a previously persisted snapshot and rebuild one if failed
204210 head , disabled , err := loadSnapshot (diskdb , triedb , root , config .CacheSize , config .Recovery , config .NoBuild )
@@ -221,6 +227,7 @@ func New(config Config, diskdb ethdb.KeyValueStore, triedb *triedb.Database, roo
221227 // Existing snapshot loaded, seed all the layers
222228 for head != nil {
223229 snap .layers [head .Root ()] = head
230+ snap .initiallyLoaded [head .Root ()] = struct {}{}
224231 head = head .Parent ()
225232 }
226233 return snap , nil
@@ -310,7 +317,17 @@ func (t *Tree) Snapshot(blockRoot common.Hash) Snapshot {
310317 t .lock .RLock ()
311318 defer t .lock .RUnlock ()
312319
313- return t .layers [blockRoot ]
320+ return t .byRoot (blockRoot )
321+ }
322+
323+ func (t * Tree ) byRoot (blockRoot common.Hash ) snapshot {
324+ for _ , snap := range t .layers {
325+ if snap .Root () == blockRoot {
326+ return snap
327+ }
328+ }
329+
330+ return nil
314331}
315332
316333// Snapshots returns all visited layers from the topmost layer with specific
@@ -323,7 +340,7 @@ func (t *Tree) Snapshots(root common.Hash, limits int, nodisk bool) []Snapshot {
323340 if limits == 0 {
324341 return nil
325342 }
326- layer := t .layers [ root ]
343+ layer := t .byRoot ( root )
327344 if layer == nil {
328345 return nil
329346 }
@@ -348,28 +365,47 @@ func (t *Tree) Snapshots(root common.Hash, limits int, nodisk bool) []Snapshot {
348365
349366// Update adds a new snapshot into the tree, if that can be linked to an existing
350367// old parent. It is disallowed to insert a disk layer (the origin of all).
351- func (t * Tree ) Update (blockRoot common.Hash , parentRoot common.Hash , destructs map [common.Hash ]struct {}, accounts map [common.Hash ][]byte , storage map [common.Hash ]map [common.Hash ][]byte ) error {
368+ func (t * Tree ) Update (blockRoot common.Hash , parentRoot common.Hash , destructs map [common.Hash ]struct {}, accounts map [common.Hash ][]byte , storage map [common.Hash ]map [common.Hash ][]byte ,
369+ opts ... LibEVMOption ) error {
352370 // Reject noop updates to avoid self-loops in the snapshot tree. This is a
353371 // special case that can only happen for Clique networks where empty blocks
354372 // don't modify the state (0 block subsidy).
355373 //
356374 // Although we could silently ignore this internally, it should be the caller's
357375 // responsibility to avoid even attempting to insert such a snapshot.
358- if blockRoot == parentRoot {
376+ opt := asLibEVMConfig (opts )
377+ layer := blockRoot
378+ if opt .hash != (common.Hash {}) {
379+ layer = opt .hash
380+ } else {
381+ panic ("block hash is required" )
382+ }
383+
384+ parentLayer := opt .parentHash
385+ _ , parentHashKnown := t .layers [opt .parentHash ]
386+ _ , isInitiallyLoaded := t .initiallyLoaded [parentRoot ]
387+ if ! parentHashKnown && isInitiallyLoaded {
388+ // Allow use of parentRoot as the key in the tree if:
389+ // - opt.parentHash is not known,
390+ // - parentRoot is known to be initially loaded.
391+ parentLayer = parentRoot
392+ }
393+ if layer == parentLayer {
359394 return errSnapshotCycle
360395 }
361396 // Generate a new snapshot on top of the parent
362- parent := t .Snapshot ( parentRoot )
397+ parent := t .layers [ parentLayer ]
363398 if parent == nil {
364399 return fmt .Errorf ("parent [%#x] snapshot missing" , parentRoot )
365400 }
366401 snap := parent .(snapshot ).Update (blockRoot , destructs , accounts , storage )
402+ t .children [parentLayer ] = append (t .children [parentLayer ], layer )
367403
368404 // Save the new snapshot for later
369405 t .lock .Lock ()
370406 defer t .lock .Unlock ()
371407
372- t .layers [snap . root ] = snap
408+ t .layers [layer ] = snap
373409 return nil
374410}
375411
0 commit comments