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