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