github.com/luckypickle/go-ethereum-vet@v1.14.2/trie/proof_test.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package trie 18 19 import ( 20 "bytes" 21 crand "crypto/rand" 22 mrand "math/rand" 23 "testing" 24 "time" 25 26 "github.com/luckypickle/go-ethereum-vet/common" 27 "github.com/luckypickle/go-ethereum-vet/crypto" 28 "github.com/luckypickle/go-ethereum-vet/ethdb" 29 ) 30 31 func init() { 32 mrand.Seed(time.Now().Unix()) 33 } 34 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 59 func TestProof(t *testing.T) { 60 trie, vals := randomTrie(500) 61 root := trie.Hash() 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 } 75 } 76 } 77 } 78 79 func TestOneElementProof(t *testing.T) { 80 trie := new(Trie) 81 updateString(trie, "k", "v") 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 } 97 } 98 } 99 100 func TestBadProof(t *testing.T) { 101 trie, vals := randomTrie(800) 102 root := trie.Hash() 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) 139 } 140 if val != nil { 141 t.Fatalf("test %d: verified value mismatch: have %x, want nil", i, val) 142 } 143 } 144 } 145 146 // mutateByte changes one byte in b. 147 func mutateByte(b []byte) { 148 for r := mrand.Intn(len(b)); ; { 149 new := byte(mrand.Intn(255)) 150 if new != b[r] { 151 b[r] = new 152 break 153 } 154 } 155 } 156 157 func BenchmarkProve(b *testing.B) { 158 trie, vals := randomTrie(100) 159 var keys []string 160 for k := range vals { 161 keys = append(keys, k) 162 } 163 164 b.ResetTimer() 165 for i := 0; i < b.N; i++ { 166 kv := vals[keys[i%len(keys)]] 167 proofs := ethdb.NewMemDatabase() 168 if trie.Prove(kv.k, 0, proofs); len(proofs.Keys()) == 0 { 169 b.Fatalf("zero length proof for %x", kv.k) 170 } 171 } 172 } 173 174 func BenchmarkVerifyProof(b *testing.B) { 175 trie, vals := randomTrie(100) 176 root := trie.Hash() 177 var keys []string 178 var proofs []*ethdb.MemDatabase 179 for k := range vals { 180 keys = append(keys, k) 181 proof := ethdb.NewMemDatabase() 182 trie.Prove([]byte(k), 0, proof) 183 proofs = append(proofs, proof) 184 } 185 186 b.ResetTimer() 187 for i := 0; i < b.N; i++ { 188 im := i % len(keys) 189 if _, _, err := VerifyProof(root, []byte(keys[im]), proofs[im]); err != nil { 190 b.Fatalf("key %x: %v", keys[im], err) 191 } 192 } 193 } 194 195 func randomTrie(n int) (*Trie, map[string]*kv) { 196 trie := new(Trie) 197 vals := make(map[string]*kv) 198 for i := byte(0); i < 100; i++ { 199 value := &kv{common.LeftPadBytes([]byte{i}, 32), []byte{i}, false} 200 value2 := &kv{common.LeftPadBytes([]byte{i + 10}, 32), []byte{i}, false} 201 trie.Update(value.k, value.v) 202 trie.Update(value2.k, value2.v) 203 vals[string(value.k)] = value 204 vals[string(value2.k)] = value2 205 } 206 for i := 0; i < n; i++ { 207 value := &kv{randBytes(32), randBytes(20), false} 208 trie.Update(value.k, value.v) 209 vals[string(value.k)] = value 210 } 211 return trie, vals 212 } 213 214 func randBytes(n int) []byte { 215 r := make([]byte, n) 216 crand.Read(r) 217 return r 218 }