Skip to content

Commit a3b9179

Browse files
holimangzliudan
authored andcommitted
trie: remove redundant returns + use stacktrie where applicable ethereum#22760
* trie: add benchmark for proofless range * trie: remove unused returns + use stacktrie
1 parent 4dbef26 commit a3b9179

File tree

3 files changed

+91
-80
lines changed

3 files changed

+91
-80
lines changed

trie/notary.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,32 +21,32 @@ import (
2121
"github.com/XinFinOrg/XDPoSChain/ethdb/memorydb"
2222
)
2323

24-
// KeyValueNotary tracks which keys have been accessed through a key-value reader
24+
// keyValueNotary tracks which keys have been accessed through a key-value reader
2525
// with te scope of verifying if certain proof datasets are maliciously bloated.
26-
type KeyValueNotary struct {
26+
type keyValueNotary struct {
2727
ethdb.KeyValueReader
2828
reads map[string]struct{}
2929
}
3030

31-
// NewKeyValueNotary wraps a key-value database with an access notary to track
31+
// newKeyValueNotary wraps a key-value database with an access notary to track
3232
// which items have bene accessed.
33-
func NewKeyValueNotary(db ethdb.KeyValueReader) *KeyValueNotary {
34-
return &KeyValueNotary{
33+
func newKeyValueNotary(db ethdb.KeyValueReader) *keyValueNotary {
34+
return &keyValueNotary{
3535
KeyValueReader: db,
3636
reads: make(map[string]struct{}),
3737
}
3838
}
3939

4040
// Get retrieves an item from the underlying database, but also tracks it as an
4141
// accessed slot for bloat checks.
42-
func (k *KeyValueNotary) Get(key []byte) ([]byte, error) {
42+
func (k *keyValueNotary) Get(key []byte) ([]byte, error) {
4343
k.reads[string(key)] = struct{}{}
4444
return k.KeyValueReader.Get(key)
4545
}
4646

4747
// Accessed returns s snapshot of the original key-value store containing only the
4848
// data accessed through the notary.
49-
func (k *KeyValueNotary) Accessed() ethdb.KeyValueStore {
49+
func (k *keyValueNotary) Accessed() ethdb.KeyValueStore {
5050
db := memorydb.New()
5151
for keystr := range k.reads {
5252
key := []byte(keystr)

trie/proof.go

Lines changed: 27 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -463,115 +463,100 @@ func hasRightElement(node node, key []byte) bool {
463463
//
464464
// Except returning the error to indicate the proof is valid or not, the function will
465465
// also return a flag to indicate whether there exists more accounts/slots in the trie.
466-
func VerifyRangeProof(rootHash common.Hash, firstKey []byte, lastKey []byte, keys [][]byte, values [][]byte, proof ethdb.KeyValueReader) (ethdb.KeyValueStore, *Trie, *KeyValueNotary, bool, error) {
466+
func VerifyRangeProof(rootHash common.Hash, firstKey []byte, lastKey []byte, keys [][]byte, values [][]byte, proof ethdb.KeyValueReader) (ethdb.KeyValueStore, bool, error) {
467467
if len(keys) != len(values) {
468-
return nil, nil, nil, false, fmt.Errorf("inconsistent proof data, keys: %d, values: %d", len(keys), len(values))
468+
return nil, false, fmt.Errorf("inconsistent proof data, keys: %d, values: %d", len(keys), len(values))
469469
}
470470
// Ensure the received batch is monotonic increasing.
471471
for i := 0; i < len(keys)-1; i++ {
472472
if bytes.Compare(keys[i], keys[i+1]) >= 0 {
473-
return nil, nil, nil, false, errors.New("range is not monotonically increasing")
473+
return nil, false, errors.New("range is not monotonically increasing")
474474
}
475475
}
476476
// Create a key-value notary to track which items from the given proof the
477477
// range prover actually needed to verify the data
478-
notary := NewKeyValueNotary(proof)
478+
notary := newKeyValueNotary(proof)
479479

480480
// Special case, there is no edge proof at all. The given range is expected
481481
// to be the whole leaf-set in the trie.
482482
if proof == nil {
483483
var (
484484
diskdb = memorydb.New()
485-
triedb = NewDatabase(diskdb)
485+
tr = NewStackTrie(diskdb)
486486
)
487-
tr, err := New(common.Hash{}, triedb)
488-
if err != nil {
489-
return nil, nil, nil, false, err
490-
}
491487
for index, key := range keys {
492488
tr.TryUpdate(key, values[index])
493489
}
494-
if tr.Hash() != rootHash {
495-
return nil, nil, nil, false, fmt.Errorf("invalid proof, want hash %x, got %x", rootHash, tr.Hash())
496-
}
497-
// Proof seems valid, serialize all the nodes into the database
498-
if _, err := tr.Commit(nil); err != nil {
499-
return nil, nil, nil, false, err
490+
if have, want := tr.Hash(), rootHash; have != want {
491+
return nil, false, fmt.Errorf("invalid proof, want hash %x, got %x", want, have)
500492
}
501-
if err := triedb.Commit(rootHash, false); err != nil {
502-
return nil, nil, nil, false, err
493+
// Proof seems valid, serialize remaining nodes into the database
494+
if _, err := tr.Commit(); err != nil {
495+
return nil, false, err
503496
}
504-
return diskdb, tr, notary, false, nil // No more elements
497+
return diskdb, false, nil // No more elements
505498
}
506499
// Special case, there is a provided edge proof but zero key/value
507500
// pairs, ensure there are no more accounts / slots in the trie.
508501
if len(keys) == 0 {
509502
root, val, err := proofToPath(rootHash, nil, firstKey, notary, true)
510503
if err != nil {
511-
return nil, nil, nil, false, err
504+
return nil, false, err
512505
}
513506
if val != nil || hasRightElement(root, firstKey) {
514-
return nil, nil, nil, false, errors.New("more entries available")
507+
return nil, false, errors.New("more entries available")
515508
}
516509
// Since the entire proof is a single path, we can construct a trie and a
517510
// node database directly out of the inputs, no need to generate them
518511
diskdb := notary.Accessed()
519-
tr := &Trie{
520-
Db: NewDatabase(diskdb),
521-
root: root,
522-
}
523-
return diskdb, tr, notary, hasRightElement(root, firstKey), nil
512+
return diskdb, hasRightElement(root, firstKey), nil
524513
}
525514
// Special case, there is only one element and two edge keys are same.
526515
// In this case, we can't construct two edge paths. So handle it here.
527516
if len(keys) == 1 && bytes.Equal(firstKey, lastKey) {
528517
root, val, err := proofToPath(rootHash, nil, firstKey, notary, false)
529518
if err != nil {
530-
return nil, nil, nil, false, err
519+
return nil, false, err
531520
}
532521
if !bytes.Equal(firstKey, keys[0]) {
533-
return nil, nil, nil, false, errors.New("correct proof but invalid key")
522+
return nil, false, errors.New("correct proof but invalid key")
534523
}
535524
if !bytes.Equal(val, values[0]) {
536-
return nil, nil, nil, false, errors.New("correct proof but invalid data")
525+
return nil, false, errors.New("correct proof but invalid data")
537526
}
538527
// Since the entire proof is a single path, we can construct a trie and a
539528
// node database directly out of the inputs, no need to generate them
540529
diskdb := notary.Accessed()
541-
tr := &Trie{
542-
Db: NewDatabase(diskdb),
543-
root: root,
544-
}
545-
return diskdb, tr, notary, hasRightElement(root, firstKey), nil
530+
return diskdb, hasRightElement(root, firstKey), nil
546531
}
547532
// Ok, in all other cases, we require two edge paths available.
548533
// First check the validity of edge keys.
549534
if bytes.Compare(firstKey, lastKey) >= 0 {
550-
return nil, nil, nil, false, errors.New("invalid edge keys")
535+
return nil, false, errors.New("invalid edge keys")
551536
}
552537
// todo(rjl493456442) different length edge keys should be supported
553538
if len(firstKey) != len(lastKey) {
554-
return nil, nil, nil, false, errors.New("inconsistent edge keys")
539+
return nil, false, errors.New("inconsistent edge keys")
555540
}
556541
// Convert the edge proofs to edge trie paths. Then we can
557542
// have the same tree architecture with the original one.
558543
// For the first edge proof, non-existent proof is allowed.
559544
root, _, err := proofToPath(rootHash, nil, firstKey, notary, true)
560545
if err != nil {
561-
return nil, nil, nil, false, err
546+
return nil, false, err
562547
}
563548
// Pass the root node here, the second path will be merged
564549
// with the first one. For the last edge proof, non-existent
565550
// proof is also allowed.
566551
root, _, err = proofToPath(rootHash, root, lastKey, notary, true)
567552
if err != nil {
568-
return nil, nil, nil, false, err
553+
return nil, false, err
569554
}
570555
// Remove all internal references. All the removed parts should
571556
// be re-filled(or re-constructed) by the given leaves range.
572557
empty, err := unsetInternal(root, firstKey, lastKey)
573558
if err != nil {
574-
return nil, nil, nil, false, err
559+
return nil, false, err
575560
}
576561
// Rebuild the trie with the leaf stream, the shape of trie
577562
// should be same with the original one.
@@ -587,16 +572,16 @@ func VerifyRangeProof(rootHash common.Hash, firstKey []byte, lastKey []byte, key
587572
tr.TryUpdate(key, values[index])
588573
}
589574
if tr.Hash() != rootHash {
590-
return nil, nil, nil, false, fmt.Errorf("invalid proof, want hash %x, got %x", rootHash, tr.Hash())
575+
return nil, false, fmt.Errorf("invalid proof, want hash %x, got %x", rootHash, tr.Hash())
591576
}
592577
// Proof seems valid, serialize all the nodes into the database
593578
if _, err := tr.Commit(nil); err != nil {
594-
return nil, nil, nil, false, err
579+
return nil, false, err
595580
}
596581
if err := triedb.Commit(rootHash, false); err != nil {
597-
return nil, nil, nil, false, err
582+
return nil, false, err
598583
}
599-
return diskdb, tr, notary, hasRightElement(root, keys[len(keys)-1]), nil
584+
return diskdb, hasRightElement(root, keys[len(keys)-1]), nil
600585
}
601586

602587
// get returns the child of the given Node. Return nil if the

0 commit comments

Comments
 (0)