github.com/Blockdaemon/celo-blockchain@v0.0.0-20200129231733-e667f6b08419/consensus/istanbul/core/roundstate_db_test.go (about) 1 package core 2 3 import ( 4 "bytes" 5 "encoding/hex" 6 blscrypto "github.com/ethereum/go-ethereum/crypto/bls" 7 "math/rand" 8 "testing" 9 10 "github.com/ethereum/go-ethereum/common" 11 "github.com/ethereum/go-ethereum/consensus/istanbul" 12 "github.com/ethereum/go-ethereum/consensus/istanbul/validator" 13 ) 14 15 func TestRSDBRoundStateDB(t *testing.T) { 16 pubkey1 := blscrypto.SerializedPublicKey{1, 2, 3} 17 pubkey2 := blscrypto.SerializedPublicKey{3, 1, 4} 18 dummyRoundState := func() RoundState { 19 valSet := validator.NewSet([]istanbul.ValidatorData{ 20 {Address: common.BytesToAddress([]byte(string(2))), BLSPublicKey: pubkey1}, 21 {Address: common.BytesToAddress([]byte(string(4))), BLSPublicKey: pubkey2}, 22 }) 23 return newRoundState(newView(2, 1), valSet, valSet.GetByIndex(0)) 24 } 25 26 t.Run("Should save view & roundState", func(t *testing.T) { 27 rsdb, _ := newRoundStateDB("", &RoundStateDBOptions{withGarbageCollector: false}) 28 rs := dummyRoundState() 29 err := rsdb.UpdateLastRoundState(rs) 30 finishOnError(t, err) 31 32 view, err := rsdb.GetLastView() 33 finishOnError(t, err) 34 assertEqualView(t, view, rs.View()) 35 36 savedRs, err := rsdb.GetRoundStateFor(view) 37 finishOnError(t, err) 38 assertEqualRoundState(t, savedRs, rs) 39 }) 40 41 t.Run("Should save view from last saved roundState", func(t *testing.T) { 42 rsdb, _ := newRoundStateDB("", &RoundStateDBOptions{withGarbageCollector: false}) 43 rs := dummyRoundState() 44 err := rsdb.UpdateLastRoundState(rs) 45 finishOnError(t, err) 46 rs.StartNewSequence(common.Big32, rs.ValidatorSet(), rs.ValidatorSet().GetByIndex(1), rs.ParentCommits()) 47 err = rsdb.UpdateLastRoundState(rs) 48 finishOnError(t, err) 49 50 view, err := rsdb.GetLastView() 51 finishOnError(t, err) 52 assertEqualView(t, view, rs.View()) 53 }) 54 55 } 56 57 func TestRSDBDeleteEntriesOlderThan(t *testing.T) { 58 pubkey1 := blscrypto.SerializedPublicKey{1, 2, 3} 59 pubkey2 := blscrypto.SerializedPublicKey{3, 1, 4} 60 createRoundState := func(view *istanbul.View) RoundState { 61 valSet := validator.NewSet([]istanbul.ValidatorData{ 62 {Address: common.BytesToAddress([]byte(string(2))), BLSPublicKey: pubkey1}, 63 {Address: common.BytesToAddress([]byte(string(4))), BLSPublicKey: pubkey2}, 64 }) 65 return newRoundState(view, valSet, valSet.GetByIndex(0)) 66 } 67 68 rsdb, _ := newRoundStateDB("", &RoundStateDBOptions{withGarbageCollector: false}) 69 for seq := uint64(1); seq <= 10; seq++ { 70 for r := uint64(0); r < 10; r++ { 71 rs := createRoundState(newView(seq, r)) 72 err := rsdb.UpdateLastRoundState(rs) 73 finishOnError(t, err) 74 } 75 } 76 77 // Will delete all entries from seq 1 78 count, err := rsdb.(*roundStateDBImpl).deleteEntriesOlderThan(newView(2, 0)) 79 if err != nil { 80 t.Fatalf("Error %v", err) 81 } 82 if count != 10 { 83 t.Fatalf("Expected 10 deleted entries but got %d", count) 84 } 85 86 // Will delete all entries from seq 2,3 and seq 4 until round 5 87 count, err = rsdb.(*roundStateDBImpl).deleteEntriesOlderThan(newView(4, 5)) 88 if err != nil { 89 t.Fatalf("Error %v", err) 90 } 91 if count != 25 { 92 t.Fatalf("Expected 10 deleted entries but got %d", count) 93 } 94 95 } 96 97 func TestRSDBKeyEncodingOrder(t *testing.T) { 98 iterations := 1000 99 100 t.Run("ViewKey enconding should decode the same view", func(t *testing.T) { 101 for i := 0; i < iterations; i++ { 102 view := newView(rand.Uint64(), rand.Uint64()) 103 key := view2Key(view) 104 parsedView := key2View(key) 105 if view.Cmp(parsedView) != 0 { 106 t.Errorf("parsedView != view: %v != %v", parsedView, view) 107 } 108 } 109 }) 110 111 t.Run("ViewKey enconding should maintain sort order", func(t *testing.T) { 112 for i := 0; i < iterations; i++ { 113 viewA := newView(rand.Uint64(), rand.Uint64()) 114 keyA := view2Key(viewA) 115 116 viewB := newView(rand.Uint64(), rand.Uint64()) 117 keyB := view2Key(viewB) 118 119 if viewA.Cmp(viewB) != bytes.Compare(keyA, keyB) { 120 t.Errorf("view order != key order (viewA: %v, viewB: %v, keyA:%v, keyB:%v )", 121 viewA, 122 viewB, 123 hex.EncodeToString(keyA), 124 hex.EncodeToString(keyB), 125 ) 126 127 } 128 } 129 }) 130 } 131 132 func TestRSDBGetOldestValidView(t *testing.T) { 133 pubkey1 := blscrypto.SerializedPublicKey{1, 2, 3} 134 pubkey2 := blscrypto.SerializedPublicKey{3, 1, 4} 135 valSet := validator.NewSet([]istanbul.ValidatorData{ 136 {Address: common.BytesToAddress([]byte(string(2))), BLSPublicKey: pubkey1}, 137 {Address: common.BytesToAddress([]byte(string(4))), BLSPublicKey: pubkey2}, 138 }) 139 sequencesToSave := uint64(100) 140 runTestCase := func(name string, viewToStore, expectedView *istanbul.View) { 141 t.Run(name, func(t *testing.T) { 142 rsdb, _ := newRoundStateDB("", &RoundStateDBOptions{ 143 withGarbageCollector: false, 144 sequencesToSave: sequencesToSave, 145 }) 146 147 if viewToStore != nil { 148 t.Logf("Saving RoundState") 149 err := rsdb.UpdateLastRoundState(newRoundState(viewToStore, valSet, valSet.GetByIndex(0))) 150 if err != nil { 151 t.Fatalf("UpdateLastRoundState error: %v", err) 152 } 153 } 154 155 view, err := rsdb.GetOldestValidView() 156 if err != nil { 157 t.Fatalf("GetOldestValidView error: %v", err) 158 } 159 if view.Cmp(expectedView) != 0 { 160 t.Errorf("Expected %v, got %v", expectedView, view) 161 } 162 }) 163 } 164 165 runTestCase("When Nothing Stored", nil, newView(0, 0)) 166 runTestCase("When StoredSequence < sequencesToSave", newView(sequencesToSave-1, 90), newView(0, 0)) 167 runTestCase("When StoredSequence == sequencesToSave", newView(sequencesToSave, 90), newView(0, 0)) 168 runTestCase("When StoredSequence > sequencesToSave", newView(sequencesToSave+1, 90), newView(1, 0)) 169 runTestCase("When StoredSequence >> sequencesToSave", newView(sequencesToSave+1000, 90), newView(1000, 0)) 170 }