Skip to content

Commit 56de337

Browse files
authored
Merge pull request #16722 from karalabe/trie-iterator-proofs
trie: support proof generation from the iterator
2 parents fbf57d5 + c934c06 commit 56de337

File tree

2 files changed

+150
-48
lines changed

2 files changed

+150
-48
lines changed

trie/iterator.go

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"errors"
2323

2424
"github.com/ethereum/go-ethereum/common"
25+
"github.com/ethereum/go-ethereum/rlp"
2526
)
2627

2728
// Iterator is a key-value trie iterator that traverses a Trie.
@@ -55,31 +56,50 @@ func (it *Iterator) Next() bool {
5556
return false
5657
}
5758

59+
// Prove generates the Merkle proof for the leaf node the iterator is currently
60+
// positioned on.
61+
func (it *Iterator) Prove() [][]byte {
62+
return it.nodeIt.LeafProof()
63+
}
64+
5865
// NodeIterator is an iterator to traverse the trie pre-order.
5966
type NodeIterator interface {
6067
// Next moves the iterator to the next node. If the parameter is false, any child
6168
// nodes will be skipped.
6269
Next(bool) bool
70+
6371
// Error returns the error status of the iterator.
6472
Error() error
6573

6674
// Hash returns the hash of the current node.
6775
Hash() common.Hash
76+
6877
// Parent returns the hash of the parent of the current node. The hash may be the one
6978
// grandparent if the immediate parent is an internal node with no hash.
7079
Parent() common.Hash
80+
7181
// Path returns the hex-encoded path to the current node.
7282
// Callers must not retain references to the return value after calling Next.
7383
// For leaf nodes, the last element of the path is the 'terminator symbol' 0x10.
7484
Path() []byte
7585

7686
// Leaf returns true iff the current node is a leaf node.
77-
// LeafBlob, LeafKey return the contents and key of the leaf node. These
78-
// method panic if the iterator is not positioned at a leaf.
79-
// Callers must not retain references to their return value after calling Next
8087
Leaf() bool
81-
LeafBlob() []byte
88+
89+
// LeafKey returns the key of the leaf. The method panics if the iterator is not
90+
// positioned at a leaf. Callers must not retain references to the value after
91+
// calling Next.
8292
LeafKey() []byte
93+
94+
// LeafBlob returns the content of the leaf. The method panics if the iterator
95+
// is not positioned at a leaf. Callers must not retain references to the value
96+
// after calling Next.
97+
LeafBlob() []byte
98+
99+
// LeafProof returns the Merkle proof of the leaf. The method panics if the
100+
// iterator is not positioned at a leaf. Callers must not retain references
101+
// to the value after calling Next.
102+
LeafProof() [][]byte
83103
}
84104

85105
// nodeIteratorState represents the iteration state at one particular node of the
@@ -139,6 +159,15 @@ func (it *nodeIterator) Leaf() bool {
139159
return hasTerm(it.path)
140160
}
141161

