github.com/ethereum-optimism/optimism/l2geth@v0.0.0-20230612200230-50b04ade19e3/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 "github.com/ethereum-optimism/optimism/l2geth/common" 33 "github.com/ethereum-optimism/optimism/l2geth/crypto" 34 "github.com/ethereum-optimism/optimism/l2geth/ethdb/leveldb" 35 "github.com/ethereum-optimism/optimism/l2geth/ethdb/memorydb" 36 "github.com/ethereum-optimism/optimism/l2geth/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 t.Skip("Skipping because empty doesn't delete") 233 234 trie := newEmpty() 235 236 vals := []struct{ k, v string }{ 237 {"do", "verb"}, 238 {"ether", "wookiedoo"}, 239 {"horse", "stallion"}, 240 {"shaman", "horse"}, 241 {"doge", "coin"}, 242 {"ether", ""}, 243 {"dog", "puppy"}, 244 {"shaman", ""}, 245 } 246 for _, val := range vals { 247 updateString(trie, val.k, val.v) 248 } 249 250 hash := trie.Hash() 251 exp := common.HexToHash("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84") 252 if hash != exp { 253 t.Errorf("expected %x got %x", exp, hash) 254 } 255 } 256 257 func TestEmptyValuesNoDelete(t *testing.T) { 258 trie := newEmpty() 259 260 updateString(trie, "shaman", "horse") 261 r := trie.Get([]byte("shaman")) 262 if !bytes.Equal(r, []byte("horse")) { 263 t.Fatalf("Trie get mismatch, expected horse, got %s", string(r)) 264 } 265 updateString(trie, "shaman", "") 266 r2 := trie.Get([]byte("shaman")) 267 if !bytes.Equal(r2, []byte("")) { 268 t.Fatalf("Trie get mismatch, expected \"\", got %s", string(r2)) 269 } 270 } 271 272 func TestReplication(t *testing.T) { 273 trie := newEmpty() 274 vals := []struct{ k, v string }{ 275 {"do", "verb"}, 276 {"ether", "wookiedoo"}, 277 {"horse", "stallion"}, 278 {"shaman", "horse"}, 279 {"doge", "coin"}, 280 {"dog", "puppy"}, 281 {"somethingveryoddindeedthis is", "myothernodedata"}, 282 } 283 for _, val := range vals { 284 updateString(trie, val.k, val.v) 285 } 286 exp, err := trie.Commit(nil) 287 if err != nil { 288 t.Fatalf("commit error: %v", err) 289 } 290 291 // create a new trie on top of the database and check that lookups work. 292 trie2, err := New(exp, trie.db) 293 if err != nil { 294 t.Fatalf("can't recreate trie at %x: %v", exp, 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, err := trie2.Commit(nil) 302 if err != nil { 303 t.Fatalf("commit error: %v", err) 304 } 305 if hash != exp { 306 t.Errorf("root failure. expected %x got %x", exp, hash) 307 } 308 309 // perform some insertions on the new trie. 310 vals2 := []struct{ k, v string }{ 311 {"do", "verb"}, 312 {"ether", "wookiedoo"}, 313 {"horse", "stallion"}, 314 // {"shaman", "horse"}, 315 // {"doge", "coin"}, 316 // {"ether", ""}, 317 // {"dog", "puppy"}, 318 // {"somethingveryoddindeedthis is", "myothernodedata"}, 319 // {"shaman", ""}, 320 } 321 for _, val := range vals2 { 322 updateString(trie2, val.k, val.v) 323 } 324 if hash := trie2.Hash(); hash != exp { 325 t.Errorf("root failure. expected %x got %x", exp, hash) 326 } 327 } 328 329 func TestLargeValue(t *testing.T) { 330 trie := newEmpty() 331 trie.Update([]byte("key1"), []byte{99, 99, 99, 99}) 332 trie.Update([]byte("key2"), bytes.Repeat([]byte{1}, 32)) 333 trie.Hash() 334 } 335 336 // TestRandomCases tests som cases that were found via random fuzzing 337 func TestRandomCases(t *testing.T) { 338 var rt []randTestStep = []randTestStep{ 339 {op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 0 340 {op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 1 341 {op: 0, key: common.Hex2Bytes("d51b182b95d677e5f1c82508c0228de96b73092d78ce78b2230cd948674f66fd1483bd"), value: common.Hex2Bytes("0000000000000002")}, // step 2 342 {op: 2, key: common.Hex2Bytes("c2a38512b83107d665c65235b0250002882ac2022eb00711552354832c5f1d030d0e408e"), value: common.Hex2Bytes("")}, // step 3 343 {op: 3, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 4 344 {op: 3, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 5 345 {op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 6 346 {op: 3, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 7 347 {op: 0, key: common.Hex2Bytes("c2a38512b83107d665c65235b0250002882ac2022eb00711552354832c5f1d030d0e408e"), value: common.Hex2Bytes("0000000000000008")}, // step 8 348 {op: 0, key: common.Hex2Bytes("d51b182b95d677e5f1c82508c0228de96b73092d78ce78b2230cd948674f66fd1483bd"), value: common.Hex2Bytes("0000000000000009")}, // step 9 349 {op: 2, key: common.Hex2Bytes("fd"), value: common.Hex2Bytes("")}, // step 10 350 {op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 11 351 {op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 12 352 {op: 0, key: common.Hex2Bytes("fd"), value: common.Hex2Bytes("000000000000000d")}, // step 13 353 {op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 14 354 {op: 1, key: common.Hex2Bytes("c2a38512b83107d665c65235b0250002882ac2022eb00711552354832c5f1d030d0e408e"), value: common.Hex2Bytes("")}, // step 15 355 {op: 3, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 16 356 {op: 0, key: common.Hex2Bytes("c2a38512b83107d665c65235b0250002882ac2022eb00711552354832c5f1d030d0e408e"), value: common.Hex2Bytes("0000000000000011")}, // step 17 357 {op: 5, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 18 358 {op: 3, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 19 359 {op: 0, key: common.Hex2Bytes("d51b182b95d677e5f1c82508c0228de96b73092d78ce78b2230cd948674f66fd1483bd"), value: common.Hex2Bytes("0000000000000014")}, // step 20 360 {op: 0, key: common.Hex2Bytes("d51b182b95d677e5f1c82508c0228de96b73092d78ce78b2230cd948674f66fd1483bd"), value: common.Hex2Bytes("0000000000000015")}, // step 21 361 {op: 0, key: common.Hex2Bytes("c2a38512b83107d665c65235b0250002882ac2022eb00711552354832c5f1d030d0e408e"), value: common.Hex2Bytes("0000000000000016")}, // step 22 362 {op: 5, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")}, // step 23 363 {op: 1, key: common.Hex2Bytes("980c393656413a15c8da01978ed9f89feb80b502f58f2d640e3a2f5f7a99a7018f1b573befd92053ac6f78fca4a87268"), value: common.Hex2Bytes("")}, // step 24 364 {op: 1, key: common.Hex2Bytes("fd"), value: common.Hex2Bytes("")}, // step 25 365 } 366 runRandTest(rt) 367 368 } 369 370 // randTest performs random trie operations. 371 // Instances of this test are created by Generate. 372 type randTest []randTestStep 373 374 type randTestStep struct { 375 op int 376 key []byte // for opUpdate, opDelete, opGet 377 value []byte // for opUpdate 378 err error // for debugging 379 } 380 381 const ( 382 opUpdate = iota 383 opDelete 384 opGet 385 opCommit 386 opHash 387 opReset 388 opItercheckhash 389 opMax // boundary value, not an actual op 390 ) 391 392 func (randTest) Generate(r *rand.Rand, size int) reflect.Value { 393 var allKeys [][]byte 394 genKey := func() []byte { 395 if len(allKeys) < 2 || r.Intn(100) < 10 { 396 // new key 397 key := make([]byte, r.Intn(50)) 398 r.Read(key) 399 allKeys = append(allKeys, key) 400 return key 401 } 402 // use existing key 403 return allKeys[r.Intn(len(allKeys))] 404 } 405 406 var steps randTest 407 for i := 0; i < size; i++ { 408 step := randTestStep{op: r.Intn(opMax)} 409 switch step.op { 410 case opUpdate: 411 step.key = genKey() 412 step.value = make([]byte, 8) 413 binary.BigEndian.PutUint64(step.value, uint64(i)) 414 case opGet, opDelete: 415 step.key = genKey() 416 } 417 steps = append(steps, step) 418 } 419 return reflect.ValueOf(steps) 420 } 421 422 func runRandTest(rt randTest) bool { 423 triedb := NewDatabase(memorydb.New()) 424 425 tr, _ := New(common.Hash{}, triedb) 426 values := make(map[string]string) // tracks content of the trie 427 428 for i, step := range rt { 429 fmt.Printf("{op: %d, key: common.Hex2Bytes(\"%x\"), value: common.Hex2Bytes(\"%x\")}, // step %d\n", 430 step.op, step.key, step.value, i) 431 switch step.op { 432 case opUpdate: 433 tr.Update(step.key, step.value) 434 values[string(step.key)] = string(step.value) 435 case opDelete: 436 tr.Delete(step.key) 437 delete(values, string(step.key)) 438 case opGet: 439 v := tr.Get(step.key) 440 want := values[string(step.key)] 441 if string(v) != want { 442 rt[i].err = fmt.Errorf("mismatch for key 0x%x, got 0x%x want 0x%x", step.key, v, want) 443 } 444 case opCommit: 445 _, rt[i].err = tr.Commit(nil) 446 case opHash: 447 tr.Hash() 448 case opReset: 449 hash, err := tr.Commit(nil) 450 if err != nil { 451 rt[i].err = err 452 return false 453 } 454 newtr, err := New(hash, triedb) 455 if err != nil { 456 rt[i].err = err 457 return false 458 } 459 tr = newtr 460 case opItercheckhash: 461 checktr, _ := New(common.Hash{}, triedb) 462 it := NewIterator(tr.NodeIterator(nil)) 463 for it.Next() { 464 checktr.Update(it.Key, it.Value) 465 } 466 if tr.Hash() != checktr.Hash() { 467 rt[i].err = fmt.Errorf("hash mismatch in opItercheckhash") 468 } 469 } 470 // Abort the test on error. 471 if rt[i].err != nil { 472 return false 473 } 474 } 475 return true 476 } 477 478 func TestRandom(t *testing.T) { 479 if err := quick.Check(runRandTest, nil); err != nil { 480 if cerr, ok := err.(*quick.CheckError); ok { 481 t.Fatalf("random test iteration %d failed: %s", cerr.Count, spew.Sdump(cerr.In)) 482 } 483 t.Fatal(err) 484 } 485 } 486 487 func BenchmarkGet(b *testing.B) { benchGet(b, false) } 488 func BenchmarkGetDB(b *testing.B) { benchGet(b, true) } 489 func BenchmarkUpdateBE(b *testing.B) { benchUpdate(b, binary.BigEndian) } 490 func BenchmarkUpdateLE(b *testing.B) { benchUpdate(b, binary.LittleEndian) } 491 492 const benchElemCount = 20000 493 494 func benchGet(b *testing.B, commit bool) { 495 trie := new(Trie) 496 if commit { 497 _, tmpdb := tempDB() 498 trie, _ = New(common.Hash{}, tmpdb) 499 } 500 k := make([]byte, 32) 501 for i := 0; i < benchElemCount; i++ { 502 binary.LittleEndian.PutUint64(k, uint64(i)) 503 trie.Update(k, k) 504 } 505 binary.LittleEndian.PutUint64(k, benchElemCount/2) 506 if commit { 507 trie.Commit(nil) 508 } 509 510 b.ResetTimer() 511 for i := 0; i < b.N; i++ { 512 trie.Get(k) 513 } 514 b.StopTimer() 515 516 if commit { 517 ldb := trie.db.diskdb.(*leveldb.Database) 518 ldb.Close() 519 os.RemoveAll(ldb.Path()) 520 } 521 } 522 523 func benchUpdate(b *testing.B, e binary.ByteOrder) *Trie { 524 trie := newEmpty() 525 k := make([]byte, 32) 526 b.ReportAllocs() 527 for i := 0; i < b.N; i++ { 528 e.PutUint64(k, uint64(i)) 529 trie.Update(k, k) 530 } 531 return trie 532 } 533 534 // Benchmarks the trie hashing. Since the trie caches the result of any operation, 535 // we cannot use b.N as the number of hashing rouns, since all rounds apart from 536 // the first one will be NOOP. As such, we'll use b.N as the number of account to 537 // insert into the trie before measuring the hashing. 538 // BenchmarkHash-6 288680 4561 ns/op 682 B/op 9 allocs/op 539 // BenchmarkHash-6 275095 4800 ns/op 685 B/op 9 allocs/op 540 // pure hasher: 541 // BenchmarkHash-6 319362 4230 ns/op 675 B/op 9 allocs/op 542 // BenchmarkHash-6 257460 4674 ns/op 689 B/op 9 allocs/op 543 // With hashing in-between and pure hasher: 544 // BenchmarkHash-6 225417 7150 ns/op 982 B/op 12 allocs/op 545 // BenchmarkHash-6 220378 6197 ns/op 983 B/op 12 allocs/op 546 // same with old hasher 547 // BenchmarkHash-6 229758 6437 ns/op 981 B/op 12 allocs/op 548 // BenchmarkHash-6 212610 7137 ns/op 986 B/op 12 allocs/op 549 func BenchmarkHash(b *testing.B) { 550 // Create a realistic account trie to hash. We're first adding and hashing N 551 // entries, then adding N more. 552 addresses, accounts := makeAccounts(2 * b.N) 553 // Insert the accounts into the trie and hash it 554 trie := newEmpty() 555 i := 0 556 for ; i < len(addresses)/2; i++ { 557 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 558 } 559 trie.Hash() 560 for ; i < len(addresses); i++ { 561 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 562 } 563 b.ResetTimer() 564 b.ReportAllocs() 565 //trie.hashRoot(nil, nil) 566 trie.Hash() 567 } 568 569 type account struct { 570 Nonce uint64 571 Balance *big.Int 572 Root common.Hash 573 Code []byte 574 } 575 576 // Benchmarks the trie Commit following a Hash. Since the trie caches the result of any operation, 577 // we cannot use b.N as the number of hashing rouns, since all rounds apart from 578 // the first one will be NOOP. As such, we'll use b.N as the number of account to 579 // insert into the trie before measuring the hashing. 580 func BenchmarkCommitAfterHash(b *testing.B) { 581 b.Run("no-onleaf", func(b *testing.B) { 582 benchmarkCommitAfterHash(b, nil) 583 }) 584 var a account 585 onleaf := func(leaf []byte, parent common.Hash) error { 586 rlp.DecodeBytes(leaf, &a) 587 return nil 588 } 589 b.Run("with-onleaf", func(b *testing.B) { 590 benchmarkCommitAfterHash(b, onleaf) 591 }) 592 } 593 594 func benchmarkCommitAfterHash(b *testing.B, onleaf LeafCallback) { 595 // Make the random benchmark deterministic 596 addresses, accounts := makeAccounts(b.N) 597 trie := newEmpty() 598 for i := 0; i < len(addresses); i++ { 599 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 600 } 601 // Insert the accounts into the trie and hash it 602 trie.Hash() 603 b.ResetTimer() 604 b.ReportAllocs() 605 trie.Commit(onleaf) 606 } 607 608 func TestTinyTrie(t *testing.T) { 609 // Create a realistic account trie to hash 610 _, accounts := makeAccounts(10000) 611 trie := newEmpty() 612 trie.Update(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001337"), accounts[3]) 613 if exp, root := common.HexToHash("4fa6efd292cffa2db0083b8bedd23add2798ae73802442f52486e95c3df7111c"), trie.Hash(); exp != root { 614 t.Fatalf("1: got %x, exp %x", root, exp) 615 } 616 trie.Update(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001338"), accounts[4]) 617 if exp, root := common.HexToHash("cb5fb1213826dad9e604f095f8ceb5258fe6b5c01805ce6ef019a50699d2d479"), trie.Hash(); exp != root { 618 t.Fatalf("2: got %x, exp %x", root, exp) 619 } 620 trie.Update(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001339"), accounts[4]) 621 if exp, root := common.HexToHash("ed7e06b4010057d8703e7b9a160a6d42cf4021f9020da3c8891030349a646987"), trie.Hash(); exp != root { 622 t.Fatalf("3: got %x, exp %x", root, exp) 623 } 624 625 checktr, _ := New(common.Hash{}, trie.db) 626 it := NewIterator(trie.NodeIterator(nil)) 627 for it.Next() { 628 checktr.Update(it.Key, it.Value) 629 } 630 if troot, itroot := trie.Hash(), checktr.Hash(); troot != itroot { 631 t.Fatalf("hash mismatch in opItercheckhash, trie: %x, check: %x", troot, itroot) 632 } 633 } 634 635 func TestCommitAfterHash(t *testing.T) { 636 // Create a realistic account trie to hash 637 addresses, accounts := makeAccounts(1000) 638 trie := newEmpty() 639 for i := 0; i < len(addresses); i++ { 640 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 641 } 642 // Insert the accounts into the trie and hash it 643 trie.Hash() 644 trie.Commit(nil) 645 root := trie.Hash() 646 exp := common.HexToHash("e5e9c29bb50446a4081e6d1d748d2892c6101c1e883a1f77cf21d4094b697822") 647 if exp != root { 648 t.Errorf("got %x, exp %x", root, exp) 649 } 650 root, _ = trie.Commit(nil) 651 if exp != root { 652 t.Errorf("got %x, exp %x", root, exp) 653 } 654 } 655 656 func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) { 657 // Make the random benchmark deterministic 658 random := rand.New(rand.NewSource(0)) 659 // Create a realistic account trie to hash 660 addresses = make([][20]byte, size) 661 for i := 0; i < len(addresses); i++ { 662 for j := 0; j < len(addresses[i]); j++ { 663 addresses[i][j] = byte(random.Intn(256)) 664 } 665 } 666 accounts = make([][]byte, len(addresses)) 667 for i := 0; i < len(accounts); i++ { 668 var ( 669 nonce = uint64(random.Int63()) 670 balance = new(big.Int).Rand(random, new(big.Int).Exp(common.Big2, common.Big256, nil)) 671 root = emptyRoot 672 code = crypto.Keccak256(nil) 673 ) 674 accounts[i], _ = rlp.EncodeToBytes(&account{nonce, balance, root, code}) 675 } 676 return addresses, accounts 677 } 678 679 // BenchmarkCommitAfterHashFixedSize benchmarks the Commit (after Hash) of a fixed number of updates to a trie. 680 // This benchmark is meant to capture the difference on efficiency of small versus large changes. Typically, 681 // storage tries are small (a couple of entries), whereas the full post-block account trie update is large (a couple 682 // of thousand entries) 683 func BenchmarkHashFixedSize(b *testing.B) { 684 b.Run("10", func(b *testing.B) { 685 b.StopTimer() 686 acc, add := makeAccounts(20) 687 for i := 0; i < b.N; i++ { 688 benchmarkHashFixedSize(b, acc, add) 689 } 690 }) 691 b.Run("100", func(b *testing.B) { 692 b.StopTimer() 693 acc, add := makeAccounts(100) 694 for i := 0; i < b.N; i++ { 695 benchmarkHashFixedSize(b, acc, add) 696 } 697 }) 698 699 b.Run("1K", func(b *testing.B) { 700 b.StopTimer() 701 acc, add := makeAccounts(1000) 702 for i := 0; i < b.N; i++ { 703 benchmarkHashFixedSize(b, acc, add) 704 } 705 }) 706 b.Run("10K", func(b *testing.B) { 707 b.StopTimer() 708 acc, add := makeAccounts(10000) 709 for i := 0; i < b.N; i++ { 710 benchmarkHashFixedSize(b, acc, add) 711 } 712 }) 713 b.Run("100K", func(b *testing.B) { 714 b.StopTimer() 715 acc, add := makeAccounts(100000) 716 for i := 0; i < b.N; i++ { 717 benchmarkHashFixedSize(b, acc, add) 718 } 719 }) 720 } 721 722 func benchmarkHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) { 723 b.ReportAllocs() 724 trie := newEmpty() 725 for i := 0; i < len(addresses); i++ { 726 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 727 } 728 // Insert the accounts into the trie and hash it 729 b.StartTimer() 730 trie.Hash() 731 b.StopTimer() 732 } 733 734 func BenchmarkCommitAfterHashFixedSize(b *testing.B) { 735 b.Run("10", func(b *testing.B) { 736 b.StopTimer() 737 acc, add := makeAccounts(20) 738 for i := 0; i < b.N; i++ { 739 benchmarkCommitAfterHashFixedSize(b, acc, add) 740 } 741 }) 742 b.Run("100", func(b *testing.B) { 743 b.StopTimer() 744 acc, add := makeAccounts(100) 745 for i := 0; i < b.N; i++ { 746 benchmarkCommitAfterHashFixedSize(b, acc, add) 747 } 748 }) 749 750 b.Run("1K", func(b *testing.B) { 751 b.StopTimer() 752 acc, add := makeAccounts(1000) 753 for i := 0; i < b.N; i++ { 754 benchmarkCommitAfterHashFixedSize(b, acc, add) 755 } 756 }) 757 b.Run("10K", func(b *testing.B) { 758 b.StopTimer() 759 acc, add := makeAccounts(10000) 760 for i := 0; i < b.N; i++ { 761 benchmarkCommitAfterHashFixedSize(b, acc, add) 762 } 763 }) 764 b.Run("100K", func(b *testing.B) { 765 b.StopTimer() 766 acc, add := makeAccounts(100000) 767 for i := 0; i < b.N; i++ { 768 benchmarkCommitAfterHashFixedSize(b, acc, add) 769 } 770 }) 771 } 772 773 func benchmarkCommitAfterHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) { 774 b.ReportAllocs() 775 trie := newEmpty() 776 for i := 0; i < len(addresses); i++ { 777 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 778 } 779 // Insert the accounts into the trie and hash it 780 trie.Hash() 781 b.StartTimer() 782 trie.Commit(nil) 783 b.StopTimer() 784 } 785 786 func BenchmarkDerefRootFixedSize(b *testing.B) { 787 b.Run("10", func(b *testing.B) { 788 b.StopTimer() 789 acc, add := makeAccounts(20) 790 for i := 0; i < b.N; i++ { 791 benchmarkDerefRootFixedSize(b, acc, add) 792 } 793 }) 794 b.Run("100", func(b *testing.B) { 795 b.StopTimer() 796 acc, add := makeAccounts(100) 797 for i := 0; i < b.N; i++ { 798 benchmarkDerefRootFixedSize(b, acc, add) 799 } 800 }) 801 802 b.Run("1K", func(b *testing.B) { 803 b.StopTimer() 804 acc, add := makeAccounts(1000) 805 for i := 0; i < b.N; i++ { 806 benchmarkDerefRootFixedSize(b, acc, add) 807 } 808 }) 809 b.Run("10K", func(b *testing.B) { 810 b.StopTimer() 811 acc, add := makeAccounts(10000) 812 for i := 0; i < b.N; i++ { 813 benchmarkDerefRootFixedSize(b, acc, add) 814 } 815 }) 816 b.Run("100K", func(b *testing.B) { 817 b.StopTimer() 818 acc, add := makeAccounts(100000) 819 for i := 0; i < b.N; i++ { 820 benchmarkDerefRootFixedSize(b, acc, add) 821 } 822 }) 823 } 824 825 func benchmarkDerefRootFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) { 826 b.ReportAllocs() 827 trie := newEmpty() 828 for i := 0; i < len(addresses); i++ { 829 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 830 } 831 h := trie.Hash() 832 trie.Commit(nil) 833 b.StartTimer() 834 trie.db.Dereference(h) 835 b.StopTimer() 836 } 837 838 func tempDB() (string, *Database) { 839 dir, err := ioutil.TempDir("", "trie-bench") 840 if err != nil { 841 panic(fmt.Sprintf("can't create temporary directory: %v", err)) 842 } 843 diskdb, err := leveldb.New(dir, 256, 0, "") 844 if err != nil { 845 panic(fmt.Sprintf("can't create temporary database: %v", err)) 846 } 847 return dir, NewDatabase(diskdb) 848 } 849 850 func getString(trie *Trie, k string) []byte { 851 return trie.Get([]byte(k)) 852 } 853 854 func updateString(trie *Trie, k, v string) { 855 trie.Update([]byte(k), []byte(v)) 856 } 857 858 func deleteString(trie *Trie, k string) { 859 trie.Delete([]byte(k)) 860 } 861 862 func TestDecodeNode(t *testing.T) { 863 t.Parallel() 864 var ( 865 hash = make([]byte, 20) 866 elems = make([]byte, 20) 867 ) 868 for i := 0; i < 5000000; i++ { 869 rand.Read(hash) 870 rand.Read(elems) 871 decodeNode(hash, elems) 872 } 873 }