github.com/iotexproject/iotex-core@v1.14.1-rc1/blockindex/contractstaking/dirty_cache_test.go (about) 1 package contractstaking 2 3 import ( 4 "math/big" 5 "testing" 6 7 "github.com/stretchr/testify/require" 8 9 "github.com/iotexproject/iotex-core/blockchain/genesis" 10 "github.com/iotexproject/iotex-core/db/batch" 11 "github.com/iotexproject/iotex-core/pkg/util/byteutil" 12 "github.com/iotexproject/iotex-core/test/identityset" 13 ) 14 15 func TestContractStakingDirty_getBucketType(t *testing.T) { 16 require := require.New(t) 17 clean := newContractStakingCache(Config{CalculateVoteWeight: calculateVoteWeightGen(genesis.Default.VoteWeightCalConsts)}) 18 dirty := newContractStakingDirty(clean) 19 20 // no bucket type 21 bt, ok := dirty.getBucketType(1) 22 require.False(ok) 23 require.Nil(bt) 24 25 // bucket type in clean cache 26 clean.PutBucketType(1, &BucketType{Amount: big.NewInt(100), Duration: 100, ActivatedAt: 1}) 27 bt, ok = dirty.getBucketType(1) 28 require.True(ok) 29 require.EqualValues(100, bt.Amount.Int64()) 30 require.EqualValues(100, bt.Duration) 31 require.EqualValues(1, bt.ActivatedAt) 32 33 // added bucket type 34 dirty.addBucketType(2, &BucketType{Amount: big.NewInt(200), Duration: 200, ActivatedAt: 2}) 35 bt, ok = dirty.getBucketType(2) 36 require.True(ok) 37 require.EqualValues(200, bt.Amount.Int64()) 38 require.EqualValues(200, bt.Duration) 39 require.EqualValues(2, bt.ActivatedAt) 40 } 41 42 func TestContractStakingDirty_getBucketInfo(t *testing.T) { 43 require := require.New(t) 44 clean := newContractStakingCache(Config{CalculateVoteWeight: calculateVoteWeightGen(genesis.Default.VoteWeightCalConsts)}) 45 dirty := newContractStakingDirty(clean) 46 47 // no bucket info 48 bi, ok := dirty.getBucketInfo(1) 49 require.False(ok) 50 require.Nil(bi) 51 52 // bucket info in clean cache 53 clean.putBucketType(1, &BucketType{Amount: big.NewInt(100), Duration: 100, ActivatedAt: 1}) 54 clean.PutBucketInfo(1, &bucketInfo{TypeIndex: 1, CreatedAt: 1, UnlockedAt: maxBlockNumber, UnstakedAt: maxBlockNumber, Delegate: identityset.Address(1), Owner: identityset.Address(2)}) 55 bi, ok = dirty.getBucketInfo(1) 56 require.True(ok) 57 require.EqualValues(1, bi.TypeIndex) 58 require.EqualValues(1, bi.CreatedAt) 59 require.EqualValues(maxBlockNumber, bi.UnlockedAt) 60 require.EqualValues(maxBlockNumber, bi.UnstakedAt) 61 require.Equal(identityset.Address(1), bi.Delegate) 62 require.Equal(identityset.Address(2), bi.Owner) 63 64 // added bucket info 65 require.NoError(dirty.addBucketType(2, &BucketType{Amount: big.NewInt(200), Duration: 200, ActivatedAt: 2})) 66 require.NoError(dirty.addBucketInfo(2, &bucketInfo{TypeIndex: 2, CreatedAt: 2, UnlockedAt: maxBlockNumber, UnstakedAt: maxBlockNumber, Delegate: identityset.Address(2), Owner: identityset.Address(3)})) 67 bi, ok = dirty.getBucketInfo(2) 68 require.True(ok) 69 require.EqualValues(2, bi.TypeIndex) 70 require.EqualValues(2, bi.CreatedAt) 71 require.EqualValues(maxBlockNumber, bi.UnlockedAt) 72 require.EqualValues(maxBlockNumber, bi.UnstakedAt) 73 require.Equal(identityset.Address(2), bi.Delegate) 74 require.Equal(identityset.Address(3), bi.Owner) 75 76 // modified bucket info 77 require.NoError(dirty.updateBucketInfo(1, &bucketInfo{TypeIndex: 2, CreatedAt: 3, UnlockedAt: maxBlockNumber, UnstakedAt: maxBlockNumber, Delegate: identityset.Address(3), Owner: identityset.Address(4)})) 78 bi, ok = dirty.getBucketInfo(1) 79 require.True(ok) 80 require.EqualValues(2, bi.TypeIndex) 81 require.EqualValues(3, bi.CreatedAt) 82 require.EqualValues(maxBlockNumber, bi.UnlockedAt) 83 require.EqualValues(maxBlockNumber, bi.UnstakedAt) 84 require.Equal(identityset.Address(3), bi.Delegate) 85 require.Equal(identityset.Address(4), bi.Owner) 86 87 // removed bucket info 88 require.NoError(dirty.deleteBucketInfo(1)) 89 bi, ok = dirty.getBucketInfo(1) 90 require.False(ok) 91 require.Nil(bi) 92 } 93 94 func TestContractStakingDirty_matchBucketType(t *testing.T) { 95 require := require.New(t) 96 clean := newContractStakingCache(Config{CalculateVoteWeight: calculateVoteWeightGen(genesis.Default.VoteWeightCalConsts)}) 97 dirty := newContractStakingDirty(clean) 98 99 // no bucket type 100 id, bt, ok := dirty.matchBucketType(big.NewInt(100), 100) 101 require.False(ok) 102 require.Nil(bt) 103 require.EqualValues(0, id) 104 105 // bucket type in clean cache 106 clean.PutBucketType(1, &BucketType{Amount: big.NewInt(100), Duration: 100, ActivatedAt: 1}) 107 id, bt, ok = dirty.matchBucketType(big.NewInt(100), 100) 108 require.True(ok) 109 require.EqualValues(100, bt.Amount.Int64()) 110 require.EqualValues(100, bt.Duration) 111 require.EqualValues(1, bt.ActivatedAt) 112 require.EqualValues(1, id) 113 114 // added bucket type 115 require.NoError(dirty.addBucketType(2, &BucketType{Amount: big.NewInt(200), Duration: 200, ActivatedAt: 2})) 116 id, bt, ok = dirty.matchBucketType(big.NewInt(200), 200) 117 require.True(ok) 118 require.EqualValues(200, bt.Amount.Int64()) 119 require.EqualValues(200, bt.Duration) 120 require.EqualValues(2, bt.ActivatedAt) 121 require.EqualValues(2, id) 122 } 123 124 func TestContractStakingDirty_getBucketTypeCount(t *testing.T) { 125 require := require.New(t) 126 clean := newContractStakingCache(Config{CalculateVoteWeight: calculateVoteWeightGen(genesis.Default.VoteWeightCalConsts)}) 127 dirty := newContractStakingDirty(clean) 128 129 // no bucket type 130 count := dirty.getBucketTypeCount() 131 require.EqualValues(0, count) 132 133 // bucket type in clean cache 134 clean.PutBucketType(1, &BucketType{Amount: big.NewInt(100), Duration: 100, ActivatedAt: 1}) 135 count = dirty.getBucketTypeCount() 136 require.EqualValues(1, count) 137 138 // added bucket type 139 require.NoError(dirty.addBucketType(2, &BucketType{Amount: big.NewInt(200), Duration: 200, ActivatedAt: 2})) 140 count = dirty.getBucketTypeCount() 141 require.EqualValues(2, count) 142 } 143 144 func TestContractStakingDirty_finalize(t *testing.T) { 145 require := require.New(t) 146 clean := newContractStakingCache(Config{CalculateVoteWeight: calculateVoteWeightGen(genesis.Default.VoteWeightCalConsts)}) 147 dirty := newContractStakingDirty(clean) 148 149 // no dirty data 150 batcher, delta := dirty.finalize() 151 require.EqualValues(1, batcher.Size()) 152 info, err := batcher.Entry(0) 153 require.NoError(err) 154 require.EqualValues(_StakingNS, info.Namespace()) 155 require.EqualValues(batch.Put, info.WriteType()) 156 require.EqualValues(_stakingTotalBucketCountKey, info.Key()) 157 require.EqualValues(byteutil.Uint64ToBytesBigEndian(0), info.Value()) 158 for _, d := range delta.BucketTypeDelta() { 159 require.Len(d, 0) 160 } 161 for _, d := range delta.BucketTypeDelta() { 162 require.Len(d, 0) 163 } 164 165 // added bucket type 166 bt := &BucketType{Amount: big.NewInt(100), Duration: 100, ActivatedAt: 1} 167 require.NoError(dirty.addBucketType(1, bt)) 168 batcher, delta = dirty.finalize() 169 require.EqualValues(2, batcher.Size()) 170 info, err = batcher.Entry(1) 171 require.NoError(err) 172 require.EqualValues(_StakingBucketTypeNS, info.Namespace()) 173 require.EqualValues(batch.Put, info.WriteType()) 174 require.EqualValues(byteutil.Uint64ToBytesBigEndian(1), info.Key()) 175 require.EqualValues(bt.Serialize(), info.Value()) 176 btDelta := delta.BucketTypeDelta() 177 require.NotNil(btDelta[deltaStateAdded]) 178 require.Len(btDelta[deltaStateAdded], 1) 179 require.EqualValues(100, btDelta[deltaStateAdded][1].Amount.Int64()) 180 require.EqualValues(100, btDelta[deltaStateAdded][1].Duration) 181 require.EqualValues(1, btDelta[deltaStateAdded][1].ActivatedAt) 182 183 // add bucket info 184 bi := &bucketInfo{TypeIndex: 1, CreatedAt: 2, UnlockedAt: 3, UnstakedAt: 4, Delegate: identityset.Address(1), Owner: identityset.Address(2)} 185 require.NoError(dirty.addBucketInfo(1, bi)) 186 batcher, delta = dirty.finalize() 187 require.EqualValues(3, batcher.Size()) 188 info, err = batcher.Entry(2) 189 require.NoError(err) 190 require.EqualValues(_StakingBucketInfoNS, info.Namespace()) 191 require.EqualValues(batch.Put, info.WriteType()) 192 require.EqualValues(byteutil.Uint64ToBytesBigEndian(1), info.Key()) 193 require.EqualValues(bi.Serialize(), info.Value()) 194 biDelta := delta.BucketInfoDelta() 195 require.NotNil(biDelta[deltaStateAdded]) 196 require.Len(biDelta[deltaStateAdded], 1) 197 require.EqualValues(1, biDelta[deltaStateAdded][1].TypeIndex) 198 require.EqualValues(2, biDelta[deltaStateAdded][1].CreatedAt) 199 require.EqualValues(3, biDelta[deltaStateAdded][1].UnlockedAt) 200 require.EqualValues(4, biDelta[deltaStateAdded][1].UnstakedAt) 201 require.EqualValues(identityset.Address(1).String(), biDelta[deltaStateAdded][1].Delegate.String()) 202 require.EqualValues(identityset.Address(2).String(), biDelta[deltaStateAdded][1].Owner.String()) 203 204 } 205 206 func TestContractStakingDirty_noSideEffectOnClean(t *testing.T) { 207 require := require.New(t) 208 clean := newContractStakingCache(Config{CalculateVoteWeight: calculateVoteWeightGen(genesis.Default.VoteWeightCalConsts)}) 209 dirty := newContractStakingDirty(clean) 210 211 // add bucket type to dirty cache 212 require.NoError(dirty.addBucketType(1, &BucketType{Amount: big.NewInt(100), Duration: 100, ActivatedAt: 1})) 213 // check that clean cache is not affected 214 bt, ok := clean.getBucketType(1) 215 require.False(ok) 216 require.Nil(bt) 217 218 // add bucket info to dirty cache 219 require.NoError(dirty.addBucketInfo(1, &bucketInfo{TypeIndex: 1, CreatedAt: 1, UnlockedAt: maxBlockNumber, UnstakedAt: maxBlockNumber, Delegate: identityset.Address(1), Owner: identityset.Address(2)})) 220 // check that clean cache is not affected 221 bi, ok := clean.getBucketInfo(1) 222 require.False(ok) 223 require.Nil(bi) 224 225 // update bucket type in dirty cache 226 require.NoError(dirty.updateBucketType(1, &BucketType{Amount: big.NewInt(200), Duration: 200, ActivatedAt: 2})) 227 // check that clean cache is not affected 228 bt, ok = clean.getBucketType(1) 229 require.False(ok) 230 require.Nil(bt) 231 232 // update bucket info in dirty cache 233 require.NoError(dirty.updateBucketInfo(1, &bucketInfo{TypeIndex: 2, CreatedAt: 3, UnlockedAt: maxBlockNumber, UnstakedAt: maxBlockNumber, Delegate: identityset.Address(3), Owner: identityset.Address(4)})) 234 // check that clean cache is not affected 235 bi, ok = clean.getBucketInfo(1) 236 require.False(ok) 237 require.Nil(bi) 238 239 // update bucket info existed in clean cache 240 clean.PutBucketInfo(2, &bucketInfo{TypeIndex: 1, CreatedAt: 1, UnlockedAt: maxBlockNumber, UnstakedAt: maxBlockNumber, Delegate: identityset.Address(1), Owner: identityset.Address(2)}) 241 // update bucket info in dirty cache 242 require.NoError(dirty.updateBucketInfo(2, &bucketInfo{TypeIndex: 1, CreatedAt: 3, UnlockedAt: maxBlockNumber, UnstakedAt: maxBlockNumber, Delegate: identityset.Address(3), Owner: identityset.Address(4)})) 243 // check that clean cache is not affected 244 bi, ok = clean.getBucketInfo(2) 245 require.True(ok) 246 require.EqualValues(1, bi.TypeIndex) 247 require.EqualValues(1, bi.CreatedAt) 248 require.EqualValues(maxBlockNumber, bi.UnlockedAt) 249 require.EqualValues(maxBlockNumber, bi.UnstakedAt) 250 require.EqualValues(identityset.Address(1).String(), bi.Delegate.String()) 251 require.EqualValues(identityset.Address(2).String(), bi.Owner.String()) 252 253 // remove bucket info existed in clean cache 254 clean.PutBucketInfo(3, &bucketInfo{TypeIndex: 1, CreatedAt: 1, UnlockedAt: maxBlockNumber, UnstakedAt: maxBlockNumber, Delegate: identityset.Address(1), Owner: identityset.Address(2)}) 255 // remove bucket info from dirty cache 256 require.NoError(dirty.deleteBucketInfo(3)) 257 // check that clean cache is not affected 258 bi, ok = clean.getBucketInfo(3) 259 require.True(ok) 260 require.EqualValues(1, bi.TypeIndex) 261 require.EqualValues(1, bi.CreatedAt) 262 require.EqualValues(maxBlockNumber, bi.UnlockedAt) 263 require.EqualValues(maxBlockNumber, bi.UnstakedAt) 264 require.EqualValues(identityset.Address(1).String(), bi.Delegate.String()) 265 require.EqualValues(identityset.Address(2).String(), bi.Owner.String()) 266 267 }