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:
cool-developer 2022-08-28 07:02:29 -07:00 committed by GitHub
parent d11196aad0
commit bc274d8d95
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 4307 additions and 3300 deletions

View File

@ -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

View File

@ -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))
}

View 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)))
}

View 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)
}
})
}
}

View 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))
}

View 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)
}
})
}
}

View 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))
}

View 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

View File

@ -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)
}
})
}

View File

@ -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)
}

View File

@ -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) {

View File

@ -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)
}
})
}

View File

@ -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))
}

View File

@ -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

View 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(&paramsmodulev1.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{}),
},
},
})

View 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)
}