Skip to content

Commit 7e04d4e

Browse files
committed
core/state/snapshot: don't resolve small storage tries in vain
1 parent 1eb3ef0 commit 7e04d4e

File tree

2 files changed

+26
-17
lines changed

2 files changed

+26
-17
lines changed

core/state/snapshot/generate.go

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,11 @@ func journalProgress(db ethdb.KeyValueWriter, marker []byte, stats *generatorSta
184184
// proofResult contains the output of range proving which can be used
185185
// for further processing no matter it's successful or not.
186186
type proofResult struct {
187-
keys [][]byte // The key set of all elements being iterated, even proving is failed
188-
vals [][]byte // The val set of all elements being iterated, even proving is failed
189-
cont bool // Indicator if there exists more elements in the range, only meaningful when proving is successful
190-
proofErr error // Indicator whether the given state range is valid or not
187+
keys [][]byte // The key set of all elements being iterated, even proving is failed
188+
vals [][]byte // The val set of all elements being iterated, even proving is failed
189+
cont bool // Indicator if there exists more elements in the range, only meaningful when proving is successful
190+
proofErr error // Indicator whether the given state range is valid or not
191+
tr *trie.Trie // The trie, in case the trie was resolved by the prover (may be nil)
191192
}
192193

193194
// valid returns the indicator that range proof is successful or not.
@@ -227,7 +228,7 @@ func (result *proofResult) forEach(callback func(key []byte, val []byte) error)
227228
//
228229
// The proof result will be returned if the range proving is finished, otherwise
229230
// the error will be returned to abort the entire procedure.
230-
func (dl *diskLayer) proveRange(root common.Hash, tr *trie.Trie, prefix []byte, kind string, origin []byte, max int, valueConvertFn func([]byte) ([]byte, error)) (*proofResult, error) {
231+
func (dl *diskLayer) proveRange(root common.Hash, prefix []byte, kind string, origin []byte, max int, valueConvertFn func([]byte) ([]byte, error)) (*proofResult, error) {
231232
var (
232233
keys [][]byte
233234
vals [][]byte
@@ -236,7 +237,6 @@ func (dl *diskLayer) proveRange(root common.Hash, tr *trie.Trie, prefix []byte,
236237
)
237238
iter := dl.diskdb.NewIterator(prefix, origin)
238239
defer iter.Release()
239-
240240
for iter.Next() {
241241
key := iter.Key()
242242
if len(key) != len(prefix)+common.HashLength {
@@ -269,6 +269,11 @@ func (dl *diskLayer) proveRange(root common.Hash, tr *trie.Trie, prefix []byte,
269269
}
270270
return &proofResult{keys: keys, vals: vals, cont: false, proofErr: nil}, nil
271271
}
272+
tr, err := trie.New(root, dl.triedb)
273+
if err != nil {
274+
log.Error("Missing trie", "root", root, "err", err)
275+
return nil, err
276+
}
272277
// Snap state is chunked, generate edge proofs for verification.
273278
// Firstly find out the key of last iterated element.
274279
var last []byte
@@ -281,40 +286,35 @@ func (dl *diskLayer) proveRange(root common.Hash, tr *trie.Trie, prefix []byte,
281286
}
282287
if err := tr.Prove(origin, 0, proof); err != nil {
283288
log.Debug("Failed to prove range", "kind", kind, "origin", origin, "err", err)
284-
return &proofResult{keys: keys, vals: vals, cont: false, proofErr: err}, nil
289+
return &proofResult{keys: keys, vals: vals, cont: false, proofErr: err, tr: tr}, nil
285290
}
286291
if last != nil {
287292
if err := tr.Prove(last, 0, proof); err != nil {
288293
log.Debug("Failed to prove range", "kind", kind, "last", last, "err", err)
289-
return &proofResult{keys: keys, vals: vals, cont: false, proofErr: err}, nil
294+
return &proofResult{keys: keys, vals: vals, cont: false, proofErr: err, tr: tr}, nil
290295
}
291296
}
292297
// Verify the state segment with range prover, ensure that all flat states
293298
// in this range correspond to merkle trie.
294299
_, _, _, cont, err := trie.VerifyRangeProof(root, origin, last, keys, vals, proof)
295300
if err != nil {
296-
return &proofResult{keys: keys, vals: vals, cont: false, proofErr: err}, nil
301+
return &proofResult{keys: keys, vals: vals, cont: false, proofErr: err, tr: tr}, nil
297302
}
298303
// Range prover says the trie still has some elements on the right side but
299304
// the database is exhausted, then data loss is detected.
300305
// TODO: Investigate if this is needed (the assumption is that it's not needed)
301306
//if cont && len(keys) < max {
302307
//return &proofResult{keys: keys, vals: vals, cont: true, proofErr: nil}, nil
303308
//}
304-
return &proofResult{keys: keys, vals: vals, cont: cont, proofErr: nil}, nil
309+
return &proofResult{keys: keys, vals: vals, cont: cont, proofErr: nil, tr: tr}, nil
305310
}
306311

307312
// genRange generates the state segment with particular prefix. Generation can
308313
// either verify the correctness of existing state through rangeproof and skip
309314
// generation, or iterate trie to regenerate state on demand.
310315
func (dl *diskLayer) genRange(root common.Hash, prefix []byte, kind string, origin []byte, max int, stats *generatorStats, onState func(key []byte, val []byte, write bool, delete bool) error, valueConvertFn func([]byte) ([]byte, error)) (bool, []byte, error) {
311-
tr, err := trie.New(root, dl.triedb)
312-
if err != nil {
313-
stats.Log("Trie missing, state snapshotting paused", root, dl.genMarker)
314-
return false, nil, err
315-
}
316316
// Use range prover to check the validity of the flat state in the range
317-
result, err := dl.proveRange(root, tr, prefix, kind, origin, max, valueConvertFn)
317+
result, err := dl.proveRange(root, prefix, kind, origin, max, valueConvertFn)
318318
if err != nil {
319319
return false, nil, err
320320
}
@@ -353,6 +353,13 @@ func (dl *diskLayer) genRange(root common.Hash, prefix []byte, kind string, orig
353353
}
354354
meter.Mark(1)
355355
}
356+
tr := result.tr
357+
if tr == nil {
358+
tr, err = trie.New(root, dl.triedb)
359+
if err != nil {
360+
return false, nil, err
361+
}
362+
}
356363
var (
357364
aborted bool
358365
iter = trie.NewIterator(tr.NodeIterator(origin))

core/state/snapshot/generate_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,9 @@ func checkSnapRoot(t *testing.T, snap *diskLayer, trieRoot common.Hash) {
175175
// - the contract(non-empty storage) misses some storage slots
176176
// - the contract(non-empty storage) has wrong storage slots
177177
func TestGenerateExistentStateWithWrongStorage(t *testing.T) {
178-
log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
178+
if false {
179+
log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
180+
}
179181

180182
// We can't use statedb to make a test trie (circular dependency), so make
181183
// a fake one manually. We're going with a small account trie of 3 accounts,

0 commit comments

Comments
 (0)