@@ -31,29 +31,50 @@ import (
3131// thread-safe to use. However, callers need to ensure the thread-safety
3232// of the referenced layer by themselves.
3333type layerTree struct {
34- lock sync. RWMutex
34+ base * diskLayer
3535 layers map [common.Hash ]layer
36+
37+ // descendants is a two-dimensional map where the keys represent
38+ // an ancestor state root, and the values are the state roots of
39+ // all its descendants.
40+ //
41+ // For example: r -> [c1, c2, ..., cn], where c1 through cn are
42+ // the descendants of state r.
43+ //
44+ // This map includes all the existing diff layers and the disk layer.
45+ descendants map [common.Hash ]map [common.Hash ]struct {}
46+ lookup * lookup
47+ lock sync.RWMutex
3648}
3749
3850// newLayerTree constructs the layerTree with the given head layer.
3951func newLayerTree (head layer ) * layerTree {
4052 tree := new (layerTree )
41- tree .reset (head )
53+ tree .init (head )
4254 return tree
4355}
4456
45- // reset initializes the layerTree by the given head layer.
46- // All the ancestors will be iterated out and linked in the tree.
47- func (tree * layerTree ) reset (head layer ) {
57+ // init initializes the layerTree by the given head layer.
58+ func (tree * layerTree ) init (head layer ) {
4859 tree .lock .Lock ()
4960 defer tree .lock .Unlock ()
5061
51- var layers = make (map [common.Hash ]layer )
52- for head != nil {
53- layers [head .rootHash ()] = head
54- head = head .parentLayer ()
62+ current := head
63+ tree .layers = make (map [common.Hash ]layer )
64+ tree .descendants = make (map [common.Hash ]map [common.Hash ]struct {})
65+
66+ for {
67+ tree .layers [current .rootHash ()] = current
68+ tree .fillAncestors (current )
69+
70+ parent := current .parentLayer ()
71+ if parent == nil {
72+ break
73+ }
74+ current = parent
5575 }
56- tree .layers = layers
76+ tree .base = current .(* diskLayer ) // panic if it's not a disk layer
77+ tree .lookup = newLookup (head , tree .isDescendant )
5778}
5879
5980// get retrieves a layer belonging to the given state root.
@@ -64,6 +85,43 @@ func (tree *layerTree) get(root common.Hash) layer {
6485 return tree .layers [root ]
6586}
6687
88+ // isDescendant returns whether the specified layer with given root is a
89+ // descendant of a specific ancestor.
90+ //
91+ // This function assumes the read lock has been held.
92+ func (tree * layerTree ) isDescendant (root common.Hash , ancestor common.Hash ) bool {
93+ subset := tree .descendants [ancestor ]
94+ if subset == nil {
95+ return false
96+ }
97+ _ , ok := subset [root ]
98+ return ok
99+ }
100+
101+ // fillAncestors identifies the ancestors of the given layer and populates the
102+ // descendants set. The ancestors include the diff layers below the supplied
103+ // layer and also the disk layer.
104+ //
105+ // This function assumes the write lock has been held.
106+ func (tree * layerTree ) fillAncestors (layer layer ) {
107+ hash := layer .rootHash ()
108+ for {
109+ parent := layer .parentLayer ()
110+ if parent == nil {
111+ break
112+ }
113+ layer = parent
114+
115+ phash := parent .rootHash ()
116+ subset := tree .descendants [phash ]
117+ if subset == nil {
118+ subset = make (map [common.Hash ]struct {})
119+ tree .descendants [phash ] = subset
120+ }
121+ subset [hash ] = struct {}{}
122+ }
123+ }
124+
67125// forEach iterates the stored layers inside and applies the
68126// given callback on them.
69127func (tree * layerTree ) forEach (onLayer func (layer )) {
@@ -101,8 +159,16 @@ func (tree *layerTree) add(root common.Hash, parentRoot common.Hash, block uint6
101159 l := parent .update (root , parent .stateID ()+ 1 , block , newNodeSet (nodes .Flatten ()), states )
102160
103161 tree .lock .Lock ()
162+ defer tree .lock .Unlock ()
163+
164+ // Link the given layer into the layer set
104165 tree .layers [l .rootHash ()] = l
105- tree .lock .Unlock ()
166+
167+ // Link the given layer into its ancestors (up to the current disk layer)
168+ tree .fillAncestors (l )
169+
170+ // Link the given layer into the state mutation history
171+ tree .lookup .addLayer (l )
106172 return nil
107173}
108174
@@ -127,8 +193,16 @@ func (tree *layerTree) cap(root common.Hash, layers int) error {
127193 if err != nil {
128194 return err
129195 }
130- // Replace the entire layer tree with the flat base
131- tree .layers = map [common.Hash ]layer {base .rootHash (): base }
196+ tree .base = base
197+
198+ // Reset the layer tree with the single new disk layer
199+ tree .layers = map [common.Hash ]layer {
200+ base .rootHash (): base ,
201+ }
202+ // Resets the descendants map, since there's only a single disk layer
203+ // with no descendants.
204+ tree .descendants = make (map [common.Hash ]map [common.Hash ]struct {})
205+ tree .lookup = newLookup (base , tree .isDescendant )
132206 return nil
133207 }
134208 // Dive until we run out of layers or reach the persistent database
@@ -143,6 +217,11 @@ func (tree *layerTree) cap(root common.Hash, layers int) error {
143217 }
144218 // We're out of layers, flatten anything below, stopping if it's the disk or if
145219 // the memory limit is not yet exceeded.
220+ var (
221+ err error
222+ replaced layer
223+ newBase * diskLayer
224+ )
146225 switch parent := diff .parentLayer ().(type ) {
147226 case * diskLayer :
148227 return nil
@@ -152,14 +231,33 @@ func (tree *layerTree) cap(root common.Hash, layers int) error {
152231 // parent is linked correctly.
153232 diff .lock .Lock ()
154233
155- base , err := parent .persist (false )
234+ // Hold the reference of the original layer being replaced
235+ replaced = parent
236+
237+ // Replace the original parent layer with new disk layer. The procedure
238+ // can be illustrated as below:
239+ //
240+ // Before change:
241+ // Chain:
242+ // C1->C2->C3->C4 (HEAD)
243+ // ->C2'->C3'->C4'
244+ //
245+ // After change:
246+ // Chain:
247+ // (a) C3->C4 (HEAD)
248+ // (b) C1->C2
249+ // ->C2'->C3'->C4'
250+ // The original C3 is replaced by the new base (with root C3)
251+ // Dangling layers in (b) will be removed later
252+ newBase , err = parent .persist (false )
156253 if err != nil {
157254 diff .lock .Unlock ()
158255 return err
159256 }
160- tree .layers [base .rootHash ()] = base
161- diff .parent = base
257+ tree .layers [newBase .rootHash ()] = newBase
162258
259+ // Link the new parent and release the lock
260+ diff .parent = newBase
163261 diff .lock .Unlock ()
164262
165263 default :
@@ -173,19 +271,28 @@ func (tree *layerTree) cap(root common.Hash, layers int) error {
173271 children [parent ] = append (children [parent ], root )
174272 }
175273 }
274+ clearDiff := func (layer layer ) {
275+ diff , ok := layer .(* diffLayer )
276+ if ! ok {
277+ return
278+ }
279+ tree .lookup .removeLayer (diff )
280+ }
176281 var remove func (root common.Hash )
177282 remove = func (root common.Hash ) {
283+ clearDiff (tree .layers [root ])
284+
285+ // Unlink the layer from the layer tree and cascade to its children
286+ delete (tree .descendants , root )
178287 delete (tree .layers , root )
179288 for _ , child := range children [root ] {
180289 remove (child )
181290 }
182291 delete (children , root )
183292 }
184- for root , layer := range tree .layers {
185- if dl , ok := layer .(* diskLayer ); ok && dl .isStale () {
186- remove (root )
187- }
188- }
293+ remove (tree .base .rootHash ()) // remove the old/stale disk layer
294+ clearDiff (replaced ) // remove the lookup data of the stale parent being replaced
295+ tree .base = newBase // update the base layer with newly constructed one
189296 return nil
190297}
191298
@@ -194,17 +301,41 @@ func (tree *layerTree) bottom() *diskLayer {
194301 tree .lock .RLock ()
195302 defer tree .lock .RUnlock ()
196303
197- if len (tree .layers ) == 0 {
198- return nil // Shouldn't happen, empty tree
304+ return tree .base
305+ }
306+
307+ // lookupAccount returns the layer that is guaranteed to contain the account data
308+ // corresponding to the specified state root being queried.
309+ func (tree * layerTree ) lookupAccount (accountHash common.Hash , state common.Hash ) (layer , error ) {
310+ // Hold the read lock to prevent the unexpected layer changes
311+ tree .lock .RLock ()
312+ defer tree .lock .RUnlock ()
313+
314+ tip := tree .lookup .accountTip (accountHash , state , tree .base .root )
315+ if tip == (common.Hash {}) {
316+ return nil , fmt .Errorf ("[%#x] %w" , state , errSnapshotStale )
199317 }
200- // pick a random one as the entry point
201- var current layer
202- for _ , layer := range tree .layers {
203- current = layer
204- break
318+ l := tree .layers [tip ]
319+ if l == nil {
320+ return nil , fmt .Errorf ("triedb layer [%#x] missing" , tip )
205321 }
206- for current .parentLayer () != nil {
207- current = current .parentLayer ()
322+ return l , nil
323+ }
324+
325+ // lookupStorage returns the layer that is guaranteed to contain the storage slot
326+ // data corresponding to the specified state root being queried.
327+ func (tree * layerTree ) lookupStorage (accountHash common.Hash , slotHash common.Hash , state common.Hash ) (layer , error ) {
328+ // Hold the read lock to prevent the unexpected layer changes
329+ tree .lock .RLock ()
330+ defer tree .lock .RUnlock ()
331+
332+ tip := tree .lookup .storageTip (accountHash , slotHash , state , tree .base .root )
333+ if tip == (common.Hash {}) {
334+ return nil , fmt .Errorf ("[%#x] %w" , state , errSnapshotStale )
335+ }
336+ l := tree .layers [tip ]
337+ if l == nil {
338+ return nil , fmt .Errorf ("triedb layer [%#x] missing" , tip )
208339 }
209- return current .( * diskLayer )
340+ return l , nil
210341}
0 commit comments