162+
func (it *nodeIterator) LeafKey() []byte {
163+
if len(it.stack) > 0 {
164+
if _, ok := it.stack[len(it.stack)-1].node.(valueNode); ok {
165+
return hexToKeybytes(it.path)
166+
}
167+
}
168+
panic("not at leaf")
169+
}
170+
142171
func (it *nodeIterator) LeafBlob() []byte {
143172
if len(it.stack) > 0 {
144173
if node, ok := it.stack[len(it.stack)-1].node.(valueNode); ok {
@@ -148,10 +177,22 @@ func (it *nodeIterator) LeafBlob() []byte {
148177
panic("not at leaf")
149178
}
150179

151-
func (it *nodeIterator) LeafKey() []byte {
180+
func (it *nodeIterator) LeafProof() [][]byte {
152181
if len(it.stack) > 0 {
153182
if _, ok := it.stack[len(it.stack)-1].node.(valueNode); ok {
154-
return hexToKeybytes(it.path)
183+
hasher := newHasher(0, 0, nil)
184+
proofs := make([][]byte, 0, len(it.stack))
185+
186+
for i, item := range it.stack[:len(it.stack)-1] {
187+
// Gather nodes that end up as hash nodes (or the root)
188+
node, _, _ := hasher.hashChildren(item.node, nil)
189+
hashed, _ := hasher.store(node, nil, false)
190+
if _, ok := hashed.(hashNode); ok || i == 0 {
191+
enc, _ := rlp.EncodeToBytes(node)
192+
proofs = append(proofs, enc)
193+
}
194+
}
195+
return proofs
155196
}
156197
}
157198
panic("not at leaf")
@@ -361,12 +402,16 @@ func (it *differenceIterator) Leaf() bool {
361402
return it.b.Leaf()
362403
}
363404

405+
func (it *differenceIterator) LeafKey() []byte {
406+
return it.b.LeafKey()
407+
}
408+
364409
func (it *differenceIterator) LeafBlob() []byte {
365410
return it.b.LeafBlob()
366411
}
367412

368-
func (it *differenceIterator) LeafKey() []byte {
369-
return it.b.LeafKey()
413+
func (it *differenceIterator) LeafProof() [][]byte {
414+
return it.b.LeafProof()
370415
}
371416

372417
func (it *differenceIterator) Path() []byte {
@@ -464,12 +509,16 @@ func (it *unionIterator) Leaf() bool {
464509
return (*it.items)[0].Leaf()
465510
}
466511

512+
func (it *unionIterator) LeafKey() []byte {
513+
return (*it.items)[0].LeafKey()
514+
}
515+
467516
func (it *unionIterator) LeafBlob() []byte {
468517
return (*it.items)[0].LeafBlob()
469518
}
470519

471-
func (it *unionIterator) LeafKey() []byte {
472-
return (*it.items)[0].LeafKey()
520+
func (it *unionIterator) LeafProof() [][]byte {
521+
return (*it.items)[0].LeafProof()
473522
}
474523

475524
func (it *unionIterator) Path() []byte {
@@ -509,12 +558,10 @@ func (it *unionIterator) Next(descend bool) bool {
509558
heap.Push(it.items, skipped)
510559
}
511560
}
512-
513561
if least.Next(descend) {
514562
it.count++
515563
heap.Push(it.items, least)
516564
}
517-
518565
return len(*it.items) > 0
519566
}
520567

trie/proof_test.go

Lines changed: 91 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -32,58 +32,113 @@ func init() {
3232
mrand.Seed(time.Now().Unix())
3333
}
3434

35+
// makeProvers creates Merkle trie provers based on different implementations to
36+
// test all variations.
37+
func makeProvers(trie *Trie) []func(key []byte) *ethdb.MemDatabase {
38+
var provers []func(key []byte) *ethdb.MemDatabase
39+
40+
// Create a direct trie based Merkle prover
41+
provers = append(provers, func(key []byte) *ethdb.MemDatabase {
42+
proof := ethdb.NewMemDatabase()
43+
trie.Prove(key, 0, proof)
44+
return proof
45+
})
46+
// Create a leaf iterator based Merkle prover
47+
provers = append(provers, func(key []byte) *ethdb.MemDatabase {
48+
proof := ethdb.NewMemDatabase()
49+
if it := NewIterator(trie.NodeIterator(key)); it.Next() && bytes.Equal(key, it.Key) {
50+
for _, p := range it.Prove() {
51+
proof.Put(crypto.Keccak256(p), p)
52+
}
53+
}
54+
return proof
55+
})
56+
return provers
57+
}
58+
3559
func TestProof(t *testing.T) {
3660
trie, vals := randomTrie(500)
3761
root := trie.Hash()
38-
for _, kv := range vals {
39-
proofs := ethdb.NewMemDatabase()
40-
if trie.Prove(kv.k, 0, proofs) != nil {
41-
t.Fatalf("missing key %x while constructing proof", kv.k)
42-
}
43-
val, _, err := VerifyProof(root, kv.k, proofs)
44-
if err != nil {
45-
t.Fatalf("VerifyProof error for key %x: %v\nraw proof: %v", kv.k, err, proofs)
46-
}
47-
if !bytes.Equal(val, kv.v) {
48-
t.Fatalf("VerifyProof returned wrong value for key %x: got %x, want %x", kv.k, val, kv.v)
62+
for i, prover := range makeProvers(trie) {
63+
for _, kv := range vals {
64+
proof := prover(kv.k)
65+
if proof == nil {
66+
t.Fatalf("prover %d: missing key %x while constructing proof", i, kv.k)
67+
}
68+
val, _, err := VerifyProof(root, kv.k, proof)
69+
if err != nil {
70+
t.Fatalf("prover %d: failed to verify proof for key %x: %v\nraw proof: %x", i, kv.k, err, proof)
71+
}
72+
if !bytes.Equal(val, kv.v) {
73+
t.Fatalf("prover %d: verified value mismatch for key %x: have %x, want %x", i, kv.k, val, kv.v)
74+
}
4975
}
5076
}
5177
}
5278

5379
func TestOneElementProof(t *testing.T) {
5480
trie := new(Trie)
5581
updateString(trie, "k", "v")
56-
proofs := ethdb.NewMemDatabase()
57-
trie.Prove([]byte("k"), 0, proofs)
58-
if len(proofs.Keys()) != 1 {
59-
t.Error("proof should have one element")
60-
}
61-
val, _, err := VerifyProof(trie.Hash(), []byte("k"), proofs)
62-
if err != nil {
63-
t.Fatalf("VerifyProof error: %v\nproof hashes: %v", err, proofs.Keys())
64-
}
65-
if !bytes.Equal(val, []byte("v")) {
66-
t.Fatalf("VerifyProof returned wrong value: got %x, want 'k'", val)
82+
for i, prover := range makeProvers(trie) {
83+
proof := prover([]byte("k"))
84+
if proof == nil {
85+
t.Fatalf("prover %d: nil proof", i)
86+
}
87+
if proof.Len() != 1 {
88+
t.Errorf("prover %d: proof should have one element", i)
89+
}
90+
val, _, err := VerifyProof(trie.Hash(), []byte("k"), proof)
91+
if err != nil {
92+
t.Fatalf("prover %d: failed to verify proof: %v\nraw proof: %x", i, err, proof)
93+
}
94+
if !bytes.Equal(val, []byte("v")) {
95+
t.Fatalf("prover %d: verified value mismatch: have %x, want 'k'", i, val)
96+
}
6797
}
6898
}
6999

70-
func TestVerifyBadProof(t *testing.T) {
100+
func TestBadProof(t *testing.T) {
71101
trie, vals := randomTrie(800)
72102
root := trie.Hash()
73-
for _, kv := range vals {
74-
proofs := ethdb.NewMemDatabase()
75-
trie.Prove(kv.k, 0, proofs)
76-
if len(proofs.Keys()) == 0 {
77-
t.Fatal("zero length proof")
103+
for i, prover := range makeProvers(trie) {
104+
for _, kv := range vals {
105+
proof := prover(kv.k)
106+
if proof == nil {
107+
t.Fatalf("prover %d: nil proof", i)
108+
}
109+
key := proof.Keys()[mrand.Intn(proof.Len())]
110+
val, _ := proof.Get(key)
111+
proof.Delete(key)
112+
113+
mutateByte(val)
114+
proof.Put(crypto.Keccak256(val), val)
115+
116+
if _, _, err := VerifyProof(root, kv.k, proof); err == nil {
117+
t.Fatalf("prover %d: expected proof to fail for key %x", i, kv.k)
118+
}
119+
}
120+
}
121+
}
122+
123+
// Tests that missing keys can also be proven. The test explicitly uses a single
124+
// entry trie and checks for missing keys both before and after the single entry.
125+
func TestMissingKeyProof(t *testing.T) {
126+
trie := new(Trie)
127+
updateString(trie, "k", "v")
128+
129+
for i, key := range []string{"a", "j", "l", "z"} {
130+
proof := ethdb.NewMemDatabase()
131+
trie.Prove([]byte(key), 0, proof)
132+
133+
if proof.Len() != 1 {
134+
t.Errorf("test %d: proof should have one element", i)
135+
}
136+
val, _, err := VerifyProof(trie.Hash(), []byte(key), proof)
137+
if err != nil {
138+
t.Fatalf("test %d: failed to verify proof: %v\nraw proof: %x", i, err, proof)
78139
}
79-
keys := proofs.Keys()
80-
key := keys[mrand.Intn(len(keys))]
81-
node, _ := proofs.Get(key)
82-
proofs.Delete(key)
83-
mutateByte(node)
84-
proofs.Put(crypto.Keccak256(node), node)
85-
if _, _, err := VerifyProof(root, kv.k, proofs); err == nil {
86-
t.Fatalf("expected proof to fail for key %x", kv.k)
140+
if val != nil {
141+
t.Fatalf("test %d: verified value mismatch: have %x, want nil", i, val)
87142
}
88143
}
89144
}

0 commit comments

Comments
 (0)