github.com/aswedchain/aswed@v1.0.1/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/aswedchain/aswed/common" 35 "github.com/aswedchain/aswed/crypto" 36 "github.com/aswedchain/aswed/ethdb" 37 "github.com/aswedchain/aswed/ethdb/leveldb" 38 "github.com/aswedchain/aswed/ethdb/memorydb" 39 "github.com/aswedchain/aswed/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 = []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(path []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(10000) 598 trie := newEmpty() 599 trie.Update(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001337"), accounts[3]) 600 if exp, root := common.HexToHash("4fa6efd292cffa2db0083b8bedd23add2798ae73802442f52486e95c3df7111c"), trie.Hash(); exp != root { 601 t.Fatalf("1: got %x, exp %x", root, exp) 602 } 603 trie.Update(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001338"), accounts[4]) 604 if exp, root := common.HexToHash("cb5fb1213826dad9e604f095f8ceb5258fe6b5c01805ce6ef019a50699d2d479"), trie.Hash(); exp != root { 605 t.Fatalf("2: got %x, exp %x", root, exp) 606 } 607 trie.Update(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001339"), accounts[4]) 608 if exp, root := common.HexToHash("ed7e06b4010057d8703e7b9a160a6d42cf4021f9020da3c8891030349a646987"), trie.Hash(); exp != root { 609 t.Fatalf("3: got %x, exp %x", root, exp) 610 } 611 612 checktr, _ := New(common.Hash{}, trie.db) 613 it := NewIterator(trie.NodeIterator(nil)) 614 for it.Next() { 615 checktr.Update(it.Key, it.Value) 616 } 617 if troot, itroot := trie.Hash(), checktr.Hash(); troot != itroot { 618 t.Fatalf("hash mismatch in opItercheckhash, trie: %x, check: %x", troot, itroot) 619 } 620 } 621 622 func TestCommitAfterHash(t *testing.T) { 623 // Create a realistic account trie to hash 624 addresses, accounts := makeAccounts(1000) 625 trie := newEmpty() 626 for i := 0; i < len(addresses); i++ { 627 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 628 } 629 // Insert the accounts into the trie and hash it 630 trie.Hash() 631 trie.Commit(nil) 632 root := trie.Hash() 633 exp := common.HexToHash("e5e9c29bb50446a4081e6d1d748d2892c6101c1e883a1f77cf21d4094b697822") 634 if exp != root { 635 t.Errorf("got %x, exp %x", root, exp) 636 } 637 root, _ = trie.Commit(nil) 638 if exp != root { 639 t.Errorf("got %x, exp %x", root, exp) 640 } 641 } 642 643 func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) { 644 // Make the random benchmark deterministic 645 random := rand.New(rand.NewSource(0)) 646 // Create a realistic account trie to hash 647 addresses = make([][20]byte, size) 648 for i := 0; i < len(addresses); i++ { 649 for j := 0; j < len(addresses[i]); j++ { 650 addresses[i][j] = byte(random.Intn(256)) 651 } 652 } 653 accounts = make([][]byte, len(addresses)) 654 for i := 0; i < len(accounts); i++ { 655 var ( 656 nonce = uint64(random.Int63()) 657 balance = new(big.Int).Rand(random, new(big.Int).Exp(common.Big2, common.Big256, nil)) 658 root = emptyRoot 659 code = crypto.Keccak256(nil) 660 ) 661 accounts[i], _ = rlp.EncodeToBytes(&account{nonce, balance, root, code}) 662 } 663 return addresses, accounts 664 } 665 666 // spongeDb is a dummy db backend which accumulates writes in a sponge 667 type spongeDb struct { 668 sponge hash.Hash 669 id string 670 journal []string 671 } 672 673 func (s *spongeDb) Has(key []byte) (bool, error) { panic("implement me") } 674 func (s *spongeDb) Get(key []byte) ([]byte, error) { return nil, errors.New("no such elem") } 675 func (s *spongeDb) Delete(key []byte) error { panic("implement me") } 676 func (s *spongeDb) NewBatch() ethdb.Batch { return &spongeBatch{s} } 677 func (s *spongeDb) Stat(property string) (string, error) { panic("implement me") } 678 func (s *spongeDb) Compact(start []byte, limit []byte) error { panic("implement me") } 679 func (s *spongeDb) Close() error { return nil } 680 func (s *spongeDb) Put(key []byte, value []byte) error { 681 valbrief := value 682 if len(valbrief) > 8 { 683 valbrief = valbrief[:8] 684 } 685 s.journal = append(s.journal, fmt.Sprintf("%v: PUT([%x...], [%d bytes] %x...)\n", s.id, key[:8], len(value), valbrief)) 686 s.sponge.Write(key) 687 s.sponge.Write(value) 688 return nil 689 } 690 func (s *spongeDb) NewIterator(prefix []byte, start []byte) ethdb.Iterator { panic("implement me") } 691 692 // spongeBatch is a dummy batch which immediately writes to the underlying spongedb 693 type spongeBatch struct { 694 db *spongeDb 695 } 696 697 func (b *spongeBatch) Put(key, value []byte) error { 698 b.db.Put(key, value) 699 return nil 700 } 701 func (b *spongeBatch) Delete(key []byte) error { panic("implement me") } 702 func (b *spongeBatch) ValueSize() int { return 100 } 703 func (b *spongeBatch) Write() error { return nil } 704 func (b *spongeBatch) Reset() {} 705 func (b *spongeBatch) Replay(w ethdb.KeyValueWriter) error { return nil } 706 707 // TestCommitSequence tests that the trie.Commit operation writes the elements of the trie 708 // in the expected order, and calls the callbacks in the expected order. 709 // The test data was based on the 'master' code, and is basically random. It can be used 710 // to check whether changes to the trie modifies the write order or data in any way. 711 func TestCommitSequence(t *testing.T) { 712 for i, tc := range []struct { 713 count int 714 expWriteSeqHash []byte 715 expCallbackSeqHash []byte 716 }{ 717 {20, common.FromHex("68c495e45209e243eb7e4f4e8ca8f9f7be71003bd9cafb8061b4534373740193"), 718 common.FromHex("01783213033d6b7781a641ab499e680d959336d025ac16f44d02f4f0c021bbf5")}, 719 {200, common.FromHex("3b20d16c13c4bc3eb3b8d0ad7a169fef3b1600e056c0665895d03d3d2b2ff236"), 720 common.FromHex("fb8db0ec82e8f02729f11228940885b181c3047ab0d654ed0110291ca57111a8")}, 721 {2000, common.FromHex("34eff3d1048bebdf77e9ae8bd939f2e7c742edc3dcd1173cff1aad9dbd20451a"), 722 common.FromHex("1c981604b1a9f8ffa40e0ae66b14830a87f5a4ed8345146a3912e6b2dcb05e63")}, 723 } { 724 addresses, accounts := makeAccounts(tc.count) 725 // This spongeDb is used to check the sequence of disk-db-writes 726 s := &spongeDb{sponge: sha3.NewLegacyKeccak256()} 727 db := NewDatabase(s) 728 trie, _ := New(common.Hash{}, db) 729 // Another sponge is used to check the callback-sequence 730 callbackSponge := sha3.NewLegacyKeccak256() 731 // Fill the trie with elements 732 for i := 0; i < tc.count; i++ { 733 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 734 } 735 // Flush trie -> database 736 root, _ := trie.Commit(nil) 737 // Flush memdb -> disk (sponge) 738 db.Commit(root, false, func(c common.Hash) { 739 // And spongify the callback-order 740 callbackSponge.Write(c[:]) 741 }) 742 if got, exp := s.sponge.Sum(nil), tc.expWriteSeqHash; !bytes.Equal(got, exp) { 743 t.Fatalf("test %d, disk write sequence wrong:\ngot %x exp %x\n", i, got, exp) 744 } 745 if got, exp := callbackSponge.Sum(nil), tc.expCallbackSeqHash; !bytes.Equal(got, exp) { 746 t.Fatalf("test %d, call back sequence wrong:\ngot: %x exp %x\n", i, got, exp) 747 } 748 } 749 } 750 751 // TestCommitSequenceRandomBlobs is identical to TestCommitSequence 752 // but uses random blobs instead of 'accounts' 753 func TestCommitSequenceRandomBlobs(t *testing.T) { 754 for i, tc := range []struct { 755 count int 756 expWriteSeqHash []byte 757 expCallbackSeqHash []byte 758 }{ 759 {20, common.FromHex("8e4a01548551d139fa9e833ebc4e66fc1ba40a4b9b7259d80db32cff7b64ebbc"), 760 common.FromHex("450238d73bc36dc6cc6f926987e5428535e64be403877c4560e238a52749ba24")}, 761 {200, common.FromHex("6869b4e7b95f3097a19ddb30ff735f922b915314047e041614df06958fc50554"), 762 common.FromHex("0ace0b03d6cb8c0b82f6289ef5b1a1838306b455a62dafc63cada8e2924f2550")}, 763 {2000, common.FromHex("444200e6f4e2df49f77752f629a96ccf7445d4698c164f962bbd85a0526ef424"), 764 common.FromHex("117d30dafaa62a1eed498c3dfd70982b377ba2b46dd3e725ed6120c80829e518")}, 765 } { 766 prng := rand.New(rand.NewSource(int64(i))) 767 // This spongeDb is used to check the sequence of disk-db-writes 768 s := &spongeDb{sponge: sha3.NewLegacyKeccak256()} 769 db := NewDatabase(s) 770 trie, _ := New(common.Hash{}, db) 771 // Another sponge is used to check the callback-sequence 772 callbackSponge := sha3.NewLegacyKeccak256() 773 // Fill the trie with elements 774 for i := 0; i < tc.count; i++ { 775 key := make([]byte, 32) 776 var val []byte 777 // 50% short elements, 50% large elements 778 if prng.Intn(2) == 0 { 779 val = make([]byte, 1+prng.Intn(32)) 780 } else { 781 val = make([]byte, 1+prng.Intn(4096)) 782 } 783 prng.Read(key) 784 prng.Read(val) 785 trie.Update(key, val) 786 } 787 // Flush trie -> database 788 root, _ := trie.Commit(nil) 789 // Flush memdb -> disk (sponge) 790 db.Commit(root, false, func(c common.Hash) { 791 // And spongify the callback-order 792 callbackSponge.Write(c[:]) 793 }) 794 if got, exp := s.sponge.Sum(nil), tc.expWriteSeqHash; !bytes.Equal(got, exp) { 795 t.Fatalf("test %d, disk write sequence wrong:\ngot %x exp %x\n", i, got, exp) 796 } 797 if got, exp := callbackSponge.Sum(nil), tc.expCallbackSeqHash; !bytes.Equal(got, exp) { 798 t.Fatalf("test %d, call back sequence wrong:\ngot: %x exp %x\n", i, got, exp) 799 } 800 } 801 } 802 803 func TestCommitSequenceStackTrie(t *testing.T) { 804 for count := 1; count < 200; count++ { 805 prng := rand.New(rand.NewSource(int64(count))) 806 // This spongeDb is used to check the sequence of disk-db-writes 807 s := &spongeDb{sponge: sha3.NewLegacyKeccak256(), id: "a"} 808 db := NewDatabase(s) 809 trie, _ := New(common.Hash{}, db) 810 // Another sponge is used for the stacktrie commits 811 stackTrieSponge := &spongeDb{sponge: sha3.NewLegacyKeccak256(), id: "b"} 812 stTrie := NewStackTrie(stackTrieSponge) 813 // Fill the trie with elements 814 for i := 1; i < count; i++ { 815 // For the stack trie, we need to do inserts in proper order 816 key := make([]byte, 32) 817 binary.BigEndian.PutUint64(key, uint64(i)) 818 var val []byte 819 // 50% short elements, 50% large elements 820 if prng.Intn(2) == 0 { 821 val = make([]byte, 1+prng.Intn(32)) 822 } else { 823 val = make([]byte, 1+prng.Intn(1024)) 824 } 825 prng.Read(val) 826 trie.TryUpdate(key, common.CopyBytes(val)) 827 stTrie.TryUpdate(key, common.CopyBytes(val)) 828 } 829 // Flush trie -> database 830 root, _ := trie.Commit(nil) 831 // Flush memdb -> disk (sponge) 832 db.Commit(root, false, nil) 833 // And flush stacktrie -> disk 834 stRoot, err := stTrie.Commit() 835 if err != nil { 836 t.Fatalf("Failed to commit stack trie %v", err) 837 } 838 if stRoot != root { 839 t.Fatalf("root wrong, got %x exp %x", stRoot, root) 840 } 841 if got, exp := stackTrieSponge.sponge.Sum(nil), s.sponge.Sum(nil); !bytes.Equal(got, exp) { 842 // Show the journal 843 t.Logf("Expected:") 844 for i, v := range s.journal { 845 t.Logf("op %d: %v", i, v) 846 } 847 t.Logf("Stacktrie:") 848 for i, v := range stackTrieSponge.journal { 849 t.Logf("op %d: %v", i, v) 850 } 851 t.Fatalf("test %d, disk write sequence wrong:\ngot %x exp %x\n", count, got, exp) 852 } 853 } 854 } 855 856 // BenchmarkCommitAfterHashFixedSize benchmarks the Commit (after Hash) of a fixed number of updates to a trie. 857 // This benchmark is meant to capture the difference on efficiency of small versus large changes. Typically, 858 // storage tries are small (a couple of entries), whereas the full post-block account trie update is large (a couple 859 // of thousand entries) 860 func BenchmarkHashFixedSize(b *testing.B) { 861 b.Run("10", func(b *testing.B) { 862 b.StopTimer() 863 acc, add := makeAccounts(20) 864 for i := 0; i < b.N; i++ { 865 benchmarkHashFixedSize(b, acc, add) 866 } 867 }) 868 b.Run("100", func(b *testing.B) { 869 b.StopTimer() 870 acc, add := makeAccounts(100) 871 for i := 0; i < b.N; i++ { 872 benchmarkHashFixedSize(b, acc, add) 873 } 874 }) 875 876 b.Run("1K", func(b *testing.B) { 877 b.StopTimer() 878 acc, add := makeAccounts(1000) 879 for i := 0; i < b.N; i++ { 880 benchmarkHashFixedSize(b, acc, add) 881 } 882 }) 883 b.Run("10K", func(b *testing.B) { 884 b.StopTimer() 885 acc, add := makeAccounts(10000) 886 for i := 0; i < b.N; i++ { 887 benchmarkHashFixedSize(b, acc, add) 888 } 889 }) 890 b.Run("100K", func(b *testing.B) { 891 b.StopTimer() 892 acc, add := makeAccounts(100000) 893 for i := 0; i < b.N; i++ { 894 benchmarkHashFixedSize(b, acc, add) 895 } 896 }) 897 } 898 899 func benchmarkHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) { 900 b.ReportAllocs() 901 trie := newEmpty() 902 for i := 0; i < len(addresses); i++ { 903 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 904 } 905 // Insert the accounts into the trie and hash it 906 b.StartTimer() 907 trie.Hash() 908 b.StopTimer() 909 } 910 911 func BenchmarkCommitAfterHashFixedSize(b *testing.B) { 912 b.Run("10", func(b *testing.B) { 913 b.StopTimer() 914 acc, add := makeAccounts(20) 915 for i := 0; i < b.N; i++ { 916 benchmarkCommitAfterHashFixedSize(b, acc, add) 917 } 918 }) 919 b.Run("100", func(b *testing.B) { 920 b.StopTimer() 921 acc, add := makeAccounts(100) 922 for i := 0; i < b.N; i++ { 923 benchmarkCommitAfterHashFixedSize(b, acc, add) 924 } 925 }) 926 927 b.Run("1K", func(b *testing.B) { 928 b.StopTimer() 929 acc, add := makeAccounts(1000) 930 for i := 0; i < b.N; i++ { 931 benchmarkCommitAfterHashFixedSize(b, acc, add) 932 } 933 }) 934 b.Run("10K", func(b *testing.B) { 935 b.StopTimer() 936 acc, add := makeAccounts(10000) 937 for i := 0; i < b.N; i++ { 938 benchmarkCommitAfterHashFixedSize(b, acc, add) 939 } 940 }) 941 b.Run("100K", func(b *testing.B) { 942 b.StopTimer() 943 acc, add := makeAccounts(100000) 944 for i := 0; i < b.N; i++ { 945 benchmarkCommitAfterHashFixedSize(b, acc, add) 946 } 947 }) 948 } 949 950 func benchmarkCommitAfterHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) { 951 b.ReportAllocs() 952 trie := newEmpty() 953 for i := 0; i < len(addresses); i++ { 954 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 955 } 956 // Insert the accounts into the trie and hash it 957 trie.Hash() 958 b.StartTimer() 959 trie.Commit(nil) 960 b.StopTimer() 961 } 962 963 func BenchmarkDerefRootFixedSize(b *testing.B) { 964 b.Run("10", func(b *testing.B) { 965 b.StopTimer() 966 acc, add := makeAccounts(20) 967 for i := 0; i < b.N; i++ { 968 benchmarkDerefRootFixedSize(b, acc, add) 969 } 970 }) 971 b.Run("100", func(b *testing.B) { 972 b.StopTimer() 973 acc, add := makeAccounts(100) 974 for i := 0; i < b.N; i++ { 975 benchmarkDerefRootFixedSize(b, acc, add) 976 } 977 }) 978 979 b.Run("1K", func(b *testing.B) { 980 b.StopTimer() 981 acc, add := makeAccounts(1000) 982 for i := 0; i < b.N; i++ { 983 benchmarkDerefRootFixedSize(b, acc, add) 984 } 985 }) 986 b.Run("10K", func(b *testing.B) { 987 b.StopTimer() 988 acc, add := makeAccounts(10000) 989 for i := 0; i < b.N; i++ { 990 benchmarkDerefRootFixedSize(b, acc, add) 991 } 992 }) 993 b.Run("100K", func(b *testing.B) { 994 b.StopTimer() 995 acc, add := makeAccounts(100000) 996 for i := 0; i < b.N; i++ { 997 benchmarkDerefRootFixedSize(b, acc, add) 998 } 999 }) 1000 } 1001 1002 func benchmarkDerefRootFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) { 1003 b.ReportAllocs() 1004 trie := newEmpty() 1005 for i := 0; i < len(addresses); i++ { 1006 trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i]) 1007 } 1008 h := trie.Hash() 1009 trie.Commit(nil) 1010 b.StartTimer() 1011 trie.db.Dereference(h) 1012 b.StopTimer() 1013 } 1014 1015 func tempDB() (string, *Database) { 1016 dir, err := ioutil.TempDir("", "trie-bench") 1017 if err != nil { 1018 panic(fmt.Sprintf("can't create temporary directory: %v", err)) 1019 } 1020 diskdb, err := leveldb.New(dir, 256, 0, "") 1021 if err != nil { 1022 panic(fmt.Sprintf("can't create temporary database: %v", err)) 1023 } 1024 return dir, NewDatabase(diskdb) 1025 } 1026 1027 func getString(trie *Trie, k string) []byte { 1028 return trie.Get([]byte(k)) 1029 } 1030 1031 func updateString(trie *Trie, k, v string) { 1032 trie.Update([]byte(k), []byte(v)) 1033 } 1034 1035 func deleteString(trie *Trie, k string) { 1036 trie.Delete([]byte(k)) 1037 } 1038 1039 func TestDecodeNode(t *testing.T) { 1040 t.Parallel() 1041 var ( 1042 hash = make([]byte, 20) 1043 elems = make([]byte, 20) 1044 ) 1045 for i := 0; i < 5000000; i++ { 1046 rand.Read(hash) 1047 rand.Read(elems) 1048 decodeNode(hash, elems) 1049 } 1050 }