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  }