github.com/aergoio/aergo@v1.3.1/pkg/trie/trie_test.go (about) 1 /** 2 * @file 3 * @copyright defined in aergo/LICENSE.txt 4 */ 5 6 package trie 7 8 import ( 9 "bytes" 10 "runtime" 11 12 //"io/ioutil" 13 "os" 14 "path" 15 "time" 16 17 //"encoding/hex" 18 "fmt" 19 "math/rand" 20 "sort" 21 "testing" 22 23 "github.com/aergoio/aergo-lib/db" 24 "github.com/aergoio/aergo/internal/common" 25 //"github.com/dgraph-io/badger" 26 //"github.com/dgraph-io/badger/options" 27 ) 28 29 func TestTrieEmpty(t *testing.T) { 30 smt := NewTrie(nil, common.Hasher, nil) 31 if len(smt.Root) != 0 { 32 t.Fatal("empty trie root hash not correct") 33 } 34 } 35 36 func TestTrieUpdateAndGet(t *testing.T) { 37 smt := NewTrie(nil, common.Hasher, nil) 38 smt.atomicUpdate = false 39 40 // Add data to empty trie 41 keys := getFreshData(10, 32) 42 values := getFreshData(10, 32) 43 ch := make(chan mresult, 1) 44 smt.update(smt.Root, keys, values, nil, 0, smt.TrieHeight, ch) 45 res := <-ch 46 root := res.update 47 48 // Check all keys have been stored 49 for i, key := range keys { 50 value, _ := smt.get(root, key, nil, 0, smt.TrieHeight) 51 if !bytes.Equal(values[i], value) { 52 t.Fatal("value not updated") 53 } 54 } 55 56 // Append to the trie 57 newKeys := getFreshData(5, 32) 58 newValues := getFreshData(5, 32) 59 ch = make(chan mresult, 1) 60 smt.update(root, newKeys, newValues, nil, 0, smt.TrieHeight, ch) 61 res = <-ch 62 newRoot := res.update 63 if bytes.Equal(root, newRoot) { 64 t.Fatal("trie not updated") 65 } 66 for i, newKey := range newKeys { 67 newValue, _ := smt.get(newRoot, newKey, nil, 0, smt.TrieHeight) 68 if !bytes.Equal(newValues[i], newValue) { 69 t.Fatal("failed to get value") 70 } 71 } 72 } 73 74 func TestTrieAtomicUpdate(t *testing.T) { 75 smt := NewTrie(nil, common.Hasher, nil) 76 smt.CacheHeightLimit = 0 77 keys := getFreshData(1, 32) 78 values := getFreshData(1, 32) 79 root, _ := smt.AtomicUpdate(keys, values) 80 updatedNb := len(smt.db.updatedNodes) 81 cacheNb := len(smt.db.liveCache) 82 newvalues := getFreshData(1, 32) 83 smt.AtomicUpdate(keys, newvalues) 84 if len(smt.db.updatedNodes) != 2*updatedNb { 85 t.Fatal("Atomic update doesnt store all tries") 86 } 87 if len(smt.db.liveCache) != cacheNb { 88 t.Fatal("Cache size should remain the same") 89 } 90 91 // check keys of previous atomic update are accessible in 92 // updated nodes with root. 93 smt.atomicUpdate = false 94 for i, key := range keys { 95 value, _ := smt.get(root, key, nil, 0, smt.TrieHeight) 96 if !bytes.Equal(values[i], value) { 97 t.Fatal("failed to get value") 98 } 99 } 100 } 101 102 func TestTriePublicUpdateAndGet(t *testing.T) { 103 smt := NewTrie(nil, common.Hasher, nil) 104 smt.CacheHeightLimit = 0 105 // Add data to empty trie 106 keys := getFreshData(20, 32) 107 values := getFreshData(20, 32) 108 root, _ := smt.Update(keys, values) 109 updatedNb := len(smt.db.updatedNodes) 110 cacheNb := len(smt.db.liveCache) 111 112 // Check all keys have been stored 113 for i, key := range keys { 114 value, _ := smt.Get(key) 115 if !bytes.Equal(values[i], value) { 116 t.Fatal("trie not updated") 117 } 118 } 119 if !bytes.Equal(root, smt.Root) { 120 t.Fatal("Root not stored") 121 } 122 123 newValues := getFreshData(20, 32) 124 smt.Update(keys, newValues) 125 126 if len(smt.db.updatedNodes) != updatedNb { 127 t.Fatal("multiple updates don't actualise updated nodes") 128 } 129 if len(smt.db.liveCache) != cacheNb { 130 t.Fatal("multiple updates don't actualise liveCache") 131 } 132 // Check all keys have been modified 133 for i, key := range keys { 134 value, _ := smt.Get(key) 135 if !bytes.Equal(newValues[i], value) { 136 t.Fatal("trie not updated") 137 } 138 } 139 } 140 141 func TestTrieDelete(t *testing.T) { 142 smt := NewTrie(nil, common.Hasher, nil) 143 // Add data to empty trie 144 keys := getFreshData(20, 32) 145 values := getFreshData(20, 32) 146 ch := make(chan mresult, 1) 147 smt.update(smt.Root, keys, values, nil, 0, smt.TrieHeight, ch) 148 result := <-ch 149 root := result.update 150 value, _ := smt.get(root, keys[0], nil, 0, smt.TrieHeight) 151 if !bytes.Equal(values[0], value) { 152 t.Fatal("trie not updated") 153 } 154 155 // Delete from trie 156 // To delete a key, just set it's value to Default leaf hash. 157 ch = make(chan mresult, 1) 158 smt.update(root, keys[0:1], [][]byte{DefaultLeaf}, nil, 0, smt.TrieHeight, ch) 159 result = <-ch 160 updatedNb := len(smt.db.updatedNodes) 161 newRoot := result.update 162 newValue, _ := smt.get(newRoot, keys[0], nil, 0, smt.TrieHeight) 163 if len(newValue) != 0 { 164 t.Fatal("Failed to delete from trie") 165 } 166 // Remove deleted key from keys and check root with a clean trie. 167 smt2 := NewTrie(nil, common.Hasher, nil) 168 ch = make(chan mresult, 1) 169 smt2.update(smt.Root, keys[1:], values[1:], nil, 0, smt.TrieHeight, ch) 170 result = <-ch 171 cleanRoot := result.update 172 if !bytes.Equal(newRoot, cleanRoot) { 173 t.Fatal("roots mismatch") 174 } 175 176 if len(smt2.db.updatedNodes) != updatedNb { 177 t.Fatal("deleting doesn't actualise updated nodes") 178 } 179 180 //Empty the trie 181 var newValues [][]byte 182 for i := 0; i < 20; i++ { 183 newValues = append(newValues, DefaultLeaf) 184 } 185 ch = make(chan mresult, 1) 186 smt.update(root, keys, newValues, nil, 0, smt.TrieHeight, ch) 187 result = <-ch 188 root = result.update 189 //if !bytes.Equal(smt.DefaultHash(256), root) { 190 if len(root) != 0 { 191 t.Fatal("empty trie root hash not correct") 192 } 193 194 // Test deleting an already empty key 195 smt = NewTrie(nil, common.Hasher, nil) 196 keys = getFreshData(2, 32) 197 values = getFreshData(2, 32) 198 root, _ = smt.Update(keys, values) 199 key0 := make([]byte, 32, 32) 200 key1 := make([]byte, 32, 32) 201 smt.Update([][]byte{key0, key1}, [][]byte{DefaultLeaf, DefaultLeaf}) 202 if !bytes.Equal(root, smt.Root) { 203 t.Fatal("deleting a default key shouldnt' modify the tree") 204 } 205 } 206 207 // test updating and deleting at the same time 208 func TestTrieUpdateAndDelete(t *testing.T) { 209 smt := NewTrie(nil, common.Hasher, nil) 210 smt.CacheHeightLimit = 0 211 key0 := make([]byte, 32, 32) 212 values := getFreshData(1, 32) 213 root, _ := smt.Update([][]byte{key0}, values) 214 cacheNb := len(smt.db.liveCache) 215 updatedNb := len(smt.db.updatedNodes) 216 smt.atomicUpdate = false 217 _, _, k, v, isShortcut, _ := smt.loadChildren(root, smt.TrieHeight, 0, nil) 218 if !isShortcut || !bytes.Equal(k[:HashLength], key0) || !bytes.Equal(v[:HashLength], values[0]) { 219 t.Fatal("leaf shortcut didn't move up to root") 220 } 221 222 key1 := make([]byte, 32, 32) 223 // set the last bit 224 bitSet(key1, 255) 225 keys := [][]byte{key0, key1} 226 values = [][]byte{DefaultLeaf, getFreshData(1, 32)[0]} 227 root, _ = smt.Update(keys, values) 228 229 if len(smt.db.liveCache) != cacheNb { 230 t.Fatal("number of cache nodes not correct after delete") 231 } 232 if len(smt.db.updatedNodes) != updatedNb { 233 t.Fatal("number of cache nodes not correct after delete") 234 } 235 236 smt.atomicUpdate = false 237 _, _, k, v, isShortcut, _ = smt.loadChildren(root, smt.TrieHeight, 0, nil) 238 if !isShortcut || !bytes.Equal(k[:HashLength], key1) || !bytes.Equal(v[:HashLength], values[1]) { 239 t.Fatal("leaf shortcut didn't move up to root") 240 } 241 } 242 243 func TestTrieMerkleProof(t *testing.T) { 244 smt := NewTrie(nil, common.Hasher, nil) 245 // Add data to empty trie 246 keys := getFreshData(10, 32) 247 values := getFreshData(10, 32) 248 smt.Update(keys, values) 249 250 for i, key := range keys { 251 ap, _, k, v, _ := smt.MerkleProof(key) 252 if !smt.VerifyInclusion(ap, key, values[i]) { 253 t.Fatalf("failed to verify inclusion proof") 254 } 255 if !bytes.Equal(key, k) && !bytes.Equal(values[i], v) { 256 t.Fatalf("merkle proof didnt return the correct key-value pair") 257 } 258 } 259 emptyKey := common.Hasher([]byte("non-member")) 260 ap, included, proofKey, proofValue, _ := smt.MerkleProof(emptyKey) 261 if included { 262 t.Fatalf("failed to verify non inclusion proof") 263 } 264 if !smt.VerifyNonInclusion(ap, emptyKey, proofValue, proofKey) { 265 t.Fatalf("failed to verify non inclusion proof") 266 } 267 } 268 269 func TestTrieMerkleProofCompressed(t *testing.T) { 270 smt := NewTrie(nil, common.Hasher, nil) 271 // Add data to empty trie 272 keys := getFreshData(10, 32) 273 values := getFreshData(10, 32) 274 smt.Update(keys, values) 275 276 for i, key := range keys { 277 bitmap, ap, length, _, k, v, _ := smt.MerkleProofCompressed(key) 278 if !smt.VerifyInclusionC(bitmap, key, values[i], ap, length) { 279 t.Fatalf("failed to verify inclusion proof") 280 } 281 if !bytes.Equal(key, k) && !bytes.Equal(values[i], v) { 282 t.Fatalf("merkle proof didnt return the correct key-value pair") 283 } 284 } 285 emptyKey := common.Hasher([]byte("non-member")) 286 bitmap, ap, length, included, proofKey, proofValue, _ := smt.MerkleProofCompressed(emptyKey) 287 if included { 288 t.Fatalf("failed to verify non inclusion proof") 289 } 290 if !smt.VerifyNonInclusionC(ap, length, bitmap, emptyKey, proofValue, proofKey) { 291 t.Fatalf("failed to verify non inclusion proof") 292 } 293 } 294 295 func TestTrieCommit(t *testing.T) { 296 dbPath := path.Join(".aergo", "db") 297 if _, err := os.Stat(dbPath); os.IsNotExist(err) { 298 _ = os.MkdirAll(dbPath, 0711) 299 } 300 st := db.NewDB(db.BadgerImpl, dbPath) 301 302 smt := NewTrie(nil, common.Hasher, st) 303 keys := getFreshData(10, 32) 304 values := getFreshData(10, 32) 305 smt.Update(keys, values) 306 smt.Commit() 307 // liveCache is deleted so the key is fetched in badger db 308 smt.db.liveCache = make(map[Hash][][]byte) 309 for i, key := range keys { 310 value, _ := smt.Get(key) 311 if !bytes.Equal(value, values[i]) { 312 t.Fatal("failed to get value in committed db") 313 } 314 } 315 st.Close() 316 os.RemoveAll(".aergo") 317 } 318 319 func TestTrieStageUpdates(t *testing.T) { 320 dbPath := path.Join(".aergo", "db") 321 if _, err := os.Stat(dbPath); os.IsNotExist(err) { 322 _ = os.MkdirAll(dbPath, 0711) 323 } 324 st := db.NewDB(db.BadgerImpl, dbPath) 325 326 smt := NewTrie(nil, common.Hasher, st) 327 keys := getFreshData(10, 32) 328 values := getFreshData(10, 32) 329 smt.Update(keys, values) 330 txn := st.NewTx() 331 smt.StageUpdates(txn.(DbTx)) 332 txn.Commit() 333 // liveCache is deleted so the key is fetched in badger db 334 smt.db.liveCache = make(map[Hash][][]byte) 335 for i, key := range keys { 336 value, _ := smt.Get(key) 337 if !bytes.Equal(value, values[i]) { 338 t.Fatal("failed to get value in committed db") 339 } 340 } 341 st.Close() 342 os.RemoveAll(".aergo") 343 } 344 345 func TestTrieRevert(t *testing.T) { 346 dbPath := path.Join(".aergo", "db") 347 if _, err := os.Stat(dbPath); os.IsNotExist(err) { 348 _ = os.MkdirAll(dbPath, 0711) 349 } 350 st := db.NewDB(db.BadgerImpl, dbPath) 351 352 smt := NewTrie(nil, common.Hasher, st) 353 354 // Edge case : Test that revert doesnt delete shortcut nodes 355 // when moved to a different position in tree 356 key0 := make([]byte, 32, 32) 357 key1 := make([]byte, 32, 32) 358 // setting the bit at 251 creates 2 shortcut batches at height 252 359 bitSet(key1, 251) 360 values := getFreshData(2, 32) 361 keys := [][]byte{key0, key1} 362 root, _ := smt.Update([][]byte{key0}, [][]byte{values[0]}) 363 smt.Commit() 364 root2, _ := smt.Update([][]byte{key1}, [][]byte{values[1]}) 365 smt.Commit() 366 smt.Revert(root) 367 if len(smt.db.Store.Get(root)) == 0 { 368 t.Fatal("shortcut node shouldnt be deleted by revert") 369 } 370 if len(smt.db.Store.Get(root2)) != 0 { 371 t.Fatal("reverted root should have been deleted") 372 } 373 key1 = make([]byte, 32, 32) 374 // setting the bit at 255 stores the keys as the tip 375 bitSet(key1, 255) 376 smt.Update([][]byte{key1}, [][]byte{values[1]}) 377 smt.Commit() 378 smt.Revert(root) 379 if len(smt.db.Store.Get(root)) == 0 { 380 t.Fatal("shortcut node shouldnt be deleted by revert") 381 } 382 383 // Test all nodes are reverted in the usual case 384 // Add data to empty trie 385 keys = getFreshData(10, 32) 386 values = getFreshData(10, 32) 387 root, _ = smt.Update(keys, values) 388 smt.Commit() 389 390 // Update the values 391 newValues := getFreshData(10, 32) 392 smt.Update(keys, newValues) 393 updatedNodes1 := smt.db.updatedNodes 394 smt.Commit() 395 newKeys := getFreshData(10, 32) 396 newValues = getFreshData(10, 32) 397 smt.Update(newKeys, newValues) 398 updatedNodes2 := smt.db.updatedNodes 399 smt.Commit() 400 401 smt.Revert(root) 402 403 if !bytes.Equal(smt.Root, root) { 404 t.Fatal("revert failed") 405 } 406 if len(smt.pastTries) != 2 { // contains empty trie + reverted trie 407 t.Fatal("past tries not updated after revert") 408 } 409 // Check all keys have been reverted 410 for i, key := range keys { 411 value, _ := smt.Get(key) 412 if !bytes.Equal(values[i], value) { 413 t.Fatal("revert failed, values not updated") 414 } 415 } 416 if len(smt.db.liveCache) != 0 { 417 t.Fatal("live cache not reset after revert") 418 } 419 // Check all reverted nodes have been deleted 420 for node, _ := range updatedNodes2 { 421 if len(smt.db.Store.Get(node[:])) != 0 { 422 t.Fatal("nodes not deleted from database", node) 423 } 424 } 425 for node, _ := range updatedNodes1 { 426 if len(smt.db.Store.Get(node[:])) != 0 { 427 t.Fatal("nodes not deleted from database", node) 428 } 429 } 430 st.Close() 431 os.RemoveAll(".aergo") 432 } 433 434 func TestTrieRaisesError(t *testing.T) { 435 dbPath := path.Join(".aergo", "db") 436 if _, err := os.Stat(dbPath); os.IsNotExist(err) { 437 _ = os.MkdirAll(dbPath, 0711) 438 } 439 st := db.NewDB(db.BadgerImpl, dbPath) 440 441 smt := NewTrie(nil, common.Hasher, st) 442 // Add data to empty trie 443 keys := getFreshData(10, 32) 444 values := getFreshData(10, 32) 445 smt.Update(keys, values) 446 smt.db.liveCache = make(map[Hash][][]byte) 447 smt.db.updatedNodes = make(map[Hash][][]byte) 448 449 // Check errors are raised is a keys is not in cache nore db 450 for _, key := range keys { 451 _, err := smt.Get(key) 452 if err == nil { 453 t.Fatal("Error not created if database doesnt have a node") 454 } 455 } 456 _, _, _, _, _, _, err := smt.MerkleProofCompressed(keys[0]) 457 if err == nil { 458 t.Fatal("Error not created if database doesnt have a node") 459 } 460 _, err = smt.Update(keys, values) 461 if err == nil { 462 t.Fatal("Error not created if database doesnt have a node") 463 } 464 st.Close() 465 os.RemoveAll(".aergo") 466 467 smt = NewTrie(nil, common.Hasher, nil) 468 err = smt.Commit() 469 if err == nil { 470 t.Fatal("Error not created if database not connected") 471 } 472 smt.db.liveCache = make(map[Hash][][]byte) 473 smt.atomicUpdate = false 474 _, _, _, _, _, err = smt.loadChildren(make([]byte, 32, 32), smt.TrieHeight, 0, nil) 475 if err == nil { 476 t.Fatal("Error not created if database not connected") 477 } 478 err = smt.LoadCache(make([]byte, 32)) 479 if err == nil { 480 t.Fatal("Error not created if database not connected") 481 } 482 } 483 484 func TestTrieLoadCache(t *testing.T) { 485 dbPath := path.Join(".aergo", "db") 486 if _, err := os.Stat(dbPath); os.IsNotExist(err) { 487 _ = os.MkdirAll(dbPath, 0711) 488 } 489 st := db.NewDB(db.BadgerImpl, dbPath) 490 491 smt := NewTrie(nil, common.Hasher, st) 492 // Test size of cache 493 smt.CacheHeightLimit = 0 494 key0 := make([]byte, 32, 32) 495 key1 := make([]byte, 32, 32) 496 bitSet(key1, 255) 497 values := getFreshData(2, 32) 498 smt.Update([][]byte{key0, key1}, values) 499 if len(smt.db.liveCache) != 66 { 500 // the nodes are at the tip, so 64 + 2 = 66 501 t.Fatal("cache size incorrect") 502 } 503 504 // Add data to empty trie 505 keys := getFreshData(10, 32) 506 values = getFreshData(10, 32) 507 smt.Update(keys, values) 508 smt.Commit() 509 510 // Simulate node restart by deleting and loading cache 511 cacheSize := len(smt.db.liveCache) 512 smt.db.liveCache = make(map[Hash][][]byte) 513 514 err := smt.LoadCache(smt.Root) 515 516 if err != nil { 517 t.Fatal(err) 518 } 519 if cacheSize != len(smt.db.liveCache) { 520 t.Fatal("Cache loading from db incorrect") 521 } 522 st.Close() 523 os.RemoveAll(".aergo") 524 } 525 526 func TestHeight0LeafShortcut(t *testing.T) { 527 keySize := 32 528 smt := NewTrie(nil, common.Hasher, nil) 529 // Add 2 sibling keys that will be stored at height 0 530 key0 := make([]byte, keySize, keySize) 531 key1 := make([]byte, keySize, keySize) 532 bitSet(key1, keySize*8-1) 533 keys := [][]byte{key0, key1} 534 values := getFreshData(2, 32) 535 smt.Update(keys, values) 536 updatedNb := len(smt.db.updatedNodes) 537 538 // Check all keys have been stored 539 for i, key := range keys { 540 value, _ := smt.Get(key) 541 if !bytes.Equal(values[i], value) { 542 t.Fatal("trie not updated") 543 } 544 } 545 bitmap, ap, length, _, k, v, err := smt.MerkleProofCompressed(key1) 546 if err != nil { 547 t.Fatal(err) 548 } 549 if !bytes.Equal(key1, k) && !bytes.Equal(values[1], v) { 550 t.Fatalf("merkle proof didnt return the correct key-value pair") 551 } 552 if length != smt.TrieHeight { 553 t.Fatal("proof should have length equal to trie height for a leaf shortcut") 554 } 555 if !smt.VerifyInclusionC(bitmap, key1, values[1], ap, length) { 556 t.Fatal("failed to verify inclusion proof") 557 } 558 559 // Delete one key and check that the remaining one moved up to the root of the tree 560 newRoot, _ := smt.AtomicUpdate(keys[0:1], [][]byte{DefaultLeaf}) 561 562 // Nb of updated nodes remains same because the new shortcut root was already stored at height 0. 563 if len(smt.db.updatedNodes) != updatedNb { 564 fmt.Println(len(smt.db.updatedNodes), updatedNb) 565 t.Fatal("number of cache nodes not correct after delete") 566 } 567 smt.atomicUpdate = false 568 _, _, k, v, isShortcut, err := smt.loadChildren(newRoot, smt.TrieHeight, 0, nil) 569 if err != nil { 570 t.Fatal(err) 571 } 572 if !isShortcut || !bytes.Equal(k[:HashLength], key1) || !bytes.Equal(v[:HashLength], values[1]) { 573 t.Fatal("leaf shortcut didn't move up to root") 574 } 575 576 _, _, length, _, k, v, _ = smt.MerkleProofCompressed(key1) 577 if length != 0 { 578 t.Fatal("proof should have length equal to trie height for a leaf shortcut") 579 } 580 if !bytes.Equal(key1, k) && !bytes.Equal(values[1], v) { 581 t.Fatalf("merkle proof didnt return the correct key-value pair") 582 } 583 } 584 585 func TestStash(t *testing.T) { 586 dbPath := path.Join(".aergo", "db") 587 if _, err := os.Stat(dbPath); os.IsNotExist(err) { 588 _ = os.MkdirAll(dbPath, 0711) 589 } 590 st := db.NewDB(db.BadgerImpl, dbPath) 591 smt := NewTrie(nil, common.Hasher, st) 592 // Add data to empty trie 593 keys := getFreshData(20, 32) 594 values := getFreshData(20, 32) 595 root, _ := smt.Update(keys, values) 596 cacheSize := len(smt.db.liveCache) 597 smt.Commit() 598 if len(smt.pastTries) != 1 { 599 t.Fatal("Past tries not updated after commit") 600 } 601 values = getFreshData(20, 32) 602 smt.Update(keys, values) 603 smt.Stash(true) 604 if len(smt.pastTries) != 1 { 605 t.Fatal("Past tries not updated after commit") 606 } 607 if !bytes.Equal(smt.Root, root) { 608 t.Fatal("Trie not rolled back") 609 } 610 if len(smt.db.updatedNodes) != 0 { 611 t.Fatal("Trie not rolled back") 612 } 613 if len(smt.db.liveCache) != cacheSize { 614 t.Fatal("Trie not rolled back") 615 } 616 keys = getFreshData(20, 32) 617 values = getFreshData(20, 32) 618 smt.AtomicUpdate(keys, values) 619 values = getFreshData(20, 32) 620 smt.AtomicUpdate(keys, values) 621 if len(smt.pastTries) != 3 { 622 t.Fatal("Past tries not updated after commit") 623 } 624 smt.Stash(true) 625 if !bytes.Equal(smt.Root, root) { 626 t.Fatal("Trie not rolled back") 627 } 628 if len(smt.db.updatedNodes) != 0 { 629 t.Fatal("Trie not rolled back") 630 } 631 if len(smt.db.liveCache) != cacheSize { 632 t.Fatal("Trie not rolled back") 633 } 634 if len(smt.pastTries) != 1 { 635 t.Fatal("Past tries not updated after commit") 636 } 637 st.Close() 638 os.RemoveAll(".aergo") 639 } 640 641 func benchmark10MAccounts10Ktps(smt *Trie, b *testing.B) { 642 //b.ReportAllocs() 643 keys := getFreshData(100, 32) 644 values := getFreshData(100, 32) 645 smt.Update(keys, values) 646 fmt.Println("\nLoading b.N x 1000 accounts") 647 for i := 0; i < b.N; i++ { 648 newkeys := getFreshData(1000, 32) 649 newvalues := getFreshData(1000, 32) 650 start := time.Now() 651 smt.Update(newkeys, newvalues) 652 end := time.Now() 653 smt.Commit() 654 end2 := time.Now() 655 for j, key := range newkeys { 656 val, _ := smt.Get(key) 657 if !bytes.Equal(val, newvalues[j]) { 658 b.Fatal("new key not included") 659 } 660 } 661 end3 := time.Now() 662 elapsed := end.Sub(start) 663 elapsed2 := end2.Sub(end) 664 elapsed3 := end3.Sub(end2) 665 var m runtime.MemStats 666 runtime.ReadMemStats(&m) 667 fmt.Println(i, " : update time : ", elapsed, "commit time : ", elapsed2, 668 "\n1000 Get time : ", elapsed3, 669 "\ndb read : ", smt.LoadDbCounter, " cache read : ", smt.LoadCacheCounter, 670 "\ncache size : ", len(smt.db.liveCache), 671 "\nRAM : ", m.Sys/1024/1024, " MiB") 672 } 673 } 674 675 //go test -run=xxx -bench=. -benchmem -test.benchtime=20s 676 func BenchmarkCacheHeightLimit233(b *testing.B) { 677 dbPath := path.Join(".aergo", "db") 678 if _, err := os.Stat(dbPath); os.IsNotExist(err) { 679 _ = os.MkdirAll(dbPath, 0711) 680 } 681 st := db.NewDB(db.BadgerImpl, dbPath) 682 smt := NewTrie(nil, common.Hasher, st) 683 smt.CacheHeightLimit = 233 684 benchmark10MAccounts10Ktps(smt, b) 685 st.Close() 686 os.RemoveAll(".aergo") 687 } 688 func BenchmarkCacheHeightLimit238(b *testing.B) { 689 dbPath := path.Join(".aergo", "db") 690 if _, err := os.Stat(dbPath); os.IsNotExist(err) { 691 _ = os.MkdirAll(dbPath, 0711) 692 } 693 st := db.NewDB(db.BadgerImpl, dbPath) 694 smt := NewTrie(nil, common.Hasher, st) 695 smt.CacheHeightLimit = 238 696 benchmark10MAccounts10Ktps(smt, b) 697 st.Close() 698 os.RemoveAll(".aergo") 699 } 700 func BenchmarkCacheHeightLimit245(b *testing.B) { 701 dbPath := path.Join(".aergo", "db") 702 if _, err := os.Stat(dbPath); os.IsNotExist(err) { 703 _ = os.MkdirAll(dbPath, 0711) 704 } 705 st := db.NewDB(db.BadgerImpl, dbPath) 706 smt := NewTrie(nil, common.Hasher, st) 707 smt.CacheHeightLimit = 245 708 benchmark10MAccounts10Ktps(smt, b) 709 st.Close() 710 os.RemoveAll(".aergo") 711 } 712 713 func getFreshData(size, length int) [][]byte { 714 var data [][]byte 715 for i := 0; i < size; i++ { 716 key := make([]byte, 32) 717 _, err := rand.Read(key) 718 if err != nil { 719 panic(err) 720 } 721 data = append(data, common.Hasher(key)[:length]) 722 } 723 sort.Sort(DataArray(data)) 724 return data 725 }