github.com/klaytn/klaytn@v1.10.2/storage/statedb/trie_test.go (about) 1 // Modifications Copyright 2018 The klaytn Authors 2 // Copyright 2014 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from trie/trie_test.go (2018/06/04). 19 // Modified and improved for the klaytn development. 20 21 package statedb 22 23 import ( 24 "bytes" 25 "encoding/binary" 26 "fmt" 27 "io/ioutil" 28 "math/big" 29 "math/rand" 30 "os" 31 "reflect" 32 "testing" 33 "testing/quick" 34 35 "github.com/davecgh/go-spew/spew" 36 "github.com/klaytn/klaytn/blockchain/types/account" 37 "github.com/klaytn/klaytn/blockchain/types/accountkey" 38 "github.com/klaytn/klaytn/common" 39 "github.com/klaytn/klaytn/crypto" 40 "github.com/klaytn/klaytn/rlp" 41 "github.com/klaytn/klaytn/storage/database" 42 ) 43 44 func init() { 45 spew.Config.Indent = " " 46 spew.Config.DisableMethods = false 47 } 48 49 // Used for testing 50 func newEmptyTrie() *Trie { 51 trie, _ := NewTrie(common.Hash{}, NewDatabase(database.NewMemoryDBManager())) 52 return trie 53 } 54 55 func TestEmptyTrie(t *testing.T) { 56 var trie Trie 57 res := trie.Hash() 58 exp := emptyRoot 59 if res != common.Hash(exp) { 60 t.Errorf("expected %x got %x", exp, res) 61 } 62 } 63 64 func TestNull(t *testing.T) { 65 var trie Trie 66 key := make([]byte, 32) 67 value := []byte("test") 68 trie.Update(key, value) 69 if !bytes.Equal(trie.Get(key), value) { 70 t.Fatal("wrong value") 71 } 72 } 73 74 func TestMissingRoot(t *testing.T) { 75 trie, err := NewTrie(common.HexToHash("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"), NewDatabase(database.NewMemoryDBManager())) 76 if trie != nil { 77 t.Error("NewTrie returned non-nil trie for invalid root") 78 } 79 if _, ok := err.(*MissingNodeError); !ok { 80 t.Errorf("NewTrie returned wrong error: %v", err) 81 } 82 } 83 84 func TestMissingNodeDisk(t *testing.T) { testMissingNode(t, false) } 85 func TestMissingNodeMemonly(t *testing.T) { testMissingNode(t, true) } 86 87 func testMissingNode(t *testing.T, memonly bool) { 88 memDBManager := database.NewMemoryDBManager() 89 diskdb := memDBManager.GetMemDB() 90 triedb := NewDatabase(memDBManager) 91 92 trie, _ := NewTrie(common.Hash{}, triedb) 93 updateString(trie, "120000", "qwerqwerqwerqwerqwerqwerqwerqwer") 94 updateString(trie, "123456", "asdfasdfasdfasdfasdfasdfasdfasdf") 95 root, _ := trie.Commit(nil) 96 if !memonly { 97 triedb.Commit(root, true, 0) 98 } 99 100 trie, _ = NewTrie(root, triedb) 101 _, err := trie.TryGet([]byte("120000")) 102 if err != nil { 103 t.Errorf("Unexpected error: %v", err) 104 } 105 trie, _ = NewTrie(root, triedb) 106 _, err = trie.TryGet([]byte("120099")) 107 if err != nil { 108 t.Errorf("Unexpected error: %v", err) 109 } 110 trie, _ = NewTrie(root, triedb) 111 _, err = trie.TryGet([]byte("123456")) 112 if err != nil { 113 t.Errorf("Unexpected error: %v", err) 114 } 115 trie, _ = NewTrie(root, triedb) 116 err = trie.TryUpdate([]byte("120099"), []byte("zxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcv")) 117 if err != nil { 118 t.Errorf("Unexpected error: %v", err) 119 } 120 trie, _ = NewTrie(root, triedb) 121 err = trie.TryDelete([]byte("123456")) 122 if err != nil { 123 t.Errorf("Unexpected error: %v", err) 124 } 125 126 hash := common.HexToHash("0xe1d943cc8f061a0c0b98162830b970395ac9315654824bf21b73b891365262f9") 127 if memonly { 128 delete(triedb.nodes, hash) 129 } else { 130 diskdb.Delete(hash[:]) 131 } 132 133 trie, _ = NewTrie(root, triedb) 134 _, err = trie.TryGet([]byte("120000")) 135 if _, ok := err.(*MissingNodeError); !ok { 136 t.Errorf("Wrong error: %v", err) 137 } 138 trie, _ = NewTrie(root, triedb) 139 _, err = trie.TryGet([]byte("120099")) 140 if _, ok := err.(*MissingNodeError); !ok { 141 t.Errorf("Wrong error: %v", err) 142 } 143 trie, _ = NewTrie(root, triedb) 144 _, err = trie.TryGet([]byte("123456")) 145 if err != nil { 146 t.Errorf("Unexpected error: %v", err) 147 } 148 trie, _ = NewTrie(root, triedb) 149 err = trie.TryUpdate([]byte("120099"), []byte("zxcv")) 150 if _, ok := err.(*MissingNodeError); !ok { 151 t.Errorf("Wrong error: %v", err) 152 } 153 trie, _ = NewTrie(root, triedb) 154 err = trie.TryDelete([]byte("123456")) 155 if _, ok := err.(*MissingNodeError); !ok { 156 t.Errorf("Wrong error: %v", err) 157 } 158 } 159 160 func TestInsert(t *testing.T) { 161 trie := newEmptyTrie() 162 163 updateString(trie, "doe", "reindeer") 164 updateString(trie, "dog", "puppy") 165 updateString(trie, "dogglesworth", "cat") 166 167 exp := common.HexToHash("8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3") 168 root := trie.Hash() 169 if root != exp { 170 t.Errorf("exp %x got %x", exp, root) 171 } 172 173 trie = newEmptyTrie() 174 updateString(trie, "A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") 175 176 exp = common.HexToHash("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab") 177 root, err := trie.Commit(nil) 178 if err != nil { 179 t.Fatalf("commit error: %v", err) 180 } 181 if root != exp { 182 t.Errorf("exp %x got %x", exp, root) 183 } 184 } 185 186 func TestGet(t *testing.T) { 187 trie := newEmptyTrie() 188 updateString(trie, "doe", "reindeer") 189 updateString(trie, "dog", "puppy") 190 updateString(trie, "dogglesworth", "cat") 191 192 for i := 0; i < 2; i++ { 193 res := getString(trie, "dog") 194 if !bytes.Equal(res, []byte("puppy")) { 195 t.Errorf("expected puppy got %x", res) 196 } 197 198 unknown := getString(trie, "unknown") 199 if unknown != nil { 200 t.Errorf("expected nil got %x", unknown) 201 } 202 203 if i == 1 { 204 return 205 } 206 trie.Commit(nil) 207 } 208 } 209 210 func TestDelete(t *testing.T) { 211 trie := newEmptyTrie() 212 vals := []struct{ k, v string }{ 213 {"do", "verb"}, 214 {"klaytn", "wookiedoo"}, 215 {"horse", "stallion"}, 216 {"shaman", "horse"}, 217 {"doge", "coin"}, 218 {"klaytn", ""}, 219 {"dog", "puppy"}, 220 {"shaman", ""}, 221 } 222 for _, val := range vals { 223 if val.v != "" { 224 updateString(trie, val.k, val.v) 225 } else { 226 deleteString(trie, val.k) 227 } 228 } 229 230 hash := trie.Hash() 231 exp := common.HexToHash("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84") 232 if hash != exp { 233 t.Errorf("expected %x got %x", exp, hash) 234 } 235 } 236 237 func TestEmptyValues(t *testing.T) { 238 trie := newEmptyTrie() 239 240 vals := []struct{ k, v string }{ 241 {"do", "verb"}, 242 {"klaytn", "wookiedoo"}, 243 {"horse", "stallion"}, 244 {"shaman", "horse"}, 245 {"doge", "coin"}, 246 {"klaytn", ""}, 247 {"dog", "puppy"}, 248 {"shaman", ""}, 249 } 250 for _, val := range vals { 251 updateString(trie, val.k, val.v) 252 } 253 254 hash := trie.Hash() 255 exp := common.HexToHash("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84") 256 if hash != exp { 257 t.Errorf("expected %x got %x", exp, hash) 258 } 259 } 260 261 func TestReplication(t *testing.T) { 262 trie := newEmptyTrie() 263 vals := []struct{ k, v string }{ 264 {"do", "verb"}, 265 {"klaytn", "wookiedoo"}, 266 {"horse", "stallion"}, 267 {"shaman", "horse"}, 268 {"doge", "coin"}, 269 {"dog", "puppy"}, 270 {"somethingveryoddindeedthis is", "myothernodedata"}, 271 } 272 for _, val := range vals { 273 updateString(trie, val.k, val.v) 274 } 275 exp, err := trie.Commit(nil) 276 if err != nil { 277 t.Fatalf("commit error: %v", err) 278 } 279 280 // create a new trie on top of the database and check that lookups work. 281 trie2, err := NewTrie(exp, trie.db) 282 if err != nil { 283 t.Fatalf("can't recreate trie at %x: %v", exp, err) 284 } 285 for _, kv := range vals { 286 if string(getString(trie2, kv.k)) != kv.v { 287 t.Errorf("trie2 doesn't have %q => %q", kv.k, kv.v) 288 } 289 } 290 hash, err := trie2.Commit(nil) 291 if err != nil { 292 t.Fatalf("commit error: %v", err) 293 } 294 if hash != exp { 295 t.Errorf("root failure. expected %x got %x", exp, hash) 296 } 297 298 // perform some insertions on the new trie. 299 vals2 := []struct{ k, v string }{ 300 {"do", "verb"}, 301 {"klaytn", "wookiedoo"}, 302 {"horse", "stallion"}, 303 // {"shaman", "horse"}, 304 // {"doge", "coin"}, 305 // {"klaytn", ""}, 306 // {"dog", "puppy"}, 307 // {"somethingveryoddindeedthis is", "myothernodedata"}, 308 // {"shaman", ""}, 309 } 310 for _, val := range vals2 { 311 updateString(trie2, val.k, val.v) 312 } 313 if hash := trie2.Hash(); hash != exp { 314 t.Errorf("root failure. expected %x got %x", exp, hash) 315 } 316 } 317 318 func TestLargeValue(t *testing.T) { 319 trie := newEmptyTrie() 320 trie.Update([]byte("key1"), []byte{99, 99, 99, 99}) 321 trie.Update([]byte("key2"), bytes.Repeat([]byte{1}, 32)) 322 trie.Hash() 323 } 324 325 type countingDB struct { 326 database.DBManager 327 gets map[string]int 328 } 329 330 //func (db *countingDB) Get(key []byte) ([]byte, error) { 331 // db.gets[string(key)]++ 332 // return db.Database.Get(key) 333 //} 334 335 // randTest performs random trie operations. 336 // Instances of this test are created by Generate. 337 type randTest []randTestStep 338 339 type randTestStep struct { 340 op int 341 key []byte // for opUpdate, opDelete, opGet 342 value []byte // for opUpdate 343 err error // for debugging 344 } 345 346 const ( 347 opUpdate = iota 348 opDelete 349 opGet 350 opCommit 351 opHash 352 opReset 353 opItercheckhash 354 opMax // boundary value, not an actual op 355 ) 356 357 func (randTest) Generate(r *rand.Rand, size int) reflect.Value { 358 var allKeys [][]byte 359 genKey := func() []byte { 360 if len(allKeys) < 2 || r.Intn(100) < 10 { 361 // new key 362 key := make([]byte, r.Intn(50)) 363 r.Read(key) 364 allKeys = append(allKeys, key) 365 return key 366 } 367 // use existing key 368 return allKeys[r.Intn(len(allKeys))] 369 } 370 371 var steps randTest 372 for i := 0; i < size; i++ { 373 step := randTestStep{op: r.Intn(opMax)} 374 switch step.op { 375 case opUpdate: 376 step.key = genKey() 377 step.value = make([]byte, 8) 378 binary.BigEndian.PutUint64(step.value, uint64(i)) 379 case opGet, opDelete: 380 step.key = genKey() 381 } 382 steps = append(steps, step) 383 } 384 return reflect.ValueOf(steps) 385 } 386 387 func runRandTest(rt randTest) bool { 388 triedb := NewDatabase(database.NewMemoryDBManager()) 389 390 tr, _ := NewTrie(common.Hash{}, triedb) 391 values := make(map[string]string) // tracks content of the trie 392 393 for i, step := range rt { 394 switch step.op { 395 case opUpdate: 396 tr.Update(step.key, step.value) 397 values[string(step.key)] = string(step.value) 398 case opDelete: 399 tr.Delete(step.key) 400 delete(values, string(step.key)) 401 case opGet: 402 v := tr.Get(step.key) 403 want := values[string(step.key)] 404 if string(v) != want { 405 rt[i].err = fmt.Errorf("mismatch for key 0x%x, got 0x%x want 0x%x", step.key, v, want) 406 } 407 case opCommit: 408 _, rt[i].err = tr.Commit(nil) 409 case opHash: 410 tr.Hash() 411 case opReset: 412 hash, err := tr.Commit(nil) 413 if err != nil { 414 rt[i].err = err 415 return false 416 } 417 newtr, err := NewTrie(hash, triedb) 418 if err != nil { 419 rt[i].err = err 420 return false 421 } 422 tr = newtr 423 case opItercheckhash: 424 checktr, _ := NewTrie(common.Hash{}, triedb) 425 it := NewIterator(tr.NodeIterator(nil)) 426 for it.Next() { 427 checktr.Update(it.Key, it.Value) 428 } 429 if tr.Hash() != checktr.Hash() { 430 rt[i].err = fmt.Errorf("hash mismatch in opItercheckhash") 431 } 432 } 433 // Abort the test on error. 434 if rt[i].err != nil { 435 return false 436 } 437 } 438 return true 439 } 440 441 func TestRandom(t *testing.T) { 442 if err := quick.Check(runRandTest, nil); err != nil { 443 if cerr, ok := err.(*quick.CheckError); ok { 444 t.Fatalf("random test iteration %d failed: %s", cerr.Count, spew.Sdump(cerr.In)) 445 } 446 t.Fatal(err) 447 } 448 } 449 450 func BenchmarkGet(b *testing.B) { benchGet(b, false) } 451 func BenchmarkGetDB(b *testing.B) { benchGet(b, true) } 452 func BenchmarkUpdateBE(b *testing.B) { benchUpdate(b, binary.BigEndian) } 453 func BenchmarkUpdateLE(b *testing.B) { benchUpdate(b, binary.LittleEndian) } 454 455 const benchElemCount = 20000 456 457 func benchGet(b *testing.B, commit bool) { 458 trie := new(Trie) 459 460 if commit { 461 dbDir, tmpdb := tempDB() 462 trie, _ = NewTrie(common.Hash{}, tmpdb) 463 464 defer os.RemoveAll(dbDir) 465 defer tmpdb.diskDB.Close() 466 } 467 468 k := make([]byte, 32) 469 for i := 0; i < benchElemCount; i++ { 470 binary.LittleEndian.PutUint64(k, uint64(i)) 471 trie.Update(k, k) 472 } 473 binary.LittleEndian.PutUint64(k, benchElemCount/2) 474 if commit { 475 trie.Commit(nil) 476 } 477 478 b.ResetTimer() 479 for i := 0; i < b.N; i++ { 480 trie.Get(k) 481 } 482 b.StopTimer() 483 } 484 485 func benchUpdate(b *testing.B, e binary.ByteOrder) *Trie { 486 trie := newEmptyTrie() 487 k := make([]byte, 32) 488 for i := 0; i < b.N; i++ { 489 e.PutUint64(k, uint64(i)) 490 trie.Update(k, k) 491 } 492 return trie 493 } 494 495 // Benchmarks the trie hashing. Since the trie caches the result of any operation, 496 // we cannot use b.N as the number of hashing rouns, since all rounds apart from 497 // the first one will be NOOP. As such, we'll use b.N as the number of account to 498 // insert into the trie before measuring the hashing. 499 func BenchmarkHash(b *testing.B) { 500 // Make the random benchmark deterministic 501 random := rand.New(rand.NewSource(0)) 502 503 // Create a realistic account trie to hash 504 addresses := make([][20]byte, b.N) 505 for i := 0; i < len(addresses); i++ { 506 for j := 0; j < len(addresses[i]); j++ { 507 addresses[i][j] = byte(random.Intn(256)) 508 } 509 } 510 accounts := make([][]byte, len(addresses)) 511 for i := 0; i < len(accounts); i++ { 512 var ( 513 nonce = uint64(random.Int63()) 514 balance = new(big.Int).Rand(random, new(big.Int).Exp(common.Big2, common.Big256, nil)) 515 root = emptyRoot 516 code = crypto.Keccak256(nil) 517 ) 518 accounts[i], _ = rlp.EncodeToBytes([]interface{}{nonce, balance, root, code}) 519 } 520 // Insert the accounts into the trie and hash it 521 trie := newEmptyTrie() 522 for i := 0; i < len(addresses); i++ { 523 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 524 } 525 b.ResetTimer() 526 b.ReportAllocs() 527 trie.Hash() 528 } 529 530 // Benchmarks the trie Commit following a Hash. Since the trie caches the result of any operation, 531 // we cannot use b.N as the number of hashing rounds, since all rounds apart from 532 // the first one will be NOOP. As such, we'll use b.N as the number of account to 533 // insert into the trie before measuring the hashing. 534 func BenchmarkCommitAfterHash(b *testing.B) { 535 b.Run("no-onleaf", func(b *testing.B) { 536 benchmarkCommitAfterHash(b) 537 }) 538 } 539 540 func benchmarkCommitAfterHash(b *testing.B) { 541 // Make the random benchmark deterministic 542 addresses, accounts := makeAccounts(b.N) 543 trie, _ := NewTrie(common.Hash{}, NewDatabase(database.NewMemoryDBManager())) 544 for i := 0; i < len(addresses); i++ { 545 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 546 } 547 // Insert the accounts into the trie and hash it 548 trie.Hash() 549 b.ResetTimer() 550 b.ReportAllocs() 551 trie.Commit(nil) 552 } 553 554 func tempDB() (string, *Database) { 555 dir, err := ioutil.TempDir("", "trie-bench") 556 if err != nil { 557 panic(fmt.Sprintf("can't create temporary directory: %v", err)) 558 } 559 dbc := &database.DBConfig{Dir: dir, DBType: database.LevelDB, LevelDBCacheSize: 256, OpenFilesLimit: 0} 560 diskDB := database.NewDBManager(dbc) 561 return dir, NewDatabase(diskDB) 562 } 563 564 func genExternallyOwnedAccount(nonce uint64, balance *big.Int) (account.Account, error) { 565 return account.NewAccountWithMap(account.ExternallyOwnedAccountType, map[account.AccountValueKeyType]interface{}{ 566 account.AccountValueKeyNonce: nonce, 567 account.AccountValueKeyBalance: balance, 568 account.AccountValueKeyHumanReadable: false, 569 account.AccountValueKeyAccountKey: accountkey.NewAccountKeyLegacy(), 570 }) 571 } 572 573 func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) { 574 // Make the random benchmark deterministic 575 random := rand.New(rand.NewSource(0)) 576 // Create a realistic account trie to hash 577 addresses = make([][20]byte, size) 578 for i := 0; i < len(addresses); i++ { 579 data := make([]byte, 20) 580 random.Read(data) 581 copy(addresses[i][:], data) 582 } 583 accounts = make([][]byte, len(addresses)) 584 for i := 0; i < len(accounts); i++ { 585 // The big.Rand function is not deterministic with regards to 64 vs 32 bit systems, 586 // and will consume different amount of data from the rand source. 587 // balance = new(big.Int).Rand(random, new(big.Int).Exp(common.Big2, common.Big256, nil)) 588 // Therefore, we instead just read via byte buffer 589 numBytes := random.Uint32() % 33 // [0, 32] bytes 590 balanceBytes := make([]byte, numBytes) 591 random.Read(balanceBytes) 592 acc, _ := genExternallyOwnedAccount(uint64(i), big.NewInt(int64(i))) 593 serializer := account.NewAccountSerializerWithAccount(acc) 594 data, _ := rlp.EncodeToBytes(serializer) 595 accounts[i] = data 596 } 597 return addresses, accounts 598 } 599 600 // BenchmarkCommitAfterHashFixedSize benchmarks the Commit (after Hash) of a fixed number of updates to a trie. 601 // This benchmark is meant to capture the difference on efficiency of small versus large changes. Typically, 602 // storage tries are small (a couple of entries), whereas the full post-block account trie update is large (a couple 603 // of thousand entries) 604 func BenchmarkHashFixedSize(b *testing.B) { 605 b.Run("10", func(b *testing.B) { 606 b.StopTimer() 607 acc, add := makeAccounts(20) 608 for i := 0; i < b.N; i++ { 609 benchmarkHashFixedSize(b, acc, add) 610 } 611 }) 612 b.Run("100", func(b *testing.B) { 613 b.StopTimer() 614 acc, add := makeAccounts(100) 615 for i := 0; i < b.N; i++ { 616 benchmarkHashFixedSize(b, acc, add) 617 } 618 }) 619 620 b.Run("1K", func(b *testing.B) { 621 b.StopTimer() 622 acc, add := makeAccounts(1000) 623 for i := 0; i < b.N; i++ { 624 benchmarkHashFixedSize(b, acc, add) 625 } 626 }) 627 b.Run("10K", func(b *testing.B) { 628 b.StopTimer() 629 acc, add := makeAccounts(10000) 630 for i := 0; i < b.N; i++ { 631 benchmarkHashFixedSize(b, acc, add) 632 } 633 }) 634 b.Run("100K", func(b *testing.B) { 635 b.StopTimer() 636 acc, add := makeAccounts(100000) 637 for i := 0; i < b.N; i++ { 638 benchmarkHashFixedSize(b, acc, add) 639 } 640 }) 641 } 642 643 func benchmarkHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) { 644 b.ReportAllocs() 645 trie, _ := NewTrie(common.Hash{}, NewDatabase(database.NewMemoryDBManager())) 646 for i := 0; i < len(addresses); i++ { 647 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 648 } 649 // Insert the accounts into the trie and hash it 650 b.StartTimer() 651 trie.Hash() 652 b.StopTimer() 653 } 654 655 func BenchmarkCommitAfterHashFixedSize(b *testing.B) { 656 b.Run("10", func(b *testing.B) { 657 b.StopTimer() 658 acc, add := makeAccounts(20) 659 for i := 0; i < b.N; i++ { 660 benchmarkCommitAfterHashFixedSize(b, acc, add) 661 } 662 }) 663 b.Run("100", func(b *testing.B) { 664 b.StopTimer() 665 acc, add := makeAccounts(100) 666 for i := 0; i < b.N; i++ { 667 benchmarkCommitAfterHashFixedSize(b, acc, add) 668 } 669 }) 670 671 b.Run("1K", func(b *testing.B) { 672 b.StopTimer() 673 acc, add := makeAccounts(1000) 674 for i := 0; i < b.N; i++ { 675 benchmarkCommitAfterHashFixedSize(b, acc, add) 676 } 677 }) 678 b.Run("10K", func(b *testing.B) { 679 b.StopTimer() 680 acc, add := makeAccounts(10000) 681 for i := 0; i < b.N; i++ { 682 benchmarkCommitAfterHashFixedSize(b, acc, add) 683 } 684 }) 685 b.Run("100K", func(b *testing.B) { 686 b.StopTimer() 687 acc, add := makeAccounts(100000) 688 for i := 0; i < b.N; i++ { 689 benchmarkCommitAfterHashFixedSize(b, acc, add) 690 } 691 }) 692 } 693 694 func benchmarkCommitAfterHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) { 695 b.ReportAllocs() 696 trie, _ := NewTrie(common.Hash{}, NewDatabase(database.NewMemoryDBManager())) 697 for i := 0; i < len(addresses); i++ { 698 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 699 } 700 // Insert the accounts into the trie and hash it 701 trie.Hash() 702 b.StartTimer() 703 trie.Commit(nil) 704 b.StopTimer() 705 } 706 707 func BenchmarkDerefRootFixedSize(b *testing.B) { 708 b.Run("10", func(b *testing.B) { 709 b.StopTimer() 710 acc, add := makeAccounts(20) 711 for i := 0; i < b.N; i++ { 712 benchmarkDerefRootFixedSize(b, acc, add) 713 } 714 }) 715 b.Run("100", func(b *testing.B) { 716 b.StopTimer() 717 acc, add := makeAccounts(100) 718 for i := 0; i < b.N; i++ { 719 benchmarkDerefRootFixedSize(b, acc, add) 720 } 721 }) 722 723 b.Run("1K", func(b *testing.B) { 724 b.StopTimer() 725 acc, add := makeAccounts(1000) 726 for i := 0; i < b.N; i++ { 727 benchmarkDerefRootFixedSize(b, acc, add) 728 } 729 }) 730 b.Run("10K", func(b *testing.B) { 731 b.StopTimer() 732 acc, add := makeAccounts(10000) 733 for i := 0; i < b.N; i++ { 734 benchmarkDerefRootFixedSize(b, acc, add) 735 } 736 }) 737 b.Run("100K", func(b *testing.B) { 738 b.StopTimer() 739 acc, add := makeAccounts(100000) 740 for i := 0; i < b.N; i++ { 741 benchmarkDerefRootFixedSize(b, acc, add) 742 } 743 }) 744 } 745 746 func benchmarkDerefRootFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) { 747 b.ReportAllocs() 748 triedb := NewDatabase(database.NewMemoryDBManager()) 749 trie, _ := NewTrie(common.Hash{}, triedb) 750 for i := 0; i < len(addresses); i++ { 751 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 752 } 753 h := trie.Hash() 754 trie.Commit(nil) 755 //_, nodes := trie.Commit(nil) 756 //triedb.Update(NewWithNodeSet(nodes)) 757 b.StartTimer() 758 triedb.Dereference(h) 759 b.StopTimer() 760 } 761 762 func getString(trie *Trie, k string) []byte { 763 return trie.Get([]byte(k)) 764 } 765 766 func updateString(trie *Trie, k, v string) { 767 trie.Update([]byte(k), []byte(v)) 768 } 769 770 func deleteString(trie *Trie, k string) { 771 trie.Delete([]byte(k)) 772 } 773 774 func TestDecodeNode(t *testing.T) { 775 t.Parallel() 776 var ( 777 hash = make([]byte, 20) 778 elems = make([]byte, 20) 779 ) 780 for i := 0; i < 5000000; i++ { 781 rand.Read(hash) 782 rand.Read(elems) 783 decodeNode(hash, elems) 784 } 785 }