918 lines
32 KiB
Go
918 lines
32 KiB
Go
package keeper_test
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"cosmossdk.io/math"
|
|
"github.com/stretchr/testify/suite"
|
|
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
|
"pgregory.net/rapid"
|
|
|
|
"github.com/cosmos/cosmos-sdk/baseapp"
|
|
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
|
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
|
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
|
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
|
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
|
|
banktestutil "github.com/cosmos/cosmos-sdk/x/bank/testutil"
|
|
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
|
|
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
|
stakingtestutil "github.com/cosmos/cosmos-sdk/x/staking/testutil"
|
|
|
|
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
|
)
|
|
|
|
var (
|
|
validator1 = "cosmosvaloper1qqqryrs09ggeuqszqygqyqd2tgqmsqzewacjj7"
|
|
validatorAddr1, _ = sdk.ValAddressFromBech32(validator1)
|
|
validator2 = "cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj"
|
|
validatorAddr2, _ = sdk.ValAddressFromBech32(validator2)
|
|
delegator1 = "cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl"
|
|
delegatorAddr1 = sdk.MustAccAddressFromBech32(delegator1)
|
|
delegator2 = "cosmos139f7kncmglres2nf3h4hc4tade85ekfr8sulz5"
|
|
delegatorAddr2 = sdk.MustAccAddressFromBech32(delegator2)
|
|
)
|
|
|
|
type DeterministicTestSuite struct {
|
|
suite.Suite
|
|
|
|
ctx sdk.Context
|
|
stakingKeeper *stakingkeeper.Keeper
|
|
bankKeeper bankkeeper.BaseKeeper
|
|
accountKeeper authkeeper.AccountKeeper
|
|
queryClient stakingtypes.QueryClient
|
|
amt1 math.Int
|
|
amt2 math.Int
|
|
}
|
|
|
|
func (s *DeterministicTestSuite) SetupTest() {
|
|
var interfaceRegistry codectypes.InterfaceRegistry
|
|
|
|
app, err := simtestutil.Setup(
|
|
stakingtestutil.AppConfig,
|
|
&s.bankKeeper,
|
|
&s.accountKeeper,
|
|
&s.stakingKeeper,
|
|
&interfaceRegistry,
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
s.ctx = app.BaseApp.NewContext(false, tmproto.Header{Height: 1, Time: time.Now()}).WithGasMeter(sdk.NewInfiniteGasMeter())
|
|
|
|
queryHelper := baseapp.NewQueryServerTestHelper(s.ctx, interfaceRegistry)
|
|
stakingtypes.RegisterQueryServer(queryHelper, stakingkeeper.Querier{Keeper: s.stakingKeeper})
|
|
s.queryClient = stakingtypes.NewQueryClient(queryHelper)
|
|
|
|
s.amt1 = s.stakingKeeper.TokensFromConsensusPower(s.ctx, 101)
|
|
s.amt2 = s.stakingKeeper.TokensFromConsensusPower(s.ctx, 102)
|
|
}
|
|
|
|
func TestDeterministicTestSuite(t *testing.T) {
|
|
suite.Run(t, new(DeterministicTestSuite))
|
|
}
|
|
|
|
func durationGenerator() *rapid.Generator[time.Duration] {
|
|
return rapid.Custom(func(t *rapid.T) time.Duration {
|
|
now := time.Now()
|
|
// range from current time to 365days.
|
|
duration := rapid.Int64Range(now.Unix(), 365*24*60*60*now.Unix()).Draw(t, "time")
|
|
return time.Duration(duration)
|
|
})
|
|
}
|
|
|
|
func pubKeyGenerator() *rapid.Generator[ed25519.PubKey] {
|
|
return rapid.Custom(func(t *rapid.T) ed25519.PubKey {
|
|
pkBz := rapid.SliceOfN(rapid.Byte(), 32, 32).Draw(t, "hex")
|
|
return ed25519.PubKey{Key: pkBz}
|
|
})
|
|
}
|
|
|
|
func bondTypeGenerator() *rapid.Generator[stakingtypes.BondStatus] {
|
|
bond_types := []stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Unbonded, stakingtypes.Unbonding}
|
|
return rapid.Custom(func(t *rapid.T) stakingtypes.BondStatus {
|
|
return bond_types[rapid.IntRange(0, 2).Draw(t, "range")]
|
|
})
|
|
}
|
|
|
|
// createValidator creates a validator with random values.
|
|
func (suite *DeterministicTestSuite) createValidator(t *rapid.T) stakingtypes.Validator {
|
|
pubkey := pubKeyGenerator().Draw(t, "pubkey")
|
|
pubkeyAny, err := codectypes.NewAnyWithValue(&pubkey)
|
|
suite.Require().NoError(err)
|
|
return stakingtypes.Validator{
|
|
OperatorAddress: sdk.ValAddress(testdata.AddressGenerator(t).Draw(t, "address")).String(),
|
|
ConsensusPubkey: pubkeyAny,
|
|
Jailed: rapid.Bool().Draw(t, "jailed"),
|
|
Status: bondTypeGenerator().Draw(t, "bond-status"),
|
|
Tokens: sdk.NewInt(rapid.Int64Min(10000).Draw(t, "tokens")),
|
|
DelegatorShares: sdk.NewDecWithPrec(rapid.Int64Range(1, 100).Draw(t, "commission"), 2),
|
|
Description: stakingtypes.NewDescription(
|
|
rapid.StringN(5, 250, 255).Draw(t, "moniker"),
|
|
rapid.StringN(5, 250, 255).Draw(t, "identity"),
|
|
rapid.StringN(5, 250, 255).Draw(t, "website"),
|
|
rapid.StringN(5, 250, 255).Draw(t, "securityContact"),
|
|
rapid.StringN(5, 250, 255).Draw(t, "details"),
|
|
),
|
|
UnbondingHeight: rapid.Int64Min(1).Draw(t, "unbonding-height"),
|
|
UnbondingTime: time.Now().Add(durationGenerator().Draw(t, "duration")),
|
|
Commission: stakingtypes.NewCommission(
|
|
sdk.NewDecWithPrec(rapid.Int64Range(0, 100).Draw(t, "rate"), 2),
|
|
sdk.NewDecWithPrec(rapid.Int64Range(0, 100).Draw(t, "max-rate"), 2),
|
|
sdk.NewDecWithPrec(rapid.Int64Range(0, 100).Draw(t, "max-change-rate"), 2),
|
|
),
|
|
MinSelfDelegation: sdk.NewInt(rapid.Int64Min(1).Draw(t, "tokens")),
|
|
}
|
|
}
|
|
|
|
// createAndSetValidatorWithStatus creates a validator with random values but with given status and sets to the state
|
|
func (suite *DeterministicTestSuite) createAndSetValidatorWithStatus(t *rapid.T, status stakingtypes.BondStatus) stakingtypes.Validator {
|
|
val := suite.createValidator(t)
|
|
val.Status = status
|
|
suite.setValidator(val)
|
|
return val
|
|
}
|
|
|
|
// createAndSetValidator creates a validator with random values and sets to the state
|
|
func (suite *DeterministicTestSuite) createAndSetValidator(t *rapid.T) stakingtypes.Validator {
|
|
val := suite.createValidator(t)
|
|
suite.setValidator(val)
|
|
return val
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) setValidator(validator stakingtypes.Validator) {
|
|
suite.stakingKeeper.SetValidator(suite.ctx, validator)
|
|
suite.stakingKeeper.SetValidatorByPowerIndex(suite.ctx, validator)
|
|
suite.stakingKeeper.SetValidatorByConsAddr(suite.ctx, validator)
|
|
suite.Require().NoError(suite.stakingKeeper.Hooks().AfterValidatorCreated(suite.ctx, validator.GetOperator()))
|
|
|
|
delegatorAddress := sdk.AccAddress(validator.GetOperator())
|
|
coins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, validator.BondedTokens()))
|
|
banktestutil.FundAccount(suite.bankKeeper, suite.ctx, delegatorAddress, coins)
|
|
|
|
_, err := suite.stakingKeeper.Delegate(suite.ctx, delegatorAddress, validator.BondedTokens(), stakingtypes.Unbonded, validator, true)
|
|
suite.Require().NoError(err)
|
|
}
|
|
|
|
// getStaticValidator creates a validator with hard-coded values and sets to the state.
|
|
func (suite *DeterministicTestSuite) getStaticValidator() stakingtypes.Validator {
|
|
pubkey := ed25519.PubKey{Key: []byte{24, 179, 242, 2, 151, 3, 34, 6, 1, 11, 0, 194, 202, 201, 77, 1, 167, 40, 249, 115, 32, 97, 18, 1, 1, 127, 255, 103, 13, 1, 34, 1}}
|
|
pubkeyAny, err := codectypes.NewAnyWithValue(&pubkey)
|
|
suite.Require().NoError(err)
|
|
|
|
validator := stakingtypes.Validator{
|
|
OperatorAddress: validator1,
|
|
ConsensusPubkey: pubkeyAny,
|
|
Jailed: false,
|
|
Status: stakingtypes.Bonded,
|
|
Tokens: sdk.NewInt(100),
|
|
DelegatorShares: sdk.NewDecWithPrec(5, 2),
|
|
Description: stakingtypes.NewDescription(
|
|
"moniker",
|
|
"identity",
|
|
"website",
|
|
"securityContact",
|
|
"details",
|
|
),
|
|
UnbondingHeight: 10,
|
|
UnbondingTime: time.Date(2022, 10, 1, 0, 0, 0, 0, time.UTC),
|
|
Commission: stakingtypes.NewCommission(
|
|
sdk.NewDecWithPrec(5, 2),
|
|
sdk.NewDecWithPrec(5, 2),
|
|
sdk.NewDecWithPrec(5, 2),
|
|
),
|
|
MinSelfDelegation: sdk.NewInt(10),
|
|
}
|
|
|
|
suite.setValidator(validator)
|
|
return validator
|
|
}
|
|
|
|
// getStaticValidator2 creates a validator with hard-coded values and sets to the state.
|
|
func (suite *DeterministicTestSuite) getStaticValidator2() stakingtypes.Validator {
|
|
pubkey := ed25519.PubKey{Key: []byte{40, 249, 115, 32, 97, 18, 1, 1, 127, 255, 103, 13, 1, 34, 1, 24, 179, 242, 2, 151, 3, 34, 6, 1, 11, 0, 194, 202, 201, 77, 1, 167}}
|
|
pubkeyAny, err := codectypes.NewAnyWithValue(&pubkey)
|
|
suite.Require().NoError(err)
|
|
|
|
validator := stakingtypes.Validator{
|
|
OperatorAddress: validator2,
|
|
ConsensusPubkey: pubkeyAny,
|
|
Jailed: true,
|
|
Status: stakingtypes.Bonded,
|
|
Tokens: sdk.NewInt(10012),
|
|
DelegatorShares: sdk.NewDecWithPrec(96, 2),
|
|
Description: stakingtypes.NewDescription(
|
|
"moniker",
|
|
"identity",
|
|
"website",
|
|
"securityContact",
|
|
"details",
|
|
),
|
|
UnbondingHeight: 100132,
|
|
UnbondingTime: time.Date(2025, 10, 1, 0, 0, 0, 0, time.UTC),
|
|
Commission: stakingtypes.NewCommission(
|
|
sdk.NewDecWithPrec(15, 2),
|
|
sdk.NewDecWithPrec(59, 2),
|
|
sdk.NewDecWithPrec(51, 2),
|
|
),
|
|
MinSelfDelegation: sdk.NewInt(1),
|
|
}
|
|
suite.setValidator(validator)
|
|
|
|
return validator
|
|
}
|
|
|
|
// createDelegationAndDelegate funds the delegator account with a random delegation in range 100-1000 and delegates.
|
|
func (suite *DeterministicTestSuite) createDelegationAndDelegate(t *rapid.T, delegator sdk.AccAddress, validator stakingtypes.Validator) (newShares math.LegacyDec, err error) {
|
|
amt := suite.stakingKeeper.TokensFromConsensusPower(suite.ctx, rapid.Int64Range(100, 1000).Draw(t, "amount"))
|
|
return suite.fundAccountAndDelegate(delegator, validator, amt)
|
|
}
|
|
|
|
// fundAccountAndDelegate funds the delegator account with the specified delegation and delegates.
|
|
func (suite *DeterministicTestSuite) fundAccountAndDelegate(delegator sdk.AccAddress, validator stakingtypes.Validator, amt math.Int) (newShares math.LegacyDec, err error) {
|
|
coins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, amt))
|
|
|
|
suite.Require().NoError(suite.bankKeeper.MintCoins(suite.ctx, minttypes.ModuleName, coins))
|
|
banktestutil.FundAccount(suite.bankKeeper, suite.ctx, delegator, coins)
|
|
|
|
shares, err := suite.stakingKeeper.Delegate(suite.ctx, delegator, amt, stakingtypes.Unbonded, validator, true)
|
|
return shares, err
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) runValidatorIterations(
|
|
req *stakingtypes.QueryValidatorRequest,
|
|
prevValRes *stakingtypes.QueryValidatorResponse,
|
|
gasConsumed uint64,
|
|
) {
|
|
for i := 0; i < 1000; i++ {
|
|
before := suite.ctx.GasMeter().GasConsumed()
|
|
res, err := suite.queryClient.Validator(suite.ctx, req)
|
|
suite.Require().Equal(suite.ctx.GasMeter().GasConsumed()-before, gasConsumed)
|
|
|
|
suite.Require().NoError(err)
|
|
suite.Require().Equal(res, prevValRes)
|
|
}
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) TestGRPCValidator() {
|
|
rapid.Check(suite.T(), func(t *rapid.T) {
|
|
val := suite.createAndSetValidator(t)
|
|
req := &stakingtypes.QueryValidatorRequest{
|
|
ValidatorAddr: val.OperatorAddress,
|
|
}
|
|
|
|
before := suite.ctx.GasMeter().GasConsumed()
|
|
res, err := suite.queryClient.Validator(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.runValidatorIterations(req, res, suite.ctx.GasMeter().GasConsumed()-before)
|
|
})
|
|
|
|
val := suite.getStaticValidator()
|
|
req := &stakingtypes.QueryValidatorRequest{
|
|
ValidatorAddr: val.OperatorAddress,
|
|
}
|
|
|
|
before := suite.ctx.GasMeter().GasConsumed()
|
|
res, err := suite.queryClient.Validator(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.runValidatorIterations(req, res, suite.ctx.GasMeter().GasConsumed()-before)
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) runValidatorsIterations(
|
|
req *stakingtypes.QueryValidatorsRequest,
|
|
prevRes *stakingtypes.QueryValidatorsResponse,
|
|
) {
|
|
for i := 0; i < 1000; i++ {
|
|
res, err := suite.queryClient.Validators(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
suite.Require().NotNil(res)
|
|
suite.Require().Equal(res, prevRes)
|
|
}
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) TestGRPCValidators() {
|
|
validatorStatus := []string{stakingtypes.BondStatusBonded, stakingtypes.BondStatusUnbonded, stakingtypes.BondStatusUnbonding, ""}
|
|
rapid.Check(suite.T(), func(t *rapid.T) {
|
|
valsCount := rapid.IntRange(1, 3).Draw(t, "num-validators")
|
|
for i := 0; i < valsCount; i++ {
|
|
suite.createAndSetValidator(t)
|
|
}
|
|
|
|
req := &stakingtypes.QueryValidatorsRequest{
|
|
Status: validatorStatus[rapid.IntRange(0, 3).Draw(t, "status")],
|
|
Pagination: testdata.PaginationGenerator(t, uint64(valsCount)).Draw(t, "pagination"),
|
|
}
|
|
res, err := suite.queryClient.Validators(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.runValidatorsIterations(req, res)
|
|
})
|
|
|
|
suite.SetupTest() // reset
|
|
suite.getStaticValidator()
|
|
suite.getStaticValidator2()
|
|
|
|
req := &stakingtypes.QueryValidatorsRequest{}
|
|
res, err := suite.queryClient.Validators(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.runValidatorsIterations(req, res)
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) runValidatorDelegationsIterations(req *stakingtypes.QueryValidatorDelegationsRequest, prevDels *stakingtypes.QueryValidatorDelegationsResponse) {
|
|
for i := 0; i < 1000; i++ {
|
|
res, err := suite.queryClient.ValidatorDelegations(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.Require().Equal(res, prevDels)
|
|
}
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) TestGRPCValidatorDelegations() {
|
|
rapid.Check(suite.T(), func(t *rapid.T) {
|
|
validator := suite.createAndSetValidatorWithStatus(t, stakingtypes.Bonded)
|
|
numDels := rapid.IntRange(1, 5).Draw(t, "num-dels")
|
|
|
|
for i := 0; i < numDels; i++ {
|
|
delegator := testdata.AddressGenerator(t).Draw(t, "delegator")
|
|
_, err := suite.createDelegationAndDelegate(t, delegator, validator)
|
|
suite.Require().NoError(err)
|
|
}
|
|
|
|
req := &stakingtypes.QueryValidatorDelegationsRequest{
|
|
ValidatorAddr: validator.OperatorAddress,
|
|
Pagination: testdata.PaginationGenerator(t, uint64(numDels)).Draw(t, "pagination"),
|
|
}
|
|
|
|
res, err := suite.queryClient.ValidatorDelegations(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
suite.runValidatorDelegationsIterations(req, res)
|
|
})
|
|
|
|
suite.SetupTest() // reset
|
|
|
|
validator := suite.getStaticValidator()
|
|
|
|
_, err := suite.fundAccountAndDelegate(delegatorAddr1, validator, suite.amt1)
|
|
suite.Require().NoError(err)
|
|
|
|
_, err = suite.fundAccountAndDelegate(delegatorAddr2, validator, suite.amt2)
|
|
suite.Require().NoError(err)
|
|
|
|
req := &stakingtypes.QueryValidatorDelegationsRequest{
|
|
ValidatorAddr: validator.OperatorAddress,
|
|
}
|
|
|
|
res, err := suite.queryClient.ValidatorDelegations(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
suite.runValidatorDelegationsIterations(req, res)
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) runValidatorUnbondingDelegationsIterations(req *stakingtypes.QueryValidatorUnbondingDelegationsRequest, prevRes *stakingtypes.QueryValidatorUnbondingDelegationsResponse) {
|
|
for i := 0; i < 1000; i++ {
|
|
res, err := suite.queryClient.ValidatorUnbondingDelegations(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
suite.Require().Equal(res, prevRes)
|
|
}
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) TestGRPCValidatorUnbondingDelegations() {
|
|
rapid.Check(suite.T(), func(t *rapid.T) {
|
|
validator := suite.createAndSetValidatorWithStatus(t, stakingtypes.Bonded)
|
|
numDels := rapid.IntRange(1, 3).Draw(t, "num-dels")
|
|
|
|
for i := 0; i < numDels; i++ {
|
|
delegator := testdata.AddressGenerator(t).Draw(t, "delegator")
|
|
shares, err := suite.createDelegationAndDelegate(t, delegator, validator)
|
|
suite.Require().NoError(err)
|
|
|
|
_, err = suite.stakingKeeper.Undelegate(suite.ctx, delegator, validator.GetOperator(), shares)
|
|
suite.Require().NoError(err)
|
|
}
|
|
|
|
req := &stakingtypes.QueryValidatorUnbondingDelegationsRequest{
|
|
ValidatorAddr: validator.OperatorAddress,
|
|
Pagination: testdata.PaginationGenerator(t, uint64(numDels)).Draw(t, "pagination"),
|
|
}
|
|
res, err := suite.queryClient.ValidatorUnbondingDelegations(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.runValidatorUnbondingDelegationsIterations(req, res)
|
|
})
|
|
|
|
suite.SetupTest() // reset
|
|
|
|
validator := suite.getStaticValidator()
|
|
shares1, err := suite.fundAccountAndDelegate(delegatorAddr1, validator, suite.amt1)
|
|
suite.Require().NoError(err)
|
|
|
|
_, err = suite.stakingKeeper.Undelegate(suite.ctx, delegatorAddr1, validatorAddr1, shares1)
|
|
suite.Require().NoError(err)
|
|
|
|
shares2, err := suite.fundAccountAndDelegate(delegatorAddr2, validator, suite.amt2)
|
|
suite.Require().NoError(err)
|
|
|
|
_, err = suite.stakingKeeper.Undelegate(suite.ctx, delegatorAddr2, validatorAddr1, shares2)
|
|
suite.Require().NoError(err)
|
|
|
|
req := &stakingtypes.QueryValidatorUnbondingDelegationsRequest{
|
|
ValidatorAddr: validator.OperatorAddress,
|
|
}
|
|
res, err := suite.queryClient.ValidatorUnbondingDelegations(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.runValidatorUnbondingDelegationsIterations(req, res)
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) runDelegationIteratons(req *stakingtypes.QueryDelegationRequest, prevRes *stakingtypes.QueryDelegationResponse) {
|
|
for i := 0; i < 1000; i++ {
|
|
res, err := suite.queryClient.Delegation(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
suite.Require().Equal(res, prevRes)
|
|
}
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) TestGRPCDelegation() {
|
|
rapid.Check(suite.T(), func(t *rapid.T) {
|
|
validator := suite.createAndSetValidatorWithStatus(t, stakingtypes.Bonded)
|
|
delegator := testdata.AddressGenerator(t).Draw(t, "delegator")
|
|
_, err := suite.createDelegationAndDelegate(t, delegator, validator)
|
|
suite.Require().NoError(err)
|
|
|
|
req := &stakingtypes.QueryDelegationRequest{
|
|
ValidatorAddr: validator.OperatorAddress,
|
|
DelegatorAddr: delegator.String(),
|
|
}
|
|
|
|
res, err := suite.queryClient.Delegation(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
suite.runDelegationIteratons(req, res)
|
|
})
|
|
|
|
suite.SetupTest() // reset
|
|
|
|
validator := suite.getStaticValidator()
|
|
_, err := suite.fundAccountAndDelegate(delegatorAddr1, validator, suite.amt1)
|
|
suite.Require().NoError(err)
|
|
|
|
req := &stakingtypes.QueryDelegationRequest{
|
|
ValidatorAddr: validator.OperatorAddress,
|
|
DelegatorAddr: delegator1,
|
|
}
|
|
|
|
res, err := suite.queryClient.Delegation(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
suite.runDelegationIteratons(req, res)
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) runUnbondingDelegationIterations(req *stakingtypes.QueryUnbondingDelegationRequest, prevRes *stakingtypes.QueryUnbondingDelegationResponse) {
|
|
for i := 0; i < 1000; i++ {
|
|
res, err := suite.queryClient.UnbondingDelegation(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
suite.Require().Equal(res, prevRes)
|
|
}
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) TestGRPCUnbondingDelegation() {
|
|
rapid.Check(suite.T(), func(t *rapid.T) {
|
|
validator := suite.createAndSetValidatorWithStatus(t, stakingtypes.Bonded)
|
|
delegator := testdata.AddressGenerator(t).Draw(t, "delegator")
|
|
shares, err := suite.createDelegationAndDelegate(t, delegator, validator)
|
|
suite.Require().NoError(err)
|
|
|
|
_, err = suite.stakingKeeper.Undelegate(suite.ctx, delegator, validator.GetOperator(), shares)
|
|
suite.Require().NoError(err)
|
|
|
|
req := &stakingtypes.QueryUnbondingDelegationRequest{
|
|
ValidatorAddr: validator.OperatorAddress,
|
|
DelegatorAddr: delegator.String(),
|
|
}
|
|
res, err := suite.queryClient.UnbondingDelegation(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.runUnbondingDelegationIterations(req, res)
|
|
})
|
|
|
|
suite.SetupTest() // reset
|
|
validator := suite.getStaticValidator()
|
|
|
|
shares1, err := suite.fundAccountAndDelegate(delegatorAddr1, validator, suite.amt1)
|
|
suite.Require().NoError(err)
|
|
|
|
_, err = suite.stakingKeeper.Undelegate(suite.ctx, delegatorAddr1, validatorAddr1, shares1)
|
|
suite.Require().NoError(err)
|
|
|
|
req := &stakingtypes.QueryUnbondingDelegationRequest{
|
|
ValidatorAddr: validator.OperatorAddress,
|
|
DelegatorAddr: delegator1,
|
|
}
|
|
res, err := suite.queryClient.UnbondingDelegation(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.runUnbondingDelegationIterations(req, res)
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) runDelegatorDelegationsIterations(req *stakingtypes.QueryDelegatorDelegationsRequest, prevDels *stakingtypes.QueryDelegatorDelegationsResponse) {
|
|
for i := 0; i < 1000; i++ {
|
|
res, err := suite.queryClient.DelegatorDelegations(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.Require().Equal(res, prevDels)
|
|
}
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) TestGRPCDelegatorDelegations() {
|
|
rapid.Check(suite.T(), func(t *rapid.T) {
|
|
numVals := rapid.IntRange(1, 3).Draw(t, "num-dels")
|
|
delegator := testdata.AddressGenerator(t).Draw(t, "delegator")
|
|
|
|
for i := 0; i < numVals; i++ {
|
|
validator := suite.createAndSetValidatorWithStatus(t, stakingtypes.Bonded)
|
|
_, err := suite.createDelegationAndDelegate(t, delegator, validator)
|
|
suite.Require().NoError(err)
|
|
}
|
|
|
|
req := &stakingtypes.QueryDelegatorDelegationsRequest{
|
|
DelegatorAddr: delegator.String(),
|
|
Pagination: testdata.PaginationGenerator(t, uint64(numVals)).Draw(t, "pagination"),
|
|
}
|
|
|
|
res, err := suite.queryClient.DelegatorDelegations(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
suite.runDelegatorDelegationsIterations(req, res)
|
|
})
|
|
|
|
suite.SetupTest() // reset
|
|
|
|
validator := suite.getStaticValidator()
|
|
_, err := suite.fundAccountAndDelegate(delegatorAddr1, validator, suite.amt1)
|
|
suite.Require().NoError(err)
|
|
|
|
req := &stakingtypes.QueryDelegatorDelegationsRequest{
|
|
DelegatorAddr: delegator1,
|
|
}
|
|
|
|
res, err := suite.queryClient.DelegatorDelegations(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
suite.runDelegatorDelegationsIterations(req, res)
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) runDelegatorValidatorIterations(req *stakingtypes.QueryDelegatorValidatorRequest, prevDels *stakingtypes.QueryDelegatorValidatorResponse) {
|
|
for i := 0; i < 1000; i++ {
|
|
res, err := suite.queryClient.DelegatorValidator(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.Require().Equal(res, prevDels)
|
|
}
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) TestGRPCDelegatorValidator() {
|
|
rapid.Check(suite.T(), func(t *rapid.T) {
|
|
validator := suite.createAndSetValidatorWithStatus(t, stakingtypes.Bonded)
|
|
|
|
delegator := testdata.AddressGenerator(t).Draw(t, "delegator")
|
|
_, err := suite.createDelegationAndDelegate(t, delegator, validator)
|
|
suite.Require().NoError(err)
|
|
|
|
req := &stakingtypes.QueryDelegatorValidatorRequest{
|
|
DelegatorAddr: delegator.String(),
|
|
ValidatorAddr: validator.OperatorAddress,
|
|
}
|
|
|
|
res, err := suite.queryClient.DelegatorValidator(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
suite.runDelegatorValidatorIterations(req, res)
|
|
})
|
|
|
|
suite.SetupTest() // reset
|
|
|
|
validator := suite.getStaticValidator()
|
|
_, err := suite.fundAccountAndDelegate(delegatorAddr1, validator, suite.amt1)
|
|
|
|
suite.Require().NoError(err)
|
|
|
|
req := &stakingtypes.QueryDelegatorValidatorRequest{
|
|
DelegatorAddr: delegator1,
|
|
ValidatorAddr: validator.OperatorAddress,
|
|
}
|
|
|
|
res, err := suite.queryClient.DelegatorValidator(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
suite.runDelegatorValidatorIterations(req, res)
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) runDelegatorUnbondingDelegationsIterations(req *stakingtypes.QueryDelegatorUnbondingDelegationsRequest, prevRes *stakingtypes.QueryDelegatorUnbondingDelegationsResponse) {
|
|
for i := 0; i < 1000; i++ {
|
|
res, err := suite.queryClient.DelegatorUnbondingDelegations(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
suite.Require().Equal(res, prevRes)
|
|
}
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) TestGRPCDelegatorUnbondingDelegations() {
|
|
rapid.Check(suite.T(), func(t *rapid.T) {
|
|
numVals := rapid.IntRange(1, 5).Draw(t, "num-vals")
|
|
delegator := testdata.AddressGenerator(t).Draw(t, "delegator")
|
|
|
|
for i := 0; i < numVals; i++ {
|
|
validator := suite.createAndSetValidatorWithStatus(t, stakingtypes.Bonded)
|
|
shares, err := suite.createDelegationAndDelegate(t, delegator, validator)
|
|
suite.Require().NoError(err)
|
|
|
|
_, err = suite.stakingKeeper.Undelegate(suite.ctx, delegator, validator.GetOperator(), shares)
|
|
suite.Require().NoError(err)
|
|
}
|
|
|
|
req := &stakingtypes.QueryDelegatorUnbondingDelegationsRequest{
|
|
DelegatorAddr: delegator.String(),
|
|
Pagination: testdata.PaginationGenerator(t, uint64(numVals)).Draw(t, "pagination"),
|
|
}
|
|
res, err := suite.queryClient.DelegatorUnbondingDelegations(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.runDelegatorUnbondingDelegationsIterations(req, res)
|
|
})
|
|
|
|
suite.SetupTest() // reset
|
|
|
|
validator := suite.getStaticValidator()
|
|
shares1, err := suite.fundAccountAndDelegate(delegatorAddr1, validator, suite.amt1)
|
|
suite.Require().NoError(err)
|
|
|
|
_, err = suite.stakingKeeper.Undelegate(suite.ctx, delegatorAddr1, validatorAddr1, shares1)
|
|
suite.Require().NoError(err)
|
|
|
|
req := &stakingtypes.QueryDelegatorUnbondingDelegationsRequest{
|
|
DelegatorAddr: delegator1,
|
|
}
|
|
res, err := suite.queryClient.DelegatorUnbondingDelegations(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.runDelegatorUnbondingDelegationsIterations(req, res)
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) runHistoricalInfoIterations(req *stakingtypes.QueryHistoricalInfoRequest, prevRes *stakingtypes.QueryHistoricalInfoResponse) {
|
|
for i := 0; i < 1000; i++ {
|
|
res, err := suite.queryClient.HistoricalInfo(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
suite.Require().Equal(res, prevRes)
|
|
}
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) TestGRPCHistoricalInfo() {
|
|
rapid.Check(suite.T(), func(t *rapid.T) {
|
|
numVals := rapid.IntRange(1, 5).Draw(t, "num-vals")
|
|
vals := make(stakingtypes.Validators, 0, numVals)
|
|
for i := 0; i < numVals; i++ {
|
|
validator := suite.createAndSetValidatorWithStatus(t, stakingtypes.Bonded)
|
|
vals = append(vals, validator)
|
|
}
|
|
|
|
historicalInfo := stakingtypes.HistoricalInfo{
|
|
Header: tmproto.Header{},
|
|
Valset: vals,
|
|
}
|
|
|
|
height := rapid.Int64Min(0).Draw(t, "height")
|
|
|
|
suite.stakingKeeper.SetHistoricalInfo(
|
|
suite.ctx,
|
|
height,
|
|
&historicalInfo,
|
|
)
|
|
|
|
req := &stakingtypes.QueryHistoricalInfoRequest{
|
|
Height: height,
|
|
}
|
|
res, err := suite.queryClient.HistoricalInfo(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.runHistoricalInfoIterations(req, res)
|
|
})
|
|
|
|
suite.SetupTest() // reset
|
|
|
|
validator := suite.getStaticValidator()
|
|
|
|
historicalInfo := stakingtypes.HistoricalInfo{
|
|
Header: tmproto.Header{},
|
|
Valset: []stakingtypes.Validator{validator},
|
|
}
|
|
|
|
height := int64(127)
|
|
|
|
suite.stakingKeeper.SetHistoricalInfo(
|
|
suite.ctx,
|
|
height,
|
|
&historicalInfo,
|
|
)
|
|
|
|
req := &stakingtypes.QueryHistoricalInfoRequest{
|
|
Height: height,
|
|
}
|
|
res, err := suite.queryClient.HistoricalInfo(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.runHistoricalInfoIterations(req, res)
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) runDelegatorValidatorsIterations(req *stakingtypes.QueryDelegatorValidatorsRequest, prevDels *stakingtypes.QueryDelegatorValidatorsResponse) {
|
|
for i := 0; i < 1000; i++ {
|
|
res, err := suite.queryClient.DelegatorValidators(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.Require().Equal(res, prevDels)
|
|
}
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) TestGRPCDelegatorValidators() {
|
|
rapid.Check(suite.T(), func(t *rapid.T) {
|
|
numVals := rapid.IntRange(1, 3).Draw(t, "num-dels")
|
|
delegator := testdata.AddressGenerator(t).Draw(t, "delegator")
|
|
|
|
for i := 0; i < numVals; i++ {
|
|
validator := suite.createAndSetValidatorWithStatus(t, stakingtypes.Bonded)
|
|
_, err := suite.createDelegationAndDelegate(t, delegator, validator)
|
|
suite.Require().NoError(err)
|
|
}
|
|
|
|
req := &stakingtypes.QueryDelegatorValidatorsRequest{
|
|
DelegatorAddr: delegator.String(),
|
|
Pagination: testdata.PaginationGenerator(t, uint64(numVals)).Draw(t, "pagination"),
|
|
}
|
|
|
|
res, err := suite.queryClient.DelegatorValidators(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
suite.runDelegatorValidatorsIterations(req, res)
|
|
})
|
|
|
|
suite.SetupTest() // reset
|
|
|
|
validator := suite.getStaticValidator()
|
|
|
|
_, err := suite.fundAccountAndDelegate(delegatorAddr1, validator, suite.amt1)
|
|
suite.Require().NoError(err)
|
|
|
|
req := &stakingtypes.QueryDelegatorValidatorsRequest{
|
|
DelegatorAddr: delegator1,
|
|
}
|
|
|
|
res, err := suite.queryClient.DelegatorValidators(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
suite.runDelegatorValidatorsIterations(req, res)
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) runPoolIterations(req *stakingtypes.QueryPoolRequest, prevDels *stakingtypes.QueryPoolResponse) {
|
|
for i := 0; i < 1000; i++ {
|
|
res, err := suite.queryClient.Pool(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.Require().Equal(res, prevDels)
|
|
}
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) TestGRPCPool() {
|
|
rapid.Check(suite.T(), func(t *rapid.T) {
|
|
suite.createAndSetValidator(t)
|
|
|
|
req := &stakingtypes.QueryPoolRequest{}
|
|
res, err := suite.queryClient.Pool(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.runPoolIterations(req, res)
|
|
})
|
|
|
|
suite.SetupTest() // reset
|
|
suite.getStaticValidator()
|
|
|
|
req := &stakingtypes.QueryPoolRequest{}
|
|
|
|
res, err := suite.queryClient.Pool(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
suite.runPoolIterations(req, res)
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) runRedelegationsIterations(req *stakingtypes.QueryRedelegationsRequest, prevDels *stakingtypes.QueryRedelegationsResponse) {
|
|
for i := 0; i < 1000; i++ {
|
|
res, err := suite.queryClient.Redelegations(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.Require().Equal(res, prevDels)
|
|
}
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) TestGRPCRedelegations() {
|
|
rapid.Check(suite.T(), func(t *rapid.T) {
|
|
validator := suite.createAndSetValidatorWithStatus(t, stakingtypes.Bonded)
|
|
srcValAddr, err := sdk.ValAddressFromBech32(validator.OperatorAddress)
|
|
suite.Require().NoError(err)
|
|
|
|
validator2 := suite.createAndSetValidatorWithStatus(t, stakingtypes.Bonded)
|
|
dstValAddr, err := sdk.ValAddressFromBech32(validator2.OperatorAddress)
|
|
suite.Require().NoError(err)
|
|
|
|
numDels := rapid.IntRange(1, 5).Draw(t, "num-dels")
|
|
|
|
delegator := testdata.AddressGenerator(t).Draw(t, "delegator")
|
|
shares, err := suite.createDelegationAndDelegate(t, delegator, validator)
|
|
suite.Require().NoError(err)
|
|
|
|
_, err = suite.stakingKeeper.BeginRedelegation(suite.ctx, delegator, srcValAddr, dstValAddr, shares)
|
|
suite.Require().NoError(err)
|
|
|
|
var req *stakingtypes.QueryRedelegationsRequest
|
|
|
|
reqType := rapid.IntRange(0, 2).Draw(t, "req-type")
|
|
switch reqType {
|
|
case 0: // queries redelegation with delegator, source and destination validators combination.
|
|
req = &stakingtypes.QueryRedelegationsRequest{
|
|
DelegatorAddr: delegator.String(),
|
|
SrcValidatorAddr: srcValAddr.String(),
|
|
DstValidatorAddr: dstValAddr.String(),
|
|
}
|
|
case 1: // queries redelegations of source validator.
|
|
req = &stakingtypes.QueryRedelegationsRequest{
|
|
SrcValidatorAddr: srcValAddr.String(),
|
|
}
|
|
case 2: // queries all redelegations of a delegator.
|
|
req = &stakingtypes.QueryRedelegationsRequest{
|
|
DelegatorAddr: delegator.String(),
|
|
}
|
|
}
|
|
|
|
req.Pagination = testdata.PaginationGenerator(t, uint64(numDels)).Draw(t, "pagination")
|
|
|
|
res, err := suite.queryClient.Redelegations(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
suite.runRedelegationsIterations(req, res)
|
|
})
|
|
|
|
suite.SetupTest() // reset
|
|
|
|
validator := suite.getStaticValidator()
|
|
_ = suite.getStaticValidator2()
|
|
|
|
shares, err := suite.fundAccountAndDelegate(delegatorAddr1, validator, suite.amt1)
|
|
suite.Require().NoError(err)
|
|
|
|
_, err = suite.stakingKeeper.BeginRedelegation(suite.ctx, delegatorAddr1, validatorAddr1, validatorAddr2, shares)
|
|
suite.Require().NoError(err)
|
|
|
|
req := &stakingtypes.QueryRedelegationsRequest{
|
|
DelegatorAddr: delegator1,
|
|
SrcValidatorAddr: validator1,
|
|
DstValidatorAddr: validator2,
|
|
}
|
|
|
|
res, err := suite.queryClient.Redelegations(suite.ctx, req)
|
|
suite.Require().NoError(err)
|
|
suite.runRedelegationsIterations(req, res)
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) runParamsIterations(prevParams stakingtypes.Params) {
|
|
for i := 0; i < 1000; i++ {
|
|
res, err := suite.queryClient.Params(suite.ctx, &stakingtypes.QueryParamsRequest{})
|
|
suite.Require().NoError(err)
|
|
suite.Require().NotNil(res)
|
|
|
|
suite.Require().Equal(res.Params, prevParams)
|
|
prevParams = res.Params
|
|
}
|
|
}
|
|
|
|
func (suite *DeterministicTestSuite) TestGRPCParams() {
|
|
rapid.Check(suite.T(), func(t *rapid.T) {
|
|
params := stakingtypes.Params{
|
|
BondDenom: rapid.StringMatching(sdk.DefaultCoinDenomRegex()).Draw(t, "bond-denom"),
|
|
UnbondingTime: durationGenerator().Draw(t, "duration"),
|
|
MaxValidators: rapid.Uint32Min(1).Draw(t, "max-validators"),
|
|
MaxEntries: rapid.Uint32Min(1).Draw(t, "max-entries"),
|
|
HistoricalEntries: rapid.Uint32Min(1).Draw(t, "historical-entries"),
|
|
MinCommissionRate: sdk.NewDecWithPrec(rapid.Int64Range(0, 100).Draw(t, "commission"), 2),
|
|
}
|
|
|
|
err := suite.stakingKeeper.SetParams(suite.ctx, params)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.runParamsIterations(params)
|
|
})
|
|
|
|
params := stakingtypes.Params{
|
|
BondDenom: "denom",
|
|
UnbondingTime: time.Hour,
|
|
MaxValidators: 85,
|
|
MaxEntries: 5,
|
|
HistoricalEntries: 5,
|
|
MinCommissionRate: sdk.NewDecWithPrec(5, 2),
|
|
}
|
|
|
|
err := suite.stakingKeeper.SetParams(suite.ctx, params)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.runParamsIterations(params)
|
|
}
|