github.com/carter-ya/go-ethereum@v0.0.0-20230628080049-d2309be3983b/trie/util_test.go (about) 1 // Copyright 2022 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 "testing" 22 23 "github.com/ethereum/go-ethereum/common" 24 "github.com/ethereum/go-ethereum/core/rawdb" 25 ) 26 27 // Tests if the trie diffs are tracked correctly. 28 func TestTrieTracer(t *testing.T) { 29 db := NewDatabase(rawdb.NewMemoryDatabase()) 30 trie := NewEmpty(db) 31 trie.tracer = newTracer() 32 33 // Insert a batch of entries, all the nodes should be marked as inserted 34 vals := []struct{ k, v string }{ 35 {"do", "verb"}, 36 {"ether", "wookiedoo"}, 37 {"horse", "stallion"}, 38 {"shaman", "horse"}, 39 {"doge", "coin"}, 40 {"dog", "puppy"}, 41 {"somethingveryoddindeedthis is", "myothernodedata"}, 42 } 43 for _, val := range vals { 44 trie.Update([]byte(val.k), []byte(val.v)) 45 } 46 trie.Hash() 47 48 seen := make(map[string]struct{}) 49 it := trie.NodeIterator(nil) 50 for it.Next(true) { 51 if it.Leaf() { 52 continue 53 } 54 seen[string(it.Path())] = struct{}{} 55 } 56 inserted := trie.tracer.insertList() 57 if len(inserted) != len(seen) { 58 t.Fatalf("Unexpected inserted node tracked want %d got %d", len(seen), len(inserted)) 59 } 60 for _, k := range inserted { 61 _, ok := seen[string(k)] 62 if !ok { 63 t.Fatalf("Unexpected inserted node") 64 } 65 } 66 deleted := trie.tracer.deleteList() 67 if len(deleted) != 0 { 68 t.Fatalf("Unexpected deleted node tracked %d", len(deleted)) 69 } 70 71 // Commit the changes and re-create with new root 72 root, nodes, _ := trie.Commit(false) 73 if err := db.Update(NewWithNodeSet(nodes)); err != nil { 74 t.Fatal(err) 75 } 76 trie, _ = New(TrieID(root), db) 77 trie.tracer = newTracer() 78 79 // Delete all the elements, check deletion set 80 for _, val := range vals { 81 trie.Delete([]byte(val.k)) 82 } 83 trie.Hash() 84 85 inserted = trie.tracer.insertList() 86 if len(inserted) != 0 { 87 t.Fatalf("Unexpected inserted node tracked %d", len(inserted)) 88 } 89 deleted = trie.tracer.deleteList() 90 if len(deleted) != len(seen) { 91 t.Fatalf("Unexpected deleted node tracked want %d got %d", len(seen), len(deleted)) 92 } 93 for _, k := range deleted { 94 _, ok := seen[string(k)] 95 if !ok { 96 t.Fatalf("Unexpected inserted node") 97 } 98 } 99 } 100 101 func TestTrieTracerNoop(t *testing.T) { 102 trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) 103 trie.tracer = newTracer() 104 105 // Insert a batch of entries, all the nodes should be marked as inserted 106 vals := []struct{ k, v string }{ 107 {"do", "verb"}, 108 {"ether", "wookiedoo"}, 109 {"horse", "stallion"}, 110 {"shaman", "horse"}, 111 {"doge", "coin"}, 112 {"dog", "puppy"}, 113 {"somethingveryoddindeedthis is", "myothernodedata"}, 114 } 115 for _, val := range vals { 116 trie.Update([]byte(val.k), []byte(val.v)) 117 } 118 for _, val := range vals { 119 trie.Delete([]byte(val.k)) 120 } 121 if len(trie.tracer.insertList()) != 0 { 122 t.Fatalf("Unexpected inserted node tracked %d", len(trie.tracer.insertList())) 123 } 124 if len(trie.tracer.deleteList()) != 0 { 125 t.Fatalf("Unexpected deleted node tracked %d", len(trie.tracer.deleteList())) 126 } 127 } 128 129 func TestTrieTracePrevValue(t *testing.T) { 130 db := NewDatabase(rawdb.NewMemoryDatabase()) 131 trie := NewEmpty(db) 132 trie.tracer = newTracer() 133 134 paths, blobs := trie.tracer.prevList() 135 if len(paths) != 0 || len(blobs) != 0 { 136 t.Fatalf("Nothing should be tracked") 137 } 138 // Insert a batch of entries, all the nodes should be marked as inserted 139 vals := []struct{ k, v string }{ 140 {"do", "verb"}, 141 {"ether", "wookiedoo"}, 142 {"horse", "stallion"}, 143 {"shaman", "horse"}, 144 {"doge", "coin"}, 145 {"dog", "puppy"}, 146 {"somethingveryoddindeedthis is", "myothernodedata"}, 147 } 148 for _, val := range vals { 149 trie.Update([]byte(val.k), []byte(val.v)) 150 } 151 paths, blobs = trie.tracer.prevList() 152 if len(paths) != 0 || len(blobs) != 0 { 153 t.Fatalf("Nothing should be tracked") 154 } 155 156 // Commit the changes and re-create with new root 157 root, nodes, _ := trie.Commit(false) 158 if err := db.Update(NewWithNodeSet(nodes)); err != nil { 159 t.Fatal(err) 160 } 161 trie, _ = New(TrieID(root), db) 162 trie.tracer = newTracer() 163 trie.resolveAndTrack(root.Bytes(), nil) 164 165 // Load all nodes in trie 166 for _, val := range vals { 167 trie.TryGet([]byte(val.k)) 168 } 169 170 // Ensure all nodes are tracked by tracer with correct prev-values 171 iter := trie.NodeIterator(nil) 172 seen := make(map[string][]byte) 173 for iter.Next(true) { 174 // Embedded nodes are ignored since they are not present in 175 // database. 176 if iter.Hash() == (common.Hash{}) { 177 continue 178 } 179 seen[string(iter.Path())] = common.CopyBytes(iter.NodeBlob()) 180 } 181 182 paths, blobs = trie.tracer.prevList() 183 if len(paths) != len(seen) || len(blobs) != len(seen) { 184 t.Fatalf("Unexpected tracked values") 185 } 186 for i, path := range paths { 187 blob := blobs[i] 188 prev, ok := seen[string(path)] 189 if !ok { 190 t.Fatalf("Missing node %v", path) 191 } 192 if !bytes.Equal(blob, prev) { 193 t.Fatalf("Unexpected value path: %v, want: %v, got: %v", path, prev, blob) 194 } 195 } 196 197 // Re-open the trie and iterate the trie, ensure nothing will be tracked. 198 // Iterator will not link any loaded nodes to trie. 199 trie, _ = New(TrieID(root), db) 200 trie.tracer = newTracer() 201 202 iter = trie.NodeIterator(nil) 203 for iter.Next(true) { 204 } 205 paths, blobs = trie.tracer.prevList() 206 if len(paths) != 0 || len(blobs) != 0 { 207 t.Fatalf("Nothing should be tracked") 208 } 209 210 // Re-open the trie and generate proof for entries, ensure nothing will 211 // be tracked. Prover will not link any loaded nodes to trie. 212 trie, _ = New(TrieID(root), db) 213 trie.tracer = newTracer() 214 for _, val := range vals { 215 trie.Prove([]byte(val.k), 0, rawdb.NewMemoryDatabase()) 216 } 217 paths, blobs = trie.tracer.prevList() 218 if len(paths) != 0 || len(blobs) != 0 { 219 t.Fatalf("Nothing should be tracked") 220 } 221 222 // Delete entries from trie, ensure all previous values are correct. 223 trie, _ = New(TrieID(root), db) 224 trie.tracer = newTracer() 225 trie.resolveAndTrack(root.Bytes(), nil) 226 227 for _, val := range vals { 228 trie.TryDelete([]byte(val.k)) 229 } 230 paths, blobs = trie.tracer.prevList() 231 if len(paths) != len(seen) || len(blobs) != len(seen) { 232 t.Fatalf("Unexpected tracked values") 233 } 234 for i, path := range paths { 235 blob := blobs[i] 236 prev, ok := seen[string(path)] 237 if !ok { 238 t.Fatalf("Missing node %v", path) 239 } 240 if !bytes.Equal(blob, prev) { 241 t.Fatalf("Unexpected value path: %v, want: %v, got: %v", path, prev, blob) 242 } 243 } 244 }