refactor: staking module using mocks (#12827)
## Description Closes: #12504 --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] added `!` to the type prefix if API or client breaking change - [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/main/CONTRIBUTING.md#pr-targeting)) - [ ] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/main/docs/building-modules) - [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/main/CONTRIBUTING.md#testing) - [ ] added a changelog entry to `CHANGELOG.md` - [ ] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [ ] reviewed "Files changed" and left comments if necessary - [ ] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable)
This commit is contained in:
parent
d11196aad0
commit
bc274d8d95
@ -24,3 +24,4 @@ $mockgen_cmd -source=x/evidence/types/expected_keepers.go -package testutil -des
|
||||
$mockgen_cmd -source=x/slashing/types/expected_keepers.go -package testutil -destination x/slashing/testutil/expected_keepers_mocks.go
|
||||
$mockgen_cmd -source=x/genutil/types/expected_keepers.go -package testutil -destination x/genutil/testutil/expected_keepers_mocks.go
|
||||
$mockgen_cmd -source=x/gov/testutil/expected_keepers.go -package testutil -destination x/gov/testutil/expected_keepers_mocks.go
|
||||
$mockgen_cmd -source=x/staking/types/expected_keepers.go -package testutil -destination x/staking/testutil/expected_keepers_mocks.go
|
||||
|
||||
@ -8,13 +8,11 @@ import (
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/network"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/client/testutil"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
func TestIntegrationTestSuite(t *testing.T) {
|
||||
cfg := network.DefaultConfig(simapp.NewTestNetworkFixture)
|
||||
cfg.NumValidators = 2
|
||||
suite.Run(t, testutil.NewIntegrationTestSuite(cfg))
|
||||
suite.Run(t, NewIntegrationTestSuite(cfg))
|
||||
}
|
||||
|
||||
98
tests/integration/staking/keeper/delegation_test.go
Normal file
98
tests/integration/staking/keeper/delegation_test.go
Normal file
@ -0,0 +1,98 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/teststaking"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
func TestUnbondingDelegationsMaxEntries(t *testing.T) {
|
||||
_, app, ctx := createTestInput(t)
|
||||
|
||||
addrDels := simapp.AddTestAddrsIncremental(app, ctx, 1, sdk.NewInt(10000))
|
||||
addrVals := simtestutil.ConvertAddrsToValAddrs(addrDels)
|
||||
|
||||
startTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 10)
|
||||
|
||||
bondDenom := app.StakingKeeper.BondDenom(ctx)
|
||||
notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens))))
|
||||
app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
|
||||
|
||||
// create a validator and a delegator to that validator
|
||||
validator := teststaking.NewValidator(t, addrVals[0], PKs[0])
|
||||
|
||||
validator, issuedShares := validator.AddTokensFromDel(startTokens)
|
||||
require.Equal(t, startTokens, issuedShares.RoundInt())
|
||||
|
||||
validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)
|
||||
require.True(math.IntEq(t, startTokens, validator.BondedTokens()))
|
||||
require.True(t, validator.IsBonded())
|
||||
|
||||
delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares)
|
||||
app.StakingKeeper.SetDelegation(ctx, delegation)
|
||||
|
||||
maxEntries := app.StakingKeeper.MaxEntries(ctx)
|
||||
|
||||
oldBonded := app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount
|
||||
oldNotBonded := app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount
|
||||
|
||||
// should all pass
|
||||
var completionTime time.Time
|
||||
for i := int64(0); i < int64(maxEntries); i++ {
|
||||
var err error
|
||||
ctx = ctx.WithBlockHeight(i)
|
||||
completionTime, err = app.StakingKeeper.Undelegate(ctx, addrDels[0], addrVals[0], math.LegacyNewDec(1))
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
newBonded := app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount
|
||||
newNotBonded := app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, newBonded, oldBonded.SubRaw(int64(maxEntries))))
|
||||
require.True(math.IntEq(t, newNotBonded, oldNotBonded.AddRaw(int64(maxEntries))))
|
||||
|
||||
oldBonded = app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount
|
||||
oldNotBonded = app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount
|
||||
|
||||
// an additional unbond should fail due to max entries
|
||||
_, err := app.StakingKeeper.Undelegate(ctx, addrDels[0], addrVals[0], math.LegacyNewDec(1))
|
||||
require.Error(t, err)
|
||||
|
||||
newBonded = app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount
|
||||
newNotBonded = app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount
|
||||
|
||||
require.True(math.IntEq(t, newBonded, oldBonded))
|
||||
require.True(math.IntEq(t, newNotBonded, oldNotBonded))
|
||||
|
||||
// mature unbonding delegations
|
||||
ctx = ctx.WithBlockTime(completionTime)
|
||||
_, err = app.StakingKeeper.CompleteUnbonding(ctx, addrDels[0], addrVals[0])
|
||||
require.NoError(t, err)
|
||||
|
||||
newBonded = app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount
|
||||
newNotBonded = app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, newBonded, oldBonded))
|
||||
require.True(math.IntEq(t, newNotBonded, oldNotBonded.SubRaw(int64(maxEntries))))
|
||||
|
||||
oldNotBonded = app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount
|
||||
|
||||
// unbonding should work again
|
||||
_, err = app.StakingKeeper.Undelegate(ctx, addrDels[0], addrVals[0], math.LegacyNewDec(1))
|
||||
require.NoError(t, err)
|
||||
|
||||
newBonded = app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount
|
||||
newNotBonded = app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, newBonded, oldBonded.SubRaw(1)))
|
||||
require.True(math.IntEq(t, newNotBonded, oldNotBonded.AddRaw(1)))
|
||||
}
|
||||
740
tests/integration/staking/keeper/grpc_query_test.go
Normal file
740
tests/integration/staking/keeper/grpc_query_test.go
Normal file
@ -0,0 +1,740 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
gocontext "context"
|
||||
"fmt"
|
||||
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/query"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
func (suite *IntegrationTestSuite) TestGRPCQueryValidators() {
|
||||
queryClient, vals := suite.queryClient, suite.vals
|
||||
var req *types.QueryValidatorsRequest
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
numVals int
|
||||
hasNext bool
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
func() {
|
||||
req = &types.QueryValidatorsRequest{}
|
||||
},
|
||||
true,
|
||||
|
||||
len(vals) + 1, // +1 validator from genesis state
|
||||
false,
|
||||
},
|
||||
{
|
||||
"empty status returns all the validators",
|
||||
func() {
|
||||
req = &types.QueryValidatorsRequest{Status: ""}
|
||||
},
|
||||
true,
|
||||
len(vals) + 1, // +1 validator from genesis state
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid request",
|
||||
func() {
|
||||
req = &types.QueryValidatorsRequest{Status: "test"}
|
||||
},
|
||||
false,
|
||||
0,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
func() {
|
||||
req = &types.QueryValidatorsRequest{
|
||||
Status: types.Bonded.String(),
|
||||
Pagination: &query.PageRequest{Limit: 1, CountTotal: true},
|
||||
}
|
||||
},
|
||||
true,
|
||||
1,
|
||||
true,
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
tc.malleate()
|
||||
valsResp, err := queryClient.Validators(gocontext.Background(), req)
|
||||
if tc.expPass {
|
||||
suite.NoError(err)
|
||||
suite.NotNil(valsResp)
|
||||
suite.Equal(tc.numVals, len(valsResp.Validators))
|
||||
suite.Equal(uint64(len(vals))+1, valsResp.Pagination.Total) // +1 validator from genesis state
|
||||
|
||||
if tc.hasNext {
|
||||
suite.NotNil(valsResp.Pagination.NextKey)
|
||||
} else {
|
||||
suite.Nil(valsResp.Pagination.NextKey)
|
||||
}
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *IntegrationTestSuite) TestGRPCQueryDelegatorValidators() {
|
||||
app, ctx, queryClient, addrs := suite.app, suite.ctx, suite.queryClient, suite.addrs
|
||||
params := app.StakingKeeper.GetParams(ctx)
|
||||
delValidators := app.StakingKeeper.GetDelegatorValidators(ctx, addrs[0], params.MaxValidators)
|
||||
var req *types.QueryDelegatorValidatorsRequest
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
func() {
|
||||
req = &types.QueryDelegatorValidatorsRequest{}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
func() {
|
||||
req = &types.QueryDelegatorValidatorsRequest{
|
||||
DelegatorAddr: addrs[0].String(),
|
||||
Pagination: &query.PageRequest{Limit: 1, CountTotal: true},
|
||||
}
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
tc.malleate()
|
||||
res, err := queryClient.DelegatorValidators(gocontext.Background(), req)
|
||||
if tc.expPass {
|
||||
suite.NoError(err)
|
||||
suite.Equal(1, len(res.Validators))
|
||||
suite.NotNil(res.Pagination.NextKey)
|
||||
suite.Equal(uint64(len(delValidators)), res.Pagination.Total)
|
||||
} else {
|
||||
suite.Error(err)
|
||||
suite.Nil(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *IntegrationTestSuite) TestGRPCQueryDelegatorValidator() {
|
||||
queryClient, addrs, vals := suite.queryClient, suite.addrs, suite.vals
|
||||
addr := addrs[1]
|
||||
addrVal, addrVal1 := vals[0].OperatorAddress, vals[1].OperatorAddress
|
||||
var req *types.QueryDelegatorValidatorRequest
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
func() {
|
||||
req = &types.QueryDelegatorValidatorRequest{}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid delegator, validator pair",
|
||||
func() {
|
||||
req = &types.QueryDelegatorValidatorRequest{
|
||||
DelegatorAddr: addr.String(),
|
||||
ValidatorAddr: addrVal,
|
||||
}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
func() {
|
||||
req = &types.QueryDelegatorValidatorRequest{
|
||||
DelegatorAddr: addr.String(),
|
||||
ValidatorAddr: addrVal1,
|
||||
}
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
tc.malleate()
|
||||
res, err := queryClient.DelegatorValidator(gocontext.Background(), req)
|
||||
if tc.expPass {
|
||||
suite.NoError(err)
|
||||
suite.Equal(addrVal1, res.Validator.OperatorAddress)
|
||||
} else {
|
||||
suite.Error(err)
|
||||
suite.Nil(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *IntegrationTestSuite) TestGRPCQueryDelegation() {
|
||||
app, ctx, queryClient, addrs, vals := suite.app, suite.ctx, suite.queryClient, suite.addrs, suite.vals
|
||||
addrAcc, addrAcc1 := addrs[0], addrs[1]
|
||||
addrVal := vals[0].OperatorAddress
|
||||
valAddr, err := sdk.ValAddressFromBech32(addrVal)
|
||||
suite.NoError(err)
|
||||
delegation, found := app.StakingKeeper.GetDelegation(ctx, addrAcc, valAddr)
|
||||
suite.True(found)
|
||||
var req *types.QueryDelegationRequest
|
||||
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
func() {
|
||||
req = &types.QueryDelegationRequest{}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid validator, delegator pair",
|
||||
func() {
|
||||
req = &types.QueryDelegationRequest{
|
||||
DelegatorAddr: addrAcc1.String(),
|
||||
ValidatorAddr: addrVal,
|
||||
}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
func() {
|
||||
req = &types.QueryDelegationRequest{DelegatorAddr: addrAcc.String(), ValidatorAddr: addrVal}
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
tc.malleate()
|
||||
res, err := queryClient.Delegation(gocontext.Background(), req)
|
||||
if tc.expPass {
|
||||
suite.Equal(delegation.ValidatorAddress, res.DelegationResponse.Delegation.ValidatorAddress)
|
||||
suite.Equal(delegation.DelegatorAddress, res.DelegationResponse.Delegation.DelegatorAddress)
|
||||
suite.Equal(sdk.NewCoin(sdk.DefaultBondDenom, delegation.Shares.TruncateInt()), res.DelegationResponse.Balance)
|
||||
} else {
|
||||
suite.Error(err)
|
||||
suite.Nil(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *IntegrationTestSuite) TestGRPCQueryDelegatorDelegations() {
|
||||
app, ctx, queryClient, addrs, vals := suite.app, suite.ctx, suite.queryClient, suite.addrs, suite.vals
|
||||
addrAcc := addrs[0]
|
||||
addrVal1 := vals[0].OperatorAddress
|
||||
valAddr, err := sdk.ValAddressFromBech32(addrVal1)
|
||||
suite.NoError(err)
|
||||
delegation, found := app.StakingKeeper.GetDelegation(ctx, addrAcc, valAddr)
|
||||
suite.True(found)
|
||||
var req *types.QueryDelegatorDelegationsRequest
|
||||
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
onSuccess func(suite *IntegrationTestSuite, response *types.QueryDelegatorDelegationsResponse)
|
||||
expErr bool
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
func() {
|
||||
req = &types.QueryDelegatorDelegationsRequest{}
|
||||
},
|
||||
func(suite *IntegrationTestSuite, response *types.QueryDelegatorDelegationsResponse) {},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"valid request with no delegations",
|
||||
func() {
|
||||
req = &types.QueryDelegatorDelegationsRequest{DelegatorAddr: addrs[4].String()}
|
||||
},
|
||||
func(suite *IntegrationTestSuite, response *types.QueryDelegatorDelegationsResponse) {
|
||||
suite.Equal(uint64(0), response.Pagination.Total)
|
||||
suite.Len(response.DelegationResponses, 0)
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
func() {
|
||||
req = &types.QueryDelegatorDelegationsRequest{
|
||||
DelegatorAddr: addrAcc.String(),
|
||||
Pagination: &query.PageRequest{Limit: 1, CountTotal: true},
|
||||
}
|
||||
},
|
||||
func(suite *IntegrationTestSuite, response *types.QueryDelegatorDelegationsResponse) {
|
||||
suite.Equal(uint64(2), response.Pagination.Total)
|
||||
suite.Len(response.DelegationResponses, 1)
|
||||
suite.Equal(sdk.NewCoin(sdk.DefaultBondDenom, delegation.Shares.TruncateInt()), response.DelegationResponses[0].Balance)
|
||||
},
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
tc.malleate()
|
||||
res, err := queryClient.DelegatorDelegations(gocontext.Background(), req)
|
||||
if tc.expErr {
|
||||
suite.Error(err)
|
||||
} else {
|
||||
suite.NoError(err)
|
||||
tc.onSuccess(suite, res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *IntegrationTestSuite) TestGRPCQueryValidatorDelegations() {
|
||||
app, ctx, queryClient, addrs, vals := suite.app, suite.ctx, suite.queryClient, suite.addrs, suite.vals
|
||||
addrAcc := addrs[0]
|
||||
addrVal1 := vals[1].OperatorAddress
|
||||
valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs)
|
||||
addrVal2 := valAddrs[4]
|
||||
valAddr, err := sdk.ValAddressFromBech32(addrVal1)
|
||||
suite.NoError(err)
|
||||
delegation, found := app.StakingKeeper.GetDelegation(ctx, addrAcc, valAddr)
|
||||
suite.True(found)
|
||||
|
||||
var req *types.QueryValidatorDelegationsRequest
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
expErr bool
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
func() {
|
||||
req = &types.QueryValidatorDelegationsRequest{}
|
||||
},
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid validator delegator pair",
|
||||
func() {
|
||||
req = &types.QueryValidatorDelegationsRequest{ValidatorAddr: addrVal2.String()}
|
||||
},
|
||||
false,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
func() {
|
||||
req = &types.QueryValidatorDelegationsRequest{
|
||||
ValidatorAddr: addrVal1,
|
||||
Pagination: &query.PageRequest{Limit: 1, CountTotal: true},
|
||||
}
|
||||
},
|
||||
true,
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
tc.malleate()
|
||||
res, err := queryClient.ValidatorDelegations(gocontext.Background(), req)
|
||||
if tc.expPass && !tc.expErr {
|
||||
suite.NoError(err)
|
||||
suite.Len(res.DelegationResponses, 1)
|
||||
suite.NotNil(res.Pagination.NextKey)
|
||||
suite.Equal(uint64(2), res.Pagination.Total)
|
||||
suite.Equal(addrVal1, res.DelegationResponses[0].Delegation.ValidatorAddress)
|
||||
suite.Equal(sdk.NewCoin(sdk.DefaultBondDenom, delegation.Shares.TruncateInt()), res.DelegationResponses[0].Balance)
|
||||
} else if !tc.expPass && !tc.expErr {
|
||||
suite.NoError(err)
|
||||
suite.Nil(res.DelegationResponses)
|
||||
} else {
|
||||
suite.Error(err)
|
||||
suite.Nil(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *IntegrationTestSuite) TestGRPCQueryUnbondingDelegation() {
|
||||
app, ctx, queryClient, addrs, vals := suite.app, suite.ctx, suite.queryClient, suite.addrs, suite.vals
|
||||
addrAcc2 := addrs[1]
|
||||
addrVal2 := vals[1].OperatorAddress
|
||||
|
||||
unbondingTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 2)
|
||||
valAddr, err1 := sdk.ValAddressFromBech32(addrVal2)
|
||||
suite.NoError(err1)
|
||||
_, err := app.StakingKeeper.Undelegate(ctx, addrAcc2, valAddr, sdk.NewDecFromInt(unbondingTokens))
|
||||
suite.NoError(err)
|
||||
|
||||
unbond, found := app.StakingKeeper.GetUnbondingDelegation(ctx, addrAcc2, valAddr)
|
||||
suite.True(found)
|
||||
var req *types.QueryUnbondingDelegationRequest
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
func() {
|
||||
req = &types.QueryUnbondingDelegationRequest{}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid request",
|
||||
func() {
|
||||
req = &types.QueryUnbondingDelegationRequest{}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
func() {
|
||||
req = &types.QueryUnbondingDelegationRequest{
|
||||
DelegatorAddr: addrAcc2.String(), ValidatorAddr: addrVal2,
|
||||
}
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
tc.malleate()
|
||||
res, err := queryClient.UnbondingDelegation(gocontext.Background(), req)
|
||||
if tc.expPass {
|
||||
suite.NotNil(res)
|
||||
suite.Equal(unbond, res.Unbond)
|
||||
} else {
|
||||
suite.Error(err)
|
||||
suite.Nil(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *IntegrationTestSuite) TestGRPCQueryDelegatorUnbondingDelegations() {
|
||||
app, ctx, queryClient, addrs, vals := suite.app, suite.ctx, suite.queryClient, suite.addrs, suite.vals
|
||||
addrAcc, addrAcc1 := addrs[0], addrs[1]
|
||||
addrVal, addrVal2 := vals[0].OperatorAddress, vals[1].OperatorAddress
|
||||
|
||||
unbondingTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 2)
|
||||
valAddr1, err1 := sdk.ValAddressFromBech32(addrVal)
|
||||
suite.NoError(err1)
|
||||
_, err := app.StakingKeeper.Undelegate(ctx, addrAcc, valAddr1, sdk.NewDecFromInt(unbondingTokens))
|
||||
suite.NoError(err)
|
||||
valAddr2, err1 := sdk.ValAddressFromBech32(addrVal2)
|
||||
suite.NoError(err1)
|
||||
_, err = app.StakingKeeper.Undelegate(ctx, addrAcc, valAddr2, sdk.NewDecFromInt(unbondingTokens))
|
||||
suite.NoError(err)
|
||||
|
||||
unbond, found := app.StakingKeeper.GetUnbondingDelegation(ctx, addrAcc, valAddr1)
|
||||
suite.True(found)
|
||||
var req *types.QueryDelegatorUnbondingDelegationsRequest
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
expErr bool
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
func() {
|
||||
req = &types.QueryDelegatorUnbondingDelegationsRequest{}
|
||||
},
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid request",
|
||||
func() {
|
||||
req = &types.QueryDelegatorUnbondingDelegationsRequest{DelegatorAddr: addrAcc1.String()}
|
||||
},
|
||||
false,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
func() {
|
||||
req = &types.QueryDelegatorUnbondingDelegationsRequest{
|
||||
DelegatorAddr: addrAcc.String(),
|
||||
Pagination: &query.PageRequest{Limit: 1, CountTotal: true},
|
||||
}
|
||||
},
|
||||
true,
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
tc.malleate()
|
||||
res, err := queryClient.DelegatorUnbondingDelegations(gocontext.Background(), req)
|
||||
if tc.expPass && !tc.expErr {
|
||||
suite.NoError(err)
|
||||
suite.NotNil(res.Pagination.NextKey)
|
||||
suite.Equal(uint64(2), res.Pagination.Total)
|
||||
suite.Len(res.UnbondingResponses, 1)
|
||||
suite.Equal(unbond, res.UnbondingResponses[0])
|
||||
} else if !tc.expPass && !tc.expErr {
|
||||
suite.NoError(err)
|
||||
suite.Nil(res.UnbondingResponses)
|
||||
} else {
|
||||
suite.Error(err)
|
||||
suite.Nil(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *IntegrationTestSuite) TestGRPCQueryPoolParameters() {
|
||||
app, ctx, queryClient := suite.app, suite.ctx, suite.queryClient
|
||||
bondDenom := sdk.DefaultBondDenom
|
||||
|
||||
// Query pool
|
||||
res, err := queryClient.Pool(gocontext.Background(), &types.QueryPoolRequest{})
|
||||
suite.NoError(err)
|
||||
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
||||
notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
suite.Equal(app.BankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom).Amount, res.Pool.NotBondedTokens)
|
||||
suite.Equal(app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount, res.Pool.BondedTokens)
|
||||
|
||||
// Query Params
|
||||
resp, err := queryClient.Params(gocontext.Background(), &types.QueryParamsRequest{})
|
||||
suite.NoError(err)
|
||||
suite.Equal(app.StakingKeeper.GetParams(ctx), resp.Params)
|
||||
}
|
||||
|
||||
func (suite *IntegrationTestSuite) TestGRPCQueryHistoricalInfo() {
|
||||
app, ctx, queryClient := suite.app, suite.ctx, suite.queryClient
|
||||
|
||||
hi, found := app.StakingKeeper.GetHistoricalInfo(ctx, 5)
|
||||
suite.True(found)
|
||||
|
||||
var req *types.QueryHistoricalInfoRequest
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
func() {
|
||||
req = &types.QueryHistoricalInfoRequest{}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid request with negative height",
|
||||
func() {
|
||||
req = &types.QueryHistoricalInfoRequest{Height: -1}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid request with old height",
|
||||
func() {
|
||||
req = &types.QueryHistoricalInfoRequest{Height: 4}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid request with current height",
|
||||
func() {
|
||||
req = &types.QueryHistoricalInfoRequest{Height: 5}
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
tc.malleate()
|
||||
res, err := queryClient.HistoricalInfo(gocontext.Background(), req)
|
||||
if tc.expPass {
|
||||
suite.NoError(err)
|
||||
suite.NotNil(res)
|
||||
suite.True(hi.Equal(res.Hist))
|
||||
} else {
|
||||
suite.Error(err)
|
||||
suite.Nil(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *IntegrationTestSuite) TestGRPCQueryRedelegations() {
|
||||
app, ctx, queryClient, addrs, vals := suite.app, suite.ctx, suite.queryClient, suite.addrs, suite.vals
|
||||
|
||||
addrAcc, addrAcc1 := addrs[0], addrs[1]
|
||||
valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs)
|
||||
val1, val2, val3, val4 := vals[0], vals[1], valAddrs[3], valAddrs[4]
|
||||
delAmount := app.StakingKeeper.TokensFromConsensusPower(ctx, 1)
|
||||
_, err := app.StakingKeeper.Delegate(ctx, addrAcc1, delAmount, types.Unbonded, val1, true)
|
||||
suite.NoError(err)
|
||||
applyValidatorSetUpdates(suite.T(), ctx, app.StakingKeeper, -1)
|
||||
|
||||
rdAmount := app.StakingKeeper.TokensFromConsensusPower(ctx, 1)
|
||||
_, err = app.StakingKeeper.BeginRedelegation(ctx, addrAcc1, val1.GetOperator(), val2.GetOperator(), sdk.NewDecFromInt(rdAmount))
|
||||
suite.NoError(err)
|
||||
applyValidatorSetUpdates(suite.T(), ctx, app.StakingKeeper, -1)
|
||||
|
||||
redel, found := app.StakingKeeper.GetRedelegation(ctx, addrAcc1, val1.GetOperator(), val2.GetOperator())
|
||||
suite.True(found)
|
||||
|
||||
var req *types.QueryRedelegationsRequest
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
expErr bool
|
||||
}{
|
||||
{
|
||||
"request redelegations for non existent addr",
|
||||
func() {
|
||||
req = &types.QueryRedelegationsRequest{DelegatorAddr: addrAcc.String()}
|
||||
},
|
||||
false,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"request redelegations with non existent pairs",
|
||||
func() {
|
||||
req = &types.QueryRedelegationsRequest{
|
||||
DelegatorAddr: addrAcc.String(), SrcValidatorAddr: val3.String(),
|
||||
DstValidatorAddr: val4.String(),
|
||||
}
|
||||
},
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"request redelegations with delegatoraddr, sourceValAddr, destValAddr",
|
||||
func() {
|
||||
req = &types.QueryRedelegationsRequest{
|
||||
DelegatorAddr: addrAcc1.String(), SrcValidatorAddr: val1.OperatorAddress,
|
||||
DstValidatorAddr: val2.OperatorAddress, Pagination: &query.PageRequest{},
|
||||
}
|
||||
},
|
||||
true,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"request redelegations with delegatoraddr and sourceValAddr",
|
||||
func() {
|
||||
req = &types.QueryRedelegationsRequest{
|
||||
DelegatorAddr: addrAcc1.String(), SrcValidatorAddr: val1.OperatorAddress,
|
||||
Pagination: &query.PageRequest{},
|
||||
}
|
||||
},
|
||||
true,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"query redelegations with sourceValAddr only",
|
||||
func() {
|
||||
req = &types.QueryRedelegationsRequest{
|
||||
SrcValidatorAddr: val1.GetOperator().String(),
|
||||
Pagination: &query.PageRequest{Limit: 1, CountTotal: true},
|
||||
}
|
||||
},
|
||||
true,
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
tc.malleate()
|
||||
res, err := queryClient.Redelegations(gocontext.Background(), req)
|
||||
if tc.expPass && !tc.expErr {
|
||||
suite.NoError(err)
|
||||
suite.Len(res.RedelegationResponses, len(redel.Entries))
|
||||
suite.Equal(redel.DelegatorAddress, res.RedelegationResponses[0].Redelegation.DelegatorAddress)
|
||||
suite.Equal(redel.ValidatorSrcAddress, res.RedelegationResponses[0].Redelegation.ValidatorSrcAddress)
|
||||
suite.Equal(redel.ValidatorDstAddress, res.RedelegationResponses[0].Redelegation.ValidatorDstAddress)
|
||||
suite.Len(redel.Entries, len(res.RedelegationResponses[0].Entries))
|
||||
} else if !tc.expPass && !tc.expErr {
|
||||
suite.NoError(err)
|
||||
suite.Nil(res.RedelegationResponses)
|
||||
} else {
|
||||
suite.Error(err)
|
||||
suite.Nil(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *IntegrationTestSuite) TestGRPCQueryValidatorUnbondingDelegations() {
|
||||
app, ctx, queryClient, addrs, vals := suite.app, suite.ctx, suite.queryClient, suite.addrs, suite.vals
|
||||
addrAcc1, _ := addrs[0], addrs[1]
|
||||
val1 := vals[0]
|
||||
|
||||
// undelegate
|
||||
undelAmount := app.StakingKeeper.TokensFromConsensusPower(ctx, 2)
|
||||
_, err := app.StakingKeeper.Undelegate(ctx, addrAcc1, val1.GetOperator(), sdk.NewDecFromInt(undelAmount))
|
||||
suite.NoError(err)
|
||||
applyValidatorSetUpdates(suite.T(), ctx, app.StakingKeeper, -1)
|
||||
|
||||
var req *types.QueryValidatorUnbondingDelegationsRequest
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
func() {
|
||||
req = &types.QueryValidatorUnbondingDelegationsRequest{}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
func() {
|
||||
req = &types.QueryValidatorUnbondingDelegationsRequest{
|
||||
ValidatorAddr: val1.GetOperator().String(),
|
||||
Pagination: &query.PageRequest{Limit: 1, CountTotal: true},
|
||||
}
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
tc.malleate()
|
||||
res, err := queryClient.ValidatorUnbondingDelegations(gocontext.Background(), req)
|
||||
if tc.expPass {
|
||||
suite.NoError(err)
|
||||
suite.Equal(uint64(1), res.Pagination.Total)
|
||||
suite.Equal(1, len(res.UnbondingResponses))
|
||||
suite.Equal(res.UnbondingResponses[0].ValidatorAddress, val1.OperatorAddress)
|
||||
} else {
|
||||
suite.Error(err)
|
||||
suite.Nil(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
76
tests/integration/staking/keeper/keeper_test.go
Normal file
76
tests/integration/staking/keeper/keeper_test.go
Normal file
@ -0,0 +1,76 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
type IntegrationTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
app *simapp.SimApp
|
||||
ctx sdk.Context
|
||||
addrs []sdk.AccAddress
|
||||
vals []types.Validator
|
||||
queryClient types.QueryClient
|
||||
msgServer types.MsgServer
|
||||
}
|
||||
|
||||
func (suite *IntegrationTestSuite) SetupTest() {
|
||||
app := simapp.Setup(suite.T(), false)
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
|
||||
querier := keeper.Querier{Keeper: app.StakingKeeper}
|
||||
|
||||
queryHelper := baseapp.NewQueryServerTestHelper(ctx, app.InterfaceRegistry())
|
||||
types.RegisterQueryServer(queryHelper, querier)
|
||||
queryClient := types.NewQueryClient(queryHelper)
|
||||
|
||||
suite.msgServer = keeper.NewMsgServerImpl(app.StakingKeeper)
|
||||
|
||||
addrs, _, validators := createValidators(suite.T(), ctx, app, []int64{9, 8, 7})
|
||||
header := tmproto.Header{
|
||||
ChainID: "HelloChain",
|
||||
Height: 5,
|
||||
}
|
||||
|
||||
// sort a copy of the validators, so that original validators does not
|
||||
// have its order changed
|
||||
sortedVals := make([]types.Validator, len(validators))
|
||||
copy(sortedVals, validators)
|
||||
hi := types.NewHistoricalInfo(header, sortedVals, app.StakingKeeper.PowerReduction(ctx))
|
||||
app.StakingKeeper.SetHistoricalInfo(ctx, 5, &hi)
|
||||
|
||||
suite.app, suite.ctx, suite.queryClient, suite.addrs, suite.vals = app, ctx, queryClient, addrs, validators
|
||||
}
|
||||
|
||||
func TestParams(t *testing.T) {
|
||||
app := simapp.Setup(t, false)
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
|
||||
expParams := types.DefaultParams()
|
||||
|
||||
// check that the empty keeper loads the default
|
||||
resParams := app.StakingKeeper.GetParams(ctx)
|
||||
require.True(t, expParams.Equal(resParams))
|
||||
|
||||
// modify a params, save, and retrieve
|
||||
expParams.MaxValidators = 777
|
||||
app.StakingKeeper.SetParams(ctx, expParams)
|
||||
resParams = app.StakingKeeper.GetParams(ctx)
|
||||
require.True(t, expParams.Equal(resParams))
|
||||
}
|
||||
|
||||
func TestIntegrationTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(IntegrationTestSuite))
|
||||
}
|
||||
146
tests/integration/staking/keeper/msg_server_test.go
Normal file
146
tests/integration/staking/keeper/msg_server_test.go
Normal file
@ -0,0 +1,146 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
)
|
||||
|
||||
func TestCancelUnbondingDelegation(t *testing.T) {
|
||||
// setup the app
|
||||
app := simapp.Setup(t, false)
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
msgServer := keeper.NewMsgServerImpl(app.StakingKeeper)
|
||||
bondDenom := app.StakingKeeper.BondDenom(ctx)
|
||||
|
||||
// set the not bonded pool module account
|
||||
notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
startTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 5)
|
||||
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), startTokens))))
|
||||
app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
|
||||
|
||||
moduleBalance := app.BankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), app.StakingKeeper.BondDenom(ctx))
|
||||
require.Equal(t, sdk.NewInt64Coin(bondDenom, startTokens.Int64()), moduleBalance)
|
||||
|
||||
// accounts
|
||||
delAddrs := simapp.AddTestAddrsIncremental(app, ctx, 2, sdk.NewInt(10000))
|
||||
validators := app.StakingKeeper.GetValidators(ctx, 10)
|
||||
require.Equal(t, len(validators), 1)
|
||||
|
||||
validatorAddr, err := sdk.ValAddressFromBech32(validators[0].OperatorAddress)
|
||||
require.NoError(t, err)
|
||||
delegatorAddr := delAddrs[0]
|
||||
|
||||
// setting the ubd entry
|
||||
unbondingAmount := sdk.NewInt64Coin(app.StakingKeeper.BondDenom(ctx), 5)
|
||||
ubd := types.NewUnbondingDelegation(
|
||||
delegatorAddr, validatorAddr, 10,
|
||||
ctx.BlockTime().Add(time.Minute*10),
|
||||
unbondingAmount.Amount,
|
||||
)
|
||||
|
||||
// set and retrieve a record
|
||||
app.StakingKeeper.SetUnbondingDelegation(ctx, ubd)
|
||||
resUnbond, found := app.StakingKeeper.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr)
|
||||
require.True(t, found)
|
||||
require.Equal(t, ubd, resUnbond)
|
||||
|
||||
testCases := []struct {
|
||||
Name string
|
||||
ExceptErr bool
|
||||
req types.MsgCancelUnbondingDelegation
|
||||
}{
|
||||
{
|
||||
Name: "invalid height",
|
||||
ExceptErr: true,
|
||||
req: types.MsgCancelUnbondingDelegation{
|
||||
DelegatorAddress: resUnbond.DelegatorAddress,
|
||||
ValidatorAddress: resUnbond.ValidatorAddress,
|
||||
Amount: sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(4)),
|
||||
CreationHeight: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "invalid coin",
|
||||
ExceptErr: true,
|
||||
req: types.MsgCancelUnbondingDelegation{
|
||||
DelegatorAddress: resUnbond.DelegatorAddress,
|
||||
ValidatorAddress: resUnbond.ValidatorAddress,
|
||||
Amount: sdk.NewCoin("dump_coin", sdk.NewInt(4)),
|
||||
CreationHeight: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "validator not exists",
|
||||
ExceptErr: true,
|
||||
req: types.MsgCancelUnbondingDelegation{
|
||||
DelegatorAddress: resUnbond.DelegatorAddress,
|
||||
ValidatorAddress: sdk.ValAddress(sdk.AccAddress("asdsad")).String(),
|
||||
Amount: unbondingAmount,
|
||||
CreationHeight: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "invalid delegator address",
|
||||
ExceptErr: true,
|
||||
req: types.MsgCancelUnbondingDelegation{
|
||||
DelegatorAddress: "invalid_delegator_addrtess",
|
||||
ValidatorAddress: resUnbond.ValidatorAddress,
|
||||
Amount: unbondingAmount,
|
||||
CreationHeight: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "invalid amount",
|
||||
ExceptErr: true,
|
||||
req: types.MsgCancelUnbondingDelegation{
|
||||
DelegatorAddress: resUnbond.DelegatorAddress,
|
||||
ValidatorAddress: resUnbond.ValidatorAddress,
|
||||
Amount: unbondingAmount.Add(sdk.NewInt64Coin(bondDenom, 10)),
|
||||
CreationHeight: 10,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "success",
|
||||
ExceptErr: false,
|
||||
req: types.MsgCancelUnbondingDelegation{
|
||||
DelegatorAddress: resUnbond.DelegatorAddress,
|
||||
ValidatorAddress: resUnbond.ValidatorAddress,
|
||||
Amount: unbondingAmount.Sub(sdk.NewInt64Coin(bondDenom, 1)),
|
||||
CreationHeight: 10,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "success",
|
||||
ExceptErr: false,
|
||||
req: types.MsgCancelUnbondingDelegation{
|
||||
DelegatorAddress: resUnbond.DelegatorAddress,
|
||||
ValidatorAddress: resUnbond.ValidatorAddress,
|
||||
Amount: unbondingAmount.Sub(unbondingAmount.Sub(sdk.NewInt64Coin(bondDenom, 1))),
|
||||
CreationHeight: 10,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.Name, func(t *testing.T) {
|
||||
_, err := msgServer.CancelUnbondingDelegation(ctx, &testCase.req)
|
||||
if testCase.ExceptErr {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
balanceForNotBondedPool := app.BankKeeper.GetBalance(ctx, sdk.AccAddress(notBondedPool.GetAddress()), bondDenom)
|
||||
require.Equal(t, balanceForNotBondedPool, moduleBalance.Sub(testCase.req.Amount))
|
||||
moduleBalance = moduleBalance.Sub(testCase.req.Amount)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
585
tests/integration/staking/keeper/slash_test.go
Normal file
585
tests/integration/staking/keeper/slash_test.go
Normal file
@ -0,0 +1,585 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/teststaking"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
// bootstrapSlashTest creates 3 validators and bootstrap the app.
|
||||
func bootstrapSlashTest(t *testing.T, power int64) (*simapp.SimApp, sdk.Context, []sdk.AccAddress, []sdk.ValAddress) {
|
||||
_, app, ctx := createTestInput(t)
|
||||
|
||||
addrDels, addrVals := generateAddresses(app, ctx, 100)
|
||||
|
||||
amt := app.StakingKeeper.TokensFromConsensusPower(ctx, power)
|
||||
totalSupply := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), amt.MulRaw(int64(len(addrDels)))))
|
||||
|
||||
notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), totalSupply))
|
||||
|
||||
app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
|
||||
|
||||
numVals := int64(3)
|
||||
bondedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), amt.MulRaw(numVals)))
|
||||
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
||||
|
||||
// set bonded pool balance
|
||||
app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), bondedCoins))
|
||||
|
||||
for i := int64(0); i < numVals; i++ {
|
||||
validator := teststaking.NewValidator(t, addrVals[i], PKs[i])
|
||||
validator, _ = validator.AddTokensFromDel(amt)
|
||||
validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)
|
||||
app.StakingKeeper.SetValidatorByConsAddr(ctx, validator)
|
||||
}
|
||||
|
||||
return app, ctx, addrDels, addrVals
|
||||
}
|
||||
|
||||
// tests slashUnbondingDelegation
|
||||
func TestSlashUnbondingDelegation(t *testing.T) {
|
||||
app, ctx, addrDels, addrVals := bootstrapSlashTest(t, 10)
|
||||
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
|
||||
// set an unbonding delegation with expiration timestamp (beyond which the
|
||||
// unbonding delegation shouldn't be slashed)
|
||||
ubd := types.NewUnbondingDelegation(addrDels[0], addrVals[0], 0,
|
||||
time.Unix(5, 0), sdk.NewInt(10))
|
||||
|
||||
app.StakingKeeper.SetUnbondingDelegation(ctx, ubd)
|
||||
|
||||
// unbonding started prior to the infraction height, stakw didn't contribute
|
||||
slashAmount := app.StakingKeeper.SlashUnbondingDelegation(ctx, ubd, 1, fraction)
|
||||
require.True(t, slashAmount.Equal(sdk.NewInt(0)))
|
||||
|
||||
// after the expiration time, no longer eligible for slashing
|
||||
ctx = ctx.WithBlockHeader(tmproto.Header{Time: time.Unix(10, 0)})
|
||||
app.StakingKeeper.SetUnbondingDelegation(ctx, ubd)
|
||||
slashAmount = app.StakingKeeper.SlashUnbondingDelegation(ctx, ubd, 0, fraction)
|
||||
require.True(t, slashAmount.Equal(sdk.NewInt(0)))
|
||||
|
||||
// test valid slash, before expiration timestamp and to which stake contributed
|
||||
notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
oldUnbondedPoolBalances := app.BankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress())
|
||||
ctx = ctx.WithBlockHeader(tmproto.Header{Time: time.Unix(0, 0)})
|
||||
app.StakingKeeper.SetUnbondingDelegation(ctx, ubd)
|
||||
slashAmount = app.StakingKeeper.SlashUnbondingDelegation(ctx, ubd, 0, fraction)
|
||||
require.True(t, slashAmount.Equal(sdk.NewInt(5)))
|
||||
ubd, found := app.StakingKeeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
|
||||
require.True(t, found)
|
||||
require.Len(t, ubd.Entries, 1)
|
||||
|
||||
// initial balance unchanged
|
||||
require.Equal(t, sdk.NewInt(10), ubd.Entries[0].InitialBalance)
|
||||
|
||||
// balance decreased
|
||||
require.Equal(t, sdk.NewInt(5), ubd.Entries[0].Balance)
|
||||
newUnbondedPoolBalances := app.BankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress())
|
||||
diffTokens := oldUnbondedPoolBalances.Sub(newUnbondedPoolBalances...)
|
||||
require.True(t, diffTokens.AmountOf(app.StakingKeeper.BondDenom(ctx)).Equal(sdk.NewInt(5)))
|
||||
}
|
||||
|
||||
// tests slashRedelegation
|
||||
func TestSlashRedelegation(t *testing.T) {
|
||||
app, ctx, addrDels, addrVals := bootstrapSlashTest(t, 10)
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
|
||||
// add bonded tokens to pool for (re)delegations
|
||||
startCoins := sdk.NewCoins(sdk.NewInt64Coin(app.StakingKeeper.BondDenom(ctx), 15))
|
||||
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
||||
balances := app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
|
||||
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), startCoins))
|
||||
app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
|
||||
|
||||
// set a redelegation with an expiration timestamp beyond which the
|
||||
// redelegation shouldn't be slashed
|
||||
rd := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 0,
|
||||
time.Unix(5, 0), sdk.NewInt(10), math.LegacyNewDec(10))
|
||||
|
||||
app.StakingKeeper.SetRedelegation(ctx, rd)
|
||||
|
||||
// set the associated delegation
|
||||
del := types.NewDelegation(addrDels[0], addrVals[1], math.LegacyNewDec(10))
|
||||
app.StakingKeeper.SetDelegation(ctx, del)
|
||||
|
||||
// started redelegating prior to the current height, stake didn't contribute to infraction
|
||||
validator, found := app.StakingKeeper.GetValidator(ctx, addrVals[1])
|
||||
require.True(t, found)
|
||||
slashAmount := app.StakingKeeper.SlashRedelegation(ctx, validator, rd, 1, fraction)
|
||||
require.True(t, slashAmount.Equal(sdk.NewInt(0)))
|
||||
|
||||
// after the expiration time, no longer eligible for slashing
|
||||
ctx = ctx.WithBlockHeader(tmproto.Header{Time: time.Unix(10, 0)})
|
||||
app.StakingKeeper.SetRedelegation(ctx, rd)
|
||||
validator, found = app.StakingKeeper.GetValidator(ctx, addrVals[1])
|
||||
require.True(t, found)
|
||||
slashAmount = app.StakingKeeper.SlashRedelegation(ctx, validator, rd, 0, fraction)
|
||||
require.True(t, slashAmount.Equal(sdk.NewInt(0)))
|
||||
|
||||
balances = app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
|
||||
|
||||
// test valid slash, before expiration timestamp and to which stake contributed
|
||||
ctx = ctx.WithBlockHeader(tmproto.Header{Time: time.Unix(0, 0)})
|
||||
app.StakingKeeper.SetRedelegation(ctx, rd)
|
||||
validator, found = app.StakingKeeper.GetValidator(ctx, addrVals[1])
|
||||
require.True(t, found)
|
||||
slashAmount = app.StakingKeeper.SlashRedelegation(ctx, validator, rd, 0, fraction)
|
||||
require.True(t, slashAmount.Equal(sdk.NewInt(5)))
|
||||
rd, found = app.StakingKeeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||
require.True(t, found)
|
||||
require.Len(t, rd.Entries, 1)
|
||||
|
||||
// end block
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1)
|
||||
|
||||
// initialbalance unchanged
|
||||
require.Equal(t, sdk.NewInt(10), rd.Entries[0].InitialBalance)
|
||||
|
||||
// shares decreased
|
||||
del, found = app.StakingKeeper.GetDelegation(ctx, addrDels[0], addrVals[1])
|
||||
require.True(t, found)
|
||||
require.Equal(t, int64(5), del.Shares.RoundInt64())
|
||||
|
||||
// pool bonded tokens should decrease
|
||||
burnedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), slashAmount))
|
||||
require.Equal(t, balances.Sub(burnedCoins...), app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress()))
|
||||
}
|
||||
|
||||
// test slash at a negative height
|
||||
// this just represents pre-genesis and should have the same effect as slashing at height 0
|
||||
func TestSlashAtNegativeHeight(t *testing.T) {
|
||||
app, ctx, _, _ := bootstrapSlashTest(t, 10)
|
||||
consAddr := sdk.ConsAddress(PKs[0].Address())
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
|
||||
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
||||
oldBondedPoolBalances := app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
|
||||
|
||||
validator, found := app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
app.StakingKeeper.Slash(ctx, consAddr, -2, 10, fraction)
|
||||
|
||||
// read updated state
|
||||
validator, found = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
|
||||
// end block
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1)
|
||||
|
||||
validator, found = app.StakingKeeper.GetValidator(ctx, validator.GetOperator())
|
||||
require.True(t, found)
|
||||
// power decreased
|
||||
require.Equal(t, int64(5), validator.GetConsensusPower(app.StakingKeeper.PowerReduction(ctx)))
|
||||
|
||||
// pool bonded shares decreased
|
||||
newBondedPoolBalances := app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
|
||||
diffTokens := oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(app.StakingKeeper.BondDenom(ctx))
|
||||
require.Equal(t, app.StakingKeeper.TokensFromConsensusPower(ctx, 5).String(), diffTokens.String())
|
||||
}
|
||||
|
||||
// tests Slash at the current height
|
||||
func TestSlashValidatorAtCurrentHeight(t *testing.T) {
|
||||
app, ctx, _, _ := bootstrapSlashTest(t, 10)
|
||||
consAddr := sdk.ConsAddress(PKs[0].Address())
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
|
||||
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
||||
oldBondedPoolBalances := app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
|
||||
|
||||
validator, found := app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
app.StakingKeeper.Slash(ctx, consAddr, ctx.BlockHeight(), 10, fraction)
|
||||
|
||||
// read updated state
|
||||
validator, found = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
|
||||
// end block
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1)
|
||||
|
||||
validator, found = app.StakingKeeper.GetValidator(ctx, validator.GetOperator())
|
||||
assert.True(t, found)
|
||||
// power decreased
|
||||
require.Equal(t, int64(5), validator.GetConsensusPower(app.StakingKeeper.PowerReduction(ctx)))
|
||||
|
||||
// pool bonded shares decreased
|
||||
newBondedPoolBalances := app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
|
||||
diffTokens := oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(app.StakingKeeper.BondDenom(ctx))
|
||||
require.Equal(t, app.StakingKeeper.TokensFromConsensusPower(ctx, 5).String(), diffTokens.String())
|
||||
}
|
||||
|
||||
// tests Slash at a previous height with an unbonding delegation
|
||||
func TestSlashWithUnbondingDelegation(t *testing.T) {
|
||||
app, ctx, addrDels, addrVals := bootstrapSlashTest(t, 10)
|
||||
|
||||
consAddr := sdk.ConsAddress(PKs[0].Address())
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
|
||||
// set an unbonding delegation with expiration timestamp beyond which the
|
||||
// unbonding delegation shouldn't be slashed
|
||||
ubdTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 4)
|
||||
ubd := types.NewUnbondingDelegation(addrDels[0], addrVals[0], 11, time.Unix(0, 0), ubdTokens)
|
||||
app.StakingKeeper.SetUnbondingDelegation(ctx, ubd)
|
||||
|
||||
// slash validator for the first time
|
||||
ctx = ctx.WithBlockHeight(12)
|
||||
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
||||
oldBondedPoolBalances := app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
|
||||
|
||||
validator, found := app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
app.StakingKeeper.Slash(ctx, consAddr, 10, 10, fraction)
|
||||
|
||||
// end block
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1)
|
||||
|
||||
// read updating unbonding delegation
|
||||
ubd, found = app.StakingKeeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
|
||||
require.True(t, found)
|
||||
require.Len(t, ubd.Entries, 1)
|
||||
|
||||
// balance decreased
|
||||
require.Equal(t, app.StakingKeeper.TokensFromConsensusPower(ctx, 2), ubd.Entries[0].Balance)
|
||||
|
||||
// bonded tokens burned
|
||||
newBondedPoolBalances := app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
|
||||
diffTokens := oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(app.StakingKeeper.BondDenom(ctx))
|
||||
require.Equal(t, app.StakingKeeper.TokensFromConsensusPower(ctx, 3), diffTokens)
|
||||
|
||||
// read updated validator
|
||||
validator, found = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
|
||||
// power decreased by 3 - 6 stake originally bonded at the time of infraction
|
||||
// was still bonded at the time of discovery and was slashed by half, 4 stake
|
||||
// bonded at the time of discovery hadn't been bonded at the time of infraction
|
||||
// and wasn't slashed
|
||||
require.Equal(t, int64(7), validator.GetConsensusPower(app.StakingKeeper.PowerReduction(ctx)))
|
||||
|
||||
// slash validator again
|
||||
ctx = ctx.WithBlockHeight(13)
|
||||
app.StakingKeeper.Slash(ctx, consAddr, 9, 10, fraction)
|
||||
|
||||
ubd, found = app.StakingKeeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
|
||||
require.True(t, found)
|
||||
require.Len(t, ubd.Entries, 1)
|
||||
|
||||
// balance decreased again
|
||||
require.Equal(t, sdk.NewInt(0), ubd.Entries[0].Balance)
|
||||
|
||||
// bonded tokens burned again
|
||||
newBondedPoolBalances = app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
|
||||
diffTokens = oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(app.StakingKeeper.BondDenom(ctx))
|
||||
require.Equal(t, app.StakingKeeper.TokensFromConsensusPower(ctx, 6), diffTokens)
|
||||
|
||||
// read updated validator
|
||||
validator, found = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
|
||||
// power decreased by 3 again
|
||||
require.Equal(t, int64(4), validator.GetConsensusPower(app.StakingKeeper.PowerReduction(ctx)))
|
||||
|
||||
// slash validator again
|
||||
// all originally bonded stake has been slashed, so this will have no effect
|
||||
// on the unbonding delegation, but it will slash stake bonded since the infraction
|
||||
// this may not be the desirable behaviour, ref https://github.com/cosmos/cosmos-sdk/issues/1440
|
||||
ctx = ctx.WithBlockHeight(13)
|
||||
app.StakingKeeper.Slash(ctx, consAddr, 9, 10, fraction)
|
||||
|
||||
ubd, found = app.StakingKeeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
|
||||
require.True(t, found)
|
||||
require.Len(t, ubd.Entries, 1)
|
||||
|
||||
// balance unchanged
|
||||
require.Equal(t, sdk.NewInt(0), ubd.Entries[0].Balance)
|
||||
|
||||
// bonded tokens burned again
|
||||
newBondedPoolBalances = app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
|
||||
diffTokens = oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(app.StakingKeeper.BondDenom(ctx))
|
||||
require.Equal(t, app.StakingKeeper.TokensFromConsensusPower(ctx, 9), diffTokens)
|
||||
|
||||
// read updated validator
|
||||
validator, found = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
|
||||
// power decreased by 3 again
|
||||
require.Equal(t, int64(1), validator.GetConsensusPower(app.StakingKeeper.PowerReduction(ctx)))
|
||||
|
||||
// slash validator again
|
||||
// all originally bonded stake has been slashed, so this will have no effect
|
||||
// on the unbonding delegation, but it will slash stake bonded since the infraction
|
||||
// this may not be the desirable behaviour, ref https://github.com/cosmos/cosmos-sdk/issues/1440
|
||||
ctx = ctx.WithBlockHeight(13)
|
||||
app.StakingKeeper.Slash(ctx, consAddr, 9, 10, fraction)
|
||||
|
||||
ubd, found = app.StakingKeeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
|
||||
require.True(t, found)
|
||||
require.Len(t, ubd.Entries, 1)
|
||||
|
||||
// balance unchanged
|
||||
require.Equal(t, sdk.NewInt(0), ubd.Entries[0].Balance)
|
||||
|
||||
// just 1 bonded token burned again since that's all the validator now has
|
||||
newBondedPoolBalances = app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
|
||||
diffTokens = oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(app.StakingKeeper.BondDenom(ctx))
|
||||
require.Equal(t, app.StakingKeeper.TokensFromConsensusPower(ctx, 10), diffTokens)
|
||||
|
||||
// apply TM updates
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, -1)
|
||||
|
||||
// read updated validator
|
||||
// power decreased by 1 again, validator is out of stake
|
||||
// validator should be in unbonding period
|
||||
validator, _ = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.Equal(t, validator.GetStatus(), types.Unbonding)
|
||||
}
|
||||
|
||||
// tests Slash at a previous height with a redelegation
|
||||
func TestSlashWithRedelegation(t *testing.T) {
|
||||
app, ctx, addrDels, addrVals := bootstrapSlashTest(t, 10)
|
||||
consAddr := sdk.ConsAddress(PKs[0].Address())
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
bondDenom := app.StakingKeeper.BondDenom(ctx)
|
||||
|
||||
// set a redelegation
|
||||
rdTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 6)
|
||||
rd := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 11, time.Unix(0, 0), rdTokens, sdk.NewDecFromInt(rdTokens))
|
||||
app.StakingKeeper.SetRedelegation(ctx, rd)
|
||||
|
||||
// set the associated delegation
|
||||
del := types.NewDelegation(addrDels[0], addrVals[1], sdk.NewDecFromInt(rdTokens))
|
||||
app.StakingKeeper.SetDelegation(ctx, del)
|
||||
|
||||
// update bonded tokens
|
||||
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
||||
notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
rdCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, rdTokens.MulRaw(2)))
|
||||
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), rdCoins))
|
||||
|
||||
app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
|
||||
|
||||
oldBonded := app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount
|
||||
oldNotBonded := app.BankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom).Amount
|
||||
|
||||
// slash validator
|
||||
ctx = ctx.WithBlockHeight(12)
|
||||
validator, found := app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
|
||||
require.NotPanics(t, func() { app.StakingKeeper.Slash(ctx, consAddr, 10, 10, fraction) })
|
||||
burnAmount := sdk.NewDecFromInt(app.StakingKeeper.TokensFromConsensusPower(ctx, 10)).Mul(fraction).TruncateInt()
|
||||
|
||||
bondedPool = app.StakingKeeper.GetBondedPool(ctx)
|
||||
notBondedPool = app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
|
||||
// burn bonded tokens from only from delegations
|
||||
bondedPoolBalance := app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, oldBonded.Sub(burnAmount), bondedPoolBalance))
|
||||
|
||||
notBondedPoolBalance := app.BankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, oldNotBonded, notBondedPoolBalance))
|
||||
oldBonded = app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount
|
||||
|
||||
// read updating redelegation
|
||||
rd, found = app.StakingKeeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||
require.True(t, found)
|
||||
require.Len(t, rd.Entries, 1)
|
||||
// read updated validator
|
||||
validator, found = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
// power decreased by 2 - 4 stake originally bonded at the time of infraction
|
||||
// was still bonded at the time of discovery and was slashed by half, 4 stake
|
||||
// bonded at the time of discovery hadn't been bonded at the time of infraction
|
||||
// and wasn't slashed
|
||||
require.Equal(t, int64(8), validator.GetConsensusPower(app.StakingKeeper.PowerReduction(ctx)))
|
||||
|
||||
// slash the validator again
|
||||
validator, found = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
|
||||
require.NotPanics(t, func() { app.StakingKeeper.Slash(ctx, consAddr, 10, 10, math.LegacyOneDec()) })
|
||||
burnAmount = app.StakingKeeper.TokensFromConsensusPower(ctx, 7)
|
||||
|
||||
// read updated pool
|
||||
bondedPool = app.StakingKeeper.GetBondedPool(ctx)
|
||||
notBondedPool = app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
|
||||
// seven bonded tokens burned
|
||||
bondedPoolBalance = app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, oldBonded.Sub(burnAmount), bondedPoolBalance))
|
||||
require.True(math.IntEq(t, oldNotBonded, notBondedPoolBalance))
|
||||
|
||||
bondedPoolBalance = app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, oldBonded.Sub(burnAmount), bondedPoolBalance))
|
||||
|
||||
notBondedPoolBalance = app.BankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, oldNotBonded, notBondedPoolBalance))
|
||||
oldBonded = app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount
|
||||
|
||||
// read updating redelegation
|
||||
rd, found = app.StakingKeeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||
require.True(t, found)
|
||||
require.Len(t, rd.Entries, 1)
|
||||
// read updated validator
|
||||
validator, found = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
// power decreased by 4
|
||||
require.Equal(t, int64(4), validator.GetConsensusPower(app.StakingKeeper.PowerReduction(ctx)))
|
||||
|
||||
// slash the validator again, by 100%
|
||||
ctx = ctx.WithBlockHeight(12)
|
||||
validator, found = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
|
||||
require.NotPanics(t, func() { app.StakingKeeper.Slash(ctx, consAddr, 10, 10, math.LegacyOneDec()) })
|
||||
|
||||
burnAmount = sdk.NewDecFromInt(app.StakingKeeper.TokensFromConsensusPower(ctx, 10)).Mul(math.LegacyOneDec()).TruncateInt()
|
||||
burnAmount = burnAmount.Sub(math.LegacyOneDec().MulInt(rdTokens).TruncateInt())
|
||||
|
||||
// read updated pool
|
||||
bondedPool = app.StakingKeeper.GetBondedPool(ctx)
|
||||
notBondedPool = app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
|
||||
bondedPoolBalance = app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, oldBonded.Sub(burnAmount), bondedPoolBalance))
|
||||
notBondedPoolBalance = app.BankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, oldNotBonded, notBondedPoolBalance))
|
||||
oldBonded = app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount
|
||||
|
||||
// read updating redelegation
|
||||
rd, found = app.StakingKeeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||
require.True(t, found)
|
||||
require.Len(t, rd.Entries, 1)
|
||||
// apply TM updates
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, -1)
|
||||
// read updated validator
|
||||
// validator decreased to zero power, should be in unbonding period
|
||||
validator, _ = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.Equal(t, validator.GetStatus(), types.Unbonding)
|
||||
|
||||
// slash the validator again, by 100%
|
||||
// no stake remains to be slashed
|
||||
ctx = ctx.WithBlockHeight(12)
|
||||
// validator still in unbonding period
|
||||
validator, _ = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.Equal(t, validator.GetStatus(), types.Unbonding)
|
||||
|
||||
require.NotPanics(t, func() { app.StakingKeeper.Slash(ctx, consAddr, 10, 10, math.LegacyOneDec()) })
|
||||
|
||||
// read updated pool
|
||||
bondedPool = app.StakingKeeper.GetBondedPool(ctx)
|
||||
notBondedPool = app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
|
||||
bondedPoolBalance = app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, oldBonded, bondedPoolBalance))
|
||||
notBondedPoolBalance = app.BankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, oldNotBonded, notBondedPoolBalance))
|
||||
|
||||
// read updating redelegation
|
||||
rd, found = app.StakingKeeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||
require.True(t, found)
|
||||
require.Len(t, rd.Entries, 1)
|
||||
// read updated validator
|
||||
// power still zero, still in unbonding period
|
||||
validator, _ = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.Equal(t, validator.GetStatus(), types.Unbonding)
|
||||
}
|
||||
|
||||
// tests Slash at a previous height with both an unbonding delegation and a redelegation
|
||||
func TestSlashBoth(t *testing.T) {
|
||||
app, ctx, addrDels, addrVals := bootstrapSlashTest(t, 10)
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
bondDenom := app.StakingKeeper.BondDenom(ctx)
|
||||
|
||||
// set a redelegation with expiration timestamp beyond which the
|
||||
// redelegation shouldn't be slashed
|
||||
rdATokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 6)
|
||||
rdA := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 11, time.Unix(0, 0), rdATokens, sdk.NewDecFromInt(rdATokens))
|
||||
app.StakingKeeper.SetRedelegation(ctx, rdA)
|
||||
|
||||
// set the associated delegation
|
||||
delA := types.NewDelegation(addrDels[0], addrVals[1], sdk.NewDecFromInt(rdATokens))
|
||||
app.StakingKeeper.SetDelegation(ctx, delA)
|
||||
|
||||
// set an unbonding delegation with expiration timestamp (beyond which the
|
||||
// unbonding delegation shouldn't be slashed)
|
||||
ubdATokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 4)
|
||||
ubdA := types.NewUnbondingDelegation(addrDels[0], addrVals[0], 11,
|
||||
time.Unix(0, 0), ubdATokens)
|
||||
app.StakingKeeper.SetUnbondingDelegation(ctx, ubdA)
|
||||
|
||||
bondedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, rdATokens.MulRaw(2)))
|
||||
notBondedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, ubdATokens))
|
||||
|
||||
// update bonded tokens
|
||||
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
||||
notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), bondedCoins))
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), notBondedCoins))
|
||||
|
||||
app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
|
||||
app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
|
||||
|
||||
oldBonded := app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount
|
||||
oldNotBonded := app.BankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom).Amount
|
||||
// slash validator
|
||||
ctx = ctx.WithBlockHeight(12)
|
||||
validator, found := app.StakingKeeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(PKs[0]))
|
||||
require.True(t, found)
|
||||
consAddr0 := sdk.ConsAddress(PKs[0].Address())
|
||||
app.StakingKeeper.Slash(ctx, consAddr0, 10, 10, fraction)
|
||||
|
||||
burnedNotBondedAmount := fraction.MulInt(ubdATokens).TruncateInt()
|
||||
burnedBondAmount := sdk.NewDecFromInt(app.StakingKeeper.TokensFromConsensusPower(ctx, 10)).Mul(fraction).TruncateInt()
|
||||
burnedBondAmount = burnedBondAmount.Sub(burnedNotBondedAmount)
|
||||
|
||||
// read updated pool
|
||||
bondedPool = app.StakingKeeper.GetBondedPool(ctx)
|
||||
notBondedPool = app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
|
||||
bondedPoolBalance := app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, oldBonded.Sub(burnedBondAmount), bondedPoolBalance))
|
||||
|
||||
notBondedPoolBalance := app.BankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, oldNotBonded.Sub(burnedNotBondedAmount), notBondedPoolBalance))
|
||||
|
||||
// read updating redelegation
|
||||
rdA, found = app.StakingKeeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||
require.True(t, found)
|
||||
require.Len(t, rdA.Entries, 1)
|
||||
// read updated validator
|
||||
validator, found = app.StakingKeeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(PKs[0]))
|
||||
require.True(t, found)
|
||||
// power not decreased, all stake was bonded since
|
||||
require.Equal(t, int64(10), validator.GetConsensusPower(app.StakingKeeper.PowerReduction(ctx)))
|
||||
}
|
||||
|
||||
func TestSlashAmount(t *testing.T) {
|
||||
app, ctx, _, _ := bootstrapSlashTest(t, 10)
|
||||
consAddr := sdk.ConsAddress(PKs[0].Address())
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
burnedCoins := app.StakingKeeper.Slash(ctx, consAddr, ctx.BlockHeight(), 10, fraction)
|
||||
require.True(t, burnedCoins.GT(math.ZeroInt()))
|
||||
|
||||
// test the case where the validator was not found, which should return no coins
|
||||
_, addrVals := generateAddresses(app, ctx, 100)
|
||||
noBurned := app.StakingKeeper.Slash(ctx, sdk.ConsAddress(addrVals[0]), ctx.BlockHeight(), 10, fraction)
|
||||
require.True(t, sdk.NewInt(0).Equal(noBurned))
|
||||
}
|
||||
834
tests/integration/staking/keeper/validator_test.go
Normal file
834
tests/integration/staking/keeper/validator_test.go
Normal file
@ -0,0 +1,834 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/teststaking"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
func newMonikerValidator(t testing.TB, operator sdk.ValAddress, pubKey cryptotypes.PubKey, moniker string) types.Validator {
|
||||
v, err := types.NewValidator(operator, pubKey, types.Description{Moniker: moniker})
|
||||
require.NoError(t, err)
|
||||
return v
|
||||
}
|
||||
|
||||
func bootstrapValidatorTest(t testing.TB, power int64, numAddrs int) (*simapp.SimApp, sdk.Context, []sdk.AccAddress, []sdk.ValAddress) {
|
||||
_, app, ctx := createTestInput(&testing.T{})
|
||||
|
||||
addrDels, addrVals := generateAddresses(app, ctx, numAddrs)
|
||||
|
||||
amt := app.StakingKeeper.TokensFromConsensusPower(ctx, power)
|
||||
totalSupply := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), amt.MulRaw(int64(len(addrDels)))))
|
||||
|
||||
notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
// set bonded pool supply
|
||||
app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
|
||||
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), totalSupply))
|
||||
|
||||
// unbond genesis validator delegations
|
||||
delegations := app.StakingKeeper.GetAllDelegations(ctx)
|
||||
require.Len(t, delegations, 1)
|
||||
delegation := delegations[0]
|
||||
|
||||
_, err := app.StakingKeeper.Undelegate(ctx, delegation.GetDelegatorAddr(), delegation.GetValidatorAddr(), delegation.Shares)
|
||||
require.NoError(t, err)
|
||||
|
||||
// end block to unbond genesis validator
|
||||
staking.EndBlocker(ctx, app.StakingKeeper)
|
||||
|
||||
return app, ctx, addrDels, addrVals
|
||||
}
|
||||
|
||||
func initValidators(t testing.TB, power int64, numAddrs int, powers []int64) (*simapp.SimApp, sdk.Context, []sdk.AccAddress, []sdk.ValAddress, []types.Validator) {
|
||||
app, ctx, addrs, valAddrs := bootstrapValidatorTest(t, power, numAddrs)
|
||||
pks := simtestutil.CreateTestPubKeys(numAddrs)
|
||||
|
||||
vs := make([]types.Validator, len(powers))
|
||||
for i, power := range powers {
|
||||
vs[i] = teststaking.NewValidator(t, sdk.ValAddress(addrs[i]), pks[i])
|
||||
tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, power)
|
||||
vs[i], _ = vs[i].AddTokensFromDel(tokens)
|
||||
}
|
||||
return app, ctx, addrs, valAddrs, vs
|
||||
}
|
||||
|
||||
func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) {
|
||||
numVals := 10
|
||||
maxVals := 5
|
||||
|
||||
// create context, keeper, and pool for tests
|
||||
app, ctx, _, valAddrs := bootstrapValidatorTest(t, 0, 100)
|
||||
|
||||
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
||||
notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
|
||||
// create keeper parameters
|
||||
params := app.StakingKeeper.GetParams(ctx)
|
||||
params.MaxValidators = uint32(maxVals)
|
||||
app.StakingKeeper.SetParams(ctx, params)
|
||||
|
||||
// create a random pool
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), app.StakingKeeper.TokensFromConsensusPower(ctx, 1234)))))
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), app.StakingKeeper.TokensFromConsensusPower(ctx, 10000)))))
|
||||
|
||||
app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
|
||||
app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
|
||||
|
||||
validators := make([]types.Validator, numVals)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
moniker := fmt.Sprintf("val#%d", int64(i))
|
||||
val := newMonikerValidator(t, valAddrs[i], PKs[i], moniker)
|
||||
delTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, int64((i+1)*10))
|
||||
val, _ = val.AddTokensFromDel(delTokens)
|
||||
|
||||
val = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, val, true)
|
||||
validators[i] = val
|
||||
}
|
||||
|
||||
nextCliffVal := validators[numVals-maxVals+1]
|
||||
|
||||
// remove enough tokens to kick out the validator below the current cliff
|
||||
// validator and next in line cliff validator
|
||||
app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, nextCliffVal)
|
||||
shares := app.StakingKeeper.TokensFromConsensusPower(ctx, 21)
|
||||
nextCliffVal, _ = nextCliffVal.RemoveDelShares(sdk.NewDecFromInt(shares))
|
||||
nextCliffVal = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, nextCliffVal, true)
|
||||
|
||||
expectedValStatus := map[int]types.BondStatus{
|
||||
9: types.Bonded, 8: types.Bonded, 7: types.Bonded, 5: types.Bonded, 4: types.Bonded,
|
||||
0: types.Unbonding, 1: types.Unbonding, 2: types.Unbonding, 3: types.Unbonding, 6: types.Unbonding,
|
||||
}
|
||||
|
||||
// require all the validators have their respective statuses
|
||||
for valIdx, status := range expectedValStatus {
|
||||
valAddr := validators[valIdx].OperatorAddress
|
||||
addr, err := sdk.ValAddressFromBech32(valAddr)
|
||||
assert.NoError(t, err)
|
||||
val, _ := app.StakingKeeper.GetValidator(ctx, addr)
|
||||
|
||||
assert.Equal(
|
||||
t, status, val.GetStatus(),
|
||||
fmt.Sprintf("expected validator at index %v to have status: %s", valIdx, status),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlashToZeroPowerRemoved(t *testing.T) {
|
||||
// initialize setup
|
||||
app, ctx, _, addrVals := bootstrapValidatorTest(t, 100, 20)
|
||||
|
||||
// add a validator
|
||||
validator := teststaking.NewValidator(t, addrVals[0], PKs[0])
|
||||
valTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 100)
|
||||
|
||||
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
||||
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), valTokens))))
|
||||
|
||||
app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
|
||||
|
||||
validator, _ = validator.AddTokensFromDel(valTokens)
|
||||
require.Equal(t, types.Unbonded, validator.Status)
|
||||
require.Equal(t, valTokens, validator.Tokens)
|
||||
app.StakingKeeper.SetValidatorByConsAddr(ctx, validator)
|
||||
validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)
|
||||
require.Equal(t, valTokens, validator.Tokens, "\nvalidator %v\npool %v", validator, valTokens)
|
||||
|
||||
// slash the validator by 100%
|
||||
app.StakingKeeper.Slash(ctx, sdk.ConsAddress(PKs[0].Address()), 0, 100, math.LegacyOneDec())
|
||||
// apply TM updates
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, -1)
|
||||
// validator should be unbonding
|
||||
validator, _ = app.StakingKeeper.GetValidator(ctx, addrVals[0])
|
||||
require.Equal(t, validator.GetStatus(), types.Unbonding)
|
||||
}
|
||||
|
||||
// test how the validators are sorted, tests GetBondedValidatorsByPower
|
||||
func TestGetValidatorSortingUnmixed(t *testing.T) {
|
||||
app, ctx, addrs, _ := bootstrapValidatorTest(t, 1000, 20)
|
||||
|
||||
// initialize some validators into the state
|
||||
amts := []math.Int{
|
||||
sdk.NewIntFromUint64(0),
|
||||
app.StakingKeeper.PowerReduction(ctx).MulRaw(100),
|
||||
app.StakingKeeper.PowerReduction(ctx),
|
||||
app.StakingKeeper.PowerReduction(ctx).MulRaw(400),
|
||||
app.StakingKeeper.PowerReduction(ctx).MulRaw(200),
|
||||
}
|
||||
n := len(amts)
|
||||
var validators [5]types.Validator
|
||||
for i, amt := range amts {
|
||||
validators[i] = teststaking.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i])
|
||||
validators[i].Status = types.Bonded
|
||||
validators[i].Tokens = amt
|
||||
validators[i].DelegatorShares = sdk.NewDecFromInt(amt)
|
||||
keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[i], true)
|
||||
}
|
||||
|
||||
// first make sure everything made it in to the gotValidator group
|
||||
resValidators := app.StakingKeeper.GetBondedValidatorsByPower(ctx)
|
||||
assert.Equal(t, n, len(resValidators))
|
||||
assert.Equal(t, sdk.NewInt(400).Mul(app.StakingKeeper.PowerReduction(ctx)), resValidators[0].BondedTokens(), "%v", resValidators)
|
||||
assert.Equal(t, sdk.NewInt(200).Mul(app.StakingKeeper.PowerReduction(ctx)), resValidators[1].BondedTokens(), "%v", resValidators)
|
||||
assert.Equal(t, sdk.NewInt(100).Mul(app.StakingKeeper.PowerReduction(ctx)), resValidators[2].BondedTokens(), "%v", resValidators)
|
||||
assert.Equal(t, sdk.NewInt(1).Mul(app.StakingKeeper.PowerReduction(ctx)), resValidators[3].BondedTokens(), "%v", resValidators)
|
||||
assert.Equal(t, sdk.NewInt(0), resValidators[4].BondedTokens(), "%v", resValidators)
|
||||
assert.Equal(t, validators[3].OperatorAddress, resValidators[0].OperatorAddress, "%v", resValidators)
|
||||
assert.Equal(t, validators[4].OperatorAddress, resValidators[1].OperatorAddress, "%v", resValidators)
|
||||
assert.Equal(t, validators[1].OperatorAddress, resValidators[2].OperatorAddress, "%v", resValidators)
|
||||
assert.Equal(t, validators[2].OperatorAddress, resValidators[3].OperatorAddress, "%v", resValidators)
|
||||
assert.Equal(t, validators[0].OperatorAddress, resValidators[4].OperatorAddress, "%v", resValidators)
|
||||
|
||||
// test a basic increase in voting power
|
||||
validators[3].Tokens = sdk.NewInt(500).Mul(app.StakingKeeper.PowerReduction(ctx))
|
||||
keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[3], true)
|
||||
resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, len(resValidators), n)
|
||||
assert.True(ValEq(t, validators[3], resValidators[0]))
|
||||
|
||||
// test a decrease in voting power
|
||||
validators[3].Tokens = sdk.NewInt(300).Mul(app.StakingKeeper.PowerReduction(ctx))
|
||||
keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[3], true)
|
||||
resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, len(resValidators), n)
|
||||
assert.True(ValEq(t, validators[3], resValidators[0]))
|
||||
assert.True(ValEq(t, validators[4], resValidators[1]))
|
||||
|
||||
// test equal voting power, different age
|
||||
validators[3].Tokens = sdk.NewInt(200).Mul(app.StakingKeeper.PowerReduction(ctx))
|
||||
ctx = ctx.WithBlockHeight(10)
|
||||
keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[3], true)
|
||||
resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, len(resValidators), n)
|
||||
assert.True(ValEq(t, validators[3], resValidators[0]))
|
||||
assert.True(ValEq(t, validators[4], resValidators[1]))
|
||||
|
||||
// no change in voting power - no change in sort
|
||||
ctx = ctx.WithBlockHeight(20)
|
||||
keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[4], true)
|
||||
resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, len(resValidators), n)
|
||||
assert.True(ValEq(t, validators[3], resValidators[0]))
|
||||
assert.True(ValEq(t, validators[4], resValidators[1]))
|
||||
|
||||
// change in voting power of both validators, both still in v-set, no age change
|
||||
validators[3].Tokens = sdk.NewInt(300).Mul(app.StakingKeeper.PowerReduction(ctx))
|
||||
validators[4].Tokens = sdk.NewInt(300).Mul(app.StakingKeeper.PowerReduction(ctx))
|
||||
keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[3], true)
|
||||
resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, len(resValidators), n)
|
||||
ctx = ctx.WithBlockHeight(30)
|
||||
keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[4], true)
|
||||
resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, len(resValidators), n, "%v", resValidators)
|
||||
assert.True(ValEq(t, validators[3], resValidators[0]))
|
||||
assert.True(ValEq(t, validators[4], resValidators[1]))
|
||||
}
|
||||
|
||||
func TestGetValidatorSortingMixed(t *testing.T) {
|
||||
app, ctx, addrs, _ := bootstrapValidatorTest(t, 1000, 20)
|
||||
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
||||
notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), app.StakingKeeper.TokensFromConsensusPower(ctx, 501)))))
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), app.StakingKeeper.TokensFromConsensusPower(ctx, 0)))))
|
||||
|
||||
app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
|
||||
app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
|
||||
|
||||
// now 2 max resValidators
|
||||
params := app.StakingKeeper.GetParams(ctx)
|
||||
params.MaxValidators = 2
|
||||
app.StakingKeeper.SetParams(ctx, params)
|
||||
|
||||
// initialize some validators into the state
|
||||
amts := []math.Int{
|
||||
sdk.NewIntFromUint64(0),
|
||||
app.StakingKeeper.PowerReduction(ctx).MulRaw(100),
|
||||
app.StakingKeeper.PowerReduction(ctx),
|
||||
app.StakingKeeper.PowerReduction(ctx).MulRaw(400),
|
||||
app.StakingKeeper.PowerReduction(ctx).MulRaw(200),
|
||||
}
|
||||
|
||||
var validators [5]types.Validator
|
||||
for i, amt := range amts {
|
||||
validators[i] = teststaking.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i])
|
||||
validators[i].DelegatorShares = sdk.NewDecFromInt(amt)
|
||||
validators[i].Status = types.Bonded
|
||||
validators[i].Tokens = amt
|
||||
keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[i], true)
|
||||
}
|
||||
|
||||
val0, found := app.StakingKeeper.GetValidator(ctx, sdk.ValAddress(addrs[0]))
|
||||
require.True(t, found)
|
||||
val1, found := app.StakingKeeper.GetValidator(ctx, sdk.ValAddress(addrs[1]))
|
||||
require.True(t, found)
|
||||
val2, found := app.StakingKeeper.GetValidator(ctx, sdk.ValAddress(addrs[2]))
|
||||
require.True(t, found)
|
||||
val3, found := app.StakingKeeper.GetValidator(ctx, sdk.ValAddress(addrs[3]))
|
||||
require.True(t, found)
|
||||
val4, found := app.StakingKeeper.GetValidator(ctx, sdk.ValAddress(addrs[4]))
|
||||
require.True(t, found)
|
||||
require.Equal(t, types.Bonded, val0.Status)
|
||||
require.Equal(t, types.Unbonding, val1.Status)
|
||||
require.Equal(t, types.Unbonding, val2.Status)
|
||||
require.Equal(t, types.Bonded, val3.Status)
|
||||
require.Equal(t, types.Bonded, val4.Status)
|
||||
|
||||
// first make sure everything made it in to the gotValidator group
|
||||
resValidators := app.StakingKeeper.GetBondedValidatorsByPower(ctx)
|
||||
// The validators returned should match the max validators
|
||||
assert.Equal(t, 2, len(resValidators))
|
||||
assert.Equal(t, sdk.NewInt(400).Mul(app.StakingKeeper.PowerReduction(ctx)), resValidators[0].BondedTokens(), "%v", resValidators)
|
||||
assert.Equal(t, sdk.NewInt(200).Mul(app.StakingKeeper.PowerReduction(ctx)), resValidators[1].BondedTokens(), "%v", resValidators)
|
||||
assert.Equal(t, validators[3].OperatorAddress, resValidators[0].OperatorAddress, "%v", resValidators)
|
||||
assert.Equal(t, validators[4].OperatorAddress, resValidators[1].OperatorAddress, "%v", resValidators)
|
||||
}
|
||||
|
||||
// TODO separate out into multiple tests
|
||||
func TestGetValidatorsEdgeCases(t *testing.T) {
|
||||
app, ctx, addrs, _ := bootstrapValidatorTest(t, 1000, 20)
|
||||
|
||||
// set max validators to 2
|
||||
params := app.StakingKeeper.GetParams(ctx)
|
||||
nMax := uint32(2)
|
||||
params.MaxValidators = nMax
|
||||
app.StakingKeeper.SetParams(ctx, params)
|
||||
|
||||
// initialize some validators into the state
|
||||
powers := []int64{0, 100, 400, 400}
|
||||
var validators [4]types.Validator
|
||||
for i, power := range powers {
|
||||
moniker := fmt.Sprintf("val#%d", int64(i))
|
||||
validators[i] = newMonikerValidator(t, sdk.ValAddress(addrs[i]), PKs[i], moniker)
|
||||
|
||||
tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, power)
|
||||
validators[i], _ = validators[i].AddTokensFromDel(tokens)
|
||||
|
||||
notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, tokens))))
|
||||
app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
|
||||
validators[i] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[i], true)
|
||||
}
|
||||
|
||||
// ensure that the first two bonded validators are the largest validators
|
||||
resValidators := app.StakingKeeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, nMax, uint32(len(resValidators)))
|
||||
assert.True(ValEq(t, validators[2], resValidators[0]))
|
||||
assert.True(ValEq(t, validators[3], resValidators[1]))
|
||||
|
||||
// delegate 500 tokens to validator 0
|
||||
app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validators[0])
|
||||
delTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 500)
|
||||
validators[0], _ = validators[0].AddTokensFromDel(delTokens)
|
||||
notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
|
||||
newTokens := sdk.NewCoins()
|
||||
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), newTokens))
|
||||
app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
|
||||
|
||||
// test that the two largest validators are
|
||||
// a) validator 0 with 500 tokens
|
||||
// b) validator 2 with 400 tokens (delegated before validator 3)
|
||||
validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], true)
|
||||
resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, nMax, uint32(len(resValidators)))
|
||||
assert.True(ValEq(t, validators[0], resValidators[0]))
|
||||
assert.True(ValEq(t, validators[2], resValidators[1]))
|
||||
|
||||
// A validator which leaves the bonded validator set due to a decrease in voting power,
|
||||
// then increases to the original voting power, does not get its spot back in the
|
||||
// case of a tie.
|
||||
//
|
||||
// Order of operations for this test:
|
||||
// - validator 3 enter validator set with 1 new token
|
||||
// - validator 3 removed validator set by removing 201 tokens (validator 2 enters)
|
||||
// - validator 3 adds 200 tokens (equal to validator 2 now) and does not get its spot back
|
||||
|
||||
// validator 3 enters bonded validator set
|
||||
ctx = ctx.WithBlockHeight(40)
|
||||
|
||||
var found bool
|
||||
validators[3], found = app.StakingKeeper.GetValidator(ctx, validators[3].GetOperator())
|
||||
assert.True(t, found)
|
||||
app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validators[3])
|
||||
validators[3], _ = validators[3].AddTokensFromDel(app.StakingKeeper.TokensFromConsensusPower(ctx, 1))
|
||||
|
||||
notBondedPool = app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
newTokens = sdk.NewCoins(sdk.NewCoin(params.BondDenom, app.StakingKeeper.TokensFromConsensusPower(ctx, 1)))
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), newTokens))
|
||||
app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
|
||||
|
||||
validators[3] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[3], true)
|
||||
resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, nMax, uint32(len(resValidators)))
|
||||
assert.True(ValEq(t, validators[0], resValidators[0]))
|
||||
assert.True(ValEq(t, validators[3], resValidators[1]))
|
||||
|
||||
// validator 3 kicked out temporarily
|
||||
app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validators[3])
|
||||
rmTokens := validators[3].TokensFromShares(math.LegacyNewDec(201)).TruncateInt()
|
||||
validators[3], _ = validators[3].RemoveDelShares(math.LegacyNewDec(201))
|
||||
|
||||
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, rmTokens))))
|
||||
app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
|
||||
|
||||
validators[3] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[3], true)
|
||||
resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, nMax, uint32(len(resValidators)))
|
||||
assert.True(ValEq(t, validators[0], resValidators[0]))
|
||||
assert.True(ValEq(t, validators[2], resValidators[1]))
|
||||
|
||||
// validator 3 does not get spot back
|
||||
app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validators[3])
|
||||
validators[3], _ = validators[3].AddTokensFromDel(sdk.NewInt(200))
|
||||
|
||||
notBondedPool = app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, sdk.NewInt(200)))))
|
||||
app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
|
||||
|
||||
validators[3] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[3], true)
|
||||
resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, nMax, uint32(len(resValidators)))
|
||||
assert.True(ValEq(t, validators[0], resValidators[0]))
|
||||
assert.True(ValEq(t, validators[2], resValidators[1]))
|
||||
_, exists := app.StakingKeeper.GetValidator(ctx, validators[3].GetOperator())
|
||||
require.True(t, exists)
|
||||
}
|
||||
|
||||
func TestValidatorBondHeight(t *testing.T) {
|
||||
app, ctx, addrs, _ := bootstrapValidatorTest(t, 1000, 20)
|
||||
|
||||
// now 2 max resValidators
|
||||
params := app.StakingKeeper.GetParams(ctx)
|
||||
params.MaxValidators = 2
|
||||
app.StakingKeeper.SetParams(ctx, params)
|
||||
|
||||
// initialize some validators into the state
|
||||
var validators [3]types.Validator
|
||||
validators[0] = teststaking.NewValidator(t, sdk.ValAddress(PKs[0].Address().Bytes()), PKs[0])
|
||||
validators[1] = teststaking.NewValidator(t, sdk.ValAddress(addrs[1]), PKs[1])
|
||||
validators[2] = teststaking.NewValidator(t, sdk.ValAddress(addrs[2]), PKs[2])
|
||||
|
||||
tokens0 := app.StakingKeeper.TokensFromConsensusPower(ctx, 200)
|
||||
tokens1 := app.StakingKeeper.TokensFromConsensusPower(ctx, 100)
|
||||
tokens2 := app.StakingKeeper.TokensFromConsensusPower(ctx, 100)
|
||||
validators[0], _ = validators[0].AddTokensFromDel(tokens0)
|
||||
validators[1], _ = validators[1].AddTokensFromDel(tokens1)
|
||||
validators[2], _ = validators[2].AddTokensFromDel(tokens2)
|
||||
|
||||
validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], true)
|
||||
|
||||
////////////////////////////////////////
|
||||
// If two validators both increase to the same voting power in the same block,
|
||||
// the one with the first transaction should become bonded
|
||||
validators[1] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[1], true)
|
||||
validators[2] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[2], true)
|
||||
|
||||
resValidators := app.StakingKeeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, uint32(len(resValidators)), params.MaxValidators)
|
||||
|
||||
assert.True(ValEq(t, validators[0], resValidators[0]))
|
||||
assert.True(ValEq(t, validators[1], resValidators[1]))
|
||||
app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validators[1])
|
||||
app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validators[2])
|
||||
delTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 50)
|
||||
validators[1], _ = validators[1].AddTokensFromDel(delTokens)
|
||||
validators[2], _ = validators[2].AddTokensFromDel(delTokens)
|
||||
validators[2] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[2], true)
|
||||
resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, params.MaxValidators, uint32(len(resValidators)))
|
||||
validators[1] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[1], true)
|
||||
assert.True(ValEq(t, validators[0], resValidators[0]))
|
||||
assert.True(ValEq(t, validators[2], resValidators[1]))
|
||||
}
|
||||
|
||||
func TestFullValidatorSetPowerChange(t *testing.T) {
|
||||
app, ctx, addrs, _ := bootstrapValidatorTest(t, 1000, 20)
|
||||
params := app.StakingKeeper.GetParams(ctx)
|
||||
max := 2
|
||||
params.MaxValidators = uint32(2)
|
||||
app.StakingKeeper.SetParams(ctx, params)
|
||||
|
||||
// initialize some validators into the state
|
||||
powers := []int64{0, 100, 400, 400, 200}
|
||||
var validators [5]types.Validator
|
||||
for i, power := range powers {
|
||||
validators[i] = teststaking.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i])
|
||||
tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, power)
|
||||
validators[i], _ = validators[i].AddTokensFromDel(tokens)
|
||||
keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[i], true)
|
||||
}
|
||||
for i := range powers {
|
||||
var found bool
|
||||
validators[i], found = app.StakingKeeper.GetValidator(ctx, validators[i].GetOperator())
|
||||
require.True(t, found)
|
||||
}
|
||||
assert.Equal(t, types.Unbonded, validators[0].Status)
|
||||
assert.Equal(t, types.Unbonding, validators[1].Status)
|
||||
assert.Equal(t, types.Bonded, validators[2].Status)
|
||||
assert.Equal(t, types.Bonded, validators[3].Status)
|
||||
assert.Equal(t, types.Unbonded, validators[4].Status)
|
||||
resValidators := app.StakingKeeper.GetBondedValidatorsByPower(ctx)
|
||||
assert.Equal(t, max, len(resValidators))
|
||||
assert.True(ValEq(t, validators[2], resValidators[0])) // in the order of txs
|
||||
assert.True(ValEq(t, validators[3], resValidators[1]))
|
||||
|
||||
// test a swap in voting power
|
||||
|
||||
tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 600)
|
||||
validators[0], _ = validators[0].AddTokensFromDel(tokens)
|
||||
validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], true)
|
||||
resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx)
|
||||
assert.Equal(t, max, len(resValidators))
|
||||
assert.True(ValEq(t, validators[0], resValidators[0]))
|
||||
assert.True(ValEq(t, validators[2], resValidators[1]))
|
||||
}
|
||||
|
||||
func TestApplyAndReturnValidatorSetUpdatesAllNone(t *testing.T) {
|
||||
app, ctx, _, _ := bootstrapValidatorTest(t, 1000, 20)
|
||||
|
||||
powers := []int64{10, 20}
|
||||
var validators [2]types.Validator
|
||||
for i, power := range powers {
|
||||
valPubKey := PKs[i+1]
|
||||
valAddr := sdk.ValAddress(valPubKey.Address().Bytes())
|
||||
|
||||
validators[i] = teststaking.NewValidator(t, valAddr, valPubKey)
|
||||
tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, power)
|
||||
validators[i], _ = validators[i].AddTokensFromDel(tokens)
|
||||
}
|
||||
|
||||
// test from nothing to something
|
||||
// tendermintUpdate set: {} -> {c1, c3}
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 0)
|
||||
app.StakingKeeper.SetValidator(ctx, validators[0])
|
||||
app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[0])
|
||||
app.StakingKeeper.SetValidator(ctx, validators[1])
|
||||
app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[1])
|
||||
|
||||
updates := applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 2)
|
||||
validators[0], _ = app.StakingKeeper.GetValidator(ctx, validators[0].GetOperator())
|
||||
validators[1], _ = app.StakingKeeper.GetValidator(ctx, validators[1].GetOperator())
|
||||
assert.Equal(t, validators[0].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[1])
|
||||
assert.Equal(t, validators[1].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0])
|
||||
}
|
||||
|
||||
func TestApplyAndReturnValidatorSetUpdatesIdentical(t *testing.T) {
|
||||
app, ctx, addrs, _ := bootstrapValidatorTest(t, 1000, 20)
|
||||
|
||||
powers := []int64{10, 20}
|
||||
var validators [2]types.Validator
|
||||
for i, power := range powers {
|
||||
validators[i] = teststaking.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i])
|
||||
|
||||
tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, power)
|
||||
validators[i], _ = validators[i].AddTokensFromDel(tokens)
|
||||
|
||||
}
|
||||
validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], false)
|
||||
validators[1] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[1], false)
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 2)
|
||||
|
||||
// test identical,
|
||||
// tendermintUpdate set: {} -> {}
|
||||
validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], false)
|
||||
validators[1] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[1], false)
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 0)
|
||||
}
|
||||
|
||||
func TestApplyAndReturnValidatorSetUpdatesSingleValueChange(t *testing.T) {
|
||||
app, ctx, addrs, _ := bootstrapValidatorTest(t, 1000, 20)
|
||||
|
||||
powers := []int64{10, 20}
|
||||
var validators [2]types.Validator
|
||||
for i, power := range powers {
|
||||
validators[i] = teststaking.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i])
|
||||
|
||||
tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, power)
|
||||
validators[i], _ = validators[i].AddTokensFromDel(tokens)
|
||||
|
||||
}
|
||||
validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], false)
|
||||
validators[1] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[1], false)
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 2)
|
||||
|
||||
// test single value change
|
||||
// tendermintUpdate set: {} -> {c1'}
|
||||
validators[0].Status = types.Bonded
|
||||
validators[0].Tokens = app.StakingKeeper.TokensFromConsensusPower(ctx, 600)
|
||||
validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], false)
|
||||
|
||||
updates := applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1)
|
||||
require.Equal(t, validators[0].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0])
|
||||
}
|
||||
|
||||
func TestApplyAndReturnValidatorSetUpdatesMultipleValueChange(t *testing.T) {
|
||||
powers := []int64{10, 20}
|
||||
// TODO: use it in other places
|
||||
app, ctx, _, _, validators := initValidators(t, 1000, 20, powers)
|
||||
|
||||
validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], false)
|
||||
validators[1] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[1], false)
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 2)
|
||||
|
||||
// test multiple value change
|
||||
// tendermintUpdate set: {c1, c3} -> {c1', c3'}
|
||||
delTokens1 := app.StakingKeeper.TokensFromConsensusPower(ctx, 190)
|
||||
delTokens2 := app.StakingKeeper.TokensFromConsensusPower(ctx, 80)
|
||||
validators[0], _ = validators[0].AddTokensFromDel(delTokens1)
|
||||
validators[1], _ = validators[1].AddTokensFromDel(delTokens2)
|
||||
validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], false)
|
||||
validators[1] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[1], false)
|
||||
|
||||
updates := applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 2)
|
||||
require.Equal(t, validators[0].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0])
|
||||
require.Equal(t, validators[1].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[1])
|
||||
}
|
||||
|
||||
func TestApplyAndReturnValidatorSetUpdatesInserted(t *testing.T) {
|
||||
powers := []int64{10, 20, 5, 15, 25}
|
||||
app, ctx, _, _, validators := initValidators(t, 1000, 20, powers)
|
||||
|
||||
validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], false)
|
||||
validators[1] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[1], false)
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 2)
|
||||
|
||||
// test validtor added at the beginning
|
||||
// tendermintUpdate set: {} -> {c0}
|
||||
app.StakingKeeper.SetValidator(ctx, validators[2])
|
||||
app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[2])
|
||||
updates := applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1)
|
||||
validators[2], _ = app.StakingKeeper.GetValidator(ctx, validators[2].GetOperator())
|
||||
require.Equal(t, validators[2].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0])
|
||||
|
||||
// test validtor added at the beginning
|
||||
// tendermintUpdate set: {} -> {c0}
|
||||
app.StakingKeeper.SetValidator(ctx, validators[3])
|
||||
app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[3])
|
||||
updates = applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1)
|
||||
validators[3], _ = app.StakingKeeper.GetValidator(ctx, validators[3].GetOperator())
|
||||
require.Equal(t, validators[3].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0])
|
||||
|
||||
// test validtor added at the end
|
||||
// tendermintUpdate set: {} -> {c0}
|
||||
app.StakingKeeper.SetValidator(ctx, validators[4])
|
||||
app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[4])
|
||||
updates = applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1)
|
||||
validators[4], _ = app.StakingKeeper.GetValidator(ctx, validators[4].GetOperator())
|
||||
require.Equal(t, validators[4].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0])
|
||||
}
|
||||
|
||||
func TestApplyAndReturnValidatorSetUpdatesWithCliffValidator(t *testing.T) {
|
||||
app, ctx, addrs, _ := bootstrapValidatorTest(t, 1000, 20)
|
||||
params := types.DefaultParams()
|
||||
params.MaxValidators = 2
|
||||
app.StakingKeeper.SetParams(ctx, params)
|
||||
|
||||
powers := []int64{10, 20, 5}
|
||||
var validators [5]types.Validator
|
||||
for i, power := range powers {
|
||||
validators[i] = teststaking.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i])
|
||||
tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, power)
|
||||
validators[i], _ = validators[i].AddTokensFromDel(tokens)
|
||||
}
|
||||
validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], false)
|
||||
validators[1] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[1], false)
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 2)
|
||||
|
||||
// test validator added at the end but not inserted in the valset
|
||||
// tendermintUpdate set: {} -> {}
|
||||
keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[2], false)
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 0)
|
||||
|
||||
// test validator change its power and become a gotValidator (pushing out an existing)
|
||||
// tendermintUpdate set: {} -> {c0, c4}
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 0)
|
||||
|
||||
tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 10)
|
||||
validators[2], _ = validators[2].AddTokensFromDel(tokens)
|
||||
app.StakingKeeper.SetValidator(ctx, validators[2])
|
||||
app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[2])
|
||||
updates := applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 2)
|
||||
validators[2], _ = app.StakingKeeper.GetValidator(ctx, validators[2].GetOperator())
|
||||
require.Equal(t, validators[0].ABCIValidatorUpdateZero(), updates[1])
|
||||
require.Equal(t, validators[2].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0])
|
||||
}
|
||||
|
||||
func TestApplyAndReturnValidatorSetUpdatesNewValidator(t *testing.T) {
|
||||
app, ctx, _, _ := bootstrapValidatorTest(t, 1000, 20)
|
||||
params := app.StakingKeeper.GetParams(ctx)
|
||||
params.MaxValidators = uint32(3)
|
||||
|
||||
app.StakingKeeper.SetParams(ctx, params)
|
||||
|
||||
powers := []int64{100, 100}
|
||||
var validators [2]types.Validator
|
||||
|
||||
// initialize some validators into the state
|
||||
for i, power := range powers {
|
||||
valPubKey := PKs[i+1]
|
||||
valAddr := sdk.ValAddress(valPubKey.Address().Bytes())
|
||||
|
||||
validators[i] = teststaking.NewValidator(t, valAddr, valPubKey)
|
||||
tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, power)
|
||||
validators[i], _ = validators[i].AddTokensFromDel(tokens)
|
||||
|
||||
app.StakingKeeper.SetValidator(ctx, validators[i])
|
||||
app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[i])
|
||||
}
|
||||
|
||||
// verify initial Tendermint updates are correct
|
||||
updates := applyValidatorSetUpdates(t, ctx, app.StakingKeeper, len(validators))
|
||||
validators[0], _ = app.StakingKeeper.GetValidator(ctx, validators[0].GetOperator())
|
||||
validators[1], _ = app.StakingKeeper.GetValidator(ctx, validators[1].GetOperator())
|
||||
require.Equal(t, validators[0].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0])
|
||||
require.Equal(t, validators[1].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[1])
|
||||
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 0)
|
||||
|
||||
// update initial validator set
|
||||
for i, power := range powers {
|
||||
|
||||
app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validators[i])
|
||||
tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, power)
|
||||
validators[i], _ = validators[i].AddTokensFromDel(tokens)
|
||||
|
||||
app.StakingKeeper.SetValidator(ctx, validators[i])
|
||||
app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[i])
|
||||
}
|
||||
|
||||
// add a new validator that goes from zero power, to non-zero power, back to
|
||||
// zero power
|
||||
valPubKey := PKs[len(validators)+1]
|
||||
valAddr := sdk.ValAddress(valPubKey.Address().Bytes())
|
||||
amt := sdk.NewInt(100)
|
||||
|
||||
validator := teststaking.NewValidator(t, valAddr, valPubKey)
|
||||
validator, _ = validator.AddTokensFromDel(amt)
|
||||
|
||||
app.StakingKeeper.SetValidator(ctx, validator)
|
||||
|
||||
validator, _ = validator.RemoveDelShares(sdk.NewDecFromInt(amt))
|
||||
app.StakingKeeper.SetValidator(ctx, validator)
|
||||
app.StakingKeeper.SetValidatorByPowerIndex(ctx, validator)
|
||||
|
||||
// add a new validator that increases in power
|
||||
valPubKey = PKs[len(validators)+2]
|
||||
valAddr = sdk.ValAddress(valPubKey.Address().Bytes())
|
||||
|
||||
validator = teststaking.NewValidator(t, valAddr, valPubKey)
|
||||
tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 500)
|
||||
validator, _ = validator.AddTokensFromDel(tokens)
|
||||
app.StakingKeeper.SetValidator(ctx, validator)
|
||||
app.StakingKeeper.SetValidatorByPowerIndex(ctx, validator)
|
||||
|
||||
// verify initial Tendermint updates are correct
|
||||
updates = applyValidatorSetUpdates(t, ctx, app.StakingKeeper, len(validators)+1)
|
||||
validator, _ = app.StakingKeeper.GetValidator(ctx, validator.GetOperator())
|
||||
validators[0], _ = app.StakingKeeper.GetValidator(ctx, validators[0].GetOperator())
|
||||
validators[1], _ = app.StakingKeeper.GetValidator(ctx, validators[1].GetOperator())
|
||||
require.Equal(t, validator.ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0])
|
||||
require.Equal(t, validators[0].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[1])
|
||||
require.Equal(t, validators[1].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[2])
|
||||
}
|
||||
|
||||
func TestApplyAndReturnValidatorSetUpdatesBondTransition(t *testing.T) {
|
||||
app, ctx, _, _ := bootstrapValidatorTest(t, 1000, 20)
|
||||
params := app.StakingKeeper.GetParams(ctx)
|
||||
params.MaxValidators = uint32(2)
|
||||
|
||||
app.StakingKeeper.SetParams(ctx, params)
|
||||
|
||||
powers := []int64{100, 200, 300}
|
||||
var validators [3]types.Validator
|
||||
|
||||
// initialize some validators into the state
|
||||
for i, power := range powers {
|
||||
moniker := fmt.Sprintf("%d", i)
|
||||
valPubKey := PKs[i+1]
|
||||
valAddr := sdk.ValAddress(valPubKey.Address().Bytes())
|
||||
|
||||
validators[i] = newMonikerValidator(t, valAddr, valPubKey, moniker)
|
||||
tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, power)
|
||||
validators[i], _ = validators[i].AddTokensFromDel(tokens)
|
||||
app.StakingKeeper.SetValidator(ctx, validators[i])
|
||||
app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[i])
|
||||
}
|
||||
|
||||
// verify initial Tendermint updates are correct
|
||||
updates := applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 2)
|
||||
validators[2], _ = app.StakingKeeper.GetValidator(ctx, validators[2].GetOperator())
|
||||
validators[1], _ = app.StakingKeeper.GetValidator(ctx, validators[1].GetOperator())
|
||||
require.Equal(t, validators[2].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0])
|
||||
require.Equal(t, validators[1].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[1])
|
||||
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 0)
|
||||
|
||||
// delegate to validator with lowest power but not enough to bond
|
||||
ctx = ctx.WithBlockHeight(1)
|
||||
|
||||
var found bool
|
||||
validators[0], found = app.StakingKeeper.GetValidator(ctx, validators[0].GetOperator())
|
||||
require.True(t, found)
|
||||
|
||||
app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validators[0])
|
||||
tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 1)
|
||||
validators[0], _ = validators[0].AddTokensFromDel(tokens)
|
||||
app.StakingKeeper.SetValidator(ctx, validators[0])
|
||||
app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[0])
|
||||
|
||||
// verify initial Tendermint updates are correct
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 0)
|
||||
|
||||
// create a series of events that will bond and unbond the validator with
|
||||
// lowest power in a single block context (height)
|
||||
ctx = ctx.WithBlockHeight(2)
|
||||
|
||||
validators[1], found = app.StakingKeeper.GetValidator(ctx, validators[1].GetOperator())
|
||||
require.True(t, found)
|
||||
|
||||
app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validators[0])
|
||||
validators[0], _ = validators[0].RemoveDelShares(validators[0].DelegatorShares)
|
||||
app.StakingKeeper.SetValidator(ctx, validators[0])
|
||||
app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[0])
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 0)
|
||||
|
||||
app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validators[1])
|
||||
tokens = app.StakingKeeper.TokensFromConsensusPower(ctx, 250)
|
||||
validators[1], _ = validators[1].AddTokensFromDel(tokens)
|
||||
app.StakingKeeper.SetValidator(ctx, validators[1])
|
||||
app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[1])
|
||||
|
||||
// verify initial Tendermint updates are correct
|
||||
updates = applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1)
|
||||
require.Equal(t, validators[1].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0])
|
||||
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 0)
|
||||
}
|
||||
|
||||
func applyValidatorSetUpdates(t *testing.T, ctx sdk.Context, k *keeper.Keeper, expectedUpdatesLen int) []abci.ValidatorUpdate {
|
||||
updates, err := k.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
require.NoError(t, err)
|
||||
if expectedUpdatesLen >= 0 {
|
||||
require.Equal(t, expectedUpdatesLen, len(updates), "%v", updates)
|
||||
}
|
||||
return updates
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -4,89 +4,17 @@ import (
|
||||
gocontext "context"
|
||||
"fmt"
|
||||
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/query"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/teststaking"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
func (suite *KeeperTestSuite) TestGRPCQueryValidators() {
|
||||
queryClient, vals := suite.queryClient, suite.vals
|
||||
var req *types.QueryValidatorsRequest
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
numVals int
|
||||
hasNext bool
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
func() {
|
||||
req = &types.QueryValidatorsRequest{}
|
||||
},
|
||||
true,
|
||||
func (s *KeeperTestSuite) TestGRPCQueryValidator() {
|
||||
ctx, keeper, queryClient := s.ctx, s.stakingKeeper, s.queryClient
|
||||
require := s.Require()
|
||||
|
||||
len(vals) + 1, // +1 validator from genesis state
|
||||
false,
|
||||
},
|
||||
{
|
||||
"empty status returns all the validators",
|
||||
func() {
|
||||
req = &types.QueryValidatorsRequest{Status: ""}
|
||||
},
|
||||
true,
|
||||
len(vals) + 1, // +1 validator from genesis state
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid request",
|
||||
func() {
|
||||
req = &types.QueryValidatorsRequest{Status: "test"}
|
||||
},
|
||||
false,
|
||||
0,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
func() {
|
||||
req = &types.QueryValidatorsRequest{
|
||||
Status: types.Bonded.String(),
|
||||
Pagination: &query.PageRequest{Limit: 1, CountTotal: true},
|
||||
}
|
||||
},
|
||||
true,
|
||||
1,
|
||||
true,
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
tc.malleate()
|
||||
valsResp, err := queryClient.Validators(gocontext.Background(), req)
|
||||
if tc.expPass {
|
||||
suite.NoError(err)
|
||||
suite.NotNil(valsResp)
|
||||
suite.Equal(tc.numVals, len(valsResp.Validators))
|
||||
suite.Equal(uint64(len(vals))+1, valsResp.Pagination.Total) // +1 validator from genesis state
|
||||
|
||||
if tc.hasNext {
|
||||
suite.NotNil(valsResp.Pagination.NextKey)
|
||||
} else {
|
||||
suite.Nil(valsResp.Pagination.NextKey)
|
||||
}
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestGRPCQueryValidator() {
|
||||
app, ctx, queryClient, vals := suite.app, suite.ctx, suite.queryClient, suite.vals
|
||||
validator, found := app.StakingKeeper.GetValidator(ctx, vals[0].GetOperator())
|
||||
suite.True(found)
|
||||
validator := teststaking.NewValidator(s.T(), sdk.ValAddress(PKs[0].Address().Bytes()), PKs[0])
|
||||
keeper.SetValidator(ctx, validator)
|
||||
var req *types.QueryValidatorRequest
|
||||
testCases := []struct {
|
||||
msg string
|
||||
@ -103,678 +31,22 @@ func (suite *KeeperTestSuite) TestGRPCQueryValidator() {
|
||||
{
|
||||
"valid request",
|
||||
func() {
|
||||
req = &types.QueryValidatorRequest{ValidatorAddr: vals[0].OperatorAddress}
|
||||
req = &types.QueryValidatorRequest{ValidatorAddr: validator.OperatorAddress}
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
s.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
tc.malleate()
|
||||
res, err := queryClient.Validator(gocontext.Background(), req)
|
||||
if tc.expPass {
|
||||
suite.NoError(err)
|
||||
suite.True(validator.Equal(&res.Validator))
|
||||
require.NoError(err)
|
||||
require.True(validator.Equal(&res.Validator))
|
||||
} else {
|
||||
suite.Error(err)
|
||||
suite.Nil(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestGRPCQueryDelegatorValidators() {
|
||||
app, ctx, queryClient, addrs := suite.app, suite.ctx, suite.queryClient, suite.addrs
|
||||
params := app.StakingKeeper.GetParams(ctx)
|
||||
delValidators := app.StakingKeeper.GetDelegatorValidators(ctx, addrs[0], params.MaxValidators)
|
||||
var req *types.QueryDelegatorValidatorsRequest
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
func() {
|
||||
req = &types.QueryDelegatorValidatorsRequest{}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
func() {
|
||||
req = &types.QueryDelegatorValidatorsRequest{
|
||||
DelegatorAddr: addrs[0].String(),
|
||||
Pagination: &query.PageRequest{Limit: 1, CountTotal: true},
|
||||
}
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
tc.malleate()
|
||||
res, err := queryClient.DelegatorValidators(gocontext.Background(), req)
|
||||
if tc.expPass {
|
||||
suite.NoError(err)
|
||||
suite.Equal(1, len(res.Validators))
|
||||
suite.NotNil(res.Pagination.NextKey)
|
||||
suite.Equal(uint64(len(delValidators)), res.Pagination.Total)
|
||||
} else {
|
||||
suite.Error(err)
|
||||
suite.Nil(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestGRPCQueryDelegatorValidator() {
|
||||
queryClient, addrs, vals := suite.queryClient, suite.addrs, suite.vals
|
||||
addr := addrs[1]
|
||||
addrVal, addrVal1 := vals[0].OperatorAddress, vals[1].OperatorAddress
|
||||
var req *types.QueryDelegatorValidatorRequest
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
func() {
|
||||
req = &types.QueryDelegatorValidatorRequest{}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid delegator, validator pair",
|
||||
func() {
|
||||
req = &types.QueryDelegatorValidatorRequest{
|
||||
DelegatorAddr: addr.String(),
|
||||
ValidatorAddr: addrVal,
|
||||
}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
func() {
|
||||
req = &types.QueryDelegatorValidatorRequest{
|
||||
DelegatorAddr: addr.String(),
|
||||
ValidatorAddr: addrVal1,
|
||||
}
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
tc.malleate()
|
||||
res, err := queryClient.DelegatorValidator(gocontext.Background(), req)
|
||||
if tc.expPass {
|
||||
suite.NoError(err)
|
||||
suite.Equal(addrVal1, res.Validator.OperatorAddress)
|
||||
} else {
|
||||
suite.Error(err)
|
||||
suite.Nil(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestGRPCQueryDelegation() {
|
||||
app, ctx, queryClient, addrs, vals := suite.app, suite.ctx, suite.queryClient, suite.addrs, suite.vals
|
||||
addrAcc, addrAcc1 := addrs[0], addrs[1]
|
||||
addrVal := vals[0].OperatorAddress
|
||||
valAddr, err := sdk.ValAddressFromBech32(addrVal)
|
||||
suite.NoError(err)
|
||||
delegation, found := app.StakingKeeper.GetDelegation(ctx, addrAcc, valAddr)
|
||||
suite.True(found)
|
||||
var req *types.QueryDelegationRequest
|
||||
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
func() {
|
||||
req = &types.QueryDelegationRequest{}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid validator, delegator pair",
|
||||
func() {
|
||||
req = &types.QueryDelegationRequest{
|
||||
DelegatorAddr: addrAcc1.String(),
|
||||
ValidatorAddr: addrVal,
|
||||
}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
func() {
|
||||
req = &types.QueryDelegationRequest{DelegatorAddr: addrAcc.String(), ValidatorAddr: addrVal}
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
tc.malleate()
|
||||
res, err := queryClient.Delegation(gocontext.Background(), req)
|
||||
if tc.expPass {
|
||||
suite.Equal(delegation.ValidatorAddress, res.DelegationResponse.Delegation.ValidatorAddress)
|
||||
suite.Equal(delegation.DelegatorAddress, res.DelegationResponse.Delegation.DelegatorAddress)
|
||||
suite.Equal(sdk.NewCoin(sdk.DefaultBondDenom, delegation.Shares.TruncateInt()), res.DelegationResponse.Balance)
|
||||
} else {
|
||||
suite.Error(err)
|
||||
suite.Nil(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestGRPCQueryDelegatorDelegations() {
|
||||
app, ctx, queryClient, addrs, vals := suite.app, suite.ctx, suite.queryClient, suite.addrs, suite.vals
|
||||
addrAcc := addrs[0]
|
||||
addrVal1 := vals[0].OperatorAddress
|
||||
valAddr, err := sdk.ValAddressFromBech32(addrVal1)
|
||||
suite.NoError(err)
|
||||
delegation, found := app.StakingKeeper.GetDelegation(ctx, addrAcc, valAddr)
|
||||
suite.True(found)
|
||||
var req *types.QueryDelegatorDelegationsRequest
|
||||
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
onSuccess func(suite *KeeperTestSuite, response *types.QueryDelegatorDelegationsResponse)
|
||||
expErr bool
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
func() {
|
||||
req = &types.QueryDelegatorDelegationsRequest{}
|
||||
},
|
||||
func(suite *KeeperTestSuite, response *types.QueryDelegatorDelegationsResponse) {},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"valid request with no delegations",
|
||||
func() {
|
||||
req = &types.QueryDelegatorDelegationsRequest{DelegatorAddr: addrs[4].String()}
|
||||
},
|
||||
func(suite *KeeperTestSuite, response *types.QueryDelegatorDelegationsResponse) {
|
||||
suite.Equal(uint64(0), response.Pagination.Total)
|
||||
suite.Len(response.DelegationResponses, 0)
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
func() {
|
||||
req = &types.QueryDelegatorDelegationsRequest{
|
||||
DelegatorAddr: addrAcc.String(),
|
||||
Pagination: &query.PageRequest{Limit: 1, CountTotal: true},
|
||||
}
|
||||
},
|
||||
func(suite *KeeperTestSuite, response *types.QueryDelegatorDelegationsResponse) {
|
||||
suite.Equal(uint64(2), response.Pagination.Total)
|
||||
suite.Len(response.DelegationResponses, 1)
|
||||
suite.Equal(sdk.NewCoin(sdk.DefaultBondDenom, delegation.Shares.TruncateInt()), response.DelegationResponses[0].Balance)
|
||||
},
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
tc.malleate()
|
||||
res, err := queryClient.DelegatorDelegations(gocontext.Background(), req)
|
||||
if tc.expErr {
|
||||
suite.Error(err)
|
||||
} else {
|
||||
suite.NoError(err)
|
||||
tc.onSuccess(suite, res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestGRPCQueryValidatorDelegations() {
|
||||
app, ctx, queryClient, addrs, vals := suite.app, suite.ctx, suite.queryClient, suite.addrs, suite.vals
|
||||
addrAcc := addrs[0]
|
||||
addrVal1 := vals[1].OperatorAddress
|
||||
valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs)
|
||||
addrVal2 := valAddrs[4]
|
||||
valAddr, err := sdk.ValAddressFromBech32(addrVal1)
|
||||
suite.NoError(err)
|
||||
delegation, found := app.StakingKeeper.GetDelegation(ctx, addrAcc, valAddr)
|
||||
suite.True(found)
|
||||
|
||||
var req *types.QueryValidatorDelegationsRequest
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
expErr bool
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
func() {
|
||||
req = &types.QueryValidatorDelegationsRequest{}
|
||||
},
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid validator delegator pair",
|
||||
func() {
|
||||
req = &types.QueryValidatorDelegationsRequest{ValidatorAddr: addrVal2.String()}
|
||||
},
|
||||
false,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
func() {
|
||||
req = &types.QueryValidatorDelegationsRequest{
|
||||
ValidatorAddr: addrVal1,
|
||||
Pagination: &query.PageRequest{Limit: 1, CountTotal: true},
|
||||
}
|
||||
},
|
||||
true,
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
tc.malleate()
|
||||
res, err := queryClient.ValidatorDelegations(gocontext.Background(), req)
|
||||
if tc.expPass && !tc.expErr {
|
||||
suite.NoError(err)
|
||||
suite.Len(res.DelegationResponses, 1)
|
||||
suite.NotNil(res.Pagination.NextKey)
|
||||
suite.Equal(uint64(2), res.Pagination.Total)
|
||||
suite.Equal(addrVal1, res.DelegationResponses[0].Delegation.ValidatorAddress)
|
||||
suite.Equal(sdk.NewCoin(sdk.DefaultBondDenom, delegation.Shares.TruncateInt()), res.DelegationResponses[0].Balance)
|
||||
} else if !tc.expPass && !tc.expErr {
|
||||
suite.NoError(err)
|
||||
suite.Nil(res.DelegationResponses)
|
||||
} else {
|
||||
suite.Error(err)
|
||||
suite.Nil(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestGRPCQueryUnbondingDelegation() {
|
||||
app, ctx, queryClient, addrs, vals := suite.app, suite.ctx, suite.queryClient, suite.addrs, suite.vals
|
||||
addrAcc2 := addrs[1]
|
||||
addrVal2 := vals[1].OperatorAddress
|
||||
|
||||
unbondingTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 2)
|
||||
valAddr, err1 := sdk.ValAddressFromBech32(addrVal2)
|
||||
suite.NoError(err1)
|
||||
_, err := app.StakingKeeper.Undelegate(ctx, addrAcc2, valAddr, sdk.NewDecFromInt(unbondingTokens))
|
||||
suite.NoError(err)
|
||||
|
||||
unbond, found := app.StakingKeeper.GetUnbondingDelegation(ctx, addrAcc2, valAddr)
|
||||
suite.True(found)
|
||||
var req *types.QueryUnbondingDelegationRequest
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
func() {
|
||||
req = &types.QueryUnbondingDelegationRequest{}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid request",
|
||||
func() {
|
||||
req = &types.QueryUnbondingDelegationRequest{}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
func() {
|
||||
req = &types.QueryUnbondingDelegationRequest{
|
||||
DelegatorAddr: addrAcc2.String(), ValidatorAddr: addrVal2,
|
||||
}
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
tc.malleate()
|
||||
res, err := queryClient.UnbondingDelegation(gocontext.Background(), req)
|
||||
if tc.expPass {
|
||||
suite.NotNil(res)
|
||||
suite.Equal(unbond, res.Unbond)
|
||||
} else {
|
||||
suite.Error(err)
|
||||
suite.Nil(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestGRPCQueryDelegatorUnbondingDelegations() {
|
||||
app, ctx, queryClient, addrs, vals := suite.app, suite.ctx, suite.queryClient, suite.addrs, suite.vals
|
||||
addrAcc, addrAcc1 := addrs[0], addrs[1]
|
||||
addrVal, addrVal2 := vals[0].OperatorAddress, vals[1].OperatorAddress
|
||||
|
||||
unbondingTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 2)
|
||||
valAddr1, err1 := sdk.ValAddressFromBech32(addrVal)
|
||||
suite.NoError(err1)
|
||||
_, err := app.StakingKeeper.Undelegate(ctx, addrAcc, valAddr1, sdk.NewDecFromInt(unbondingTokens))
|
||||
suite.NoError(err)
|
||||
valAddr2, err1 := sdk.ValAddressFromBech32(addrVal2)
|
||||
suite.NoError(err1)
|
||||
_, err = app.StakingKeeper.Undelegate(ctx, addrAcc, valAddr2, sdk.NewDecFromInt(unbondingTokens))
|
||||
suite.NoError(err)
|
||||
|
||||
unbond, found := app.StakingKeeper.GetUnbondingDelegation(ctx, addrAcc, valAddr1)
|
||||
suite.True(found)
|
||||
var req *types.QueryDelegatorUnbondingDelegationsRequest
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
expErr bool
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
func() {
|
||||
req = &types.QueryDelegatorUnbondingDelegationsRequest{}
|
||||
},
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid request",
|
||||
func() {
|
||||
req = &types.QueryDelegatorUnbondingDelegationsRequest{DelegatorAddr: addrAcc1.String()}
|
||||
},
|
||||
false,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
func() {
|
||||
req = &types.QueryDelegatorUnbondingDelegationsRequest{
|
||||
DelegatorAddr: addrAcc.String(),
|
||||
Pagination: &query.PageRequest{Limit: 1, CountTotal: true},
|
||||
}
|
||||
},
|
||||
true,
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
tc.malleate()
|
||||
res, err := queryClient.DelegatorUnbondingDelegations(gocontext.Background(), req)
|
||||
if tc.expPass && !tc.expErr {
|
||||
suite.NoError(err)
|
||||
suite.NotNil(res.Pagination.NextKey)
|
||||
suite.Equal(uint64(2), res.Pagination.Total)
|
||||
suite.Len(res.UnbondingResponses, 1)
|
||||
suite.Equal(unbond, res.UnbondingResponses[0])
|
||||
} else if !tc.expPass && !tc.expErr {
|
||||
suite.NoError(err)
|
||||
suite.Nil(res.UnbondingResponses)
|
||||
} else {
|
||||
suite.Error(err)
|
||||
suite.Nil(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestGRPCQueryPoolParameters() {
|
||||
app, ctx, queryClient := suite.app, suite.ctx, suite.queryClient
|
||||
bondDenom := sdk.DefaultBondDenom
|
||||
|
||||
// Query pool
|
||||
res, err := queryClient.Pool(gocontext.Background(), &types.QueryPoolRequest{})
|
||||
suite.NoError(err)
|
||||
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
||||
notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
suite.Equal(app.BankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom).Amount, res.Pool.NotBondedTokens)
|
||||
suite.Equal(app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount, res.Pool.BondedTokens)
|
||||
|
||||
// Query Params
|
||||
resp, err := queryClient.Params(gocontext.Background(), &types.QueryParamsRequest{})
|
||||
suite.NoError(err)
|
||||
suite.Equal(app.StakingKeeper.GetParams(ctx), resp.Params)
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestGRPCQueryHistoricalInfo() {
|
||||
app, ctx, queryClient := suite.app, suite.ctx, suite.queryClient
|
||||
|
||||
hi, found := app.StakingKeeper.GetHistoricalInfo(ctx, 5)
|
||||
suite.True(found)
|
||||
|
||||
var req *types.QueryHistoricalInfoRequest
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
func() {
|
||||
req = &types.QueryHistoricalInfoRequest{}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid request with negative height",
|
||||
func() {
|
||||
req = &types.QueryHistoricalInfoRequest{Height: -1}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid request with old height",
|
||||
func() {
|
||||
req = &types.QueryHistoricalInfoRequest{Height: 4}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid request with current height",
|
||||
func() {
|
||||
req = &types.QueryHistoricalInfoRequest{Height: 5}
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
tc.malleate()
|
||||
res, err := queryClient.HistoricalInfo(gocontext.Background(), req)
|
||||
if tc.expPass {
|
||||
suite.NoError(err)
|
||||
suite.NotNil(res)
|
||||
suite.True(hi.Equal(res.Hist))
|
||||
} else {
|
||||
suite.Error(err)
|
||||
suite.Nil(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestGRPCQueryRedelegations() {
|
||||
app, ctx, queryClient, addrs, vals := suite.app, suite.ctx, suite.queryClient, suite.addrs, suite.vals
|
||||
|
||||
addrAcc, addrAcc1 := addrs[0], addrs[1]
|
||||
valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs)
|
||||
val1, val2, val3, val4 := vals[0], vals[1], valAddrs[3], valAddrs[4]
|
||||
delAmount := app.StakingKeeper.TokensFromConsensusPower(ctx, 1)
|
||||
_, err := app.StakingKeeper.Delegate(ctx, addrAcc1, delAmount, types.Unbonded, val1, true)
|
||||
suite.NoError(err)
|
||||
applyValidatorSetUpdates(suite.T(), ctx, app.StakingKeeper, -1)
|
||||
|
||||
rdAmount := app.StakingKeeper.TokensFromConsensusPower(ctx, 1)
|
||||
_, err = app.StakingKeeper.BeginRedelegation(ctx, addrAcc1, val1.GetOperator(), val2.GetOperator(), sdk.NewDecFromInt(rdAmount))
|
||||
suite.NoError(err)
|
||||
applyValidatorSetUpdates(suite.T(), ctx, app.StakingKeeper, -1)
|
||||
|
||||
redel, found := app.StakingKeeper.GetRedelegation(ctx, addrAcc1, val1.GetOperator(), val2.GetOperator())
|
||||
suite.True(found)
|
||||
|
||||
var req *types.QueryRedelegationsRequest
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
expErr bool
|
||||
}{
|
||||
{
|
||||
"request redelegations for non existent addr",
|
||||
func() {
|
||||
req = &types.QueryRedelegationsRequest{DelegatorAddr: addrAcc.String()}
|
||||
},
|
||||
false,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"request redelegations with non existent pairs",
|
||||
func() {
|
||||
req = &types.QueryRedelegationsRequest{
|
||||
DelegatorAddr: addrAcc.String(), SrcValidatorAddr: val3.String(),
|
||||
DstValidatorAddr: val4.String(),
|
||||
}
|
||||
},
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"request redelegations with delegatoraddr, sourceValAddr, destValAddr",
|
||||
func() {
|
||||
req = &types.QueryRedelegationsRequest{
|
||||
DelegatorAddr: addrAcc1.String(), SrcValidatorAddr: val1.OperatorAddress,
|
||||
DstValidatorAddr: val2.OperatorAddress, Pagination: &query.PageRequest{},
|
||||
}
|
||||
},
|
||||
true,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"request redelegations with delegatoraddr and sourceValAddr",
|
||||
func() {
|
||||
req = &types.QueryRedelegationsRequest{
|
||||
DelegatorAddr: addrAcc1.String(), SrcValidatorAddr: val1.OperatorAddress,
|
||||
Pagination: &query.PageRequest{},
|
||||
}
|
||||
},
|
||||
true,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"query redelegations with sourceValAddr only",
|
||||
func() {
|
||||
req = &types.QueryRedelegationsRequest{
|
||||
SrcValidatorAddr: val1.GetOperator().String(),
|
||||
Pagination: &query.PageRequest{Limit: 1, CountTotal: true},
|
||||
}
|
||||
},
|
||||
true,
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
tc.malleate()
|
||||
res, err := queryClient.Redelegations(gocontext.Background(), req)
|
||||
if tc.expPass && !tc.expErr {
|
||||
suite.NoError(err)
|
||||
suite.Len(res.RedelegationResponses, len(redel.Entries))
|
||||
suite.Equal(redel.DelegatorAddress, res.RedelegationResponses[0].Redelegation.DelegatorAddress)
|
||||
suite.Equal(redel.ValidatorSrcAddress, res.RedelegationResponses[0].Redelegation.ValidatorSrcAddress)
|
||||
suite.Equal(redel.ValidatorDstAddress, res.RedelegationResponses[0].Redelegation.ValidatorDstAddress)
|
||||
suite.Len(redel.Entries, len(res.RedelegationResponses[0].Entries))
|
||||
} else if !tc.expPass && !tc.expErr {
|
||||
suite.NoError(err)
|
||||
suite.Nil(res.RedelegationResponses)
|
||||
} else {
|
||||
suite.Error(err)
|
||||
suite.Nil(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestGRPCQueryValidatorUnbondingDelegations() {
|
||||
app, ctx, queryClient, addrs, vals := suite.app, suite.ctx, suite.queryClient, suite.addrs, suite.vals
|
||||
addrAcc1, _ := addrs[0], addrs[1]
|
||||
val1 := vals[0]
|
||||
|
||||
// undelegate
|
||||
undelAmount := app.StakingKeeper.TokensFromConsensusPower(ctx, 2)
|
||||
_, err := app.StakingKeeper.Undelegate(ctx, addrAcc1, val1.GetOperator(), sdk.NewDecFromInt(undelAmount))
|
||||
suite.NoError(err)
|
||||
applyValidatorSetUpdates(suite.T(), ctx, app.StakingKeeper, -1)
|
||||
|
||||
var req *types.QueryValidatorUnbondingDelegationsRequest
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
func() {
|
||||
req = &types.QueryValidatorUnbondingDelegationsRequest{}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
func() {
|
||||
req = &types.QueryValidatorUnbondingDelegationsRequest{
|
||||
ValidatorAddr: val1.GetOperator().String(),
|
||||
Pagination: &query.PageRequest{Limit: 1, CountTotal: true},
|
||||
}
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
tc.malleate()
|
||||
res, err := queryClient.ValidatorUnbondingDelegations(gocontext.Background(), req)
|
||||
if tc.expPass {
|
||||
suite.NoError(err)
|
||||
suite.Equal(uint64(1), res.Pagination.Total)
|
||||
suite.Equal(1, len(res.UnbondingResponses))
|
||||
suite.Equal(res.UnbondingResponses[0].ValidatorAddress, val1.OperatorAddress)
|
||||
} else {
|
||||
suite.Error(err)
|
||||
suite.Nil(res)
|
||||
require.Error(err)
|
||||
require.Nil(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -1,67 +1,61 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"github.com/stretchr/testify/require"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/teststaking"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
// IsValSetSorted reports whether valset is sorted.
|
||||
func IsValSetSorted(data []types.Validator, powerReduction math.Int) bool {
|
||||
func IsValSetSorted(data []stakingtypes.Validator, powerReduction math.Int) bool {
|
||||
n := len(data)
|
||||
for i := n - 1; i > 0; i-- {
|
||||
if types.ValidatorsByVotingPower(data).Less(i, i-1, powerReduction) {
|
||||
if stakingtypes.ValidatorsByVotingPower(data).Less(i, i-1, powerReduction) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func TestHistoricalInfo(t *testing.T) {
|
||||
_, app, ctx := createTestInput(t)
|
||||
func (s *KeeperTestSuite) TestHistoricalInfo() {
|
||||
ctx, keeper := s.ctx, s.stakingKeeper
|
||||
require := s.Require()
|
||||
|
||||
addrDels := simapp.AddTestAddrsIncremental(app, ctx, 50, sdk.NewInt(0))
|
||||
addrVals := simtestutil.ConvertAddrsToValAddrs(addrDels)
|
||||
_, addrVals := createValAddrs(50)
|
||||
|
||||
validators := make([]types.Validator, len(addrVals))
|
||||
validators := make([]stakingtypes.Validator, len(addrVals))
|
||||
|
||||
for i, valAddr := range addrVals {
|
||||
validators[i] = teststaking.NewValidator(t, valAddr, PKs[i])
|
||||
validators[i] = teststaking.NewValidator(s.T(), valAddr, PKs[i])
|
||||
}
|
||||
|
||||
hi := types.NewHistoricalInfo(ctx.BlockHeader(), validators, app.StakingKeeper.PowerReduction(ctx))
|
||||
app.StakingKeeper.SetHistoricalInfo(ctx, 2, &hi)
|
||||
hi := stakingtypes.NewHistoricalInfo(ctx.BlockHeader(), validators, keeper.PowerReduction(ctx))
|
||||
keeper.SetHistoricalInfo(ctx, 2, &hi)
|
||||
|
||||
recv, found := app.StakingKeeper.GetHistoricalInfo(ctx, 2)
|
||||
require.True(t, found, "HistoricalInfo not found after set")
|
||||
require.Equal(t, hi, recv, "HistoricalInfo not equal")
|
||||
require.True(t, IsValSetSorted(recv.Valset, app.StakingKeeper.PowerReduction(ctx)), "HistoricalInfo validators is not sorted")
|
||||
recv, found := keeper.GetHistoricalInfo(ctx, 2)
|
||||
require.True(found, "HistoricalInfo not found after set")
|
||||
require.Equal(hi, recv, "HistoricalInfo not equal")
|
||||
require.True(IsValSetSorted(recv.Valset, keeper.PowerReduction(ctx)), "HistoricalInfo validators is not sorted")
|
||||
|
||||
app.StakingKeeper.DeleteHistoricalInfo(ctx, 2)
|
||||
keeper.DeleteHistoricalInfo(ctx, 2)
|
||||
|
||||
recv, found = app.StakingKeeper.GetHistoricalInfo(ctx, 2)
|
||||
require.False(t, found, "HistoricalInfo found after delete")
|
||||
require.Equal(t, types.HistoricalInfo{}, recv, "HistoricalInfo is not empty")
|
||||
recv, found = keeper.GetHistoricalInfo(ctx, 2)
|
||||
require.False(found, "HistoricalInfo found after delete")
|
||||
require.Equal(stakingtypes.HistoricalInfo{}, recv, "HistoricalInfo is not empty")
|
||||
}
|
||||
|
||||
func TestTrackHistoricalInfo(t *testing.T) {
|
||||
_, app, ctx := createTestInput(t)
|
||||
func (s *KeeperTestSuite) TestTrackHistoricalInfo() {
|
||||
ctx, keeper := s.ctx, s.stakingKeeper
|
||||
require := s.Require()
|
||||
|
||||
addrDels := simapp.AddTestAddrsIncremental(app, ctx, 50, sdk.NewInt(0))
|
||||
addrVals := simtestutil.ConvertAddrsToValAddrs(addrDels)
|
||||
_, addrVals := createValAddrs(50)
|
||||
|
||||
// set historical entries in params to 5
|
||||
params := types.DefaultParams()
|
||||
params := stakingtypes.DefaultParams()
|
||||
params.HistoricalEntries = 5
|
||||
app.StakingKeeper.SetParams(ctx, params)
|
||||
keeper.SetParams(ctx, params)
|
||||
|
||||
// set historical info at 5, 4 which should be pruned
|
||||
// and check that it has been stored
|
||||
@ -73,39 +67,35 @@ func TestTrackHistoricalInfo(t *testing.T) {
|
||||
ChainID: "HelloChain",
|
||||
Height: 5,
|
||||
}
|
||||
valSet := []types.Validator{
|
||||
teststaking.NewValidator(t, addrVals[0], PKs[0]),
|
||||
teststaking.NewValidator(t, addrVals[1], PKs[1]),
|
||||
valSet := []stakingtypes.Validator{
|
||||
teststaking.NewValidator(s.T(), addrVals[0], PKs[0]),
|
||||
teststaking.NewValidator(s.T(), addrVals[1], PKs[1]),
|
||||
}
|
||||
hi4 := types.NewHistoricalInfo(h4, valSet, app.StakingKeeper.PowerReduction(ctx))
|
||||
hi5 := types.NewHistoricalInfo(h5, valSet, app.StakingKeeper.PowerReduction(ctx))
|
||||
app.StakingKeeper.SetHistoricalInfo(ctx, 4, &hi4)
|
||||
app.StakingKeeper.SetHistoricalInfo(ctx, 5, &hi5)
|
||||
recv, found := app.StakingKeeper.GetHistoricalInfo(ctx, 4)
|
||||
require.True(t, found)
|
||||
require.Equal(t, hi4, recv)
|
||||
recv, found = app.StakingKeeper.GetHistoricalInfo(ctx, 5)
|
||||
require.True(t, found)
|
||||
require.Equal(t, hi5, recv)
|
||||
|
||||
// genesis validator
|
||||
genesisVals := app.StakingKeeper.GetAllValidators(ctx)
|
||||
require.Len(t, genesisVals, 1)
|
||||
hi4 := stakingtypes.NewHistoricalInfo(h4, valSet, keeper.PowerReduction(ctx))
|
||||
hi5 := stakingtypes.NewHistoricalInfo(h5, valSet, keeper.PowerReduction(ctx))
|
||||
keeper.SetHistoricalInfo(ctx, 4, &hi4)
|
||||
keeper.SetHistoricalInfo(ctx, 5, &hi5)
|
||||
recv, found := keeper.GetHistoricalInfo(ctx, 4)
|
||||
require.True(found)
|
||||
require.Equal(hi4, recv)
|
||||
recv, found = keeper.GetHistoricalInfo(ctx, 5)
|
||||
require.True(found)
|
||||
require.Equal(hi5, recv)
|
||||
|
||||
// Set bonded validators in keeper
|
||||
val1 := teststaking.NewValidator(t, addrVals[2], PKs[2])
|
||||
val1.Status = types.Bonded // when not bonded, consensus power is Zero
|
||||
val1.Tokens = app.StakingKeeper.TokensFromConsensusPower(ctx, 10)
|
||||
app.StakingKeeper.SetValidator(ctx, val1)
|
||||
app.StakingKeeper.SetLastValidatorPower(ctx, val1.GetOperator(), 10)
|
||||
val2 := teststaking.NewValidator(t, addrVals[3], PKs[3])
|
||||
val1.Status = types.Bonded
|
||||
val2.Tokens = app.StakingKeeper.TokensFromConsensusPower(ctx, 80)
|
||||
app.StakingKeeper.SetValidator(ctx, val2)
|
||||
app.StakingKeeper.SetLastValidatorPower(ctx, val2.GetOperator(), 80)
|
||||
val1 := teststaking.NewValidator(s.T(), addrVals[2], PKs[2])
|
||||
val1.Status = stakingtypes.Bonded // when not bonded, consensus power is Zero
|
||||
val1.Tokens = keeper.TokensFromConsensusPower(ctx, 10)
|
||||
keeper.SetValidator(ctx, val1)
|
||||
keeper.SetLastValidatorPower(ctx, val1.GetOperator(), 10)
|
||||
val2 := teststaking.NewValidator(s.T(), addrVals[3], PKs[3])
|
||||
val1.Status = stakingtypes.Bonded
|
||||
val2.Tokens = keeper.TokensFromConsensusPower(ctx, 80)
|
||||
keeper.SetValidator(ctx, val2)
|
||||
keeper.SetLastValidatorPower(ctx, val2.GetOperator(), 80)
|
||||
|
||||
vals := []types.Validator{val1, genesisVals[0], val2}
|
||||
require.True(t, IsValSetSorted(vals, app.StakingKeeper.PowerReduction(ctx)))
|
||||
vals := []stakingtypes.Validator{val1, val2}
|
||||
require.True(IsValSetSorted(vals, keeper.PowerReduction(ctx)))
|
||||
|
||||
// Set Header for BeginBlock context
|
||||
header := tmproto.Header{
|
||||
@ -114,55 +104,51 @@ func TestTrackHistoricalInfo(t *testing.T) {
|
||||
}
|
||||
ctx = ctx.WithBlockHeader(header)
|
||||
|
||||
app.StakingKeeper.TrackHistoricalInfo(ctx)
|
||||
keeper.TrackHistoricalInfo(ctx)
|
||||
|
||||
// Check HistoricalInfo at height 10 is persisted
|
||||
expected := types.HistoricalInfo{
|
||||
expected := stakingtypes.HistoricalInfo{
|
||||
Header: header,
|
||||
Valset: vals,
|
||||
}
|
||||
recv, found = app.StakingKeeper.GetHistoricalInfo(ctx, 10)
|
||||
require.True(t, found, "GetHistoricalInfo failed after BeginBlock")
|
||||
require.Equal(t, expected, recv, "GetHistoricalInfo returned unexpected result")
|
||||
recv, found = keeper.GetHistoricalInfo(ctx, 10)
|
||||
require.True(found, "GetHistoricalInfo failed after BeginBlock")
|
||||
require.Equal(expected, recv, "GetHistoricalInfo returned unexpected result")
|
||||
|
||||
// Check HistoricalInfo at height 5, 4 is pruned
|
||||
recv, found = app.StakingKeeper.GetHistoricalInfo(ctx, 4)
|
||||
require.False(t, found, "GetHistoricalInfo did not prune earlier height")
|
||||
require.Equal(t, types.HistoricalInfo{}, recv, "GetHistoricalInfo at height 4 is not empty after prune")
|
||||
recv, found = app.StakingKeeper.GetHistoricalInfo(ctx, 5)
|
||||
require.False(t, found, "GetHistoricalInfo did not prune first prune height")
|
||||
require.Equal(t, types.HistoricalInfo{}, recv, "GetHistoricalInfo at height 5 is not empty after prune")
|
||||
recv, found = keeper.GetHistoricalInfo(ctx, 4)
|
||||
require.False(found, "GetHistoricalInfo did not prune earlier height")
|
||||
require.Equal(stakingtypes.HistoricalInfo{}, recv, "GetHistoricalInfo at height 4 is not empty after prune")
|
||||
recv, found = keeper.GetHistoricalInfo(ctx, 5)
|
||||
require.False(found, "GetHistoricalInfo did not prune first prune height")
|
||||
require.Equal(stakingtypes.HistoricalInfo{}, recv, "GetHistoricalInfo at height 5 is not empty after prune")
|
||||
}
|
||||
|
||||
func TestGetAllHistoricalInfo(t *testing.T) {
|
||||
_, app, ctx := createTestInput(t)
|
||||
// clear historical info
|
||||
infos := app.StakingKeeper.GetAllHistoricalInfo(ctx)
|
||||
require.Len(t, infos, 1)
|
||||
app.StakingKeeper.DeleteHistoricalInfo(ctx, infos[0].Header.Height)
|
||||
func (s *KeeperTestSuite) TestGetAllHistoricalInfo() {
|
||||
ctx, keeper := s.ctx, s.stakingKeeper
|
||||
require := s.Require()
|
||||
|
||||
addrDels := simapp.AddTestAddrsIncremental(app, ctx, 50, sdk.NewInt(0))
|
||||
addrVals := simtestutil.ConvertAddrsToValAddrs(addrDels)
|
||||
_, addrVals := createValAddrs(50)
|
||||
|
||||
valSet := []types.Validator{
|
||||
teststaking.NewValidator(t, addrVals[0], PKs[0]),
|
||||
teststaking.NewValidator(t, addrVals[1], PKs[1]),
|
||||
valSet := []stakingtypes.Validator{
|
||||
teststaking.NewValidator(s.T(), addrVals[0], PKs[0]),
|
||||
teststaking.NewValidator(s.T(), addrVals[1], PKs[1]),
|
||||
}
|
||||
|
||||
header1 := tmproto.Header{ChainID: "HelloChain", Height: 10}
|
||||
header2 := tmproto.Header{ChainID: "HelloChain", Height: 11}
|
||||
header3 := tmproto.Header{ChainID: "HelloChain", Height: 12}
|
||||
|
||||
hist1 := types.HistoricalInfo{Header: header1, Valset: valSet}
|
||||
hist2 := types.HistoricalInfo{Header: header2, Valset: valSet}
|
||||
hist3 := types.HistoricalInfo{Header: header3, Valset: valSet}
|
||||
hist1 := stakingtypes.HistoricalInfo{Header: header1, Valset: valSet}
|
||||
hist2 := stakingtypes.HistoricalInfo{Header: header2, Valset: valSet}
|
||||
hist3 := stakingtypes.HistoricalInfo{Header: header3, Valset: valSet}
|
||||
|
||||
expHistInfos := []types.HistoricalInfo{hist1, hist2, hist3}
|
||||
expHistInfos := []stakingtypes.HistoricalInfo{hist1, hist2, hist3}
|
||||
|
||||
for i, hi := range expHistInfos {
|
||||
app.StakingKeeper.SetHistoricalInfo(ctx, int64(10+i), &hi)
|
||||
keeper.SetHistoricalInfo(ctx, int64(10+i), &hi)
|
||||
}
|
||||
|
||||
infos = app.StakingKeeper.GetAllHistoricalInfo(ctx)
|
||||
require.Equal(t, expHistInfos, infos)
|
||||
infos := keeper.GetAllHistoricalInfo(ctx)
|
||||
require.Equal(expHistInfos, infos)
|
||||
}
|
||||
|
||||
@ -3,72 +3,95 @@ package keeper_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/suite"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
stakingtestutil "github.com/cosmos/cosmos-sdk/x/staking/testutil"
|
||||
)
|
||||
|
||||
var (
|
||||
bondedAcc = authtypes.NewEmptyModuleAccount(stakingtypes.BondedPoolName)
|
||||
notBondedAcc = authtypes.NewEmptyModuleAccount(stakingtypes.NotBondedPoolName)
|
||||
PKs = simtestutil.CreateTestPubKeys(500)
|
||||
)
|
||||
|
||||
type KeeperTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
app *simapp.SimApp
|
||||
ctx sdk.Context
|
||||
addrs []sdk.AccAddress
|
||||
vals []types.Validator
|
||||
queryClient types.QueryClient
|
||||
msgServer types.MsgServer
|
||||
ctx sdk.Context
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
bankKeeper *stakingtestutil.MockBankKeeper
|
||||
accountKeeper *stakingtestutil.MockAccountKeeper
|
||||
queryClient stakingtypes.QueryClient
|
||||
msgServer stakingtypes.MsgServer
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) SetupTest() {
|
||||
app := simapp.Setup(suite.T(), false)
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
func (s *KeeperTestSuite) SetupTest() {
|
||||
key := sdk.NewKVStoreKey(stakingtypes.StoreKey)
|
||||
testCtx := testutil.DefaultContextWithDB(s.T(), key, sdk.NewTransientStoreKey("transient_test"))
|
||||
ctx := testCtx.Ctx.WithBlockHeader(tmproto.Header{Time: tmtime.Now()})
|
||||
encCfg := moduletestutil.MakeTestEncodingConfig()
|
||||
|
||||
querier := keeper.Querier{Keeper: app.StakingKeeper}
|
||||
ctrl := gomock.NewController(s.T())
|
||||
accountKeeper := stakingtestutil.NewMockAccountKeeper(ctrl)
|
||||
accountKeeper.EXPECT().GetModuleAddress(stakingtypes.BondedPoolName).Return(bondedAcc.GetAddress())
|
||||
accountKeeper.EXPECT().GetModuleAddress(stakingtypes.NotBondedPoolName).Return(notBondedAcc.GetAddress())
|
||||
bankKeeper := stakingtestutil.NewMockBankKeeper(ctrl)
|
||||
|
||||
queryHelper := baseapp.NewQueryServerTestHelper(ctx, app.InterfaceRegistry())
|
||||
types.RegisterQueryServer(queryHelper, querier)
|
||||
queryClient := types.NewQueryClient(queryHelper)
|
||||
keeper := stakingkeeper.NewKeeper(
|
||||
encCfg.Codec,
|
||||
key,
|
||||
accountKeeper,
|
||||
bankKeeper,
|
||||
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
|
||||
)
|
||||
keeper.SetParams(ctx, stakingtypes.DefaultParams())
|
||||
|
||||
suite.msgServer = keeper.NewMsgServerImpl(app.StakingKeeper)
|
||||
s.ctx = ctx
|
||||
s.stakingKeeper = keeper
|
||||
s.bankKeeper = bankKeeper
|
||||
s.accountKeeper = accountKeeper
|
||||
|
||||
addrs, _, validators := createValidators(suite.T(), ctx, app, []int64{9, 8, 7})
|
||||
header := tmproto.Header{
|
||||
ChainID: "HelloChain",
|
||||
Height: 5,
|
||||
}
|
||||
|
||||
// sort a copy of the validators, so that original validators does not
|
||||
// have its order changed
|
||||
sortedVals := make([]types.Validator, len(validators))
|
||||
copy(sortedVals, validators)
|
||||
hi := types.NewHistoricalInfo(header, sortedVals, app.StakingKeeper.PowerReduction(ctx))
|
||||
app.StakingKeeper.SetHistoricalInfo(ctx, 5, &hi)
|
||||
|
||||
suite.app, suite.ctx, suite.queryClient, suite.addrs, suite.vals = app, ctx, queryClient, addrs, validators
|
||||
stakingtypes.RegisterInterfaces(encCfg.InterfaceRegistry)
|
||||
queryHelper := baseapp.NewQueryServerTestHelper(ctx, encCfg.InterfaceRegistry)
|
||||
stakingtypes.RegisterQueryServer(queryHelper, stakingkeeper.Querier{Keeper: keeper})
|
||||
s.queryClient = stakingtypes.NewQueryClient(queryHelper)
|
||||
s.msgServer = stakingkeeper.NewMsgServerImpl(keeper)
|
||||
}
|
||||
|
||||
func TestParams(t *testing.T) {
|
||||
app := simapp.Setup(t, false)
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
func (s *KeeperTestSuite) TestParams() {
|
||||
ctx, keeper := s.ctx, s.stakingKeeper
|
||||
require := s.Require()
|
||||
|
||||
expParams := types.DefaultParams()
|
||||
expParams := stakingtypes.DefaultParams()
|
||||
expParams.MaxValidators = 555
|
||||
expParams.MaxEntries = 111
|
||||
keeper.SetParams(ctx, expParams)
|
||||
resParams := keeper.GetParams(ctx)
|
||||
require.True(expParams.Equal(resParams))
|
||||
}
|
||||
|
||||
// check that the empty keeper loads the default
|
||||
resParams := app.StakingKeeper.GetParams(ctx)
|
||||
require.True(t, expParams.Equal(resParams))
|
||||
func (s *KeeperTestSuite) TestLastTotalPower() {
|
||||
ctx, keeper := s.ctx, s.stakingKeeper
|
||||
require := s.Require()
|
||||
|
||||
// modify a params, save, and retrieve
|
||||
expParams.MaxValidators = 777
|
||||
app.StakingKeeper.SetParams(ctx, expParams)
|
||||
resParams = app.StakingKeeper.GetParams(ctx)
|
||||
require.True(t, expParams.Equal(resParams))
|
||||
expTotalPower := math.NewInt(10 ^ 9)
|
||||
keeper.SetLastTotalPower(ctx, expTotalPower)
|
||||
resTotalPower := keeper.GetLastTotalPower(ctx)
|
||||
require.True(expTotalPower.Equal(resTotalPower))
|
||||
}
|
||||
|
||||
func TestKeeperTestSuite(t *testing.T) {
|
||||
|
||||
@ -2,189 +2,49 @@ package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
func TestCancelUnbondingDelegation(t *testing.T) {
|
||||
// setup the app
|
||||
app := simapp.Setup(t, false)
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
msgServer := keeper.NewMsgServerImpl(app.StakingKeeper)
|
||||
bondDenom := app.StakingKeeper.BondDenom(ctx)
|
||||
|
||||
// set the not bonded pool module account
|
||||
notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
startTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 5)
|
||||
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), startTokens))))
|
||||
app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
|
||||
|
||||
moduleBalance := app.BankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), app.StakingKeeper.BondDenom(ctx))
|
||||
require.Equal(t, sdk.NewInt64Coin(bondDenom, startTokens.Int64()), moduleBalance)
|
||||
|
||||
// accounts
|
||||
delAddrs := simapp.AddTestAddrsIncremental(app, ctx, 2, sdk.NewInt(10000))
|
||||
validators := app.StakingKeeper.GetValidators(ctx, 10)
|
||||
require.Equal(t, len(validators), 1)
|
||||
|
||||
validatorAddr, err := sdk.ValAddressFromBech32(validators[0].OperatorAddress)
|
||||
require.NoError(t, err)
|
||||
delegatorAddr := delAddrs[0]
|
||||
|
||||
// setting the ubd entry
|
||||
unbondingAmount := sdk.NewInt64Coin(app.StakingKeeper.BondDenom(ctx), 5)
|
||||
ubd := types.NewUnbondingDelegation(
|
||||
delegatorAddr, validatorAddr, 10,
|
||||
ctx.BlockTime().Add(time.Minute*10),
|
||||
unbondingAmount.Amount,
|
||||
)
|
||||
|
||||
// set and retrieve a record
|
||||
app.StakingKeeper.SetUnbondingDelegation(ctx, ubd)
|
||||
resUnbond, found := app.StakingKeeper.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr)
|
||||
require.True(t, found)
|
||||
require.Equal(t, ubd, resUnbond)
|
||||
|
||||
testCases := []struct {
|
||||
Name string
|
||||
ExceptErr bool
|
||||
req types.MsgCancelUnbondingDelegation
|
||||
}{
|
||||
{
|
||||
Name: "invalid height",
|
||||
ExceptErr: true,
|
||||
req: types.MsgCancelUnbondingDelegation{
|
||||
DelegatorAddress: resUnbond.DelegatorAddress,
|
||||
ValidatorAddress: resUnbond.ValidatorAddress,
|
||||
Amount: sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(4)),
|
||||
CreationHeight: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "invalid coin",
|
||||
ExceptErr: true,
|
||||
req: types.MsgCancelUnbondingDelegation{
|
||||
DelegatorAddress: resUnbond.DelegatorAddress,
|
||||
ValidatorAddress: resUnbond.ValidatorAddress,
|
||||
Amount: sdk.NewCoin("dump_coin", sdk.NewInt(4)),
|
||||
CreationHeight: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "validator not exists",
|
||||
ExceptErr: true,
|
||||
req: types.MsgCancelUnbondingDelegation{
|
||||
DelegatorAddress: resUnbond.DelegatorAddress,
|
||||
ValidatorAddress: sdk.ValAddress(sdk.AccAddress("asdsad")).String(),
|
||||
Amount: unbondingAmount,
|
||||
CreationHeight: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "invalid delegator address",
|
||||
ExceptErr: true,
|
||||
req: types.MsgCancelUnbondingDelegation{
|
||||
DelegatorAddress: "invalid_delegator_addrtess",
|
||||
ValidatorAddress: resUnbond.ValidatorAddress,
|
||||
Amount: unbondingAmount,
|
||||
CreationHeight: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "invalid amount",
|
||||
ExceptErr: true,
|
||||
req: types.MsgCancelUnbondingDelegation{
|
||||
DelegatorAddress: resUnbond.DelegatorAddress,
|
||||
ValidatorAddress: resUnbond.ValidatorAddress,
|
||||
Amount: unbondingAmount.Add(sdk.NewInt64Coin(bondDenom, 10)),
|
||||
CreationHeight: 10,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "success",
|
||||
ExceptErr: false,
|
||||
req: types.MsgCancelUnbondingDelegation{
|
||||
DelegatorAddress: resUnbond.DelegatorAddress,
|
||||
ValidatorAddress: resUnbond.ValidatorAddress,
|
||||
Amount: unbondingAmount.Sub(sdk.NewInt64Coin(bondDenom, 1)),
|
||||
CreationHeight: 10,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "success",
|
||||
ExceptErr: false,
|
||||
req: types.MsgCancelUnbondingDelegation{
|
||||
DelegatorAddress: resUnbond.DelegatorAddress,
|
||||
ValidatorAddress: resUnbond.ValidatorAddress,
|
||||
Amount: unbondingAmount.Sub(unbondingAmount.Sub(sdk.NewInt64Coin(bondDenom, 1))),
|
||||
CreationHeight: 10,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.Name, func(t *testing.T) {
|
||||
_, err := msgServer.CancelUnbondingDelegation(ctx, &testCase.req)
|
||||
if testCase.ExceptErr {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
balanceForNotBondedPool := app.BankKeeper.GetBalance(ctx, sdk.AccAddress(notBondedPool.GetAddress()), bondDenom)
|
||||
require.Equal(t, balanceForNotBondedPool, moduleBalance.Sub(testCase.req.Amount))
|
||||
moduleBalance = moduleBalance.Sub(testCase.req.Amount)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMsgUpdateParams(t *testing.T) {
|
||||
app := simapp.Setup(t, false)
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
msgServer := keeper.NewMsgServerImpl(app.StakingKeeper)
|
||||
func (s *KeeperTestSuite) TestMsgUpdateParams() {
|
||||
ctx, keeper, msgServer := s.ctx, s.stakingKeeper, s.msgServer
|
||||
require := s.Require()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
input *types.MsgUpdateParams
|
||||
input *stakingtypes.MsgUpdateParams
|
||||
expErr bool
|
||||
expErrMsg string
|
||||
}{
|
||||
{
|
||||
name: "valid params",
|
||||
input: &types.MsgUpdateParams{
|
||||
Authority: app.StakingKeeper.GetAuthority(),
|
||||
Params: types.DefaultParams(),
|
||||
input: &stakingtypes.MsgUpdateParams{
|
||||
Authority: keeper.GetAuthority(),
|
||||
Params: stakingtypes.DefaultParams(),
|
||||
},
|
||||
expErr: false,
|
||||
},
|
||||
{
|
||||
name: "invalid authority",
|
||||
input: &types.MsgUpdateParams{
|
||||
input: &stakingtypes.MsgUpdateParams{
|
||||
Authority: "invalid",
|
||||
Params: types.DefaultParams(),
|
||||
Params: stakingtypes.DefaultParams(),
|
||||
},
|
||||
expErr: true,
|
||||
expErrMsg: "invalid authority",
|
||||
},
|
||||
{
|
||||
name: "negative commission rate",
|
||||
input: &types.MsgUpdateParams{
|
||||
Authority: app.StakingKeeper.GetAuthority(),
|
||||
Params: types.Params{
|
||||
input: &stakingtypes.MsgUpdateParams{
|
||||
Authority: keeper.GetAuthority(),
|
||||
Params: stakingtypes.Params{
|
||||
MinCommissionRate: math.LegacyNewDec(-10),
|
||||
UnbondingTime: types.DefaultUnbondingTime,
|
||||
MaxValidators: types.DefaultMaxValidators,
|
||||
MaxEntries: types.DefaultMaxEntries,
|
||||
HistoricalEntries: types.DefaultHistoricalEntries,
|
||||
BondDenom: types.BondStatusBonded,
|
||||
UnbondingTime: stakingtypes.DefaultUnbondingTime,
|
||||
MaxValidators: stakingtypes.DefaultMaxValidators,
|
||||
MaxEntries: stakingtypes.DefaultMaxEntries,
|
||||
HistoricalEntries: stakingtypes.DefaultHistoricalEntries,
|
||||
BondDenom: stakingtypes.BondStatusBonded,
|
||||
},
|
||||
},
|
||||
expErr: true,
|
||||
@ -192,15 +52,15 @@ func TestMsgUpdateParams(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "commission rate cannot be bigger than 100",
|
||||
input: &types.MsgUpdateParams{
|
||||
Authority: app.StakingKeeper.GetAuthority(),
|
||||
Params: types.Params{
|
||||
input: &stakingtypes.MsgUpdateParams{
|
||||
Authority: keeper.GetAuthority(),
|
||||
Params: stakingtypes.Params{
|
||||
MinCommissionRate: math.LegacyNewDec(2),
|
||||
UnbondingTime: types.DefaultUnbondingTime,
|
||||
MaxValidators: types.DefaultMaxValidators,
|
||||
MaxEntries: types.DefaultMaxEntries,
|
||||
HistoricalEntries: types.DefaultHistoricalEntries,
|
||||
BondDenom: types.BondStatusBonded,
|
||||
UnbondingTime: stakingtypes.DefaultUnbondingTime,
|
||||
MaxValidators: stakingtypes.DefaultMaxValidators,
|
||||
MaxEntries: stakingtypes.DefaultMaxEntries,
|
||||
HistoricalEntries: stakingtypes.DefaultHistoricalEntries,
|
||||
BondDenom: stakingtypes.BondStatusBonded,
|
||||
},
|
||||
},
|
||||
expErr: true,
|
||||
@ -208,14 +68,14 @@ func TestMsgUpdateParams(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "invalid bond denom",
|
||||
input: &types.MsgUpdateParams{
|
||||
Authority: app.StakingKeeper.GetAuthority(),
|
||||
Params: types.Params{
|
||||
MinCommissionRate: types.DefaultMinCommissionRate,
|
||||
UnbondingTime: types.DefaultUnbondingTime,
|
||||
MaxValidators: types.DefaultMaxValidators,
|
||||
MaxEntries: types.DefaultMaxEntries,
|
||||
HistoricalEntries: types.DefaultHistoricalEntries,
|
||||
input: &stakingtypes.MsgUpdateParams{
|
||||
Authority: keeper.GetAuthority(),
|
||||
Params: stakingtypes.Params{
|
||||
MinCommissionRate: stakingtypes.DefaultMinCommissionRate,
|
||||
UnbondingTime: stakingtypes.DefaultUnbondingTime,
|
||||
MaxValidators: stakingtypes.DefaultMaxValidators,
|
||||
MaxEntries: stakingtypes.DefaultMaxEntries,
|
||||
HistoricalEntries: stakingtypes.DefaultHistoricalEntries,
|
||||
BondDenom: "",
|
||||
},
|
||||
},
|
||||
@ -224,15 +84,15 @@ func TestMsgUpdateParams(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "max validators most be positive",
|
||||
input: &types.MsgUpdateParams{
|
||||
Authority: app.StakingKeeper.GetAuthority(),
|
||||
Params: types.Params{
|
||||
MinCommissionRate: types.DefaultMinCommissionRate,
|
||||
UnbondingTime: types.DefaultUnbondingTime,
|
||||
input: &stakingtypes.MsgUpdateParams{
|
||||
Authority: keeper.GetAuthority(),
|
||||
Params: stakingtypes.Params{
|
||||
MinCommissionRate: stakingtypes.DefaultMinCommissionRate,
|
||||
UnbondingTime: stakingtypes.DefaultUnbondingTime,
|
||||
MaxValidators: 0,
|
||||
MaxEntries: types.DefaultMaxEntries,
|
||||
HistoricalEntries: types.DefaultHistoricalEntries,
|
||||
BondDenom: types.BondStatusBonded,
|
||||
MaxEntries: stakingtypes.DefaultMaxEntries,
|
||||
HistoricalEntries: stakingtypes.DefaultHistoricalEntries,
|
||||
BondDenom: stakingtypes.BondStatusBonded,
|
||||
},
|
||||
},
|
||||
expErr: true,
|
||||
@ -240,15 +100,15 @@ func TestMsgUpdateParams(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "max entries most be positive",
|
||||
input: &types.MsgUpdateParams{
|
||||
Authority: app.StakingKeeper.GetAuthority(),
|
||||
Params: types.Params{
|
||||
MinCommissionRate: types.DefaultMinCommissionRate,
|
||||
UnbondingTime: types.DefaultUnbondingTime,
|
||||
MaxValidators: types.DefaultMaxValidators,
|
||||
input: &stakingtypes.MsgUpdateParams{
|
||||
Authority: keeper.GetAuthority(),
|
||||
Params: stakingtypes.Params{
|
||||
MinCommissionRate: stakingtypes.DefaultMinCommissionRate,
|
||||
UnbondingTime: stakingtypes.DefaultUnbondingTime,
|
||||
MaxValidators: stakingtypes.DefaultMaxValidators,
|
||||
MaxEntries: 0,
|
||||
HistoricalEntries: types.DefaultHistoricalEntries,
|
||||
BondDenom: types.BondStatusBonded,
|
||||
HistoricalEntries: stakingtypes.DefaultHistoricalEntries,
|
||||
BondDenom: stakingtypes.BondStatusBonded,
|
||||
},
|
||||
},
|
||||
expErr: true,
|
||||
@ -258,13 +118,13 @@ func TestMsgUpdateParams(t *testing.T) {
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
s.T().Run(tc.name, func(t *testing.T) {
|
||||
_, err := msgServer.UpdateParams(ctx, tc.input)
|
||||
if tc.expErr {
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tc.expErrMsg)
|
||||
require.Error(err)
|
||||
require.Contains(err.Error(), tc.expErrMsg)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.NoError(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -4,12 +4,12 @@ import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
func (suite *KeeperTestSuite) TestTokensToConsensusPower() {
|
||||
suite.Require().Equal(int64(0), suite.app.StakingKeeper.TokensToConsensusPower(suite.ctx, sdk.DefaultPowerReduction.Sub(sdk.NewInt(1))))
|
||||
suite.Require().Equal(int64(1), suite.app.StakingKeeper.TokensToConsensusPower(suite.ctx, sdk.DefaultPowerReduction))
|
||||
func (s *KeeperTestSuite) TestTokensToConsensusPower() {
|
||||
s.Require().Equal(int64(0), s.stakingKeeper.TokensToConsensusPower(s.ctx, sdk.DefaultPowerReduction.Sub(sdk.NewInt(1))))
|
||||
s.Require().Equal(int64(1), s.stakingKeeper.TokensToConsensusPower(s.ctx, sdk.DefaultPowerReduction))
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestTokensFromConsensusPower() {
|
||||
suite.Require().Equal(sdk.NewInt(0), suite.app.StakingKeeper.TokensFromConsensusPower(suite.ctx, 0))
|
||||
suite.Require().Equal(sdk.DefaultPowerReduction, suite.app.StakingKeeper.TokensFromConsensusPower(suite.ctx, 1))
|
||||
func (s *KeeperTestSuite) TestTokensFromConsensusPower() {
|
||||
s.Require().Equal(sdk.NewInt(0), s.stakingKeeper.TokensFromConsensusPower(s.ctx, 0))
|
||||
s.Require().Equal(sdk.DefaultPowerReduction, s.stakingKeeper.TokensFromConsensusPower(s.ctx, 1))
|
||||
}
|
||||
|
||||
@ -1,618 +1,50 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/teststaking"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
// bootstrapSlashTest creates 3 validators and bootstrap the app.
|
||||
func bootstrapSlashTest(t *testing.T, power int64) (*simapp.SimApp, sdk.Context, []sdk.AccAddress, []sdk.ValAddress) {
|
||||
_, app, ctx := createTestInput(t)
|
||||
|
||||
addrDels, addrVals := generateAddresses(app, ctx, 100)
|
||||
|
||||
amt := app.StakingKeeper.TokensFromConsensusPower(ctx, power)
|
||||
totalSupply := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), amt.MulRaw(int64(len(addrDels)))))
|
||||
|
||||
notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), totalSupply))
|
||||
|
||||
app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
|
||||
|
||||
numVals := int64(3)
|
||||
bondedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), amt.MulRaw(numVals)))
|
||||
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
||||
|
||||
// set bonded pool balance
|
||||
app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), bondedCoins))
|
||||
|
||||
for i := int64(0); i < numVals; i++ {
|
||||
validator := teststaking.NewValidator(t, addrVals[i], PKs[i])
|
||||
validator, _ = validator.AddTokensFromDel(amt)
|
||||
validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)
|
||||
app.StakingKeeper.SetValidatorByConsAddr(ctx, validator)
|
||||
}
|
||||
|
||||
return app, ctx, addrDels, addrVals
|
||||
}
|
||||
|
||||
// tests Jail, Unjail
|
||||
func TestRevocation(t *testing.T) {
|
||||
app, ctx, _, addrVals := bootstrapSlashTest(t, 5)
|
||||
func (s *KeeperTestSuite) TestRevocation() {
|
||||
ctx, keeper := s.ctx, s.stakingKeeper
|
||||
require := s.Require()
|
||||
|
||||
valAddr := sdk.ValAddress(PKs[0].Address().Bytes())
|
||||
consAddr := sdk.ConsAddress(PKs[0].Address())
|
||||
validator := teststaking.NewValidator(s.T(), valAddr, PKs[0])
|
||||
|
||||
// initial state
|
||||
val, found := app.StakingKeeper.GetValidator(ctx, addrVals[0])
|
||||
require.True(t, found)
|
||||
require.False(t, val.IsJailed())
|
||||
keeper.SetValidator(ctx, validator)
|
||||
keeper.SetValidatorByConsAddr(ctx, validator)
|
||||
val, found := keeper.GetValidator(ctx, valAddr)
|
||||
require.True(found)
|
||||
require.False(val.IsJailed())
|
||||
|
||||
// test jail
|
||||
app.StakingKeeper.Jail(ctx, consAddr)
|
||||
val, found = app.StakingKeeper.GetValidator(ctx, addrVals[0])
|
||||
require.True(t, found)
|
||||
require.True(t, val.IsJailed())
|
||||
keeper.Jail(ctx, consAddr)
|
||||
val, found = keeper.GetValidator(ctx, valAddr)
|
||||
require.True(found)
|
||||
require.True(val.IsJailed())
|
||||
|
||||
// test unjail
|
||||
app.StakingKeeper.Unjail(ctx, consAddr)
|
||||
val, found = app.StakingKeeper.GetValidator(ctx, addrVals[0])
|
||||
require.True(t, found)
|
||||
require.False(t, val.IsJailed())
|
||||
}
|
||||
|
||||
// tests slashUnbondingDelegation
|
||||
func TestSlashUnbondingDelegation(t *testing.T) {
|
||||
app, ctx, addrDels, addrVals := bootstrapSlashTest(t, 10)
|
||||
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
|
||||
// set an unbonding delegation with expiration timestamp (beyond which the
|
||||
// unbonding delegation shouldn't be slashed)
|
||||
ubd := types.NewUnbondingDelegation(addrDels[0], addrVals[0], 0,
|
||||
time.Unix(5, 0), sdk.NewInt(10))
|
||||
|
||||
app.StakingKeeper.SetUnbondingDelegation(ctx, ubd)
|
||||
|
||||
// unbonding started prior to the infraction height, stakw didn't contribute
|
||||
slashAmount := app.StakingKeeper.SlashUnbondingDelegation(ctx, ubd, 1, fraction)
|
||||
require.True(t, slashAmount.Equal(sdk.NewInt(0)))
|
||||
|
||||
// after the expiration time, no longer eligible for slashing
|
||||
ctx = ctx.WithBlockHeader(tmproto.Header{Time: time.Unix(10, 0)})
|
||||
app.StakingKeeper.SetUnbondingDelegation(ctx, ubd)
|
||||
slashAmount = app.StakingKeeper.SlashUnbondingDelegation(ctx, ubd, 0, fraction)
|
||||
require.True(t, slashAmount.Equal(sdk.NewInt(0)))
|
||||
|
||||
// test valid slash, before expiration timestamp and to which stake contributed
|
||||
notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
oldUnbondedPoolBalances := app.BankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress())
|
||||
ctx = ctx.WithBlockHeader(tmproto.Header{Time: time.Unix(0, 0)})
|
||||
app.StakingKeeper.SetUnbondingDelegation(ctx, ubd)
|
||||
slashAmount = app.StakingKeeper.SlashUnbondingDelegation(ctx, ubd, 0, fraction)
|
||||
require.True(t, slashAmount.Equal(sdk.NewInt(5)))
|
||||
ubd, found := app.StakingKeeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
|
||||
require.True(t, found)
|
||||
require.Len(t, ubd.Entries, 1)
|
||||
|
||||
// initial balance unchanged
|
||||
require.Equal(t, sdk.NewInt(10), ubd.Entries[0].InitialBalance)
|
||||
|
||||
// balance decreased
|
||||
require.Equal(t, sdk.NewInt(5), ubd.Entries[0].Balance)
|
||||
newUnbondedPoolBalances := app.BankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress())
|
||||
diffTokens := oldUnbondedPoolBalances.Sub(newUnbondedPoolBalances...)
|
||||
require.True(t, diffTokens.AmountOf(app.StakingKeeper.BondDenom(ctx)).Equal(sdk.NewInt(5)))
|
||||
}
|
||||
|
||||
// tests slashRedelegation
|
||||
func TestSlashRedelegation(t *testing.T) {
|
||||
app, ctx, addrDels, addrVals := bootstrapSlashTest(t, 10)
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
|
||||
// add bonded tokens to pool for (re)delegations
|
||||
startCoins := sdk.NewCoins(sdk.NewInt64Coin(app.StakingKeeper.BondDenom(ctx), 15))
|
||||
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
||||
balances := app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
|
||||
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), startCoins))
|
||||
app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
|
||||
|
||||
// set a redelegation with an expiration timestamp beyond which the
|
||||
// redelegation shouldn't be slashed
|
||||
rd := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 0,
|
||||
time.Unix(5, 0), sdk.NewInt(10), math.LegacyNewDec(10))
|
||||
|
||||
app.StakingKeeper.SetRedelegation(ctx, rd)
|
||||
|
||||
// set the associated delegation
|
||||
del := types.NewDelegation(addrDels[0], addrVals[1], math.LegacyNewDec(10))
|
||||
app.StakingKeeper.SetDelegation(ctx, del)
|
||||
|
||||
// started redelegating prior to the current height, stake didn't contribute to infraction
|
||||
validator, found := app.StakingKeeper.GetValidator(ctx, addrVals[1])
|
||||
require.True(t, found)
|
||||
slashAmount := app.StakingKeeper.SlashRedelegation(ctx, validator, rd, 1, fraction)
|
||||
require.True(t, slashAmount.Equal(sdk.NewInt(0)))
|
||||
|
||||
// after the expiration time, no longer eligible for slashing
|
||||
ctx = ctx.WithBlockHeader(tmproto.Header{Time: time.Unix(10, 0)})
|
||||
app.StakingKeeper.SetRedelegation(ctx, rd)
|
||||
validator, found = app.StakingKeeper.GetValidator(ctx, addrVals[1])
|
||||
require.True(t, found)
|
||||
slashAmount = app.StakingKeeper.SlashRedelegation(ctx, validator, rd, 0, fraction)
|
||||
require.True(t, slashAmount.Equal(sdk.NewInt(0)))
|
||||
|
||||
balances = app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
|
||||
|
||||
// test valid slash, before expiration timestamp and to which stake contributed
|
||||
ctx = ctx.WithBlockHeader(tmproto.Header{Time: time.Unix(0, 0)})
|
||||
app.StakingKeeper.SetRedelegation(ctx, rd)
|
||||
validator, found = app.StakingKeeper.GetValidator(ctx, addrVals[1])
|
||||
require.True(t, found)
|
||||
slashAmount = app.StakingKeeper.SlashRedelegation(ctx, validator, rd, 0, fraction)
|
||||
require.True(t, slashAmount.Equal(sdk.NewInt(5)))
|
||||
rd, found = app.StakingKeeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||
require.True(t, found)
|
||||
require.Len(t, rd.Entries, 1)
|
||||
|
||||
// end block
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1)
|
||||
|
||||
// initialbalance unchanged
|
||||
require.Equal(t, sdk.NewInt(10), rd.Entries[0].InitialBalance)
|
||||
|
||||
// shares decreased
|
||||
del, found = app.StakingKeeper.GetDelegation(ctx, addrDels[0], addrVals[1])
|
||||
require.True(t, found)
|
||||
require.Equal(t, int64(5), del.Shares.RoundInt64())
|
||||
|
||||
// pool bonded tokens should decrease
|
||||
burnedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), slashAmount))
|
||||
require.Equal(t, balances.Sub(burnedCoins...), app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress()))
|
||||
keeper.Unjail(ctx, consAddr)
|
||||
val, found = keeper.GetValidator(ctx, valAddr)
|
||||
require.True(found)
|
||||
require.False(val.IsJailed())
|
||||
}
|
||||
|
||||
// tests Slash at a future height (must panic)
|
||||
func TestSlashAtFutureHeight(t *testing.T) {
|
||||
app, ctx, _, _ := bootstrapSlashTest(t, 10)
|
||||
func (s *KeeperTestSuite) TestSlashAtFutureHeight() {
|
||||
ctx, keeper := s.ctx, s.stakingKeeper
|
||||
require := s.Require()
|
||||
|
||||
consAddr := sdk.ConsAddress(PKs[0].Address())
|
||||
validator := teststaking.NewValidator(s.T(), sdk.ValAddress(PKs[0].Address().Bytes()), PKs[0])
|
||||
keeper.SetValidator(ctx, validator)
|
||||
err := keeper.SetValidatorByConsAddr(ctx, validator)
|
||||
require.NoError(err)
|
||||
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
require.Panics(t, func() { app.StakingKeeper.Slash(ctx, consAddr, 1, 10, fraction) })
|
||||
}
|
||||
|
||||
// test slash at a negative height
|
||||
// this just represents pre-genesis and should have the same effect as slashing at height 0
|
||||
func TestSlashAtNegativeHeight(t *testing.T) {
|
||||
app, ctx, _, _ := bootstrapSlashTest(t, 10)
|
||||
consAddr := sdk.ConsAddress(PKs[0].Address())
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
|
||||
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
||||
oldBondedPoolBalances := app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
|
||||
|
||||
validator, found := app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
app.StakingKeeper.Slash(ctx, consAddr, -2, 10, fraction)
|
||||
|
||||
// read updated state
|
||||
validator, found = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
|
||||
// end block
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1)
|
||||
|
||||
validator, found = app.StakingKeeper.GetValidator(ctx, validator.GetOperator())
|
||||
require.True(t, found)
|
||||
// power decreased
|
||||
require.Equal(t, int64(5), validator.GetConsensusPower(app.StakingKeeper.PowerReduction(ctx)))
|
||||
|
||||
// pool bonded shares decreased
|
||||
newBondedPoolBalances := app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
|
||||
diffTokens := oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(app.StakingKeeper.BondDenom(ctx))
|
||||
require.Equal(t, app.StakingKeeper.TokensFromConsensusPower(ctx, 5).String(), diffTokens.String())
|
||||
}
|
||||
|
||||
// tests Slash at the current height
|
||||
func TestSlashValidatorAtCurrentHeight(t *testing.T) {
|
||||
app, ctx, _, _ := bootstrapSlashTest(t, 10)
|
||||
consAddr := sdk.ConsAddress(PKs[0].Address())
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
|
||||
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
||||
oldBondedPoolBalances := app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
|
||||
|
||||
validator, found := app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
app.StakingKeeper.Slash(ctx, consAddr, ctx.BlockHeight(), 10, fraction)
|
||||
|
||||
// read updated state
|
||||
validator, found = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
|
||||
// end block
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1)
|
||||
|
||||
validator, found = app.StakingKeeper.GetValidator(ctx, validator.GetOperator())
|
||||
assert.True(t, found)
|
||||
// power decreased
|
||||
require.Equal(t, int64(5), validator.GetConsensusPower(app.StakingKeeper.PowerReduction(ctx)))
|
||||
|
||||
// pool bonded shares decreased
|
||||
newBondedPoolBalances := app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
|
||||
diffTokens := oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(app.StakingKeeper.BondDenom(ctx))
|
||||
require.Equal(t, app.StakingKeeper.TokensFromConsensusPower(ctx, 5).String(), diffTokens.String())
|
||||
}
|
||||
|
||||
// tests Slash at a previous height with an unbonding delegation
|
||||
func TestSlashWithUnbondingDelegation(t *testing.T) {
|
||||
app, ctx, addrDels, addrVals := bootstrapSlashTest(t, 10)
|
||||
|
||||
consAddr := sdk.ConsAddress(PKs[0].Address())
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
|
||||
// set an unbonding delegation with expiration timestamp beyond which the
|
||||
// unbonding delegation shouldn't be slashed
|
||||
ubdTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 4)
|
||||
ubd := types.NewUnbondingDelegation(addrDels[0], addrVals[0], 11, time.Unix(0, 0), ubdTokens)
|
||||
app.StakingKeeper.SetUnbondingDelegation(ctx, ubd)
|
||||
|
||||
// slash validator for the first time
|
||||
ctx = ctx.WithBlockHeight(12)
|
||||
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
||||
oldBondedPoolBalances := app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
|
||||
|
||||
validator, found := app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
app.StakingKeeper.Slash(ctx, consAddr, 10, 10, fraction)
|
||||
|
||||
// end block
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1)
|
||||
|
||||
// read updating unbonding delegation
|
||||
ubd, found = app.StakingKeeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
|
||||
require.True(t, found)
|
||||
require.Len(t, ubd.Entries, 1)
|
||||
|
||||
// balance decreased
|
||||
require.Equal(t, app.StakingKeeper.TokensFromConsensusPower(ctx, 2), ubd.Entries[0].Balance)
|
||||
|
||||
// bonded tokens burned
|
||||
newBondedPoolBalances := app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
|
||||
diffTokens := oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(app.StakingKeeper.BondDenom(ctx))
|
||||
require.Equal(t, app.StakingKeeper.TokensFromConsensusPower(ctx, 3), diffTokens)
|
||||
|
||||
// read updated validator
|
||||
validator, found = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
|
||||
// power decreased by 3 - 6 stake originally bonded at the time of infraction
|
||||
// was still bonded at the time of discovery and was slashed by half, 4 stake
|
||||
// bonded at the time of discovery hadn't been bonded at the time of infraction
|
||||
// and wasn't slashed
|
||||
require.Equal(t, int64(7), validator.GetConsensusPower(app.StakingKeeper.PowerReduction(ctx)))
|
||||
|
||||
// slash validator again
|
||||
ctx = ctx.WithBlockHeight(13)
|
||||
app.StakingKeeper.Slash(ctx, consAddr, 9, 10, fraction)
|
||||
|
||||
ubd, found = app.StakingKeeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
|
||||
require.True(t, found)
|
||||
require.Len(t, ubd.Entries, 1)
|
||||
|
||||
// balance decreased again
|
||||
require.Equal(t, sdk.NewInt(0), ubd.Entries[0].Balance)
|
||||
|
||||
// bonded tokens burned again
|
||||
newBondedPoolBalances = app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
|
||||
diffTokens = oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(app.StakingKeeper.BondDenom(ctx))
|
||||
require.Equal(t, app.StakingKeeper.TokensFromConsensusPower(ctx, 6), diffTokens)
|
||||
|
||||
// read updated validator
|
||||
validator, found = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
|
||||
// power decreased by 3 again
|
||||
require.Equal(t, int64(4), validator.GetConsensusPower(app.StakingKeeper.PowerReduction(ctx)))
|
||||
|
||||
// slash validator again
|
||||
// all originally bonded stake has been slashed, so this will have no effect
|
||||
// on the unbonding delegation, but it will slash stake bonded since the infraction
|
||||
// this may not be the desirable behaviour, ref https://github.com/cosmos/cosmos-sdk/issues/1440
|
||||
ctx = ctx.WithBlockHeight(13)
|
||||
app.StakingKeeper.Slash(ctx, consAddr, 9, 10, fraction)
|
||||
|
||||
ubd, found = app.StakingKeeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
|
||||
require.True(t, found)
|
||||
require.Len(t, ubd.Entries, 1)
|
||||
|
||||
// balance unchanged
|
||||
require.Equal(t, sdk.NewInt(0), ubd.Entries[0].Balance)
|
||||
|
||||
// bonded tokens burned again
|
||||
newBondedPoolBalances = app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
|
||||
diffTokens = oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(app.StakingKeeper.BondDenom(ctx))
|
||||
require.Equal(t, app.StakingKeeper.TokensFromConsensusPower(ctx, 9), diffTokens)
|
||||
|
||||
// read updated validator
|
||||
validator, found = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
|
||||
// power decreased by 3 again
|
||||
require.Equal(t, int64(1), validator.GetConsensusPower(app.StakingKeeper.PowerReduction(ctx)))
|
||||
|
||||
// slash validator again
|
||||
// all originally bonded stake has been slashed, so this will have no effect
|
||||
// on the unbonding delegation, but it will slash stake bonded since the infraction
|
||||
// this may not be the desirable behaviour, ref https://github.com/cosmos/cosmos-sdk/issues/1440
|
||||
ctx = ctx.WithBlockHeight(13)
|
||||
app.StakingKeeper.Slash(ctx, consAddr, 9, 10, fraction)
|
||||
|
||||
ubd, found = app.StakingKeeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
|
||||
require.True(t, found)
|
||||
require.Len(t, ubd.Entries, 1)
|
||||
|
||||
// balance unchanged
|
||||
require.Equal(t, sdk.NewInt(0), ubd.Entries[0].Balance)
|
||||
|
||||
// just 1 bonded token burned again since that's all the validator now has
|
||||
newBondedPoolBalances = app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
|
||||
diffTokens = oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(app.StakingKeeper.BondDenom(ctx))
|
||||
require.Equal(t, app.StakingKeeper.TokensFromConsensusPower(ctx, 10), diffTokens)
|
||||
|
||||
// apply TM updates
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, -1)
|
||||
|
||||
// read updated validator
|
||||
// power decreased by 1 again, validator is out of stake
|
||||
// validator should be in unbonding period
|
||||
validator, _ = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.Equal(t, validator.GetStatus(), types.Unbonding)
|
||||
}
|
||||
|
||||
// tests Slash at a previous height with a redelegation
|
||||
func TestSlashWithRedelegation(t *testing.T) {
|
||||
app, ctx, addrDels, addrVals := bootstrapSlashTest(t, 10)
|
||||
consAddr := sdk.ConsAddress(PKs[0].Address())
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
bondDenom := app.StakingKeeper.BondDenom(ctx)
|
||||
|
||||
// set a redelegation
|
||||
rdTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 6)
|
||||
rd := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 11, time.Unix(0, 0), rdTokens, sdk.NewDecFromInt(rdTokens))
|
||||
app.StakingKeeper.SetRedelegation(ctx, rd)
|
||||
|
||||
// set the associated delegation
|
||||
del := types.NewDelegation(addrDels[0], addrVals[1], sdk.NewDecFromInt(rdTokens))
|
||||
app.StakingKeeper.SetDelegation(ctx, del)
|
||||
|
||||
// update bonded tokens
|
||||
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
||||
notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
rdCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, rdTokens.MulRaw(2)))
|
||||
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), rdCoins))
|
||||
|
||||
app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
|
||||
|
||||
oldBonded := app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount
|
||||
oldNotBonded := app.BankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom).Amount
|
||||
|
||||
// slash validator
|
||||
ctx = ctx.WithBlockHeight(12)
|
||||
validator, found := app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
|
||||
require.NotPanics(t, func() { app.StakingKeeper.Slash(ctx, consAddr, 10, 10, fraction) })
|
||||
burnAmount := sdk.NewDecFromInt(app.StakingKeeper.TokensFromConsensusPower(ctx, 10)).Mul(fraction).TruncateInt()
|
||||
|
||||
bondedPool = app.StakingKeeper.GetBondedPool(ctx)
|
||||
notBondedPool = app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
|
||||
// burn bonded tokens from only from delegations
|
||||
bondedPoolBalance := app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, oldBonded.Sub(burnAmount), bondedPoolBalance))
|
||||
|
||||
notBondedPoolBalance := app.BankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, oldNotBonded, notBondedPoolBalance))
|
||||
oldBonded = app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount
|
||||
|
||||
// read updating redelegation
|
||||
rd, found = app.StakingKeeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||
require.True(t, found)
|
||||
require.Len(t, rd.Entries, 1)
|
||||
// read updated validator
|
||||
validator, found = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
// power decreased by 2 - 4 stake originally bonded at the time of infraction
|
||||
// was still bonded at the time of discovery and was slashed by half, 4 stake
|
||||
// bonded at the time of discovery hadn't been bonded at the time of infraction
|
||||
// and wasn't slashed
|
||||
require.Equal(t, int64(8), validator.GetConsensusPower(app.StakingKeeper.PowerReduction(ctx)))
|
||||
|
||||
// slash the validator again
|
||||
validator, found = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
|
||||
require.NotPanics(t, func() { app.StakingKeeper.Slash(ctx, consAddr, 10, 10, math.LegacyOneDec()) })
|
||||
burnAmount = app.StakingKeeper.TokensFromConsensusPower(ctx, 7)
|
||||
|
||||
// read updated pool
|
||||
bondedPool = app.StakingKeeper.GetBondedPool(ctx)
|
||||
notBondedPool = app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
|
||||
// seven bonded tokens burned
|
||||
bondedPoolBalance = app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, oldBonded.Sub(burnAmount), bondedPoolBalance))
|
||||
require.True(math.IntEq(t, oldNotBonded, notBondedPoolBalance))
|
||||
|
||||
bondedPoolBalance = app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, oldBonded.Sub(burnAmount), bondedPoolBalance))
|
||||
|
||||
notBondedPoolBalance = app.BankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, oldNotBonded, notBondedPoolBalance))
|
||||
oldBonded = app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount
|
||||
|
||||
// read updating redelegation
|
||||
rd, found = app.StakingKeeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||
require.True(t, found)
|
||||
require.Len(t, rd.Entries, 1)
|
||||
// read updated validator
|
||||
validator, found = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
// power decreased by 4
|
||||
require.Equal(t, int64(4), validator.GetConsensusPower(app.StakingKeeper.PowerReduction(ctx)))
|
||||
|
||||
// slash the validator again, by 100%
|
||||
ctx = ctx.WithBlockHeight(12)
|
||||
validator, found = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.True(t, found)
|
||||
|
||||
require.NotPanics(t, func() { app.StakingKeeper.Slash(ctx, consAddr, 10, 10, math.LegacyOneDec()) })
|
||||
|
||||
burnAmount = sdk.NewDecFromInt(app.StakingKeeper.TokensFromConsensusPower(ctx, 10)).Mul(math.LegacyOneDec()).TruncateInt()
|
||||
burnAmount = burnAmount.Sub(math.LegacyOneDec().MulInt(rdTokens).TruncateInt())
|
||||
|
||||
// read updated pool
|
||||
bondedPool = app.StakingKeeper.GetBondedPool(ctx)
|
||||
notBondedPool = app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
|
||||
bondedPoolBalance = app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, oldBonded.Sub(burnAmount), bondedPoolBalance))
|
||||
notBondedPoolBalance = app.BankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, oldNotBonded, notBondedPoolBalance))
|
||||
oldBonded = app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount
|
||||
|
||||
// read updating redelegation
|
||||
rd, found = app.StakingKeeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||
require.True(t, found)
|
||||
require.Len(t, rd.Entries, 1)
|
||||
// apply TM updates
|
||||
applyValidatorSetUpdates(t, ctx, app.StakingKeeper, -1)
|
||||
// read updated validator
|
||||
// validator decreased to zero power, should be in unbonding period
|
||||
validator, _ = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.Equal(t, validator.GetStatus(), types.Unbonding)
|
||||
|
||||
// slash the validator again, by 100%
|
||||
// no stake remains to be slashed
|
||||
ctx = ctx.WithBlockHeight(12)
|
||||
// validator still in unbonding period
|
||||
validator, _ = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.Equal(t, validator.GetStatus(), types.Unbonding)
|
||||
|
||||
require.NotPanics(t, func() { app.StakingKeeper.Slash(ctx, consAddr, 10, 10, math.LegacyOneDec()) })
|
||||
|
||||
// read updated pool
|
||||
bondedPool = app.StakingKeeper.GetBondedPool(ctx)
|
||||
notBondedPool = app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
|
||||
bondedPoolBalance = app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, oldBonded, bondedPoolBalance))
|
||||
notBondedPoolBalance = app.BankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, oldNotBonded, notBondedPoolBalance))
|
||||
|
||||
// read updating redelegation
|
||||
rd, found = app.StakingKeeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||
require.True(t, found)
|
||||
require.Len(t, rd.Entries, 1)
|
||||
// read updated validator
|
||||
// power still zero, still in unbonding period
|
||||
validator, _ = app.StakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||
require.Equal(t, validator.GetStatus(), types.Unbonding)
|
||||
}
|
||||
|
||||
// tests Slash at a previous height with both an unbonding delegation and a redelegation
|
||||
func TestSlashBoth(t *testing.T) {
|
||||
app, ctx, addrDels, addrVals := bootstrapSlashTest(t, 10)
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
bondDenom := app.StakingKeeper.BondDenom(ctx)
|
||||
|
||||
// set a redelegation with expiration timestamp beyond which the
|
||||
// redelegation shouldn't be slashed
|
||||
rdATokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 6)
|
||||
rdA := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 11, time.Unix(0, 0), rdATokens, sdk.NewDecFromInt(rdATokens))
|
||||
app.StakingKeeper.SetRedelegation(ctx, rdA)
|
||||
|
||||
// set the associated delegation
|
||||
delA := types.NewDelegation(addrDels[0], addrVals[1], sdk.NewDecFromInt(rdATokens))
|
||||
app.StakingKeeper.SetDelegation(ctx, delA)
|
||||
|
||||
// set an unbonding delegation with expiration timestamp (beyond which the
|
||||
// unbonding delegation shouldn't be slashed)
|
||||
ubdATokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 4)
|
||||
ubdA := types.NewUnbondingDelegation(addrDels[0], addrVals[0], 11,
|
||||
time.Unix(0, 0), ubdATokens)
|
||||
app.StakingKeeper.SetUnbondingDelegation(ctx, ubdA)
|
||||
|
||||
bondedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, rdATokens.MulRaw(2)))
|
||||
notBondedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, ubdATokens))
|
||||
|
||||
// update bonded tokens
|
||||
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
||||
notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), bondedCoins))
|
||||
require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), notBondedCoins))
|
||||
|
||||
app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
|
||||
app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
|
||||
|
||||
oldBonded := app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount
|
||||
oldNotBonded := app.BankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom).Amount
|
||||
// slash validator
|
||||
ctx = ctx.WithBlockHeight(12)
|
||||
validator, found := app.StakingKeeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(PKs[0]))
|
||||
require.True(t, found)
|
||||
consAddr0 := sdk.ConsAddress(PKs[0].Address())
|
||||
app.StakingKeeper.Slash(ctx, consAddr0, 10, 10, fraction)
|
||||
|
||||
burnedNotBondedAmount := fraction.MulInt(ubdATokens).TruncateInt()
|
||||
burnedBondAmount := sdk.NewDecFromInt(app.StakingKeeper.TokensFromConsensusPower(ctx, 10)).Mul(fraction).TruncateInt()
|
||||
burnedBondAmount = burnedBondAmount.Sub(burnedNotBondedAmount)
|
||||
|
||||
// read updated pool
|
||||
bondedPool = app.StakingKeeper.GetBondedPool(ctx)
|
||||
notBondedPool = app.StakingKeeper.GetNotBondedPool(ctx)
|
||||
|
||||
bondedPoolBalance := app.BankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, oldBonded.Sub(burnedBondAmount), bondedPoolBalance))
|
||||
|
||||
notBondedPoolBalance := app.BankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom).Amount
|
||||
require.True(math.IntEq(t, oldNotBonded.Sub(burnedNotBondedAmount), notBondedPoolBalance))
|
||||
|
||||
// read updating redelegation
|
||||
rdA, found = app.StakingKeeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||
require.True(t, found)
|
||||
require.Len(t, rdA.Entries, 1)
|
||||
// read updated validator
|
||||
validator, found = app.StakingKeeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(PKs[0]))
|
||||
require.True(t, found)
|
||||
// power not decreased, all stake was bonded since
|
||||
require.Equal(t, int64(10), validator.GetConsensusPower(app.StakingKeeper.PowerReduction(ctx)))
|
||||
}
|
||||
|
||||
func TestSlashAmount(t *testing.T) {
|
||||
app, ctx, _, _ := bootstrapSlashTest(t, 10)
|
||||
consAddr := sdk.ConsAddress(PKs[0].Address())
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
burnedCoins := app.StakingKeeper.Slash(ctx, consAddr, ctx.BlockHeight(), 10, fraction)
|
||||
require.True(t, burnedCoins.GT(math.ZeroInt()))
|
||||
|
||||
// test the case where the validator was not found, which should return no coins
|
||||
_, addrVals := generateAddresses(app, ctx, 100)
|
||||
noBurned := app.StakingKeeper.Slash(ctx, sdk.ConsAddress(addrVals[0]), ctx.BlockHeight(), 10, fraction)
|
||||
require.True(t, sdk.NewInt(0).Equal(noBurned))
|
||||
require.Panics(func() { keeper.Slash(ctx, consAddr, 1, 10, fraction) })
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
122
x/staking/testutil/app_config.go
Normal file
122
x/staking/testutil/app_config.go
Normal file
@ -0,0 +1,122 @@
|
||||
package testutil
|
||||
|
||||
import (
|
||||
_ "github.com/cosmos/cosmos-sdk/x/auth"
|
||||
_ "github.com/cosmos/cosmos-sdk/x/auth/tx/module"
|
||||
_ "github.com/cosmos/cosmos-sdk/x/bank"
|
||||
_ "github.com/cosmos/cosmos-sdk/x/distribution"
|
||||
_ "github.com/cosmos/cosmos-sdk/x/genutil"
|
||||
_ "github.com/cosmos/cosmos-sdk/x/mint"
|
||||
_ "github.com/cosmos/cosmos-sdk/x/params"
|
||||
_ "github.com/cosmos/cosmos-sdk/x/slashing"
|
||||
_ "github.com/cosmos/cosmos-sdk/x/staking"
|
||||
|
||||
"cosmossdk.io/core/appconfig"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
|
||||
paramstypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
|
||||
runtimev1alpha1 "cosmossdk.io/api/cosmos/app/runtime/v1alpha1"
|
||||
appv1alpha1 "cosmossdk.io/api/cosmos/app/v1alpha1"
|
||||
authmodulev1 "cosmossdk.io/api/cosmos/auth/module/v1"
|
||||
bankmodulev1 "cosmossdk.io/api/cosmos/bank/module/v1"
|
||||
distrmodulev1 "cosmossdk.io/api/cosmos/distribution/module/v1"
|
||||
genutilmodulev1 "cosmossdk.io/api/cosmos/genutil/module/v1"
|
||||
mintmodulev1 "cosmossdk.io/api/cosmos/mint/module/v1"
|
||||
paramsmodulev1 "cosmossdk.io/api/cosmos/params/module/v1"
|
||||
slashingmodulev1 "cosmossdk.io/api/cosmos/slashing/module/v1"
|
||||
stakingmodulev1 "cosmossdk.io/api/cosmos/staking/module/v1"
|
||||
txmodulev1 "cosmossdk.io/api/cosmos/tx/module/v1"
|
||||
)
|
||||
|
||||
var AppConfig = appconfig.Compose(&appv1alpha1.Config{
|
||||
Modules: []*appv1alpha1.ModuleConfig{
|
||||
{
|
||||
Name: "runtime",
|
||||
Config: appconfig.WrapAny(&runtimev1alpha1.Module{
|
||||
AppName: "StakingApp",
|
||||
BeginBlockers: []string{
|
||||
minttypes.ModuleName,
|
||||
distrtypes.ModuleName,
|
||||
stakingtypes.ModuleName,
|
||||
authtypes.ModuleName,
|
||||
banktypes.ModuleName,
|
||||
genutiltypes.ModuleName,
|
||||
slashingtypes.ModuleName,
|
||||
paramstypes.ModuleName,
|
||||
},
|
||||
EndBlockers: []string{
|
||||
stakingtypes.ModuleName,
|
||||
authtypes.ModuleName,
|
||||
banktypes.ModuleName,
|
||||
genutiltypes.ModuleName,
|
||||
distrtypes.ModuleName,
|
||||
minttypes.ModuleName,
|
||||
slashingtypes.ModuleName,
|
||||
paramstypes.ModuleName,
|
||||
},
|
||||
InitGenesis: []string{
|
||||
authtypes.ModuleName,
|
||||
banktypes.ModuleName,
|
||||
distrtypes.ModuleName,
|
||||
stakingtypes.ModuleName,
|
||||
minttypes.ModuleName,
|
||||
slashingtypes.ModuleName,
|
||||
genutiltypes.ModuleName,
|
||||
paramstypes.ModuleName,
|
||||
},
|
||||
}),
|
||||
},
|
||||
{
|
||||
Name: authtypes.ModuleName,
|
||||
Config: appconfig.WrapAny(&authmodulev1.Module{
|
||||
Bech32Prefix: "cosmos",
|
||||
ModuleAccountPermissions: []*authmodulev1.ModuleAccountPermission{
|
||||
{Account: authtypes.FeeCollectorName},
|
||||
{Account: distrtypes.ModuleName},
|
||||
{Account: minttypes.ModuleName, Permissions: []string{authtypes.Minter}},
|
||||
{Account: stakingtypes.BondedPoolName, Permissions: []string{authtypes.Burner, stakingtypes.ModuleName}},
|
||||
{Account: stakingtypes.NotBondedPoolName, Permissions: []string{authtypes.Burner, stakingtypes.ModuleName}},
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
||||
{
|
||||
Name: banktypes.ModuleName,
|
||||
Config: appconfig.WrapAny(&bankmodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: stakingtypes.ModuleName,
|
||||
Config: appconfig.WrapAny(&stakingmodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: slashingtypes.ModuleName,
|
||||
Config: appconfig.WrapAny(&slashingmodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: paramstypes.ModuleName,
|
||||
Config: appconfig.WrapAny(¶msmodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: "tx",
|
||||
Config: appconfig.WrapAny(&txmodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: genutiltypes.ModuleName,
|
||||
Config: appconfig.WrapAny(&genutilmodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: minttypes.ModuleName,
|
||||
Config: appconfig.WrapAny(&mintmodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: distrtypes.ModuleName,
|
||||
Config: appconfig.WrapAny(&distrmodulev1.Module{}),
|
||||
},
|
||||
},
|
||||
})
|
||||
697
x/staking/testutil/expected_keepers_mocks.go
Normal file
697
x/staking/testutil/expected_keepers_mocks.go
Normal file
@ -0,0 +1,697 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: x/staking/types/expected_keepers.go
|
||||
|
||||
// Package testutil is a generated GoMock package.
|
||||
package testutil
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
|
||||
math "cosmossdk.io/math"
|
||||
types "github.com/cosmos/cosmos-sdk/types"
|
||||
types0 "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
types1 "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
// MockDistributionKeeper is a mock of DistributionKeeper interface.
|
||||
type MockDistributionKeeper struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockDistributionKeeperMockRecorder
|
||||
}
|
||||
|
||||
// MockDistributionKeeperMockRecorder is the mock recorder for MockDistributionKeeper.
|
||||
type MockDistributionKeeperMockRecorder struct {
|
||||
mock *MockDistributionKeeper
|
||||
}
|
||||
|
||||
// NewMockDistributionKeeper creates a new mock instance.
|
||||
func NewMockDistributionKeeper(ctrl *gomock.Controller) *MockDistributionKeeper {
|
||||
mock := &MockDistributionKeeper{ctrl: ctrl}
|
||||
mock.recorder = &MockDistributionKeeperMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockDistributionKeeper) EXPECT() *MockDistributionKeeperMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// GetFeePoolCommunityCoins mocks base method.
|
||||
func (m *MockDistributionKeeper) GetFeePoolCommunityCoins(ctx types.Context) types.DecCoins {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetFeePoolCommunityCoins", ctx)
|
||||
ret0, _ := ret[0].(types.DecCoins)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetFeePoolCommunityCoins indicates an expected call of GetFeePoolCommunityCoins.
|
||||
func (mr *MockDistributionKeeperMockRecorder) GetFeePoolCommunityCoins(ctx interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFeePoolCommunityCoins", reflect.TypeOf((*MockDistributionKeeper)(nil).GetFeePoolCommunityCoins), ctx)
|
||||
}
|
||||
|
||||
// GetValidatorOutstandingRewardsCoins mocks base method.
|
||||
func (m *MockDistributionKeeper) GetValidatorOutstandingRewardsCoins(ctx types.Context, val types.ValAddress) types.DecCoins {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetValidatorOutstandingRewardsCoins", ctx, val)
|
||||
ret0, _ := ret[0].(types.DecCoins)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetValidatorOutstandingRewardsCoins indicates an expected call of GetValidatorOutstandingRewardsCoins.
|
||||
func (mr *MockDistributionKeeperMockRecorder) GetValidatorOutstandingRewardsCoins(ctx, val interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetValidatorOutstandingRewardsCoins", reflect.TypeOf((*MockDistributionKeeper)(nil).GetValidatorOutstandingRewardsCoins), ctx, val)
|
||||
}
|
||||
|
||||
// MockAccountKeeper is a mock of AccountKeeper interface.
|
||||
type MockAccountKeeper struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockAccountKeeperMockRecorder
|
||||
}
|
||||
|
||||
// MockAccountKeeperMockRecorder is the mock recorder for MockAccountKeeper.
|
||||
type MockAccountKeeperMockRecorder struct {
|
||||
mock *MockAccountKeeper
|
||||
}
|
||||
|
||||
// NewMockAccountKeeper creates a new mock instance.
|
||||
func NewMockAccountKeeper(ctrl *gomock.Controller) *MockAccountKeeper {
|
||||
mock := &MockAccountKeeper{ctrl: ctrl}
|
||||
mock.recorder = &MockAccountKeeperMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockAccountKeeper) EXPECT() *MockAccountKeeperMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// GetAccount mocks base method.
|
||||
func (m *MockAccountKeeper) GetAccount(ctx types.Context, addr types.AccAddress) types0.AccountI {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetAccount", ctx, addr)
|
||||
ret0, _ := ret[0].(types0.AccountI)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetAccount indicates an expected call of GetAccount.
|
||||
func (mr *MockAccountKeeperMockRecorder) GetAccount(ctx, addr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAccount", reflect.TypeOf((*MockAccountKeeper)(nil).GetAccount), ctx, addr)
|
||||
}
|
||||
|
||||
// GetModuleAccount mocks base method.
|
||||
func (m *MockAccountKeeper) GetModuleAccount(ctx types.Context, moduleName string) types0.ModuleAccountI {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetModuleAccount", ctx, moduleName)
|
||||
ret0, _ := ret[0].(types0.ModuleAccountI)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetModuleAccount indicates an expected call of GetModuleAccount.
|
||||
func (mr *MockAccountKeeperMockRecorder) GetModuleAccount(ctx, moduleName interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetModuleAccount", reflect.TypeOf((*MockAccountKeeper)(nil).GetModuleAccount), ctx, moduleName)
|
||||
}
|
||||
|
||||
// GetModuleAddress mocks base method.
|
||||
func (m *MockAccountKeeper) GetModuleAddress(name string) types.AccAddress {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetModuleAddress", name)
|
||||
ret0, _ := ret[0].(types.AccAddress)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetModuleAddress indicates an expected call of GetModuleAddress.
|
||||
func (mr *MockAccountKeeperMockRecorder) GetModuleAddress(name interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetModuleAddress", reflect.TypeOf((*MockAccountKeeper)(nil).GetModuleAddress), name)
|
||||
}
|
||||
|
||||
// IterateAccounts mocks base method.
|
||||
func (m *MockAccountKeeper) IterateAccounts(ctx types.Context, process func(types0.AccountI) bool) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "IterateAccounts", ctx, process)
|
||||
}
|
||||
|
||||
// IterateAccounts indicates an expected call of IterateAccounts.
|
||||
func (mr *MockAccountKeeperMockRecorder) IterateAccounts(ctx, process interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IterateAccounts", reflect.TypeOf((*MockAccountKeeper)(nil).IterateAccounts), ctx, process)
|
||||
}
|
||||
|
||||
// SetModuleAccount mocks base method.
|
||||
func (m *MockAccountKeeper) SetModuleAccount(arg0 types.Context, arg1 types0.ModuleAccountI) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "SetModuleAccount", arg0, arg1)
|
||||
}
|
||||
|
||||
// SetModuleAccount indicates an expected call of SetModuleAccount.
|
||||
func (mr *MockAccountKeeperMockRecorder) SetModuleAccount(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetModuleAccount", reflect.TypeOf((*MockAccountKeeper)(nil).SetModuleAccount), arg0, arg1)
|
||||
}
|
||||
|
||||
// MockBankKeeper is a mock of BankKeeper interface.
|
||||
type MockBankKeeper struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockBankKeeperMockRecorder
|
||||
}
|
||||
|
||||
// MockBankKeeperMockRecorder is the mock recorder for MockBankKeeper.
|
||||
type MockBankKeeperMockRecorder struct {
|
||||
mock *MockBankKeeper
|
||||
}
|
||||
|
||||
// NewMockBankKeeper creates a new mock instance.
|
||||
func NewMockBankKeeper(ctrl *gomock.Controller) *MockBankKeeper {
|
||||
mock := &MockBankKeeper{ctrl: ctrl}
|
||||
mock.recorder = &MockBankKeeperMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockBankKeeper) EXPECT() *MockBankKeeperMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// BurnCoins mocks base method.
|
||||
func (m *MockBankKeeper) BurnCoins(ctx types.Context, name string, amt types.Coins) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "BurnCoins", ctx, name, amt)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// BurnCoins indicates an expected call of BurnCoins.
|
||||
func (mr *MockBankKeeperMockRecorder) BurnCoins(ctx, name, amt interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BurnCoins", reflect.TypeOf((*MockBankKeeper)(nil).BurnCoins), ctx, name, amt)
|
||||
}
|
||||
|
||||
// DelegateCoinsFromAccountToModule mocks base method.
|
||||
func (m *MockBankKeeper) DelegateCoinsFromAccountToModule(ctx types.Context, senderAddr types.AccAddress, recipientModule string, amt types.Coins) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "DelegateCoinsFromAccountToModule", ctx, senderAddr, recipientModule, amt)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// DelegateCoinsFromAccountToModule indicates an expected call of DelegateCoinsFromAccountToModule.
|
||||
func (mr *MockBankKeeperMockRecorder) DelegateCoinsFromAccountToModule(ctx, senderAddr, recipientModule, amt interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelegateCoinsFromAccountToModule", reflect.TypeOf((*MockBankKeeper)(nil).DelegateCoinsFromAccountToModule), ctx, senderAddr, recipientModule, amt)
|
||||
}
|
||||
|
||||
// GetAllBalances mocks base method.
|
||||
func (m *MockBankKeeper) GetAllBalances(ctx types.Context, addr types.AccAddress) types.Coins {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetAllBalances", ctx, addr)
|
||||
ret0, _ := ret[0].(types.Coins)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetAllBalances indicates an expected call of GetAllBalances.
|
||||
func (mr *MockBankKeeperMockRecorder) GetAllBalances(ctx, addr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllBalances", reflect.TypeOf((*MockBankKeeper)(nil).GetAllBalances), ctx, addr)
|
||||
}
|
||||
|
||||
// GetBalance mocks base method.
|
||||
func (m *MockBankKeeper) GetBalance(ctx types.Context, addr types.AccAddress, denom string) types.Coin {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetBalance", ctx, addr, denom)
|
||||
ret0, _ := ret[0].(types.Coin)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetBalance indicates an expected call of GetBalance.
|
||||
func (mr *MockBankKeeperMockRecorder) GetBalance(ctx, addr, denom interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBalance", reflect.TypeOf((*MockBankKeeper)(nil).GetBalance), ctx, addr, denom)
|
||||
}
|
||||
|
||||
// GetSupply mocks base method.
|
||||
func (m *MockBankKeeper) GetSupply(ctx types.Context, denom string) types.Coin {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetSupply", ctx, denom)
|
||||
ret0, _ := ret[0].(types.Coin)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetSupply indicates an expected call of GetSupply.
|
||||
func (mr *MockBankKeeperMockRecorder) GetSupply(ctx, denom interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSupply", reflect.TypeOf((*MockBankKeeper)(nil).GetSupply), ctx, denom)
|
||||
}
|
||||
|
||||
// LockedCoins mocks base method.
|
||||
func (m *MockBankKeeper) LockedCoins(ctx types.Context, addr types.AccAddress) types.Coins {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "LockedCoins", ctx, addr)
|
||||
ret0, _ := ret[0].(types.Coins)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// LockedCoins indicates an expected call of LockedCoins.
|
||||
func (mr *MockBankKeeperMockRecorder) LockedCoins(ctx, addr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LockedCoins", reflect.TypeOf((*MockBankKeeper)(nil).LockedCoins), ctx, addr)
|
||||
}
|
||||
|
||||
// SendCoinsFromModuleToModule mocks base method.
|
||||
func (m *MockBankKeeper) SendCoinsFromModuleToModule(ctx types.Context, senderPool, recipientPool string, amt types.Coins) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SendCoinsFromModuleToModule", ctx, senderPool, recipientPool, amt)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SendCoinsFromModuleToModule indicates an expected call of SendCoinsFromModuleToModule.
|
||||
func (mr *MockBankKeeperMockRecorder) SendCoinsFromModuleToModule(ctx, senderPool, recipientPool, amt interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromModuleToModule", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromModuleToModule), ctx, senderPool, recipientPool, amt)
|
||||
}
|
||||
|
||||
// SpendableCoins mocks base method.
|
||||
func (m *MockBankKeeper) SpendableCoins(ctx types.Context, addr types.AccAddress) types.Coins {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SpendableCoins", ctx, addr)
|
||||
ret0, _ := ret[0].(types.Coins)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SpendableCoins indicates an expected call of SpendableCoins.
|
||||
func (mr *MockBankKeeperMockRecorder) SpendableCoins(ctx, addr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpendableCoins", reflect.TypeOf((*MockBankKeeper)(nil).SpendableCoins), ctx, addr)
|
||||
}
|
||||
|
||||
// UndelegateCoinsFromModuleToAccount mocks base method.
|
||||
func (m *MockBankKeeper) UndelegateCoinsFromModuleToAccount(ctx types.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UndelegateCoinsFromModuleToAccount", ctx, senderModule, recipientAddr, amt)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UndelegateCoinsFromModuleToAccount indicates an expected call of UndelegateCoinsFromModuleToAccount.
|
||||
func (mr *MockBankKeeperMockRecorder) UndelegateCoinsFromModuleToAccount(ctx, senderModule, recipientAddr, amt interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UndelegateCoinsFromModuleToAccount", reflect.TypeOf((*MockBankKeeper)(nil).UndelegateCoinsFromModuleToAccount), ctx, senderModule, recipientAddr, amt)
|
||||
}
|
||||
|
||||
// MockValidatorSet is a mock of ValidatorSet interface.
|
||||
type MockValidatorSet struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockValidatorSetMockRecorder
|
||||
}
|
||||
|
||||
// MockValidatorSetMockRecorder is the mock recorder for MockValidatorSet.
|
||||
type MockValidatorSetMockRecorder struct {
|
||||
mock *MockValidatorSet
|
||||
}
|
||||
|
||||
// NewMockValidatorSet creates a new mock instance.
|
||||
func NewMockValidatorSet(ctrl *gomock.Controller) *MockValidatorSet {
|
||||
mock := &MockValidatorSet{ctrl: ctrl}
|
||||
mock.recorder = &MockValidatorSetMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockValidatorSet) EXPECT() *MockValidatorSetMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Delegation mocks base method.
|
||||
func (m *MockValidatorSet) Delegation(arg0 types.Context, arg1 types.AccAddress, arg2 types.ValAddress) types1.DelegationI {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Delegation", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(types1.DelegationI)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Delegation indicates an expected call of Delegation.
|
||||
func (mr *MockValidatorSetMockRecorder) Delegation(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delegation", reflect.TypeOf((*MockValidatorSet)(nil).Delegation), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// IterateBondedValidatorsByPower mocks base method.
|
||||
func (m *MockValidatorSet) IterateBondedValidatorsByPower(arg0 types.Context, arg1 func(int64, types1.ValidatorI) bool) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "IterateBondedValidatorsByPower", arg0, arg1)
|
||||
}
|
||||
|
||||
// IterateBondedValidatorsByPower indicates an expected call of IterateBondedValidatorsByPower.
|
||||
func (mr *MockValidatorSetMockRecorder) IterateBondedValidatorsByPower(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IterateBondedValidatorsByPower", reflect.TypeOf((*MockValidatorSet)(nil).IterateBondedValidatorsByPower), arg0, arg1)
|
||||
}
|
||||
|
||||
// IterateLastValidators mocks base method.
|
||||
func (m *MockValidatorSet) IterateLastValidators(arg0 types.Context, arg1 func(int64, types1.ValidatorI) bool) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "IterateLastValidators", arg0, arg1)
|
||||
}
|
||||
|
||||
// IterateLastValidators indicates an expected call of IterateLastValidators.
|
||||
func (mr *MockValidatorSetMockRecorder) IterateLastValidators(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IterateLastValidators", reflect.TypeOf((*MockValidatorSet)(nil).IterateLastValidators), arg0, arg1)
|
||||
}
|
||||
|
||||
// IterateValidators mocks base method.
|
||||
func (m *MockValidatorSet) IterateValidators(arg0 types.Context, arg1 func(int64, types1.ValidatorI) bool) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "IterateValidators", arg0, arg1)
|
||||
}
|
||||
|
||||
// IterateValidators indicates an expected call of IterateValidators.
|
||||
func (mr *MockValidatorSetMockRecorder) IterateValidators(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IterateValidators", reflect.TypeOf((*MockValidatorSet)(nil).IterateValidators), arg0, arg1)
|
||||
}
|
||||
|
||||
// Jail mocks base method.
|
||||
func (m *MockValidatorSet) Jail(arg0 types.Context, arg1 types.ConsAddress) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "Jail", arg0, arg1)
|
||||
}
|
||||
|
||||
// Jail indicates an expected call of Jail.
|
||||
func (mr *MockValidatorSetMockRecorder) Jail(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Jail", reflect.TypeOf((*MockValidatorSet)(nil).Jail), arg0, arg1)
|
||||
}
|
||||
|
||||
// MaxValidators mocks base method.
|
||||
func (m *MockValidatorSet) MaxValidators(arg0 types.Context) uint32 {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "MaxValidators", arg0)
|
||||
ret0, _ := ret[0].(uint32)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// MaxValidators indicates an expected call of MaxValidators.
|
||||
func (mr *MockValidatorSetMockRecorder) MaxValidators(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MaxValidators", reflect.TypeOf((*MockValidatorSet)(nil).MaxValidators), arg0)
|
||||
}
|
||||
|
||||
// Slash mocks base method.
|
||||
func (m *MockValidatorSet) Slash(arg0 types.Context, arg1 types.ConsAddress, arg2, arg3 int64, arg4 types.Dec) math.Int {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Slash", arg0, arg1, arg2, arg3, arg4)
|
||||
ret0, _ := ret[0].(math.Int)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Slash indicates an expected call of Slash.
|
||||
func (mr *MockValidatorSetMockRecorder) Slash(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Slash", reflect.TypeOf((*MockValidatorSet)(nil).Slash), arg0, arg1, arg2, arg3, arg4)
|
||||
}
|
||||
|
||||
// StakingTokenSupply mocks base method.
|
||||
func (m *MockValidatorSet) StakingTokenSupply(arg0 types.Context) math.Int {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "StakingTokenSupply", arg0)
|
||||
ret0, _ := ret[0].(math.Int)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// StakingTokenSupply indicates an expected call of StakingTokenSupply.
|
||||
func (mr *MockValidatorSetMockRecorder) StakingTokenSupply(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StakingTokenSupply", reflect.TypeOf((*MockValidatorSet)(nil).StakingTokenSupply), arg0)
|
||||
}
|
||||
|
||||
// TotalBondedTokens mocks base method.
|
||||
func (m *MockValidatorSet) TotalBondedTokens(arg0 types.Context) math.Int {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "TotalBondedTokens", arg0)
|
||||
ret0, _ := ret[0].(math.Int)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// TotalBondedTokens indicates an expected call of TotalBondedTokens.
|
||||
func (mr *MockValidatorSetMockRecorder) TotalBondedTokens(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TotalBondedTokens", reflect.TypeOf((*MockValidatorSet)(nil).TotalBondedTokens), arg0)
|
||||
}
|
||||
|
||||
// Unjail mocks base method.
|
||||
func (m *MockValidatorSet) Unjail(arg0 types.Context, arg1 types.ConsAddress) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "Unjail", arg0, arg1)
|
||||
}
|
||||
|
||||
// Unjail indicates an expected call of Unjail.
|
||||
func (mr *MockValidatorSetMockRecorder) Unjail(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unjail", reflect.TypeOf((*MockValidatorSet)(nil).Unjail), arg0, arg1)
|
||||
}
|
||||
|
||||
// Validator mocks base method.
|
||||
func (m *MockValidatorSet) Validator(arg0 types.Context, arg1 types.ValAddress) types1.ValidatorI {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Validator", arg0, arg1)
|
||||
ret0, _ := ret[0].(types1.ValidatorI)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Validator indicates an expected call of Validator.
|
||||
func (mr *MockValidatorSetMockRecorder) Validator(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Validator", reflect.TypeOf((*MockValidatorSet)(nil).Validator), arg0, arg1)
|
||||
}
|
||||
|
||||
// ValidatorByConsAddr mocks base method.
|
||||
func (m *MockValidatorSet) ValidatorByConsAddr(arg0 types.Context, arg1 types.ConsAddress) types1.ValidatorI {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ValidatorByConsAddr", arg0, arg1)
|
||||
ret0, _ := ret[0].(types1.ValidatorI)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ValidatorByConsAddr indicates an expected call of ValidatorByConsAddr.
|
||||
func (mr *MockValidatorSetMockRecorder) ValidatorByConsAddr(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidatorByConsAddr", reflect.TypeOf((*MockValidatorSet)(nil).ValidatorByConsAddr), arg0, arg1)
|
||||
}
|
||||
|
||||
// MockDelegationSet is a mock of DelegationSet interface.
|
||||
type MockDelegationSet struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockDelegationSetMockRecorder
|
||||
}
|
||||
|
||||
// MockDelegationSetMockRecorder is the mock recorder for MockDelegationSet.
|
||||
type MockDelegationSetMockRecorder struct {
|
||||
mock *MockDelegationSet
|
||||
}
|
||||
|
||||
// NewMockDelegationSet creates a new mock instance.
|
||||
func NewMockDelegationSet(ctrl *gomock.Controller) *MockDelegationSet {
|
||||
mock := &MockDelegationSet{ctrl: ctrl}
|
||||
mock.recorder = &MockDelegationSetMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockDelegationSet) EXPECT() *MockDelegationSetMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// GetValidatorSet mocks base method.
|
||||
func (m *MockDelegationSet) GetValidatorSet() types1.ValidatorSet {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetValidatorSet")
|
||||
ret0, _ := ret[0].(types1.ValidatorSet)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetValidatorSet indicates an expected call of GetValidatorSet.
|
||||
func (mr *MockDelegationSetMockRecorder) GetValidatorSet() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetValidatorSet", reflect.TypeOf((*MockDelegationSet)(nil).GetValidatorSet))
|
||||
}
|
||||
|
||||
// IterateDelegations mocks base method.
|
||||
func (m *MockDelegationSet) IterateDelegations(ctx types.Context, delegator types.AccAddress, fn func(int64, types1.DelegationI) bool) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "IterateDelegations", ctx, delegator, fn)
|
||||
}
|
||||
|
||||
// IterateDelegations indicates an expected call of IterateDelegations.
|
||||
func (mr *MockDelegationSetMockRecorder) IterateDelegations(ctx, delegator, fn interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IterateDelegations", reflect.TypeOf((*MockDelegationSet)(nil).IterateDelegations), ctx, delegator, fn)
|
||||
}
|
||||
|
||||
// MockStakingHooks is a mock of StakingHooks interface.
|
||||
type MockStakingHooks struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockStakingHooksMockRecorder
|
||||
}
|
||||
|
||||
// MockStakingHooksMockRecorder is the mock recorder for MockStakingHooks.
|
||||
type MockStakingHooksMockRecorder struct {
|
||||
mock *MockStakingHooks
|
||||
}
|
||||
|
||||
// NewMockStakingHooks creates a new mock instance.
|
||||
func NewMockStakingHooks(ctrl *gomock.Controller) *MockStakingHooks {
|
||||
mock := &MockStakingHooks{ctrl: ctrl}
|
||||
mock.recorder = &MockStakingHooksMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockStakingHooks) EXPECT() *MockStakingHooksMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// AfterDelegationModified mocks base method.
|
||||
func (m *MockStakingHooks) AfterDelegationModified(ctx types.Context, delAddr types.AccAddress, valAddr types.ValAddress) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AfterDelegationModified", ctx, delAddr, valAddr)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// AfterDelegationModified indicates an expected call of AfterDelegationModified.
|
||||
func (mr *MockStakingHooksMockRecorder) AfterDelegationModified(ctx, delAddr, valAddr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AfterDelegationModified", reflect.TypeOf((*MockStakingHooks)(nil).AfterDelegationModified), ctx, delAddr, valAddr)
|
||||
}
|
||||
|
||||
// AfterValidatorBeginUnbonding mocks base method.
|
||||
func (m *MockStakingHooks) AfterValidatorBeginUnbonding(ctx types.Context, consAddr types.ConsAddress, valAddr types.ValAddress) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AfterValidatorBeginUnbonding", ctx, consAddr, valAddr)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// AfterValidatorBeginUnbonding indicates an expected call of AfterValidatorBeginUnbonding.
|
||||
func (mr *MockStakingHooksMockRecorder) AfterValidatorBeginUnbonding(ctx, consAddr, valAddr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AfterValidatorBeginUnbonding", reflect.TypeOf((*MockStakingHooks)(nil).AfterValidatorBeginUnbonding), ctx, consAddr, valAddr)
|
||||
}
|
||||
|
||||
// AfterValidatorBonded mocks base method.
|
||||
func (m *MockStakingHooks) AfterValidatorBonded(ctx types.Context, consAddr types.ConsAddress, valAddr types.ValAddress) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AfterValidatorBonded", ctx, consAddr, valAddr)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// AfterValidatorBonded indicates an expected call of AfterValidatorBonded.
|
||||
func (mr *MockStakingHooksMockRecorder) AfterValidatorBonded(ctx, consAddr, valAddr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AfterValidatorBonded", reflect.TypeOf((*MockStakingHooks)(nil).AfterValidatorBonded), ctx, consAddr, valAddr)
|
||||
}
|
||||
|
||||
// AfterValidatorCreated mocks base method.
|
||||
func (m *MockStakingHooks) AfterValidatorCreated(ctx types.Context, valAddr types.ValAddress) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AfterValidatorCreated", ctx, valAddr)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// AfterValidatorCreated indicates an expected call of AfterValidatorCreated.
|
||||
func (mr *MockStakingHooksMockRecorder) AfterValidatorCreated(ctx, valAddr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AfterValidatorCreated", reflect.TypeOf((*MockStakingHooks)(nil).AfterValidatorCreated), ctx, valAddr)
|
||||
}
|
||||
|
||||
// AfterValidatorRemoved mocks base method.
|
||||
func (m *MockStakingHooks) AfterValidatorRemoved(ctx types.Context, consAddr types.ConsAddress, valAddr types.ValAddress) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AfterValidatorRemoved", ctx, consAddr, valAddr)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// AfterValidatorRemoved indicates an expected call of AfterValidatorRemoved.
|
||||
func (mr *MockStakingHooksMockRecorder) AfterValidatorRemoved(ctx, consAddr, valAddr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AfterValidatorRemoved", reflect.TypeOf((*MockStakingHooks)(nil).AfterValidatorRemoved), ctx, consAddr, valAddr)
|
||||
}
|
||||
|
||||
// BeforeDelegationCreated mocks base method.
|
||||
func (m *MockStakingHooks) BeforeDelegationCreated(ctx types.Context, delAddr types.AccAddress, valAddr types.ValAddress) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "BeforeDelegationCreated", ctx, delAddr, valAddr)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// BeforeDelegationCreated indicates an expected call of BeforeDelegationCreated.
|
||||
func (mr *MockStakingHooksMockRecorder) BeforeDelegationCreated(ctx, delAddr, valAddr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BeforeDelegationCreated", reflect.TypeOf((*MockStakingHooks)(nil).BeforeDelegationCreated), ctx, delAddr, valAddr)
|
||||
}
|
||||
|
||||
// BeforeDelegationRemoved mocks base method.
|
||||
func (m *MockStakingHooks) BeforeDelegationRemoved(ctx types.Context, delAddr types.AccAddress, valAddr types.ValAddress) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "BeforeDelegationRemoved", ctx, delAddr, valAddr)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// BeforeDelegationRemoved indicates an expected call of BeforeDelegationRemoved.
|
||||
func (mr *MockStakingHooksMockRecorder) BeforeDelegationRemoved(ctx, delAddr, valAddr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BeforeDelegationRemoved", reflect.TypeOf((*MockStakingHooks)(nil).BeforeDelegationRemoved), ctx, delAddr, valAddr)
|
||||
}
|
||||
|
||||
// BeforeDelegationSharesModified mocks base method.
|
||||
func (m *MockStakingHooks) BeforeDelegationSharesModified(ctx types.Context, delAddr types.AccAddress, valAddr types.ValAddress) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "BeforeDelegationSharesModified", ctx, delAddr, valAddr)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// BeforeDelegationSharesModified indicates an expected call of BeforeDelegationSharesModified.
|
||||
func (mr *MockStakingHooksMockRecorder) BeforeDelegationSharesModified(ctx, delAddr, valAddr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BeforeDelegationSharesModified", reflect.TypeOf((*MockStakingHooks)(nil).BeforeDelegationSharesModified), ctx, delAddr, valAddr)
|
||||
}
|
||||
|
||||
// BeforeValidatorModified mocks base method.
|
||||
func (m *MockStakingHooks) BeforeValidatorModified(ctx types.Context, valAddr types.ValAddress) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "BeforeValidatorModified", ctx, valAddr)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// BeforeValidatorModified indicates an expected call of BeforeValidatorModified.
|
||||
func (mr *MockStakingHooksMockRecorder) BeforeValidatorModified(ctx, valAddr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BeforeValidatorModified", reflect.TypeOf((*MockStakingHooks)(nil).BeforeValidatorModified), ctx, valAddr)
|
||||
}
|
||||
|
||||
// BeforeValidatorSlashed mocks base method.
|
||||
func (m *MockStakingHooks) BeforeValidatorSlashed(ctx types.Context, valAddr types.ValAddress, fraction types.Dec) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "BeforeValidatorSlashed", ctx, valAddr, fraction)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// BeforeValidatorSlashed indicates an expected call of BeforeValidatorSlashed.
|
||||
func (mr *MockStakingHooksMockRecorder) BeforeValidatorSlashed(ctx, valAddr, fraction interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BeforeValidatorSlashed", reflect.TypeOf((*MockStakingHooks)(nil).BeforeValidatorSlashed), ctx, valAddr, fraction)
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user