github.com/r8d8/go-ethereum@v5.5.2+incompatible/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/ethereumproject/go-ethereum/common" 27 "github.com/ethereumproject/go-ethereum/crypto" 28 "github.com/ethereumproject/go-ethereum/ethdb" 29 ) 30 31 func init() { 32 // FIXME: BEWARE 33 mrand.Seed(time.Now().Unix()) 34 } 35 36 func TestProof(t *testing.T) { 37 trie, vals := randomTrie(500) 38 root := trie.Hash() 39 for _, kv := range vals { 40 proofs, _ := ethdb.NewMemDatabase() 41 if trie.Prove(kv.k, 0, proofs) != nil { 42 t.Fatalf("missing key %x while constructing proof", kv.k) 43 } 44 val, err, _ := VerifyProof(root, kv.k, proofs) 45 if err != nil { 46 t.Fatalf("VerifyProof error for key %x: %v\nraw proof: %v", kv.k, err, proofs) 47 } 48 if !bytes.Equal(val, kv.v) { 49 t.Fatalf("VerifyProof returned wrong value for key %x: got %x, want %x", kv.k, val, kv.v) 50 } 51 } 52 } 53 54 func TestOneElementProof(t *testing.T) { 55 trie := new(Trie) 56 updateString(trie, "k", "v") 57 proofs, _ := ethdb.NewMemDatabase() 58 trie.Prove([]byte("k"), 0, proofs) 59 if len(proofs.Keys()) != 1 { 60 t.Error("proof should have one element") 61 } 62 val, err, _ := VerifyProof(trie.Hash(), []byte("k"), proofs) 63 if err != nil { 64 t.Fatalf("VerifyProof error: %v\nproof hashes: %v", err, proofs.Keys()) 65 } 66 if !bytes.Equal(val, []byte("v")) { 67 t.Fatalf("VerifyProof returned wrong value: got %x, want 'k'", val) 68 } 69 } 70 71 func TestVerifyBadProof(t *testing.T) { 72 trie, vals := randomTrie(800) 73 root := trie.Hash() 74 for _, kv := range vals { 75 proofs, _ := ethdb.NewMemDatabase() 76 trie.Prove(kv.k, 0, proofs) 77 if len(proofs.Keys()) == 0 { 78 t.Fatal("zero length proof") 79 } 80 keys := proofs.Keys() 81 key := keys[mrand.Intn(len(keys))] 82 node, _ := proofs.Get(key) 83 proofs.Delete(key) 84 mutateByte(node) 85 proofs.Put(crypto.Keccak256(node), node) 86 if _, err, _ := VerifyProof(root, kv.k, proofs); err == nil { 87 t.Fatalf("expected proof to fail for key %x", kv.k) 88 } 89 } 90 } 91 92 // mutateByte changes one byte in b. 93 func mutateByte(b []byte) { 94 for r := mrand.Intn(len(b)); ; { 95 new := byte(mrand.Intn(255)) 96 if new != b[r] { 97 b[r] = new 98 break 99 } 100 } 101 } 102 103 func BenchmarkProve(b *testing.B) { 104 trie, vals := randomTrie(100) 105 var keys []string 106 for k := range vals { 107 keys = append(keys, k) 108 } 109 110 b.ResetTimer() 111 for i := 0; i < b.N; i++ { 112 kv := vals[keys[i%len(keys)]] 113 proofs, _ := ethdb.NewMemDatabase() 114 if trie.Prove(kv.k, 0, proofs); len(proofs.Keys()) == 0 { 115 b.Fatalf("zero length proof for %x", kv.k) 116 } 117 } 118 } 119 120 func BenchmarkVerifyProof(b *testing.B) { 121 trie, vals := randomTrie(100) 122 root := trie.Hash() 123 var keys []string 124 var proofs []*ethdb.MemDatabase 125 for k := range vals { 126 keys = append(keys, k) 127 proof, _ := ethdb.NewMemDatabase() 128 trie.Prove([]byte(k), 0, proof) 129 proofs = append(proofs, proof) 130 } 131 132 b.ResetTimer() 133 for i := 0; i < b.N; i++ { 134 im := i % len(keys) 135 if _, err, _ := VerifyProof(root, []byte(keys[im]), proofs[im]); err != nil { 136 b.Fatalf("key %x: %v", keys[im], err) 137 } 138 } 139 } 140 141 func randomTrie(n int) (*Trie, map[string]*kv) { 142 trie := new(Trie) 143 vals := make(map[string]*kv) 144 for i := byte(0); i < 100; i++ { 145 value := &kv{common.LeftPadBytes([]byte{i}, 32), []byte{i}, false} 146 value2 := &kv{common.LeftPadBytes([]byte{i + 10}, 32), []byte{i}, false} 147 trie.Update(value.k, value.v) 148 trie.Update(value2.k, value2.v) 149 vals[string(value.k)] = value 150 vals[string(value2.k)] = value2 151 } 152 for i := 0; i < n; i++ { 153 value := &kv{randBytes(32), randBytes(20), false} 154 trie.Update(value.k, value.v) 155 vals[string(value.k)] = value 156 } 157 return trie, vals 158 } 159 160 func randBytes(n int) []byte { 161 r := make([]byte, n) 162 crand.Read(r) 163 return r 164 }