github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/trie/trie_test.go (about) 1 // Copyright 2014 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 "encoding/binary" 22 "errors" 23 "fmt" 24 "hash" 25 "io" 26 "math/rand" 27 "reflect" 28 "sort" 29 "testing" 30 "testing/quick" 31 32 "github.com/davecgh/go-spew/spew" 33 "github.com/ethereum/go-ethereum/common" 34 "github.com/ethereum/go-ethereum/core/rawdb" 35 "github.com/ethereum/go-ethereum/core/types" 36 "github.com/ethereum/go-ethereum/crypto" 37 "github.com/ethereum/go-ethereum/ethdb" 38 "github.com/ethereum/go-ethereum/rlp" 39 "github.com/ethereum/go-ethereum/trie/trienode" 40 "github.com/holiman/uint256" 41 "golang.org/x/crypto/sha3" 42 ) 43 44 func init() { 45 spew.Config.Indent = " " 46 spew.Config.DisableMethods = false 47 } 48 49 func TestEmptyTrie(t *testing.T) { 50 trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) 51 res := trie.Hash() 52 exp := types.EmptyRootHash 53 if res != exp { 54 t.Errorf("expected %x got %x", exp, res) 55 } 56 } 57 58 func TestNull(t *testing.T) { 59 trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) 60 key := make([]byte, 32) 61 value := []byte("test") 62 trie.MustUpdate(key, value) 63 if !bytes.Equal(trie.MustGet(key), value) { 64 t.Fatal("wrong value") 65 } 66 } 67 68 func TestMissingRoot(t *testing.T) { 69 testMissingRoot(t, rawdb.HashScheme) 70 testMissingRoot(t, rawdb.PathScheme) 71 } 72 73 func testMissingRoot(t *testing.T, scheme string) { 74 root := common.HexToHash("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33") 75 trie, err := New(TrieID(root), newTestDatabase(rawdb.NewMemoryDatabase(), scheme)) 76 if trie != nil { 77 t.Error("New returned non-nil trie for invalid root") 78 } 79 if _, ok := err.(*MissingNodeError); !ok { 80 t.Errorf("New returned wrong error: %v", err) 81 } 82 } 83 84 func TestMissingNode(t *testing.T) { 85 testMissingNode(t, false, rawdb.HashScheme) 86 testMissingNode(t, false, rawdb.PathScheme) 87 testMissingNode(t, true, rawdb.HashScheme) 88 testMissingNode(t, true, rawdb.PathScheme) 89 } 90 91 func testMissingNode(t *testing.T, memonly bool, scheme string) { 92 diskdb := rawdb.NewMemoryDatabase() 93 triedb := newTestDatabase(diskdb, scheme) 94 95 trie := NewEmpty(triedb) 96 updateString(trie, "120000", "qwerqwerqwerqwerqwerqwerqwerqwer") 97 updateString(trie, "123456", "asdfasdfasdfasdfasdfasdfasdfasdf") 98 root, nodes, _ := trie.Commit(false) 99 triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) 100 101 if !memonly { 102 triedb.Commit(root) 103 } 104 105 trie, _ = New(TrieID(root), triedb) 106 _, err := trie.Get([]byte("120000")) 107 if err != nil { 108 t.Errorf("Unexpected error: %v", err) 109 } 110 trie, _ = New(TrieID(root), triedb) 111 _, err = trie.Get([]byte("120099")) 112 if err != nil { 113 t.Errorf("Unexpected error: %v", err) 114 } 115 trie, _ = New(TrieID(root), triedb) 116 _, err = trie.Get([]byte("123456")) 117 if err != nil { 118 t.Errorf("Unexpected error: %v", err) 119 } 120 trie, _ = New(TrieID(root), triedb) 121 err = trie.Update([]byte("120099"), []byte("zxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcv")) 122 if err != nil { 123 t.Errorf("Unexpected error: %v", err) 124 } 125 trie, _ = New(TrieID(root), triedb) 126 err = trie.Delete([]byte("123456")) 127 if err != nil { 128 t.Errorf("Unexpected error: %v", err) 129 } 130 131 var ( 132 path []byte 133 hash = common.HexToHash("0xe1d943cc8f061a0c0b98162830b970395ac9315654824bf21b73b891365262f9") 134 ) 135 for p, n := range nodes.Nodes { 136 if n.Hash == hash { 137 path = common.CopyBytes([]byte(p)) 138 break 139 } 140 } 141 trie, _ = New(TrieID(root), triedb) 142 if memonly { 143 trie.reader.banned = map[string]struct{}{string(path): {}} 144 } else { 145 rawdb.DeleteTrieNode(diskdb, common.Hash{}, path, hash, scheme) 146 } 147 148 _, err = trie.Get([]byte("120000")) 149 if _, ok := err.(*MissingNodeError); !ok { 150 t.Errorf("Wrong error: %v", err) 151 } 152 _, err = trie.Get([]byte("120099")) 153 if _, ok := err.(*MissingNodeError); !ok { 154 t.Errorf("Wrong error: %v", err) 155 } 156 _, err = trie.Get([]byte("123456")) 157 if err != nil { 158 t.Errorf("Unexpected error: %v", err) 159 } 160 err = trie.Update([]byte("120099"), []byte("zxcv")) 161 if _, ok := err.(*MissingNodeError); !ok { 162 t.Errorf("Wrong error: %v", err) 163 } 164 err = trie.Delete([]byte("123456")) 165 if _, ok := err.(*MissingNodeError); !ok { 166 t.Errorf("Wrong error: %v", err) 167 } 168 } 169 170 func TestInsert(t *testing.T) { 171 trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) 172 173 updateString(trie, "doe", "reindeer") 174 updateString(trie, "dog", "puppy") 175 updateString(trie, "dogglesworth", "cat") 176 177 exp := common.HexToHash("8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3") 178 root := trie.Hash() 179 if root != exp { 180 t.Errorf("case 1: exp %x got %x", exp, root) 181 } 182 183 trie = NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) 184 updateString(trie, "A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") 185 186 exp = common.HexToHash("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab") 187 root, _, _ = trie.Commit(false) 188 if root != exp { 189 t.Errorf("case 2: exp %x got %x", exp, root) 190 } 191 } 192 193 func TestGet(t *testing.T) { 194 db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme) 195 trie := NewEmpty(db) 196 updateString(trie, "doe", "reindeer") 197 updateString(trie, "dog", "puppy") 198 updateString(trie, "dogglesworth", "cat") 199 200 for i := 0; i < 2; i++ { 201 res := getString(trie, "dog") 202 if !bytes.Equal(res, []byte("puppy")) { 203 t.Errorf("expected puppy got %x", res) 204 } 205 unknown := getString(trie, "unknown") 206 if unknown != nil { 207 t.Errorf("expected nil got %x", unknown) 208 } 209 if i == 1 { 210 return 211 } 212 root, nodes, _ := trie.Commit(false) 213 db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) 214 trie, _ = New(TrieID(root), db) 215 } 216 } 217 218 func TestDelete(t *testing.T) { 219 db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme) 220 trie := NewEmpty(db) 221 vals := []struct{ k, v string }{ 222 {"do", "verb"}, 223 {"ether", "wookiedoo"}, 224 {"horse", "stallion"}, 225 {"shaman", "horse"}, 226 {"doge", "coin"}, 227 {"ether", ""}, 228 {"dog", "puppy"}, 229 {"shaman", ""}, 230 } 231 for _, val := range vals { 232 if val.v != "" { 233 updateString(trie, val.k, val.v) 234 } else { 235 deleteString(trie, val.k) 236 } 237 } 238 239 hash := trie.Hash() 240 exp := common.HexToHash("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84") 241 if hash != exp { 242 t.Errorf("expected %x got %x", exp, hash) 243 } 244 } 245 246 func TestEmptyValues(t *testing.T) { 247 trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) 248 249 vals := []struct{ k, v string }{ 250 {"do", "verb"}, 251 {"ether", "wookiedoo"}, 252 {"horse", "stallion"}, 253 {"shaman", "horse"}, 254 {"doge", "coin"}, 255 {"ether", ""}, 256 {"dog", "puppy"}, 257 {"shaman", ""}, 258 } 259 for _, val := range vals { 260 updateString(trie, val.k, val.v) 261 } 262 263 hash := trie.Hash() 264 exp := common.HexToHash("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84") 265 if hash != exp { 266 t.Errorf("expected %x got %x", exp, hash) 267 } 268 } 269 270 func TestReplication(t *testing.T) { 271 db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme) 272 trie := NewEmpty(db) 273 vals := []struct{ k, v string }{ 274 {"do", "verb"}, 275 {"ether", "wookiedoo"}, 276 {"horse", "stallion"}, 277 {"shaman", "horse"}, 278 {"doge", "coin"}, 279 {"dog", "puppy"}, 280 {"somethingveryoddindeedthis is", "myothernodedata"}, 281 } 282 for _, val := range vals { 283 updateString(trie, val.k, val.v) 284 } 285 root, nodes, _ := trie.Commit(false) 286 db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) 287 288 // create a new trie on top of the database and check that lookups work. 289 trie2, err := New(TrieID(root), db) 290 if err != nil { 291 t.Fatalf("can't recreate trie at %x: %v", root, err) 292 } 293 for _, kv := range vals { 294 if string(getString(trie2, kv.k)) != kv.v { 295 t.Errorf("trie2 doesn't have %q => %q", kv.k, kv.v) 296 } 297 } 298 hash, nodes, _ := trie2.Commit(false) 299 if hash != root { 300 t.Errorf("root failure. expected %x got %x", root, hash) 301 } 302 303 // recreate the trie after commit 304 if nodes != nil { 305 db.Update(hash, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) 306 } 307 trie2, err = New(TrieID(hash), db) 308 if err != nil { 309 t.Fatalf("can't recreate trie at %x: %v", hash, err) 310 } 311 // perform some insertions on the new trie. 312 vals2 := []struct{ k, v string }{ 313 {"do", "verb"}, 314 {"ether", "wookiedoo"}, 315 {"horse", "stallion"}, 316 // {"shaman", "horse"}, 317 // {"doge", "coin"}, 318 // {"ether", ""}, 319 // {"dog", "puppy"}, 320 // {"somethingveryoddindeedthis is", "myothernodedata"}, 321 // {"shaman", ""}, 322 } 323 for _, val := range vals2 { 324 updateString(trie2, val.k, val.v) 325 } 326 if trie2.Hash() != hash { 327 t.Errorf("root failure. expected %x got %x", hash, hash) 328 } 329 } 330 331 func TestLargeValue(t *testing.T) { 332 trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) 333 trie.MustUpdate([]byte("key1"), []byte{99, 99, 99, 99}) 334 trie.MustUpdate([]byte("key2"), bytes.Repeat([]byte{1}, 32)) 335 trie.Hash() 336 } 337 338 // TestRandomCases tests some cases that were found via random fuzzing 339 func TestRandomCases(t *testing.T) { 340 var rt = []randTestStep{ 341 {op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 0 342 {op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 1 343 {op: 0, key: common.Hex2Bytes("d51b182b95d677e5f1c82508c0228de96b73092d78ce78b2230cd948674f66fd1483bd"), value: common.Hex2Bytes("0000000000000002")}, // step 2 344 {op: 2, key: common.Hex2Bytes("c2a38512b83107d665c65235b0250002882ac2022eb00711552354832c5f1d030d0e408e"), value: common.Hex2Bytes("")}, // step 3 345 {op: 3, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 4 346 {op: 3, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 5 347 {op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 6 348 {op: 3, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 7 349 {op: 0, key: common.Hex2Bytes("c2a38512b83107d665c65235b0250002882ac2022eb00711552354832c5f1d030d0e408e"), value: common.Hex2Bytes("0000000000000008")}, // step 8 350 {op: 0, key: common.Hex2Bytes("d51b182b95d677e5f1c82508c0228de96b73092d78ce78b2230cd948674f66fd1483bd"), value: common.Hex2Bytes("0000000000000009")}, // step 9 351 {op: 2, key: common.Hex2Bytes("fd"), value: common.Hex2Bytes("")}, // step 10 352 {op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 11 353 {op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 12 354 {op: 0, key: common.Hex2Bytes("fd"), value: common.Hex2Bytes("000000000000000d")}, // step 13 355 {op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 14 356 {op: 1, key: common.Hex2Bytes("c2a38512b83107d665c65235b0250002882ac2022eb00711552354832c5f1d030d0e408e"), value: common.Hex2Bytes("")}, // step 15 357 {op: 3, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 16 358 {op: 0, key: common.Hex2Bytes("c2a38512b83107d665c65235b0250002882ac2022eb00711552354832c5f1d030d0e408e"), value: common.Hex2Bytes("0000000000000011")}, // step 17 359 {op: 5, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 18 360 {op: 3, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 19 361 {op: 0, key: common.Hex2Bytes("d51b182b95d677e5f1c82508c0228de96b73092d78ce78b2230cd948674f66fd1483bd"), value: common.Hex2Bytes("0000000000000014")}, // step 20 362 {op: 0, key: common.Hex2Bytes("d51b182b95d677e5f1c82508c0228de96b73092d78ce78b2230cd948674f66fd1483bd"), value: common.Hex2Bytes("0000000000000015")}, // step 21 363 {op: 0, key: common.Hex2Bytes("c2a38512b83107d665c65235b0250002882ac2022eb00711552354832c5f1d030d0e408e"), value: common.Hex2Bytes("0000000000000016")}, // step 22 364 {op: 5, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 23 365 {op: 1, key: common.Hex2Bytes("980c393656413a15c8da01978ed9f89feb80b502f58f2d640e3a2f5f7a99a7018f1b573befd92053ac6f78fca4a87268"), value: common.Hex2Bytes("")}, // step 24 366 {op: 1, key: common.Hex2Bytes("fd"), value: common.Hex2Bytes("")}, // step 25 367 } 368 if err := runRandTest(rt); err != nil { 369 t.Fatal(err) 370 } 371 } 372 373 // randTest performs random trie operations. 374 // Instances of this test are created by Generate. 375 type randTest []randTestStep 376 377 // compile-time interface check 378 var _ quick.Generator = (randTest)(nil) 379 380 type randTestStep struct { 381 op int 382 key []byte // for opUpdate, opDelete, opGet 383 value []byte // for opUpdate 384 err error // for debugging 385 } 386 387 const ( 388 opUpdate = iota 389 opDelete 390 opGet 391 opHash 392 opCommit 393 opItercheckhash 394 opNodeDiff 395 opProve 396 opMax // boundary value, not an actual op 397 ) 398 399 func (randTest) Generate(r *rand.Rand, size int) reflect.Value { 400 var finishedFn = func() bool { 401 size-- 402 return size == 0 403 } 404 return reflect.ValueOf(generateSteps(finishedFn, r)) 405 } 406 407 func generateSteps(finished func() bool, r io.Reader) randTest { 408 var allKeys [][]byte 409 var one = []byte{0} 410 genKey := func() []byte { 411 r.Read(one) 412 if len(allKeys) < 2 || one[0]%100 > 90 { 413 // new key 414 size := one[0] % 50 415 key := make([]byte, size) 416 r.Read(key) 417 allKeys = append(allKeys, key) 418 return key 419 } 420 // use existing key 421 idx := int(one[0]) % len(allKeys) 422 return allKeys[idx] 423 } 424 var steps randTest 425 for !finished() { 426 r.Read(one) 427 step := randTestStep{op: int(one[0]) % opMax} 428 switch step.op { 429 case opUpdate: 430 step.key = genKey() 431 step.value = make([]byte, 8) 432 binary.BigEndian.PutUint64(step.value, uint64(len(steps))) 433 case opGet, opDelete, opProve: 434 step.key = genKey() 435 } 436 steps = append(steps, step) 437 } 438 return steps 439 } 440 441 func verifyAccessList(old *Trie, new *Trie, set *trienode.NodeSet) error { 442 deletes, inserts, updates := diffTries(old, new) 443 444 // Check insertion set 445 for path := range inserts { 446 n, ok := set.Nodes[path] 447 if !ok || n.IsDeleted() { 448 return errors.New("expect new node") 449 } 450 //if len(n.Prev) > 0 { 451 // return errors.New("unexpected origin value") 452 //} 453 } 454 // Check deletion set 455 for path := range deletes { 456 n, ok := set.Nodes[path] 457 if !ok || !n.IsDeleted() { 458 return errors.New("expect deleted node") 459 } 460 //if len(n.Prev) == 0 { 461 // return errors.New("expect origin value") 462 //} 463 //if !bytes.Equal(n.Prev, blob) { 464 // return errors.New("invalid origin value") 465 //} 466 } 467 // Check update set 468 for path := range updates { 469 n, ok := set.Nodes[path] 470 if !ok || n.IsDeleted() { 471 return errors.New("expect updated node") 472 } 473 //if len(n.Prev) == 0 { 474 // return errors.New("expect origin value") 475 //} 476 //if !bytes.Equal(n.Prev, blob) { 477 // return errors.New("invalid origin value") 478 //} 479 } 480 return nil 481 } 482 483 // runRandTestBool coerces error to boolean, for use in quick.Check 484 func runRandTestBool(rt randTest) bool { 485 return runRandTest(rt) == nil 486 } 487 488 func runRandTest(rt randTest) error { 489 var scheme = rawdb.HashScheme 490 if rand.Intn(2) == 0 { 491 scheme = rawdb.PathScheme 492 } 493 var ( 494 origin = types.EmptyRootHash 495 triedb = newTestDatabase(rawdb.NewMemoryDatabase(), scheme) 496 tr = NewEmpty(triedb) 497 values = make(map[string]string) // tracks content of the trie 498 origTrie = NewEmpty(triedb) 499 ) 500 for i, step := range rt { 501 // fmt.Printf("{op: %d, key: common.Hex2Bytes(\"%x\"), value: common.Hex2Bytes(\"%x\")}, // step %d\n", 502 // step.op, step.key, step.value, i) 503 504 switch step.op { 505 case opUpdate: 506 tr.MustUpdate(step.key, step.value) 507 values[string(step.key)] = string(step.value) 508 case opDelete: 509 tr.MustDelete(step.key) 510 delete(values, string(step.key)) 511 case opGet: 512 v := tr.MustGet(step.key) 513 want := values[string(step.key)] 514 if string(v) != want { 515 rt[i].err = fmt.Errorf("mismatch for key %#x, got %#x want %#x", step.key, v, want) 516 } 517 case opProve: 518 hash := tr.Hash() 519 if hash == types.EmptyRootHash { 520 continue 521 } 522 proofDb := rawdb.NewMemoryDatabase() 523 err := tr.Prove(step.key, proofDb) 524 if err != nil { 525 rt[i].err = fmt.Errorf("failed for proving key %#x, %v", step.key, err) 526 } 527 _, err = VerifyProof(hash, step.key, proofDb) 528 if err != nil { 529 rt[i].err = fmt.Errorf("failed for verifying key %#x, %v", step.key, err) 530 } 531 case opHash: 532 tr.Hash() 533 case opCommit: 534 root, nodes, _ := tr.Commit(true) 535 if nodes != nil { 536 triedb.Update(root, origin, trienode.NewWithNodeSet(nodes)) 537 } 538 newtr, err := New(TrieID(root), triedb) 539 if err != nil { 540 rt[i].err = err 541 return err 542 } 543 if nodes != nil { 544 if err := verifyAccessList(origTrie, newtr, nodes); err != nil { 545 rt[i].err = err 546 return err 547 } 548 } 549 tr = newtr 550 origTrie = tr.Copy() 551 origin = root 552 case opItercheckhash: 553 checktr := NewEmpty(triedb) 554 it := NewIterator(tr.MustNodeIterator(nil)) 555 for it.Next() { 556 checktr.MustUpdate(it.Key, it.Value) 557 } 558 if tr.Hash() != checktr.Hash() { 559 rt[i].err = errors.New("hash mismatch in opItercheckhash") 560 } 561 case opNodeDiff: 562 var ( 563 origIter = origTrie.MustNodeIterator(nil) 564 curIter = tr.MustNodeIterator(nil) 565 origSeen = make(map[string]struct{}) 566 curSeen = make(map[string]struct{}) 567 ) 568 for origIter.Next(true) { 569 if origIter.Leaf() { 570 continue 571 } 572 origSeen[string(origIter.Path())] = struct{}{} 573 } 574 for curIter.Next(true) { 575 if curIter.Leaf() { 576 continue 577 } 578 curSeen[string(curIter.Path())] = struct{}{} 579 } 580 var ( 581 insertExp = make(map[string]struct{}) 582 deleteExp = make(map[string]struct{}) 583 ) 584 for path := range curSeen { 585 _, present := origSeen[path] 586 if !present { 587 insertExp[path] = struct{}{} 588 } 589 } 590 for path := range origSeen { 591 _, present := curSeen[path] 592 if !present { 593 deleteExp[path] = struct{}{} 594 } 595 } 596 if len(insertExp) != len(tr.tracer.inserts) { 597 rt[i].err = errors.New("insert set mismatch") 598 } 599 if len(deleteExp) != len(tr.tracer.deletes) { 600 rt[i].err = errors.New("delete set mismatch") 601 } 602 for insert := range tr.tracer.inserts { 603 if _, present := insertExp[insert]; !present { 604 rt[i].err = errors.New("missing inserted node") 605 } 606 } 607 for del := range tr.tracer.deletes { 608 if _, present := deleteExp[del]; !present { 609 rt[i].err = errors.New("missing deleted node") 610 } 611 } 612 } 613 // Abort the test on error. 614 if rt[i].err != nil { 615 return rt[i].err 616 } 617 } 618 return nil 619 } 620 621 func TestRandom(t *testing.T) { 622 if err := quick.Check(runRandTestBool, nil); err != nil { 623 if cerr, ok := err.(*quick.CheckError); ok { 624 t.Fatalf("random test iteration %d failed: %s", cerr.Count, spew.Sdump(cerr.In)) 625 } 626 t.Fatal(err) 627 } 628 } 629 630 func BenchmarkGet(b *testing.B) { benchGet(b) } 631 func BenchmarkUpdateBE(b *testing.B) { benchUpdate(b, binary.BigEndian) } 632 func BenchmarkUpdateLE(b *testing.B) { benchUpdate(b, binary.LittleEndian) } 633 634 const benchElemCount = 20000 635 636 func benchGet(b *testing.B) { 637 triedb := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme) 638 trie := NewEmpty(triedb) 639 k := make([]byte, 32) 640 for i := 0; i < benchElemCount; i++ { 641 binary.LittleEndian.PutUint64(k, uint64(i)) 642 v := make([]byte, 32) 643 binary.LittleEndian.PutUint64(v, uint64(i)) 644 trie.MustUpdate(k, v) 645 } 646 binary.LittleEndian.PutUint64(k, benchElemCount/2) 647 648 b.ResetTimer() 649 for i := 0; i < b.N; i++ { 650 trie.MustGet(k) 651 } 652 b.StopTimer() 653 } 654 655 func benchUpdate(b *testing.B, e binary.ByteOrder) *Trie { 656 trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) 657 k := make([]byte, 32) 658 b.ReportAllocs() 659 for i := 0; i < b.N; i++ { 660 v := make([]byte, 32) 661 e.PutUint64(k, uint64(i)) 662 e.PutUint64(v, uint64(i)) 663 trie.MustUpdate(k, v) 664 } 665 return trie 666 } 667 668 // Benchmarks the trie hashing. Since the trie caches the result of any operation, 669 // we cannot use b.N as the number of hashing rounds, since all rounds apart from 670 // the first one will be NOOP. As such, we'll use b.N as the number of account to 671 // insert into the trie before measuring the hashing. 672 // BenchmarkHash-6 288680 4561 ns/op 682 B/op 9 allocs/op 673 // BenchmarkHash-6 275095 4800 ns/op 685 B/op 9 allocs/op 674 // pure hasher: 675 // BenchmarkHash-6 319362 4230 ns/op 675 B/op 9 allocs/op 676 // BenchmarkHash-6 257460 4674 ns/op 689 B/op 9 allocs/op 677 // With hashing in-between and pure hasher: 678 // BenchmarkHash-6 225417 7150 ns/op 982 B/op 12 allocs/op 679 // BenchmarkHash-6 220378 6197 ns/op 983 B/op 12 allocs/op 680 // same with old hasher 681 // BenchmarkHash-6 229758 6437 ns/op 981 B/op 12 allocs/op 682 // BenchmarkHash-6 212610 7137 ns/op 986 B/op 12 allocs/op 683 func BenchmarkHash(b *testing.B) { 684 // Create a realistic account trie to hash. We're first adding and hashing N 685 // entries, then adding N more. 686 addresses, accounts := makeAccounts(2 * b.N) 687 // Insert the accounts into the trie and hash it 688 trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) 689 i := 0 690 for ; i < len(addresses)/2; i++ { 691 trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) 692 } 693 trie.Hash() 694 for ; i < len(addresses); i++ { 695 trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) 696 } 697 b.ResetTimer() 698 b.ReportAllocs() 699 //trie.hashRoot(nil, nil) 700 trie.Hash() 701 } 702 703 // Benchmarks the trie Commit following a Hash. Since the trie caches the result of any operation, 704 // we cannot use b.N as the number of hashing rounds, since all rounds apart from 705 // the first one will be NOOP. As such, we'll use b.N as the number of account to 706 // insert into the trie before measuring the hashing. 707 func BenchmarkCommitAfterHash(b *testing.B) { 708 b.Run("no-onleaf", func(b *testing.B) { 709 benchmarkCommitAfterHash(b, false) 710 }) 711 b.Run("with-onleaf", func(b *testing.B) { 712 benchmarkCommitAfterHash(b, true) 713 }) 714 } 715 716 func benchmarkCommitAfterHash(b *testing.B, collectLeaf bool) { 717 // Make the random benchmark deterministic 718 addresses, accounts := makeAccounts(b.N) 719 trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) 720 for i := 0; i < len(addresses); i++ { 721 trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) 722 } 723 // Insert the accounts into the trie and hash it 724 trie.Hash() 725 b.ResetTimer() 726 b.ReportAllocs() 727 trie.Commit(collectLeaf) 728 } 729 730 func TestTinyTrie(t *testing.T) { 731 // Create a realistic account trie to hash 732 _, accounts := makeAccounts(5) 733 trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) 734 trie.MustUpdate(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001337"), accounts[3]) 735 if exp, root := common.HexToHash("8c6a85a4d9fda98feff88450299e574e5378e32391f75a055d470ac0653f1005"), trie.Hash(); exp != root { 736 t.Errorf("1: got %x, exp %x", root, exp) 737 } 738 trie.MustUpdate(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001338"), accounts[4]) 739 if exp, root := common.HexToHash("ec63b967e98a5720e7f720482151963982890d82c9093c0d486b7eb8883a66b1"), trie.Hash(); exp != root { 740 t.Errorf("2: got %x, exp %x", root, exp) 741 } 742 trie.MustUpdate(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001339"), accounts[4]) 743 if exp, root := common.HexToHash("0608c1d1dc3905fa22204c7a0e43644831c3b6d3def0f274be623a948197e64a"), trie.Hash(); exp != root { 744 t.Errorf("3: got %x, exp %x", root, exp) 745 } 746 checktr := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) 747 it := NewIterator(trie.MustNodeIterator(nil)) 748 for it.Next() { 749 checktr.MustUpdate(it.Key, it.Value) 750 } 751 if troot, itroot := trie.Hash(), checktr.Hash(); troot != itroot { 752 t.Fatalf("hash mismatch in opItercheckhash, trie: %x, check: %x", troot, itroot) 753 } 754 } 755 756 func TestCommitAfterHash(t *testing.T) { 757 // Create a realistic account trie to hash 758 addresses, accounts := makeAccounts(1000) 759 trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) 760 for i := 0; i < len(addresses); i++ { 761 trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) 762 } 763 // Insert the accounts into the trie and hash it 764 trie.Hash() 765 trie.Commit(false) 766 root := trie.Hash() 767 exp := common.HexToHash("72f9d3f3fe1e1dd7b8936442e7642aef76371472d94319900790053c493f3fe6") 768 if exp != root { 769 t.Errorf("got %x, exp %x", root, exp) 770 } 771 root, _, _ = trie.Commit(false) 772 if exp != root { 773 t.Errorf("got %x, exp %x", root, exp) 774 } 775 } 776 777 func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) { 778 // Make the random benchmark deterministic 779 random := rand.New(rand.NewSource(0)) 780 // Create a realistic account trie to hash 781 addresses = make([][20]byte, size) 782 for i := 0; i < len(addresses); i++ { 783 data := make([]byte, 20) 784 random.Read(data) 785 copy(addresses[i][:], data) 786 } 787 accounts = make([][]byte, len(addresses)) 788 for i := 0; i < len(accounts); i++ { 789 var ( 790 nonce = uint64(random.Int63()) 791 root = types.EmptyRootHash 792 code = crypto.Keccak256(nil) 793 ) 794 // The big.Rand function is not deterministic with regards to 64 vs 32 bit systems, 795 // and will consume different amount of data from the rand source. 796 //balance = new(big.Int).Rand(random, new(big.Int).Exp(common.Big2, common.Big256, nil)) 797 // Therefore, we instead just read via byte buffer 798 numBytes := random.Uint32() % 33 // [0, 32] bytes 799 balanceBytes := make([]byte, numBytes) 800 random.Read(balanceBytes) 801 balance := new(uint256.Int).SetBytes(balanceBytes) 802 data, _ := rlp.EncodeToBytes(&types.StateAccount{Nonce: nonce, Balance: balance, Root: root, CodeHash: code}) 803 accounts[i] = data 804 } 805 return addresses, accounts 806 } 807 808 // spongeDb is a dummy db backend which accumulates writes in a sponge 809 type spongeDb struct { 810 sponge hash.Hash 811 id string 812 journal []string 813 keys []string 814 values map[string]string 815 } 816 817 func (s *spongeDb) Has(key []byte) (bool, error) { panic("implement me") } 818 func (s *spongeDb) Get(key []byte) ([]byte, error) { return nil, errors.New("no such elem") } 819 func (s *spongeDb) Delete(key []byte) error { panic("implement me") } 820 func (s *spongeDb) NewBatch() ethdb.Batch { return &spongeBatch{s} } 821 func (s *spongeDb) NewBatchWithSize(size int) ethdb.Batch { return &spongeBatch{s} } 822 func (s *spongeDb) NewSnapshot() (ethdb.Snapshot, error) { panic("implement me") } 823 func (s *spongeDb) Stat(property string) (string, error) { panic("implement me") } 824 func (s *spongeDb) Compact(start []byte, limit []byte) error { panic("implement me") } 825 func (s *spongeDb) Close() error { return nil } 826 func (s *spongeDb) Put(key []byte, value []byte) error { 827 var ( 828 keybrief = key 829 valbrief = value 830 ) 831 if len(keybrief) > 8 { 832 keybrief = keybrief[:8] 833 } 834 if len(valbrief) > 8 { 835 valbrief = valbrief[:8] 836 } 837 s.journal = append(s.journal, fmt.Sprintf("%v: PUT([%x...], [%d bytes] %x...)\n", s.id, keybrief, len(value), valbrief)) 838 839 if s.values == nil { 840 s.sponge.Write(key) 841 s.sponge.Write(value) 842 } else { 843 s.keys = append(s.keys, string(key)) 844 s.values[string(key)] = string(value) 845 } 846 return nil 847 } 848 func (s *spongeDb) NewIterator(prefix []byte, start []byte) ethdb.Iterator { panic("implement me") } 849 850 func (s *spongeDb) Flush() { 851 // Bottom-up, the longest path first 852 sort.Sort(sort.Reverse(sort.StringSlice(s.keys))) 853 for _, key := range s.keys { 854 s.sponge.Write([]byte(key)) 855 s.sponge.Write([]byte(s.values[key])) 856 } 857 } 858 859 // spongeBatch is a dummy batch which immediately writes to the underlying spongedb 860 type spongeBatch struct { 861 db *spongeDb 862 } 863 864 func (b *spongeBatch) Put(key, value []byte) error { 865 b.db.Put(key, value) 866 return nil 867 } 868 func (b *spongeBatch) Delete(key []byte) error { panic("implement me") } 869 func (b *spongeBatch) ValueSize() int { return 100 } 870 func (b *spongeBatch) Write() error { return nil } 871 func (b *spongeBatch) Reset() {} 872 func (b *spongeBatch) Replay(w ethdb.KeyValueWriter) error { return nil } 873 874 // TestCommitSequence tests that the trie.Commit operation writes the elements of the trie 875 // in the expected order. 876 // The test data was based on the 'master' code, and is basically random. It can be used 877 // to check whether changes to the trie modifies the write order or data in any way. 878 func TestCommitSequence(t *testing.T) { 879 for i, tc := range []struct { 880 count int 881 expWriteSeqHash []byte 882 }{ 883 {20, common.FromHex("330b0afae2853d96b9f015791fbe0fb7f239bf65f335f16dfc04b76c7536276d")}, 884 {200, common.FromHex("5162b3735c06b5d606b043a3ee8adbdbbb408543f4966bca9dcc63da82684eeb")}, 885 {2000, common.FromHex("4574cd8e6b17f3fe8ad89140d1d0bf4f1bd7a87a8ac3fb623b33550544c77635")}, 886 } { 887 addresses, accounts := makeAccounts(tc.count) 888 // This spongeDb is used to check the sequence of disk-db-writes 889 s := &spongeDb{sponge: crypto.NewKeccakState()} 890 db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme) 891 trie := NewEmpty(db) 892 // Fill the trie with elements 893 for i := 0; i < tc.count; i++ { 894 trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) 895 } 896 // Flush trie -> database 897 root, nodes, _ := trie.Commit(false) 898 db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) 899 // Flush memdb -> disk (sponge) 900 db.Commit(root) 901 if got, exp := s.sponge.Sum(nil), tc.expWriteSeqHash; !bytes.Equal(got, exp) { 902 t.Errorf("test %d, disk write sequence wrong:\ngot %x exp %x\n", i, got, exp) 903 } 904 } 905 } 906 907 // TestCommitSequenceRandomBlobs is identical to TestCommitSequence 908 // but uses random blobs instead of 'accounts' 909 func TestCommitSequenceRandomBlobs(t *testing.T) { 910 for i, tc := range []struct { 911 count int 912 expWriteSeqHash []byte 913 }{ 914 {20, common.FromHex("8016650c7a50cf88485fd06cde52d634a89711051107f00d21fae98234f2f13d")}, 915 {200, common.FromHex("dde92ca9812e068e6982d04b40846dc65a61a9fd4996fc0f55f2fde172a8e13c")}, 916 {2000, common.FromHex("ab553a7f9aff82e3929c382908e30ef7dd17a332933e92ba3fe873fc661ef382")}, 917 } { 918 prng := rand.New(rand.NewSource(int64(i))) 919 // This spongeDb is used to check the sequence of disk-db-writes 920 s := &spongeDb{sponge: crypto.NewKeccakState()} 921 db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme) 922 trie := NewEmpty(db) 923 // Fill the trie with elements 924 for i := 0; i < tc.count; i++ { 925 key := make([]byte, 32) 926 var val []byte 927 // 50% short elements, 50% large elements 928 if prng.Intn(2) == 0 { 929 val = make([]byte, 1+prng.Intn(32)) 930 } else { 931 val = make([]byte, 1+prng.Intn(4096)) 932 } 933 prng.Read(key) 934 prng.Read(val) 935 trie.MustUpdate(key, val) 936 } 937 // Flush trie -> database 938 root, nodes, _ := trie.Commit(false) 939 db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) 940 // Flush memdb -> disk (sponge) 941 db.Commit(root) 942 if got, exp := s.sponge.Sum(nil), tc.expWriteSeqHash; !bytes.Equal(got, exp) { 943 t.Fatalf("test %d, disk write sequence wrong:\ngot %x exp %x\n", i, got, exp) 944 } 945 } 946 } 947 948 func TestCommitSequenceStackTrie(t *testing.T) { 949 for count := 1; count < 200; count++ { 950 prng := rand.New(rand.NewSource(int64(count))) 951 // This spongeDb is used to check the sequence of disk-db-writes 952 s := &spongeDb{ 953 sponge: sha3.NewLegacyKeccak256(), 954 id: "a", 955 values: make(map[string]string), 956 } 957 db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme) 958 trie := NewEmpty(db) 959 960 // Another sponge is used for the stacktrie commits 961 stackTrieSponge := &spongeDb{ 962 sponge: sha3.NewLegacyKeccak256(), 963 id: "b", 964 values: make(map[string]string), 965 } 966 stTrie := NewStackTrie(func(path []byte, hash common.Hash, blob []byte) { 967 rawdb.WriteTrieNode(stackTrieSponge, common.Hash{}, path, hash, blob, db.Scheme()) 968 }) 969 970 // Fill the trie with elements 971 for i := 0; i < count; i++ { 972 // For the stack trie, we need to do inserts in proper order 973 key := make([]byte, 32) 974 binary.BigEndian.PutUint64(key, uint64(i)) 975 var val []byte 976 // 50% short elements, 50% large elements 977 if prng.Intn(2) == 0 { 978 val = make([]byte, 1+prng.Intn(32)) 979 } else { 980 val = make([]byte, 1+prng.Intn(1024)) 981 } 982 prng.Read(val) 983 trie.Update(key, val) 984 stTrie.Update(key, val) 985 } 986 // Flush trie -> database 987 root, nodes, _ := trie.Commit(false) 988 // Flush memdb -> disk (sponge) 989 db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) 990 db.Commit(root) 991 s.Flush() 992 993 // And flush stacktrie -> disk 994 stRoot := stTrie.Hash() 995 if stRoot != root { 996 t.Fatalf("root wrong, got %x exp %x", stRoot, root) 997 } 998 stackTrieSponge.Flush() 999 if got, exp := stackTrieSponge.sponge.Sum(nil), s.sponge.Sum(nil); !bytes.Equal(got, exp) { 1000 // Show the journal 1001 t.Logf("Expected:") 1002 for i, v := range s.journal { 1003 t.Logf("op %d: %v", i, v) 1004 } 1005 t.Logf("Stacktrie:") 1006 for i, v := range stackTrieSponge.journal { 1007 t.Logf("op %d: %v", i, v) 1008 } 1009 t.Fatalf("test %d, disk write sequence wrong:\ngot %x exp %x\n", count, got, exp) 1010 } 1011 } 1012 } 1013 1014 // TestCommitSequenceSmallRoot tests that a trie which is essentially only a 1015 // small (<32 byte) shortnode with an included value is properly committed to a 1016 // database. 1017 // This case might not matter, since in practice, all keys are 32 bytes, which means 1018 // that even a small trie which contains a leaf will have an extension making it 1019 // not fit into 32 bytes, rlp-encoded. However, it's still the correct thing to do. 1020 func TestCommitSequenceSmallRoot(t *testing.T) { 1021 s := &spongeDb{ 1022 sponge: sha3.NewLegacyKeccak256(), 1023 id: "a", 1024 values: make(map[string]string), 1025 } 1026 db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme) 1027 trie := NewEmpty(db) 1028 1029 // Another sponge is used for the stacktrie commits 1030 stackTrieSponge := &spongeDb{ 1031 sponge: sha3.NewLegacyKeccak256(), 1032 id: "b", 1033 values: make(map[string]string), 1034 } 1035 stTrie := NewStackTrie(func(path []byte, hash common.Hash, blob []byte) { 1036 rawdb.WriteTrieNode(stackTrieSponge, common.Hash{}, path, hash, blob, db.Scheme()) 1037 }) 1038 // Add a single small-element to the trie(s) 1039 key := make([]byte, 5) 1040 key[0] = 1 1041 trie.Update(key, []byte{0x1}) 1042 stTrie.Update(key, []byte{0x1}) 1043 1044 // Flush trie -> database 1045 root, nodes, _ := trie.Commit(false) 1046 // Flush memdb -> disk (sponge) 1047 db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) 1048 db.Commit(root) 1049 1050 // And flush stacktrie -> disk 1051 stRoot := stTrie.Hash() 1052 if stRoot != root { 1053 t.Fatalf("root wrong, got %x exp %x", stRoot, root) 1054 } 1055 t.Logf("root: %x\n", stRoot) 1056 1057 s.Flush() 1058 stackTrieSponge.Flush() 1059 if got, exp := stackTrieSponge.sponge.Sum(nil), s.sponge.Sum(nil); !bytes.Equal(got, exp) { 1060 t.Fatalf("test, disk write sequence wrong:\ngot %x exp %x\n", got, exp) 1061 } 1062 } 1063 1064 // BenchmarkHashFixedSize benchmarks the hash of a fixed number of updates to a trie. 1065 // This benchmark is meant to capture the difference on efficiency of small versus large changes. Typically, 1066 // storage tries are small (a couple of entries), whereas the full post-block account trie update is large (a couple 1067 // of thousand entries) 1068 func BenchmarkHashFixedSize(b *testing.B) { 1069 b.Run("10", func(b *testing.B) { 1070 b.StopTimer() 1071 acc, add := makeAccounts(20) 1072 for i := 0; i < b.N; i++ { 1073 benchmarkHashFixedSize(b, acc, add) 1074 } 1075 }) 1076 b.Run("100", func(b *testing.B) { 1077 b.StopTimer() 1078 acc, add := makeAccounts(100) 1079 for i := 0; i < b.N; i++ { 1080 benchmarkHashFixedSize(b, acc, add) 1081 } 1082 }) 1083 1084 b.Run("1K", func(b *testing.B) { 1085 b.StopTimer() 1086 acc, add := makeAccounts(1000) 1087 for i := 0; i < b.N; i++ { 1088 benchmarkHashFixedSize(b, acc, add) 1089 } 1090 }) 1091 b.Run("10K", func(b *testing.B) { 1092 b.StopTimer() 1093 acc, add := makeAccounts(10000) 1094 for i := 0; i < b.N; i++ { 1095 benchmarkHashFixedSize(b, acc, add) 1096 } 1097 }) 1098 b.Run("100K", func(b *testing.B) { 1099 b.StopTimer() 1100 acc, add := makeAccounts(100000) 1101 for i := 0; i < b.N; i++ { 1102 benchmarkHashFixedSize(b, acc, add) 1103 } 1104 }) 1105 } 1106 1107 func benchmarkHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) { 1108 b.ReportAllocs() 1109 trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) 1110 for i := 0; i < len(addresses); i++ { 1111 trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) 1112 } 1113 // Insert the accounts into the trie and hash it 1114 b.StartTimer() 1115 trie.Hash() 1116 b.StopTimer() 1117 } 1118 1119 func BenchmarkCommitAfterHashFixedSize(b *testing.B) { 1120 b.Run("10", func(b *testing.B) { 1121 b.StopTimer() 1122 acc, add := makeAccounts(20) 1123 for i := 0; i < b.N; i++ { 1124 benchmarkCommitAfterHashFixedSize(b, acc, add) 1125 } 1126 }) 1127 b.Run("100", func(b *testing.B) { 1128 b.StopTimer() 1129 acc, add := makeAccounts(100) 1130 for i := 0; i < b.N; i++ { 1131 benchmarkCommitAfterHashFixedSize(b, acc, add) 1132 } 1133 }) 1134 1135 b.Run("1K", func(b *testing.B) { 1136 b.StopTimer() 1137 acc, add := makeAccounts(1000) 1138 for i := 0; i < b.N; i++ { 1139 benchmarkCommitAfterHashFixedSize(b, acc, add) 1140 } 1141 }) 1142 b.Run("10K", func(b *testing.B) { 1143 b.StopTimer() 1144 acc, add := makeAccounts(10000) 1145 for i := 0; i < b.N; i++ { 1146 benchmarkCommitAfterHashFixedSize(b, acc, add) 1147 } 1148 }) 1149 b.Run("100K", func(b *testing.B) { 1150 b.StopTimer() 1151 acc, add := makeAccounts(100000) 1152 for i := 0; i < b.N; i++ { 1153 benchmarkCommitAfterHashFixedSize(b, acc, add) 1154 } 1155 }) 1156 } 1157 1158 func benchmarkCommitAfterHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) { 1159 b.ReportAllocs() 1160 trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) 1161 for i := 0; i < len(addresses); i++ { 1162 trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) 1163 } 1164 // Insert the accounts into the trie and hash it 1165 trie.Hash() 1166 b.StartTimer() 1167 trie.Commit(false) 1168 b.StopTimer() 1169 } 1170 1171 func getString(trie *Trie, k string) []byte { 1172 return trie.MustGet([]byte(k)) 1173 } 1174 1175 func updateString(trie *Trie, k, v string) { 1176 trie.MustUpdate([]byte(k), []byte(v)) 1177 } 1178 1179 func deleteString(trie *Trie, k string) { 1180 trie.MustDelete([]byte(k)) 1181 } 1182 1183 func TestDecodeNode(t *testing.T) { 1184 t.Parallel() 1185 1186 var ( 1187 hash = make([]byte, 20) 1188 elems = make([]byte, 20) 1189 ) 1190 for i := 0; i < 5000000; i++ { 1191 prng.Read(hash) 1192 prng.Read(elems) 1193 decodeNode(hash, elems) 1194 } 1195 } 1196 1197 func FuzzTrie(f *testing.F) { 1198 f.Fuzz(func(t *testing.T, data []byte) { 1199 var steps = 500 1200 var input = bytes.NewReader(data) 1201 var finishedFn = func() bool { 1202 steps-- 1203 return steps < 0 || input.Len() == 0 1204 } 1205 if err := runRandTest(generateSteps(finishedFn, input)); err != nil { 1206 t.Fatal(err) 1207 } 1208 }) 1209 }