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