github.com/iotexproject/iotex-core@v1.14.1-rc1/action/protocol/staking/bucket_validation_test.go (about) 1 package staking 2 3 import ( 4 "context" 5 "math/big" 6 "testing" 7 "time" 8 9 "github.com/golang/mock/gomock" 10 "github.com/stretchr/testify/require" 11 12 "github.com/iotexproject/iotex-core/action/protocol" 13 "github.com/iotexproject/iotex-core/blockchain/genesis" 14 "github.com/iotexproject/iotex-core/test/identityset" 15 "github.com/iotexproject/iotex-core/testutil/testdb" 16 ) 17 18 func TestValidateBucket(t *testing.T) { 19 r := require.New(t) 20 initState := func() (CandidateStateManager, *EndorsementStateManager) { 21 ctrl := gomock.NewController(t) 22 sm := testdb.NewMockStateManager(ctrl) 23 v, _, err := CreateBaseView(sm, false) 24 r.NoError(err) 25 sm.WriteView(_protocolID, v) 26 csm, err := NewCandidateStateManager(sm, false) 27 r.NoError(err) 28 esm := NewEndorsementStateManager(sm) 29 return csm, esm 30 } 31 t.Run("validate bucket owner", func(t *testing.T) { 32 csm, _ := initState() 33 owner1 := identityset.Address(1) 34 owner2 := identityset.Address(2) 35 bkt := NewVoteBucket(owner1, owner1, big.NewInt(0), 1, time.Now(), false) 36 _, err := csm.putBucketAndIndex(bkt) 37 r.NoError(err) 38 r.Nil(validateBucketOwner(bkt, owner1)) 39 r.ErrorContains(validateBucketOwner(bkt, owner2), "bucket owner does not match") 40 }) 41 t.Run("validate bucket min amount", func(t *testing.T) { 42 csm, _ := initState() 43 owner := identityset.Address(1) 44 bkt := NewVoteBucket(owner, owner, big.NewInt(10000), 1, time.Now(), false) 45 _, err := csm.putBucketAndIndex(bkt) 46 r.NoError(err) 47 r.Nil(validateBucketMinAmount(bkt, big.NewInt(1000))) 48 r.ErrorContains(validateBucketMinAmount(bkt, big.NewInt(100000)), "bucket amount is unsufficient") 49 }) 50 t.Run("validate bucket staked", func(t *testing.T) { 51 csm, _ := initState() 52 owner := identityset.Address(1) 53 // staked bucket 54 bkt := NewVoteBucket(owner, owner, big.NewInt(10000), 1, time.Now(), false) 55 _, err := csm.putBucketAndIndex(bkt) 56 r.NoError(err) 57 r.Nil(validateBucketStake(bkt, true)) 58 r.ErrorContains(validateBucketStake(bkt, false), "bucket is staked") 59 // unstaked bucket 60 bkt.UnstakeStartTime = bkt.StakeStartTime.Add(1 * time.Hour) 61 _, err = csm.putBucketAndIndex(bkt) 62 r.NoError(err) 63 r.Nil(validateBucketStake(bkt, false)) 64 r.ErrorContains(validateBucketStake(bkt, true), "bucket is unstaked") 65 }) 66 t.Run("validate bucket candidate", func(t *testing.T) { 67 csm, _ := initState() 68 owner := identityset.Address(1) 69 candidate1 := identityset.Address(2) 70 candidate2 := identityset.Address(3) 71 bkt := NewVoteBucket(candidate1, owner, big.NewInt(10000), 1, time.Now(), false) 72 _, err := csm.putBucketAndIndex(bkt) 73 r.NoError(err) 74 r.Nil(validateBucketCandidate(bkt, candidate1)) 75 r.ErrorContains(validateBucketCandidate(bkt, candidate2), "bucket is not voted to the candidate") 76 }) 77 t.Run("validate bucket self staked", func(t *testing.T) { 78 csm, _ := initState() 79 owner := identityset.Address(1) 80 candidate := identityset.Address(2) 81 // not selfstaked bucket 82 bkt := NewVoteBucket(candidate, owner, big.NewInt(10000), 1, time.Now(), false) 83 bktIdx, err := csm.putBucketAndIndex(bkt) 84 r.NoError(err) 85 ctx := protocol.WithBlockCtx(context.Background(), 86 protocol.BlockCtx{ 87 BlockHeight: 0, 88 }, 89 ) 90 ctx = protocol.WithFeatureCtx(genesis.WithGenesisContext(ctx, genesis.Default)) 91 featureCtx := protocol.MustGetFeatureCtx(ctx) 92 r.Nil(validateBucketSelfStake(featureCtx, csm, bkt, false)) 93 r.ErrorContains(validateBucketSelfStake(featureCtx, csm, bkt, true), "bucket is not self staking") 94 // selfstaked bucket 95 r.NoError(csm.Upsert(&Candidate{ 96 Owner: candidate, 97 Operator: candidate, 98 Reward: candidate, 99 Name: "test", 100 Votes: big.NewInt(10000), 101 SelfStakeBucketIdx: bktIdx, 102 SelfStake: big.NewInt(10000), 103 })) 104 r.Nil(validateBucketSelfStake(featureCtx, csm, bkt, true)) 105 r.ErrorContains(validateBucketSelfStake(featureCtx, csm, bkt, false), "self staking bucket cannot be processed") 106 }) 107 t.Run("validate bucket endorsed", func(t *testing.T) { 108 csm, esm := initState() 109 owner := identityset.Address(1) 110 candidate := identityset.Address(2) 111 bkt := NewVoteBucket(candidate, owner, big.NewInt(10000), 1, time.Now(), false) 112 bktIdx, err := csm.putBucketAndIndex(bkt) 113 r.NoError(err) 114 blkHeight := uint64(10) 115 // not endorsed bucket 116 r.Nil(validateBucketWithoutEndorsement(esm, bkt, blkHeight)) 117 r.ErrorContains(validateBucketWithEndorsement(esm, bkt, blkHeight), "bucket is not an endorse bucket") 118 // endorsed bucket 119 r.NoError(esm.Put(bktIdx, &Endorsement{ExpireHeight: endorsementNotExpireHeight})) 120 r.Nil(validateBucketWithEndorsement(esm, bkt, blkHeight)) 121 r.ErrorContains(validateBucketWithoutEndorsement(esm, bkt, blkHeight), "bucket is still endorsed") 122 // unendorsing bucket 123 r.NoError(esm.Put(bktIdx, &Endorsement{ExpireHeight: blkHeight + 1})) 124 r.Nil(validateBucketWithEndorsement(esm, bkt, blkHeight)) 125 r.ErrorContains(validateBucketWithoutEndorsement(esm, bkt, blkHeight), "bucket is still endorsed") 126 // endorse expired bucket 127 r.NoError(esm.Put(bktIdx, &Endorsement{ExpireHeight: blkHeight})) 128 r.Nil(validateBucketWithoutEndorsement(esm, bkt, blkHeight)) 129 r.ErrorContains(validateBucketWithEndorsement(esm, bkt, blkHeight), "bucket is not an endorse bucket") 130 }) 131 }