github.com/chain5j/chain5j-pkg@v1.0.7/collection/trees/tree/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 tree 18 19 import ( 20 "bytes" 21 crand "crypto/rand" 22 mrand "math/rand" 23 "testing" 24 "time" 25 26 "github.com/chain5j/chain5j-pkg/crypto/keccak" 27 "github.com/chain5j/chain5j-pkg/database/kvstore/memorydb" 28 "github.com/chain5j/chain5j-pkg/util/hexutil" 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) *memorydb.Database { 38 var provers []func(key []byte) *memorydb.Database 39 40 // Create a direct trie based Merkle prover 41 provers = append(provers, func(key []byte) *memorydb.Database { 42 proof := memorydb.New() 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) *memorydb.Database { 48 proof := memorydb.New() 49 if it := NewIterator(trie.NodeIterator(key)); it.Next() && bytes.Equal(key, it.Key) { 50 for _, p := range it.Prove() { 51 proof.Put(keccak.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 it := proof.NewIterator() 110 for i, d := 0, mrand.Intn(proof.Len()); i <= d; i++ { 111 it.Next() 112 } 113 key := it.Key() 114 val, _ := proof.Get(key) 115 proof.Delete(key) 116 it.Release() 117 118 mutateByte(val) 119 proof.Put(keccak.Keccak256(val), val) 120 121 if _, _, err := VerifyProof(root, kv.k, proof); err == nil { 122 t.Fatalf("prover %d: expected proof to fail for key %x", i, kv.k) 123 } 124 } 125 } 126 } 127 128 // Tests that missing keys can also be proven. The test explicitly uses a single 129 // entry trie and checks for missing keys both before and after the single entry. 130 func TestMissingKeyProof(t *testing.T) { 131 trie := new(Trie) 132 updateString(trie, "k", "v") 133 134 for i, key := range []string{"a", "j", "l", "z"} { 135 proof := memorydb.New() 136 trie.Prove([]byte(key), 0, proof) 137 138 if proof.Len() != 1 { 139 t.Errorf("test %d: proof should have one element", i) 140 } 141 val, _, err := VerifyProof(trie.Hash(), []byte(key), proof) 142 if err != nil { 143 t.Fatalf("test %d: failed to verify proof: %v\nraw proof: %x", i, err, proof) 144 } 145 if val != nil { 146 t.Fatalf("test %d: verified value mismatch: have %x, want nil", i, val) 147 } 148 } 149 } 150 151 // mutateByte changes one byte in b. 152 func mutateByte(b []byte) { 153 for r := mrand.Intn(len(b)); ; { 154 new := byte(mrand.Intn(255)) 155 if new != b[r] { 156 b[r] = new 157 break 158 } 159 } 160 } 161 162 func BenchmarkProve(b *testing.B) { 163 trie, vals := randomTrie(100) 164 var keys []string 165 for k := range vals { 166 keys = append(keys, k) 167 } 168 169 b.ResetTimer() 170 for i := 0; i < b.N; i++ { 171 kv := vals[keys[i%len(keys)]] 172 proofs := memorydb.New() 173 if trie.Prove(kv.k, 0, proofs); proofs.Len() == 0 { 174 b.Fatalf("zero length proof for %x", kv.k) 175 } 176 } 177 } 178 179 func BenchmarkVerifyProof(b *testing.B) { 180 trie, vals := randomTrie(100) 181 root := trie.Hash() 182 var keys []string 183 var proofs []*memorydb.Database 184 for k := range vals { 185 keys = append(keys, k) 186 proof := memorydb.New() 187 trie.Prove([]byte(k), 0, proof) 188 proofs = append(proofs, proof) 189 } 190 191 b.ResetTimer() 192 for i := 0; i < b.N; i++ { 193 im := i % len(keys) 194 if _, _, err := VerifyProof(root, []byte(keys[im]), proofs[im]); err != nil { 195 b.Fatalf("key %x: %v", keys[im], err) 196 } 197 } 198 } 199 200 func randomTrie(n int) (*Trie, map[string]*kv) { 201 trie := new(Trie) 202 vals := make(map[string]*kv) 203 for i := byte(0); i < 100; i++ { 204 value := &kv{hexutil.LeftPadBytes([]byte{i}, 32), []byte{i}, false} 205 value2 := &kv{hexutil.LeftPadBytes([]byte{i + 10}, 32), []byte{i}, false} 206 trie.Update(value.k, value.v) 207 trie.Update(value2.k, value2.v) 208 vals[string(value.k)] = value 209 vals[string(value2.k)] = value2 210 } 211 for i := 0; i < n; i++ { 212 value := &kv{randBytes(32), randBytes(20), false} 213 trie.Update(value.k, value.v) 214 vals[string(value.k)] = value 215 } 216 return trie, vals 217 } 218 219 func randBytes(n int) []byte { 220 r := make([]byte, n) 221 crand.Read(r) 222 return r 223 }