@@ -96,11 +96,15 @@ type tester struct {
96
96
snapStorages map [common.Hash ]map [common.Hash ]map [common.Hash ][]byte
97
97
}
98
98
99
- func newTester (t * testing.T ) * tester {
99
+ func newTester (t * testing.T , historyLimit uint64 ) * tester {
100
100
var (
101
101
disk , _ = rawdb .NewDatabaseWithFreezer (rawdb .NewMemoryDatabase (), t .TempDir (), "" , false )
102
- db = New (disk , & Config {CleanCacheSize : 256 * 1024 , DirtyCacheSize : 256 * 1024 })
103
- obj = & tester {
102
+ db = New (disk , & Config {
103
+ StateHistory : historyLimit ,
104
+ CleanCacheSize : 256 * 1024 ,
105
+ DirtyCacheSize : 256 * 1024 ,
106
+ })
107
+ obj = & tester {
104
108
db : db ,
105
109
preimages : make (map [common.Hash ]common.Address ),
106
110
accounts : make (map [common.Hash ][]byte ),
@@ -376,7 +380,7 @@ func (t *tester) bottomIndex() int {
376
380
377
381
func TestDatabaseRollback (t * testing.T ) {
378
382
// Verify state histories
379
- tester := newTester (t )
383
+ tester := newTester (t , 0 )
380
384
defer tester .release ()
381
385
382
386
if err := tester .verifyHistory (); err != nil {
@@ -402,7 +406,7 @@ func TestDatabaseRollback(t *testing.T) {
402
406
403
407
func TestDatabaseRecoverable (t * testing.T ) {
404
408
var (
405
- tester = newTester (t )
409
+ tester = newTester (t , 0 )
406
410
index = tester .bottomIndex ()
407
411
)
408
412
defer tester .release ()
@@ -440,7 +444,7 @@ func TestDatabaseRecoverable(t *testing.T) {
440
444
}
441
445
442
446
func TestDisable (t * testing.T ) {
443
- tester := newTester (t )
447
+ tester := newTester (t , 0 )
444
448
defer tester .release ()
445
449
446
450
_ , stored := rawdb .ReadAccountTrieNode (tester .db .diskdb , nil )
@@ -476,7 +480,7 @@ func TestDisable(t *testing.T) {
476
480
}
477
481
478
482
func TestCommit (t * testing.T ) {
479
- tester := newTester (t )
483
+ tester := newTester (t , 0 )
480
484
defer tester .release ()
481
485
482
486
if err := tester .db .Commit (tester .lastHash (), false ); err != nil {
@@ -500,7 +504,7 @@ func TestCommit(t *testing.T) {
500
504
}
501
505
502
506
func TestJournal (t * testing.T ) {
503
- tester := newTester (t )
507
+ tester := newTester (t , 0 )
504
508
defer tester .release ()
505
509
506
510
if err := tester .db .Journal (tester .lastHash ()); err != nil {
@@ -524,7 +528,7 @@ func TestJournal(t *testing.T) {
524
528
}
525
529
526
530
func TestCorruptedJournal (t * testing.T ) {
527
- tester := newTester (t )
531
+ tester := newTester (t , 0 )
528
532
defer tester .release ()
529
533
530
534
if err := tester .db .Journal (tester .lastHash ()); err != nil {
@@ -553,6 +557,35 @@ func TestCorruptedJournal(t *testing.T) {
553
557
}
554
558
}
555
559
560
+ // TestTailTruncateHistory function is designed to test a specific edge case where,
561
+ // when history objects are removed from the end, it should trigger a state flush
562
+ // if the ID of the new tail object is even higher than the persisted state ID.
563
+ //
564
+ // For example, let's say the ID of the persistent state is 10, and the current
565
+ // history objects range from ID(5) to ID(15). As we accumulate six more objects,
566
+ // the history will expand to cover ID(11) to ID(21). ID(11) then becomes the
567
+ // oldest history object, and its ID is even higher than the stored state.
568
+ //
569
+ // In this scenario, it is mandatory to update the persistent state before
570
+ // truncating the tail histories. This ensures that the ID of the persistent state
571
+ // always falls within the range of [oldest-history-id, latest-history-id].
572
+ func TestTailTruncateHistory (t * testing.T ) {
573
+ tester := newTester (t , 10 )
574
+ defer tester .release ()
575
+
576
+ tester .db .Close ()
577
+ tester .db = New (tester .db .diskdb , & Config {StateHistory : 10 })
578
+
579
+ head , err := tester .db .freezer .Ancients ()
580
+ if err != nil {
581
+ t .Fatalf ("Failed to obtain freezer head" )
582
+ }
583
+ stored := rawdb .ReadPersistentStateID (tester .db .diskdb )
584
+ if head != stored {
585
+ t .Fatalf ("Failed to truncate excess history object above, stored: %d, head: %d" , stored , head )
586
+ }
587
+ }
588
+
556
589
// copyAccounts returns a deep-copied account set of the provided one.
557
590
func copyAccounts (set map [common.Hash ][]byte ) map [common.Hash ][]byte {
558
591
copied := make (map [common.Hash ][]byte , len (set ))
0 commit comments