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  }