git.pirl.io/community/pirl@v0.0.0-20201111064343-9d3d31ff74be/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 "fmt" 23 "io/ioutil" 24 "math/big" 25 "math/rand" 26 "os" 27 "reflect" 28 "testing" 29 "testing/quick" 30 31 "github.com/davecgh/go-spew/spew" 32 "git.pirl.io/community/pirl/common" 33 "git.pirl.io/community/pirl/crypto" 34 "git.pirl.io/community/pirl/ethdb/leveldb" 35 "git.pirl.io/community/pirl/ethdb/memorydb" 36 "git.pirl.io/community/pirl/rlp" 37 ) 38 39 func init() { 40 spew.Config.Indent = " " 41 spew.Config.DisableMethods = false 42 } 43 44 // Used for testing 45 func newEmpty() *Trie { 46 trie, _ := New(common.Hash{}, NewDatabase(memorydb.New())) 47 return trie 48 } 49 50 func TestEmptyTrie(t *testing.T) { 51 var trie Trie 52 res := trie.Hash() 53 exp := emptyRoot 54 if res != exp { 55 t.Errorf("expected %x got %x", exp, res) 56 } 57 } 58 59 func TestNull(t *testing.T) { 60 var trie Trie 61 key := make([]byte, 32) 62 value := []byte("test") 63 trie.Update(key, value) 64 if !bytes.Equal(trie.Get(key), value) { 65 t.Fatal("wrong value") 66 } 67 } 68 69 func TestMissingRoot(t *testing.T) { 70 trie, err := New(common.HexToHash("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"), NewDatabase(memorydb.New())) 71 if trie != nil { 72 t.Error("New returned non-nil trie for invalid root") 73 } 74 if _, ok := err.(*MissingNodeError); !ok { 75 t.Errorf("New returned wrong error: %v", err) 76 } 77 } 78 79 func TestMissingNodeDisk(t *testing.T) { testMissingNode(t, false) } 80 func TestMissingNodeMemonly(t *testing.T) { testMissingNode(t, true) } 81 82 func testMissingNode(t *testing.T, memonly bool) { 83 diskdb := memorydb.New() 84 triedb := NewDatabase(diskdb) 85 86 trie, _ := New(common.Hash{}, triedb) 87 updateString(trie, "120000", "qwerqwerqwerqwerqwerqwerqwerqwer") 88 updateString(trie, "123456", "asdfasdfasdfasdfasdfasdfasdfasdf") 89 root, _ := trie.Commit(nil) 90 if !memonly { 91 triedb.Commit(root, true) 92 } 93 94 trie, _ = New(root, triedb) 95 _, err := trie.TryGet([]byte("120000")) 96 if err != nil { 97 t.Errorf("Unexpected error: %v", err) 98 } 99 trie, _ = New(root, triedb) 100 _, err = trie.TryGet([]byte("120099")) 101 if err != nil { 102 t.Errorf("Unexpected error: %v", err) 103 } 104 trie, _ = New(root, triedb) 105 _, err = trie.TryGet([]byte("123456")) 106 if err != nil { 107 t.Errorf("Unexpected error: %v", err) 108 } 109 trie, _ = New(root, triedb) 110 err = trie.TryUpdate([]byte("120099"), []byte("zxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcv")) 111 if err != nil { 112 t.Errorf("Unexpected error: %v", err) 113 } 114 trie, _ = New(root, triedb) 115 err = trie.TryDelete([]byte("123456")) 116 if err != nil { 117 t.Errorf("Unexpected error: %v", err) 118 } 119 120 hash := common.HexToHash("0xe1d943cc8f061a0c0b98162830b970395ac9315654824bf21b73b891365262f9") 121 if memonly { 122 delete(triedb.dirties, hash) 123 } else { 124 diskdb.Delete(hash[:]) 125 } 126 127 trie, _ = New(root, triedb) 128 _, err = trie.TryGet([]byte("120000")) 129 if _, ok := err.(*MissingNodeError); !ok { 130 t.Errorf("Wrong error: %v", err) 131 } 132 trie, _ = New(root, triedb) 133 _, err = trie.TryGet([]byte("120099")) 134 if _, ok := err.(*MissingNodeError); !ok { 135 t.Errorf("Wrong error: %v", err) 136 } 137 trie, _ = New(root, triedb) 138 _, err = trie.TryGet([]byte("123456")) 139 if err != nil { 140 t.Errorf("Unexpected error: %v", err) 141 } 142 trie, _ = New(root, triedb) 143 err = trie.TryUpdate([]byte("120099"), []byte("zxcv")) 144 if _, ok := err.(*MissingNodeError); !ok { 145 t.Errorf("Wrong error: %v", err) 146 } 147 trie, _ = New(root, triedb) 148 err = trie.TryDelete([]byte("123456")) 149 if _, ok := err.(*MissingNodeError); !ok { 150 t.Errorf("Wrong error: %v", err) 151 } 152 } 153 154 func TestInsert(t *testing.T) { 155 trie := newEmpty() 156 157 updateString(trie, "doe", "reindeer") 158 updateString(trie, "dog", "puppy") 159 updateString(trie, "dogglesworth", "cat") 160 161 exp := common.HexToHash("8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3") 162 root := trie.Hash() 163 if root != exp { 164 t.Errorf("case 1: exp %x got %x", exp, root) 165 } 166 167 trie = newEmpty() 168 updateString(trie, "A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") 169 170 exp = common.HexToHash("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab") 171 root, err := trie.Commit(nil) 172 if err != nil { 173 t.Fatalf("commit error: %v", err) 174 } 175 if root != exp { 176 t.Errorf("case 2: exp %x got %x", exp, root) 177 } 178 } 179 180 func TestGet(t *testing.T) { 181 trie := newEmpty() 182 updateString(trie, "doe", "reindeer") 183 updateString(trie, "dog", "puppy") 184 updateString(trie, "dogglesworth", "cat") 185 186 for i := 0; i < 2; i++ { 187 res := getString(trie, "dog") 188 if !bytes.Equal(res, []byte("puppy")) { 189 t.Errorf("expected puppy got %x", res) 190 } 191 192 unknown := getString(trie, "unknown") 193 if unknown != nil { 194 t.Errorf("expected nil got %x", unknown) 195 } 196 197 if i == 1 { 198 return 199 } 200 trie.Commit(nil) 201 } 202 } 203 204 func TestDelete(t *testing.T) { 205 trie := newEmpty() 206 vals := []struct{ k, v string }{ 207 {"do", "verb"}, 208 {"ether", "wookiedoo"}, 209 {"horse", "stallion"}, 210 {"shaman", "horse"}, 211 {"doge", "coin"}, 212 {"ether", ""}, 213 {"dog", "puppy"}, 214 {"shaman", ""}, 215 } 216 for _, val := range vals { 217 if val.v != "" { 218 updateString(trie, val.k, val.v) 219 } else { 220 deleteString(trie, val.k) 221 } 222 } 223 224 hash := trie.Hash() 225 exp := common.HexToHash("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84") 226 if hash != exp { 227 t.Errorf("expected %x got %x", exp, hash) 228 } 229 } 230 231 func TestEmptyValues(t *testing.T) { 232 trie := newEmpty() 233 234 vals := []struct{ k, v string }{ 235 {"do", "verb"}, 236 {"ether", "wookiedoo"}, 237 {"horse", "stallion"}, 238 {"shaman", "horse"}, 239 {"doge", "coin"}, 240 {"ether", ""}, 241 {"dog", "puppy"}, 242 {"shaman", ""}, 243 } 244 for _, val := range vals { 245 updateString(trie, val.k, val.v) 246 } 247 248 hash := trie.Hash() 249 exp := common.HexToHash("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84") 250 if hash != exp { 251 t.Errorf("expected %x got %x", exp, hash) 252 } 253 } 254 255 func TestReplication(t *testing.T) { 256 trie := newEmpty() 257 vals := []struct{ k, v string }{ 258 {"do", "verb"}, 259 {"ether", "wookiedoo"}, 260 {"horse", "stallion"}, 261 {"shaman", "horse"}, 262 {"doge", "coin"}, 263 {"dog", "puppy"}, 264 {"somethingveryoddindeedthis is", "myothernodedata"}, 265 } 266 for _, val := range vals { 267 updateString(trie, val.k, val.v) 268 } 269 exp, err := trie.Commit(nil) 270 if err != nil { 271 t.Fatalf("commit error: %v", err) 272 } 273 274 // create a new trie on top of the database and check that lookups work. 275 trie2, err := New(exp, trie.db) 276 if err != nil { 277 t.Fatalf("can't recreate trie at %x: %v", exp, err) 278 } 279 for _, kv := range vals { 280 if string(getString(trie2, kv.k)) != kv.v { 281 t.Errorf("trie2 doesn't have %q => %q", kv.k, kv.v) 282 } 283 } 284 hash, err := trie2.Commit(nil) 285 if err != nil { 286 t.Fatalf("commit error: %v", err) 287 } 288 if hash != exp { 289 t.Errorf("root failure. expected %x got %x", exp, hash) 290 } 291 292 // perform some insertions on the new trie. 293 vals2 := []struct{ k, v string }{ 294 {"do", "verb"}, 295 {"ether", "wookiedoo"}, 296 {"horse", "stallion"}, 297 // {"shaman", "horse"}, 298 // {"doge", "coin"}, 299 // {"ether", ""}, 300 // {"dog", "puppy"}, 301 // {"somethingveryoddindeedthis is", "myothernodedata"}, 302 // {"shaman", ""}, 303 } 304 for _, val := range vals2 { 305 updateString(trie2, val.k, val.v) 306 } 307 if hash := trie2.Hash(); hash != exp { 308 t.Errorf("root failure. expected %x got %x", exp, hash) 309 } 310 } 311 312 func TestLargeValue(t *testing.T) { 313 trie := newEmpty() 314 trie.Update([]byte("key1"), []byte{99, 99, 99, 99}) 315 trie.Update([]byte("key2"), bytes.Repeat([]byte{1}, 32)) 316 trie.Hash() 317 } 318 319 // TestRandomCases tests som cases that were found via random fuzzing 320 func TestRandomCases(t *testing.T) { 321 var rt []randTestStep = []randTestStep{ 322 {op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 0 323 {op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 1 324 {op: 0, key: common.Hex2Bytes("d51b182b95d677e5f1c82508c0228de96b73092d78ce78b2230cd948674f66fd1483bd"), value: common.Hex2Bytes("0000000000000002")}, // step 2 325 {op: 2, key: common.Hex2Bytes("c2a38512b83107d665c65235b0250002882ac2022eb00711552354832c5f1d030d0e408e"), value: common.Hex2Bytes("")}, // step 3 326 {op: 3, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 4 327 {op: 3, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 5 328 {op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 6 329 {op: 3, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 7 330 {op: 0, key: common.Hex2Bytes("c2a38512b83107d665c65235b0250002882ac2022eb00711552354832c5f1d030d0e408e"), value: common.Hex2Bytes("0000000000000008")}, // step 8 331 {op: 0, key: common.Hex2Bytes("d51b182b95d677e5f1c82508c0228de96b73092d78ce78b2230cd948674f66fd1483bd"), value: common.Hex2Bytes("0000000000000009")}, // step 9 332 {op: 2, key: common.Hex2Bytes("fd"), value: common.Hex2Bytes("")}, // step 10 333 {op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 11 334 {op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 12 335 {op: 0, key: common.Hex2Bytes("fd"), value: common.Hex2Bytes("000000000000000d")}, // step 13 336 {op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 14 337 {op: 1, key: common.Hex2Bytes("c2a38512b83107d665c65235b0250002882ac2022eb00711552354832c5f1d030d0e408e"), value: common.Hex2Bytes("")}, // step 15 338 {op: 3, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 16 339 {op: 0, key: common.Hex2Bytes("c2a38512b83107d665c65235b0250002882ac2022eb00711552354832c5f1d030d0e408e"), value: common.Hex2Bytes("0000000000000011")}, // step 17 340 {op: 5, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 18 341 {op: 3, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 19 342 {op: 0, key: common.Hex2Bytes("d51b182b95d677e5f1c82508c0228de96b73092d78ce78b2230cd948674f66fd1483bd"), value: common.Hex2Bytes("0000000000000014")}, // step 20 343 {op: 0, key: common.Hex2Bytes("d51b182b95d677e5f1c82508c0228de96b73092d78ce78b2230cd948674f66fd1483bd"), value: common.Hex2Bytes("0000000000000015")}, // step 21 344 {op: 0, key: common.Hex2Bytes("c2a38512b83107d665c65235b0250002882ac2022eb00711552354832c5f1d030d0e408e"), value: common.Hex2Bytes("0000000000000016")}, // step 22 345 {op: 5, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 23 346 {op: 1, key: common.Hex2Bytes("980c393656413a15c8da01978ed9f89feb80b502f58f2d640e3a2f5f7a99a7018f1b573befd92053ac6f78fca4a87268"), value: common.Hex2Bytes("")}, // step 24 347 {op: 1, key: common.Hex2Bytes("fd"), value: common.Hex2Bytes("")}, // step 25 348 } 349 runRandTest(rt) 350 351 } 352 353 // randTest performs random trie operations. 354 // Instances of this test are created by Generate. 355 type randTest []randTestStep 356 357 type randTestStep struct { 358 op int 359 key []byte // for opUpdate, opDelete, opGet 360 value []byte // for opUpdate 361 err error // for debugging 362 } 363 364 const ( 365 opUpdate = iota 366 opDelete 367 opGet 368 opCommit 369 opHash 370 opReset 371 opItercheckhash 372 opMax // boundary value, not an actual op 373 ) 374 375 func (randTest) Generate(r *rand.Rand, size int) reflect.Value { 376 var allKeys [][]byte 377 genKey := func() []byte { 378 if len(allKeys) < 2 || r.Intn(100) < 10 { 379 // new key 380 key := make([]byte, r.Intn(50)) 381 r.Read(key) 382 allKeys = append(allKeys, key) 383 return key 384 } 385 // use existing key 386 return allKeys[r.Intn(len(allKeys))] 387 } 388 389 var steps randTest 390 for i := 0; i < size; i++ { 391 step := randTestStep{op: r.Intn(opMax)} 392 switch step.op { 393 case opUpdate: 394 step.key = genKey() 395 step.value = make([]byte, 8) 396 binary.BigEndian.PutUint64(step.value, uint64(i)) 397 case opGet, opDelete: 398 step.key = genKey() 399 } 400 steps = append(steps, step) 401 } 402 return reflect.ValueOf(steps) 403 } 404 405 func runRandTest(rt randTest) bool { 406 triedb := NewDatabase(memorydb.New()) 407 408 tr, _ := New(common.Hash{}, triedb) 409 values := make(map[string]string) // tracks content of the trie 410 411 for i, step := range rt { 412 fmt.Printf("{op: %d, key: common.Hex2Bytes(\"%x\"), value: common.Hex2Bytes(\"%x\")}, // step %d\n", 413 step.op, step.key, step.value, i) 414 switch step.op { 415 case opUpdate: 416 tr.Update(step.key, step.value) 417 values[string(step.key)] = string(step.value) 418 case opDelete: 419 tr.Delete(step.key) 420 delete(values, string(step.key)) 421 case opGet: 422 v := tr.Get(step.key) 423 want := values[string(step.key)] 424 if string(v) != want { 425 rt[i].err = fmt.Errorf("mismatch for key 0x%x, got 0x%x want 0x%x", step.key, v, want) 426 } 427 case opCommit: 428 _, rt[i].err = tr.Commit(nil) 429 case opHash: 430 tr.Hash() 431 case opReset: 432 hash, err := tr.Commit(nil) 433 if err != nil { 434 rt[i].err = err 435 return false 436 } 437 newtr, err := New(hash, triedb) 438 if err != nil { 439 rt[i].err = err 440 return false 441 } 442 tr = newtr 443 case opItercheckhash: 444 checktr, _ := New(common.Hash{}, triedb) 445 it := NewIterator(tr.NodeIterator(nil)) 446 for it.Next() { 447 checktr.Update(it.Key, it.Value) 448 } 449 if tr.Hash() != checktr.Hash() { 450 rt[i].err = fmt.Errorf("hash mismatch in opItercheckhash") 451 } 452 } 453 // Abort the test on error. 454 if rt[i].err != nil { 455 return false 456 } 457 } 458 return true 459 } 460 461 func TestRandom(t *testing.T) { 462 if err := quick.Check(runRandTest, nil); err != nil { 463 if cerr, ok := err.(*quick.CheckError); ok { 464 t.Fatalf("random test iteration %d failed: %s", cerr.Count, spew.Sdump(cerr.In)) 465 } 466 t.Fatal(err) 467 } 468 } 469 470 func BenchmarkGet(b *testing.B) { benchGet(b, false) } 471 func BenchmarkGetDB(b *testing.B) { benchGet(b, true) } 472 func BenchmarkUpdateBE(b *testing.B) { benchUpdate(b, binary.BigEndian) } 473 func BenchmarkUpdateLE(b *testing.B) { benchUpdate(b, binary.LittleEndian) } 474 475 const benchElemCount = 20000 476 477 func benchGet(b *testing.B, commit bool) { 478 trie := new(Trie) 479 if commit { 480 _, tmpdb := tempDB() 481 trie, _ = New(common.Hash{}, tmpdb) 482 } 483 k := make([]byte, 32) 484 for i := 0; i < benchElemCount; i++ { 485 binary.LittleEndian.PutUint64(k, uint64(i)) 486 trie.Update(k, k) 487 } 488 binary.LittleEndian.PutUint64(k, benchElemCount/2) 489 if commit { 490 trie.Commit(nil) 491 } 492 493 b.ResetTimer() 494 for i := 0; i < b.N; i++ { 495 trie.Get(k) 496 } 497 b.StopTimer() 498 499 if commit { 500 ldb := trie.db.diskdb.(*leveldb.Database) 501 ldb.Close() 502 os.RemoveAll(ldb.Path()) 503 } 504 } 505 506 func benchUpdate(b *testing.B, e binary.ByteOrder) *Trie { 507 trie := newEmpty() 508 k := make([]byte, 32) 509 b.ReportAllocs() 510 for i := 0; i < b.N; i++ { 511 e.PutUint64(k, uint64(i)) 512 trie.Update(k, k) 513 } 514 return trie 515 } 516 517 // Benchmarks the trie hashing. Since the trie caches the result of any operation, 518 // we cannot use b.N as the number of hashing rouns, since all rounds apart from 519 // the first one will be NOOP. As such, we'll use b.N as the number of account to 520 // insert into the trie before measuring the hashing. 521 // BenchmarkHash-6 288680 4561 ns/op 682 B/op 9 allocs/op 522 // BenchmarkHash-6 275095 4800 ns/op 685 B/op 9 allocs/op 523 // pure hasher: 524 // BenchmarkHash-6 319362 4230 ns/op 675 B/op 9 allocs/op 525 // BenchmarkHash-6 257460 4674 ns/op 689 B/op 9 allocs/op 526 // With hashing in-between and pure hasher: 527 // BenchmarkHash-6 225417 7150 ns/op 982 B/op 12 allocs/op 528 // BenchmarkHash-6 220378 6197 ns/op 983 B/op 12 allocs/op 529 // same with old hasher 530 // BenchmarkHash-6 229758 6437 ns/op 981 B/op 12 allocs/op 531 // BenchmarkHash-6 212610 7137 ns/op 986 B/op 12 allocs/op 532 func BenchmarkHash(b *testing.B) { 533 // Create a realistic account trie to hash. We're first adding and hashing N 534 // entries, then adding N more. 535 addresses, accounts := makeAccounts(2 * b.N) 536 // Insert the accounts into the trie and hash it 537 trie := newEmpty() 538 i := 0 539 for ; i < len(addresses)/2; i++ { 540 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 541 } 542 trie.Hash() 543 for ; i < len(addresses); i++ { 544 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 545 } 546 b.ResetTimer() 547 b.ReportAllocs() 548 //trie.hashRoot(nil, nil) 549 trie.Hash() 550 } 551 552 type account struct { 553 Nonce uint64 554 Balance *big.Int 555 Root common.Hash 556 Code []byte 557 } 558 559 // Benchmarks the trie Commit following a Hash. Since the trie caches the result of any operation, 560 // we cannot use b.N as the number of hashing rouns, since all rounds apart from 561 // the first one will be NOOP. As such, we'll use b.N as the number of account to 562 // insert into the trie before measuring the hashing. 563 func BenchmarkCommitAfterHash(b *testing.B) { 564 b.Run("no-onleaf", func(b *testing.B) { 565 benchmarkCommitAfterHash(b, nil) 566 }) 567 var a account 568 onleaf := func(leaf []byte, parent common.Hash) error { 569 rlp.DecodeBytes(leaf, &a) 570 return nil 571 } 572 b.Run("with-onleaf", func(b *testing.B) { 573 benchmarkCommitAfterHash(b, onleaf) 574 }) 575 } 576 577 func benchmarkCommitAfterHash(b *testing.B, onleaf LeafCallback) { 578 // Make the random benchmark deterministic 579 addresses, accounts := makeAccounts(b.N) 580 trie := newEmpty() 581 for i := 0; i < len(addresses); i++ { 582 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 583 } 584 // Insert the accounts into the trie and hash it 585 trie.Hash() 586 b.ResetTimer() 587 b.ReportAllocs() 588 trie.Commit(onleaf) 589 } 590 591 func TestTinyTrie(t *testing.T) { 592 // Create a realistic account trie to hash 593 _, accounts := makeAccounts(10000) 594 trie := newEmpty() 595 trie.Update(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001337"), accounts[3]) 596 if exp, root := common.HexToHash("4fa6efd292cffa2db0083b8bedd23add2798ae73802442f52486e95c3df7111c"), trie.Hash(); exp != root { 597 t.Fatalf("1: got %x, exp %x", root, exp) 598 } 599 trie.Update(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001338"), accounts[4]) 600 if exp, root := common.HexToHash("cb5fb1213826dad9e604f095f8ceb5258fe6b5c01805ce6ef019a50699d2d479"), trie.Hash(); exp != root { 601 t.Fatalf("2: got %x, exp %x", root, exp) 602 } 603 trie.Update(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001339"), accounts[4]) 604 if exp, root := common.HexToHash("ed7e06b4010057d8703e7b9a160a6d42cf4021f9020da3c8891030349a646987"), trie.Hash(); exp != root { 605 t.Fatalf("3: got %x, exp %x", root, exp) 606 } 607 608 checktr, _ := New(common.Hash{}, trie.db) 609 it := NewIterator(trie.NodeIterator(nil)) 610 for it.Next() { 611 checktr.Update(it.Key, it.Value) 612 } 613 if troot, itroot := trie.Hash(), checktr.Hash(); troot != itroot { 614 t.Fatalf("hash mismatch in opItercheckhash, trie: %x, check: %x", troot, itroot) 615 } 616 } 617 618 func TestCommitAfterHash(t *testing.T) { 619 // Create a realistic account trie to hash 620 addresses, accounts := makeAccounts(1000) 621 trie := newEmpty() 622 for i := 0; i < len(addresses); i++ { 623 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 624 } 625 // Insert the accounts into the trie and hash it 626 trie.Hash() 627 trie.Commit(nil) 628 root := trie.Hash() 629 exp := common.HexToHash("e5e9c29bb50446a4081e6d1d748d2892c6101c1e883a1f77cf21d4094b697822") 630 if exp != root { 631 t.Errorf("got %x, exp %x", root, exp) 632 } 633 root, _ = trie.Commit(nil) 634 if exp != root { 635 t.Errorf("got %x, exp %x", root, exp) 636 } 637 } 638 639 func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) { 640 // Make the random benchmark deterministic 641 random := rand.New(rand.NewSource(0)) 642 // Create a realistic account trie to hash 643 addresses = make([][20]byte, size) 644 for i := 0; i < len(addresses); i++ { 645 for j := 0; j < len(addresses[i]); j++ { 646 addresses[i][j] = byte(random.Intn(256)) 647 } 648 } 649 accounts = make([][]byte, len(addresses)) 650 for i := 0; i < len(accounts); i++ { 651 var ( 652 nonce = uint64(random.Int63()) 653 balance = new(big.Int).Rand(random, new(big.Int).Exp(common.Big2, common.Big256, nil)) 654 root = emptyRoot 655 code = crypto.Keccak256(nil) 656 ) 657 accounts[i], _ = rlp.EncodeToBytes(&account{nonce, balance, root, code}) 658 } 659 return addresses, accounts 660 } 661 662 // BenchmarkCommitAfterHashFixedSize benchmarks the Commit (after Hash) of a fixed number of updates to a trie. 663 // This benchmark is meant to capture the difference on efficiency of small versus large changes. Typically, 664 // storage tries are small (a couple of entries), whereas the full post-block account trie update is large (a couple 665 // of thousand entries) 666 func BenchmarkHashFixedSize(b *testing.B) { 667 b.Run("10", func(b *testing.B) { 668 b.StopTimer() 669 acc, add := makeAccounts(20) 670 for i := 0; i < b.N; i++ { 671 benchmarkHashFixedSize(b, acc, add) 672 } 673 }) 674 b.Run("100", func(b *testing.B) { 675 b.StopTimer() 676 acc, add := makeAccounts(100) 677 for i := 0; i < b.N; i++ { 678 benchmarkHashFixedSize(b, acc, add) 679 } 680 }) 681 682 b.Run("1K", func(b *testing.B) { 683 b.StopTimer() 684 acc, add := makeAccounts(1000) 685 for i := 0; i < b.N; i++ { 686 benchmarkHashFixedSize(b, acc, add) 687 } 688 }) 689 b.Run("10K", func(b *testing.B) { 690 b.StopTimer() 691 acc, add := makeAccounts(10000) 692 for i := 0; i < b.N; i++ { 693 benchmarkHashFixedSize(b, acc, add) 694 } 695 }) 696 b.Run("100K", func(b *testing.B) { 697 b.StopTimer() 698 acc, add := makeAccounts(100000) 699 for i := 0; i < b.N; i++ { 700 benchmarkHashFixedSize(b, acc, add) 701 } 702 }) 703 } 704 705 func benchmarkHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) { 706 b.ReportAllocs() 707 trie := newEmpty() 708 for i := 0; i < len(addresses); i++ { 709 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 710 } 711 // Insert the accounts into the trie and hash it 712 b.StartTimer() 713 trie.Hash() 714 b.StopTimer() 715 } 716 717 func BenchmarkCommitAfterHashFixedSize(b *testing.B) { 718 b.Run("10", func(b *testing.B) { 719 b.StopTimer() 720 acc, add := makeAccounts(20) 721 for i := 0; i < b.N; i++ { 722 benchmarkCommitAfterHashFixedSize(b, acc, add) 723 } 724 }) 725 b.Run("100", func(b *testing.B) { 726 b.StopTimer() 727 acc, add := makeAccounts(100) 728 for i := 0; i < b.N; i++ { 729 benchmarkCommitAfterHashFixedSize(b, acc, add) 730 } 731 }) 732 733 b.Run("1K", func(b *testing.B) { 734 b.StopTimer() 735 acc, add := makeAccounts(1000) 736 for i := 0; i < b.N; i++ { 737 benchmarkCommitAfterHashFixedSize(b, acc, add) 738 } 739 }) 740 b.Run("10K", func(b *testing.B) { 741 b.StopTimer() 742 acc, add := makeAccounts(10000) 743 for i := 0; i < b.N; i++ { 744 benchmarkCommitAfterHashFixedSize(b, acc, add) 745 } 746 }) 747 b.Run("100K", func(b *testing.B) { 748 b.StopTimer() 749 acc, add := makeAccounts(100000) 750 for i := 0; i < b.N; i++ { 751 benchmarkCommitAfterHashFixedSize(b, acc, add) 752 } 753 }) 754 } 755 756 func benchmarkCommitAfterHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) { 757 b.ReportAllocs() 758 trie := newEmpty() 759 for i := 0; i < len(addresses); i++ { 760 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 761 } 762 // Insert the accounts into the trie and hash it 763 trie.Hash() 764 b.StartTimer() 765 trie.Commit(nil) 766 b.StopTimer() 767 } 768 769 func BenchmarkDerefRootFixedSize(b *testing.B) { 770 b.Run("10", func(b *testing.B) { 771 b.StopTimer() 772 acc, add := makeAccounts(20) 773 for i := 0; i < b.N; i++ { 774 benchmarkDerefRootFixedSize(b, acc, add) 775 } 776 }) 777 b.Run("100", func(b *testing.B) { 778 b.StopTimer() 779 acc, add := makeAccounts(100) 780 for i := 0; i < b.N; i++ { 781 benchmarkDerefRootFixedSize(b, acc, add) 782 } 783 }) 784 785 b.Run("1K", func(b *testing.B) { 786 b.StopTimer() 787 acc, add := makeAccounts(1000) 788 for i := 0; i < b.N; i++ { 789 benchmarkDerefRootFixedSize(b, acc, add) 790 } 791 }) 792 b.Run("10K", func(b *testing.B) { 793 b.StopTimer() 794 acc, add := makeAccounts(10000) 795 for i := 0; i < b.N; i++ { 796 benchmarkDerefRootFixedSize(b, acc, add) 797 } 798 }) 799 b.Run("100K", func(b *testing.B) { 800 b.StopTimer() 801 acc, add := makeAccounts(100000) 802 for i := 0; i < b.N; i++ { 803 benchmarkDerefRootFixedSize(b, acc, add) 804 } 805 }) 806 } 807 808 func benchmarkDerefRootFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) { 809 b.ReportAllocs() 810 trie := newEmpty() 811 for i := 0; i < len(addresses); i++ { 812 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 813 } 814 h := trie.Hash() 815 trie.Commit(nil) 816 b.StartTimer() 817 trie.db.Dereference(h) 818 b.StopTimer() 819 } 820 821 func tempDB() (string, *Database) { 822 dir, err := ioutil.TempDir("", "trie-bench") 823 if err != nil { 824 panic(fmt.Sprintf("can't create temporary directory: %v", err)) 825 } 826 diskdb, err := leveldb.New(dir, 256, 0, "") 827 if err != nil { 828 panic(fmt.Sprintf("can't create temporary database: %v", err)) 829 } 830 return dir, NewDatabase(diskdb) 831 } 832 833 func getString(trie *Trie, k string) []byte { 834 return trie.Get([]byte(k)) 835 } 836 837 func updateString(trie *Trie, k, v string) { 838 trie.Update([]byte(k), []byte(v)) 839 } 840 841 func deleteString(trie *Trie, k string) { 842 trie.Delete([]byte(k)) 843 } 844 845 func TestDecodeNode(t *testing.T) { 846 t.Parallel() 847 var ( 848 hash = make([]byte, 20) 849 elems = make([]byte, 20) 850 ) 851 for i := 0; i < 5000000; i++ { 852 rand.Read(hash) 853 rand.Read(elems) 854 decodeNode(hash, elems) 855 } 856 }