refactor(x/staking)!: KVStoreService, return errors and use context.Context (#16324)

Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com>
This commit is contained in:
Facundo Medica 2023-06-16 20:40:44 +02:00 committed by GitHub
parent c44957890a
commit 1be7d9805e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
111 changed files with 3580 additions and 2216 deletions

View File

@ -45,6 +45,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
### API Breaking Changes
* (x/staking) [#16324](https://github.com/cosmos/cosmos-sdk/pull/16324) `NewKeeper` now takes a `KVStoreService` instead of a `StoreKey`, and methods in the `Keeper` now take a `context.Context` instead of a `sdk.Context` and return an `error`. Notable changes:
* `Validator` method now returns `types.ErrNoValidatorFound` instead of `nil` when not found.
* (x/distribution) [#16440](https://github.com/cosmos/cosmos-sdk/pull/16440) use collections for `DelegatorWithdrawAddresState`:
* remove `Keeper`: `SetDelegatorWithdrawAddr`, `DeleteDelegatorWithdrawAddr`, `IterateDelegatorWithdrawAddrs`.
* (x/distribution) [#16459](https://github.com/cosmos/cosmos-sdk/pull/16459) use collections for `ValidatorCurrentRewards` state management:

View File

@ -321,7 +321,7 @@ func NewSimApp(
logger,
)
app.StakingKeeper = stakingkeeper.NewKeeper(
appCodec, keys[stakingtypes.StoreKey], app.AccountKeeper, app.BankKeeper, authtypes.NewModuleAddress(govtypes.ModuleName).String(),
appCodec, runtime.NewKVStoreService(keys[stakingtypes.StoreKey]), app.AccountKeeper, app.BankKeeper, authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
app.MintKeeper = mintkeeper.NewKeeper(appCodec, runtime.NewKVStoreService(keys[minttypes.StoreKey]), app.StakingKeeper, app.AccountKeeper, app.BankKeeper, authtypes.FeeCollectorName, authtypes.NewModuleAddress(govtypes.ModuleName).String())

View File

@ -77,13 +77,20 @@ func (app *SimApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []
/* Handle fee distribution state. */
// withdraw all validator commission
app.StakingKeeper.IterateValidators(ctx, func(_ int64, val stakingtypes.ValidatorI) (stop bool) {
err := app.StakingKeeper.IterateValidators(ctx, func(_ int64, val stakingtypes.ValidatorI) (stop bool) {
_, _ = app.DistrKeeper.WithdrawValidatorCommission(ctx, val.GetOperator())
return false
})
if err != nil {
panic(err)
}
// withdraw all delegator rewards
dels := app.StakingKeeper.GetAllDelegations(ctx)
dels, err := app.StakingKeeper.GetAllDelegations(ctx)
if err != nil {
panic(err)
}
for _, delegation := range dels {
valAddr, err := sdk.ValAddressFromBech32(delegation.ValidatorAddress)
if err != nil {
@ -156,7 +163,10 @@ func (app *SimApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []
for i := range red.Entries {
red.Entries[i].CreationHeight = 0
}
app.StakingKeeper.SetRedelegation(ctx, red)
err = app.StakingKeeper.SetRedelegation(ctx, red)
if err != nil {
panic(err)
}
return false
})
@ -165,7 +175,10 @@ func (app *SimApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []
for i := range ubd.Entries {
ubd.Entries[i].CreationHeight = 0
}
app.StakingKeeper.SetUnbondingDelegation(ctx, ubd)
err = app.StakingKeeper.SetUnbondingDelegation(ctx, ubd)
if err != nil {
panic(err)
}
return false
})
@ -177,8 +190,8 @@ func (app *SimApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []
for ; iter.Valid(); iter.Next() {
addr := sdk.ValAddress(stakingtypes.AddressFromValidatorsKey(iter.Key()))
validator, found := app.StakingKeeper.GetValidator(ctx, addr)
if !found {
validator, err := app.StakingKeeper.GetValidator(ctx, addr)
if err != nil {
panic("expected validator, not found")
}
@ -196,7 +209,7 @@ func (app *SimApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []
return
}
_, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
_, err = app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
if err != nil {
log.Fatal(err)
}

View File

@ -190,8 +190,12 @@ func AddTestAddrsIncremental(app *SimApp, ctx sdk.Context, accNum int, accAmt sd
func addTestAddrs(app *SimApp, ctx sdk.Context, accNum int, accAmt sdkmath.Int, strategy simtestutil.GenerateAccountStrategy) []sdk.AccAddress {
testAddrs := strategy(accNum)
bondDenom, err := app.StakingKeeper.BondDenom(ctx)
if err != nil {
panic(err)
}
initCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), accAmt))
initCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, accAmt))
for _, addr := range testAddrs {
initAccountWithCoins(app, ctx, addr, initCoins)

View File

@ -95,12 +95,14 @@ func TestMigrateVestingAccounts(t *testing.T) {
"delayed vesting has vested, multiple delegations less than the total account balance",
func(ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
baseAccount := createBaseAccount(delegatorAddr)
vestedCoins := sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdkmath.NewInt(200)))
bondDenom, err := stakingKeeper.BondDenom(ctx)
require.NoError(t, err)
vestedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, sdkmath.NewInt(200)))
delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().Unix())
ctx = ctx.WithBlockTime(ctx.BlockTime().AddDate(1, 0, 0))
err := accountKeeper.Params.Set(ctx, authtypes.DefaultParams())
err = accountKeeper.Params.Set(ctx, authtypes.DefaultParams())
require.NoError(t, err)
accountKeeper.SetAccount(ctx, delayedAccount)
@ -121,9 +123,10 @@ func TestMigrateVestingAccounts(t *testing.T) {
{
"delayed vesting has vested, single delegations which exceed the vested amount",
func(ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
bondDenom, err := stakingKeeper.BondDenom(ctx)
require.NoError(t, err)
baseAccount := createBaseAccount(delegatorAddr)
vestedCoins := sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdkmath.NewInt(200)))
vestedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, sdkmath.NewInt(200)))
delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().Unix())
ctx = ctx.WithBlockTime(ctx.BlockTime().AddDate(1, 0, 0))
@ -143,7 +146,9 @@ func TestMigrateVestingAccounts(t *testing.T) {
"delayed vesting has vested, multiple delegations which exceed the vested amount",
func(ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
baseAccount := createBaseAccount(delegatorAddr)
vestedCoins := sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdkmath.NewInt(200)))
bondDenom, err := stakingKeeper.BondDenom(ctx)
require.NoError(t, err)
vestedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, sdkmath.NewInt(200)))
delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().Unix())
ctx = ctx.WithBlockTime(ctx.BlockTime().AddDate(1, 0, 0))
@ -167,7 +172,9 @@ func TestMigrateVestingAccounts(t *testing.T) {
"delayed vesting has not vested, single delegations which exceed the vested amount",
func(ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
baseAccount := createBaseAccount(delegatorAddr)
vestedCoins := sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdkmath.NewInt(200)))
bondDenom, err := stakingKeeper.BondDenom(ctx)
require.NoError(t, err)
vestedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, sdkmath.NewInt(200)))
delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().AddDate(1, 0, 0).Unix())
accountKeeper.SetAccount(ctx, delayedAccount)
@ -185,7 +192,9 @@ func TestMigrateVestingAccounts(t *testing.T) {
"delayed vesting has not vested, multiple delegations which exceed the vested amount",
func(ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
baseAccount := createBaseAccount(delegatorAddr)
vestedCoins := sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdkmath.NewInt(200)))
bondDenom, err := stakingKeeper.BondDenom(ctx)
require.NoError(t, err)
vestedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, sdkmath.NewInt(200)))
delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().AddDate(1, 0, 0).Unix())
accountKeeper.SetAccount(ctx, delayedAccount)
@ -207,7 +216,9 @@ func TestMigrateVestingAccounts(t *testing.T) {
"not end time",
func(ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
baseAccount := createBaseAccount(delegatorAddr)
vestedCoins := sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdkmath.NewInt(300)))
bondDenom, err := stakingKeeper.BondDenom(ctx)
require.NoError(t, err)
vestedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, sdkmath.NewInt(300)))
delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().AddDate(1, 0, 0).Unix())
accountKeeper.SetAccount(ctx, delayedAccount)
@ -229,7 +240,9 @@ func TestMigrateVestingAccounts(t *testing.T) {
"delayed vesting has not vested, single delegation greater than the total account balance",
func(ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
baseAccount := createBaseAccount(delegatorAddr)
vestedCoins := sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdkmath.NewInt(300)))
bondDenom, err := stakingKeeper.BondDenom(ctx)
require.NoError(t, err)
vestedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, sdkmath.NewInt(300)))
delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().AddDate(1, 0, 0).Unix())
accountKeeper.SetAccount(ctx, delayedAccount)
@ -247,7 +260,9 @@ func TestMigrateVestingAccounts(t *testing.T) {
"delayed vesting has vested, single delegation greater than the total account balance",
func(ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
baseAccount := createBaseAccount(delegatorAddr)
vestedCoins := sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdkmath.NewInt(300)))
bondDenom, err := stakingKeeper.BondDenom(ctx)
require.NoError(t, err)
vestedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, sdkmath.NewInt(300)))
delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().Unix())
ctx = ctx.WithBlockTime(ctx.BlockTime().AddDate(1, 0, 0))
@ -269,7 +284,9 @@ func TestMigrateVestingAccounts(t *testing.T) {
startTime := ctx.BlockTime().AddDate(1, 0, 0).Unix()
endTime := ctx.BlockTime().AddDate(2, 0, 0).Unix()
baseAccount := createBaseAccount(delegatorAddr)
vestedCoins := sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdkmath.NewInt(300)))
bondDenom, err := stakingKeeper.BondDenom(ctx)
require.NoError(t, err)
vestedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, sdkmath.NewInt(300)))
delayedAccount := types.NewContinuousVestingAccount(baseAccount, vestedCoins, startTime, endTime)
ctx = ctx.WithBlockTime(ctx.BlockTime().AddDate(1, 0, 0))
@ -291,7 +308,9 @@ func TestMigrateVestingAccounts(t *testing.T) {
startTime := ctx.BlockTime().AddDate(-1, 0, 0).Unix()
endTime := ctx.BlockTime().AddDate(2, 0, 0).Unix()
baseAccount := createBaseAccount(delegatorAddr)
vestedCoins := sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdkmath.NewInt(300)))
bondDenom, err := stakingKeeper.BondDenom(ctx)
require.NoError(t, err)
vestedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, sdkmath.NewInt(300)))
delayedAccount := types.NewContinuousVestingAccount(baseAccount, vestedCoins, startTime, endTime)
ctx = ctx.WithBlockTime(ctx.BlockTime().AddDate(1, 0, 0))
@ -313,7 +332,9 @@ func TestMigrateVestingAccounts(t *testing.T) {
startTime := ctx.BlockTime().AddDate(-2, 0, 0).Unix()
endTime := ctx.BlockTime().AddDate(-1, 0, 0).Unix()
baseAccount := createBaseAccount(delegatorAddr)
vestedCoins := sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdkmath.NewInt(300)))
bondDenom, err := stakingKeeper.BondDenom(ctx)
require.NoError(t, err)
vestedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, sdkmath.NewInt(300)))
delayedAccount := types.NewContinuousVestingAccount(baseAccount, vestedCoins, startTime, endTime)
ctx = ctx.WithBlockTime(ctx.BlockTime().AddDate(1, 0, 0))
@ -333,7 +354,9 @@ func TestMigrateVestingAccounts(t *testing.T) {
"periodic vesting account, yet to be vested, some rewards delegated",
func(ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
baseAccount := createBaseAccount(delegatorAddr)
vestedCoins := sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdkmath.NewInt(100)))
bondDenom, err := stakingKeeper.BondDenom(ctx)
require.NoError(t, err)
vestedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, sdkmath.NewInt(100)))
start := ctx.BlockTime().Unix() + int64(time.Hour/time.Second)
@ -371,19 +394,21 @@ func TestMigrateVestingAccounts(t *testing.T) {
*/
startTime := int64(1601042400)
baseAccount := createBaseAccount(delegatorAddr)
vestedCoins := sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdk.NewInt(3666666670000)))
bondDenom, err := stakingKeeper.BondDenom(ctx)
require.NoError(t, err)
vestedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, sdkmath.NewInt(3666666670000)))
periods := []types.Period{
{
Length: 31536000,
Amount: sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdk.NewInt(1833333335000))),
Amount: sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(1833333335000))),
},
{
Length: 15638400,
Amount: sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
Amount: sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(916666667500))),
},
{
Length: 15897600,
Amount: sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
Amount: sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(916666667500))),
},
}
@ -415,19 +440,21 @@ func TestMigrateVestingAccounts(t *testing.T) {
*/
startTime := int64(1601042400)
baseAccount := createBaseAccount(delegatorAddr)
vestedCoins := sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdk.NewInt(3666666670000)))
bondDenom, err := stakingKeeper.BondDenom(ctx)
require.NoError(t, err)
vestedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(3666666670000)))
periods := []types.Period{
{
Length: 31536000,
Amount: sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdk.NewInt(1833333335000))),
Amount: sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(1833333335000))),
},
{
Length: 15638400,
Amount: sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
Amount: sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(916666667500))),
},
{
Length: 15897600,
Amount: sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
Amount: sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(916666667500))),
},
}
@ -461,19 +488,21 @@ func TestMigrateVestingAccounts(t *testing.T) {
*/
startTime := int64(1601042400)
baseAccount := createBaseAccount(delegatorAddr)
vestedCoins := sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdk.NewInt(3666666670000)))
bondDenom, err := stakingKeeper.BondDenom(ctx)
require.NoError(t, err)
vestedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(3666666670000)))
periods := []types.Period{
{
Length: 31536000,
Amount: sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdk.NewInt(1833333335000))),
Amount: sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(1833333335000))),
},
{
Length: 15638400,
Amount: sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
Amount: sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(916666667500))),
},
{
Length: 15897600,
Amount: sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
Amount: sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(916666667500))),
},
}
@ -507,19 +536,21 @@ func TestMigrateVestingAccounts(t *testing.T) {
*/
startTime := int64(1601042400)
baseAccount := createBaseAccount(delegatorAddr)
vestedCoins := sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdk.NewInt(3666666670000)))
bondDenom, err := stakingKeeper.BondDenom(ctx)
require.NoError(t, err)
vestedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(3666666670000)))
periods := []types.Period{
{
Length: 31536000,
Amount: sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdk.NewInt(1833333335000))),
Amount: sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(1833333335000))),
},
{
Length: 15638400,
Amount: sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
Amount: sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(916666667500))),
},
{
Length: 15897600,
Amount: sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
Amount: sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(916666667500))),
},
}
@ -543,7 +574,9 @@ func TestMigrateVestingAccounts(t *testing.T) {
"vesting account has unbonding delegations in place",
func(ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
baseAccount := createBaseAccount(delegatorAddr)
vestedCoins := sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdk.NewInt(300)))
bondDenom, err := stakingKeeper.BondDenom(ctx)
require.NoError(t, err)
vestedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(300)))
delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().AddDate(10, 0, 0).Unix())
@ -572,7 +605,9 @@ func TestMigrateVestingAccounts(t *testing.T) {
"vesting account has never delegated anything",
func(ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
baseAccount := createBaseAccount(delegatorAddr)
vestedCoins := sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdk.NewInt(300)))
bondDenom, err := stakingKeeper.BondDenom(ctx)
require.NoError(t, err)
vestedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(300)))
delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().AddDate(10, 0, 0).Unix())
@ -588,7 +623,9 @@ func TestMigrateVestingAccounts(t *testing.T) {
"vesting account has no delegation but dirty DelegatedFree and DelegatedVesting fields",
func(ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
baseAccount := createBaseAccount(delegatorAddr)
vestedCoins := sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdk.NewInt(300)))
bondDenom, err := stakingKeeper.BondDenom(ctx)
require.NoError(t, err)
vestedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(300)))
delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().AddDate(10, 0, 0).Unix())
@ -612,8 +649,8 @@ func TestMigrateVestingAccounts(t *testing.T) {
delegatorAddr := addrs[0]
_, valAddr := createValidator(t, ctx, bankKeeper, stakingKeeper, tc.tokenAmount*2)
validator, found := stakingKeeper.GetValidator(ctx, valAddr)
require.True(t, found)
validator, err := stakingKeeper.GetValidator(ctx, valAddr)
require.NoError(t, err)
tc.prepareFunc(ctx, validator, delegatorAddr)
@ -633,12 +670,15 @@ func TestMigrateVestingAccounts(t *testing.T) {
var expVested sdk.Coins
var expFree sdk.Coins
bondDenom, err := stakingKeeper.BondDenom(ctx)
require.NoError(t, err)
if tc.expVested != 0 {
expVested = sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdk.NewInt(tc.expVested)))
expVested = sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(tc.expVested)))
}
if tc.expFree != 0 {
expFree = sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdk.NewInt(tc.expFree)))
expFree = sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(tc.expFree)))
}
trackingCorrected(

View File

@ -96,7 +96,7 @@ func initFixture(t testing.TB) *fixture {
log.NewNopLogger(),
)
stakingKeeper := stakingkeeper.NewKeeper(cdc, keys[stakingtypes.StoreKey], accountKeeper, bankKeeper, authority.String())
stakingKeeper := stakingkeeper.NewKeeper(cdc, runtime.NewKVStoreService(keys[stakingtypes.StoreKey]), accountKeeper, bankKeeper, authority.String())
distrKeeper := distrkeeper.NewKeeper(
cdc, runtime.NewKVStoreService(keys[distrtypes.StoreKey]), accountKeeper, bankKeeper, stakingKeeper, distrtypes.ModuleName, authority.String(),
@ -245,7 +245,7 @@ func TestMsgWithdrawDelegatorReward(t *testing.T) {
ValidatorAddress: f.valAddr.String(),
},
expErr: true,
expErrMsg: "no delegation distribution info",
expErrMsg: "no delegation for (address, validator) tuple",
},
{
name: "validator with no delegations",
@ -254,7 +254,7 @@ func TestMsgWithdrawDelegatorReward(t *testing.T) {
ValidatorAddress: sdk.ValAddress(sdk.AccAddress(PKS[2].Address())).String(),
},
expErr: true,
expErrMsg: "no validator distribution info",
expErrMsg: "validator does not exist",
},
{
name: "valid msg",
@ -891,6 +891,9 @@ func TestMsgDepositValidatorRewardsPool(t *testing.T) {
f.bankKeeper.MintCoins(f.sdkCtx, distrtypes.ModuleName, amt)
f.bankKeeper.SendCoinsFromModuleToAccount(f.sdkCtx, distrtypes.ModuleName, addr, amt)
bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx)
require.NoError(t, err)
testCases := []struct {
name string
msg *distrtypes.MsgDepositValidatorRewardsPool
@ -902,7 +905,7 @@ func TestMsgDepositValidatorRewardsPool(t *testing.T) {
msg: &distrtypes.MsgDepositValidatorRewardsPool{
Depositor: addr.String(),
ValidatorAddress: valAddr1.String(),
Amount: sdk.NewCoins(sdk.NewCoin(f.stakingKeeper.BondDenom(f.sdkCtx), sdk.NewInt(100))),
Amount: sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(100))),
},
},
{
@ -918,7 +921,7 @@ func TestMsgDepositValidatorRewardsPool(t *testing.T) {
msg: &distrtypes.MsgDepositValidatorRewardsPool{
Depositor: addr.String(),
ValidatorAddress: sdk.ValAddress([]byte("addr1_______________")).String(),
Amount: sdk.NewCoins(sdk.NewCoin(f.stakingKeeper.BondDenom(f.sdkCtx), sdk.NewInt(100))),
Amount: sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(100))),
},
expErr: true,
expErrMsg: "validator does not exist",

View File

@ -117,7 +117,7 @@ func initFixture(t testing.TB) *fixture {
log.NewNopLogger(),
)
stakingKeeper := stakingkeeper.NewKeeper(cdc, keys[stakingtypes.StoreKey], accountKeeper, bankKeeper, authority.String())
stakingKeeper := stakingkeeper.NewKeeper(cdc, runtime.NewKVStoreService(keys[stakingtypes.StoreKey]), accountKeeper, bankKeeper, authority.String())
slashingKeeper := slashingkeeper.NewKeeper(cdc, codec.NewLegacyAmino(), runtime.NewKVStoreService(keys[slashingtypes.StoreKey]), stakingKeeper, authority.String())
@ -164,35 +164,40 @@ func TestHandleDoubleSign(t *testing.T) {
populateValidators(t, f)
power := int64(100)
stakingParams := f.stakingKeeper.GetParams(ctx)
operatorAddr, val := valAddresses[0], pubkeys[0]
stakingParams, err := f.stakingKeeper.GetParams(ctx)
assert.NilError(t, err)
operatorAddr, valpubkey := valAddresses[0], pubkeys[0]
tstaking := stakingtestutil.NewHelper(t, ctx, f.stakingKeeper)
selfDelegation := tstaking.CreateValidatorWithValPower(operatorAddr, val, power, true)
selfDelegation := tstaking.CreateValidatorWithValPower(operatorAddr, valpubkey, power, true)
// execute end-blocker and verify validator attributes
_, err := f.stakingKeeper.EndBlocker(f.sdkCtx)
_, err = f.stakingKeeper.EndBlocker(f.sdkCtx)
assert.NilError(t, err)
assert.DeepEqual(t,
f.bankKeeper.GetAllBalances(ctx, sdk.AccAddress(operatorAddr)).String(),
sdk.NewCoins(sdk.NewCoin(stakingParams.BondDenom, initAmt.Sub(selfDelegation))).String(),
)
assert.DeepEqual(t, selfDelegation, f.stakingKeeper.Validator(ctx, operatorAddr).GetBondedTokens())
val, err := f.stakingKeeper.Validator(ctx, operatorAddr)
assert.NilError(t, err)
assert.DeepEqual(t, selfDelegation, val.GetBondedTokens())
assert.NilError(t, f.slashingKeeper.AddPubkey(f.sdkCtx, val))
assert.NilError(t, f.slashingKeeper.AddPubkey(f.sdkCtx, valpubkey))
info := slashingtypes.NewValidatorSigningInfo(sdk.ConsAddress(val.Address()), f.sdkCtx.BlockHeight(), int64(0), time.Unix(0, 0), false, int64(0))
f.slashingKeeper.SetValidatorSigningInfo(f.sdkCtx, sdk.ConsAddress(val.Address()), info)
info := slashingtypes.NewValidatorSigningInfo(sdk.ConsAddress(valpubkey.Address()), f.sdkCtx.BlockHeight(), int64(0), time.Unix(0, 0), false, int64(0))
f.slashingKeeper.SetValidatorSigningInfo(f.sdkCtx, sdk.ConsAddress(valpubkey.Address()), info)
// handle a signature to set signing info
f.slashingKeeper.HandleValidatorSignature(ctx, val.Address(), selfDelegation.Int64(), comet.BlockIDFlagCommit)
f.slashingKeeper.HandleValidatorSignature(ctx, valpubkey.Address(), selfDelegation.Int64(), comet.BlockIDFlagCommit)
// double sign less than max age
oldTokens := f.stakingKeeper.Validator(ctx, operatorAddr).GetTokens()
val, err = f.stakingKeeper.Validator(ctx, operatorAddr)
assert.NilError(t, err)
oldTokens := val.GetTokens()
nci := NewCometInfo(abci.RequestFinalizeBlock{
Misbehavior: []abci.Misbehavior{{
Validator: abci.Validator{Address: val.Address(), Power: power},
Validator: abci.Validator{Address: valpubkey.Address(), Power: power},
Type: abci.MisbehaviorType_DUPLICATE_VOTE,
Time: time.Now().UTC(),
Height: 1,
@ -203,18 +208,22 @@ func TestHandleDoubleSign(t *testing.T) {
assert.NilError(t, f.evidenceKeeper.BeginBlocker(ctx.WithCometInfo(nci)))
// should be jailed and tombstoned
assert.Assert(t, f.stakingKeeper.Validator(ctx, operatorAddr).IsJailed())
assert.Assert(t, f.slashingKeeper.IsTombstoned(ctx, sdk.ConsAddress(val.Address())))
val, err = f.stakingKeeper.Validator(ctx, operatorAddr)
assert.NilError(t, err)
assert.Assert(t, val.IsJailed())
assert.Assert(t, f.slashingKeeper.IsTombstoned(ctx, sdk.ConsAddress(valpubkey.Address())))
// tokens should be decreased
newTokens := f.stakingKeeper.Validator(ctx, operatorAddr).GetTokens()
newTokens := val.GetTokens()
assert.Assert(t, newTokens.LT(oldTokens))
// submit duplicate evidence
assert.NilError(t, f.evidenceKeeper.BeginBlocker(ctx))
// tokens should be the same (capped slash)
assert.Assert(t, f.stakingKeeper.Validator(ctx, operatorAddr).GetTokens().Equal(newTokens))
val, err = f.stakingKeeper.Validator(ctx, operatorAddr)
assert.NilError(t, err)
assert.Assert(t, val.GetTokens().Equal(newTokens))
// jump to past the unbonding period
ctx = ctx.WithBlockTime(time.Unix(1, 0).Add(stakingParams.UnbondingTime))
@ -247,25 +256,28 @@ func TestHandleDoubleSign_TooOld(t *testing.T) {
populateValidators(t, f)
power := int64(100)
stakingParams := f.stakingKeeper.GetParams(ctx)
operatorAddr, val := valAddresses[0], pubkeys[0]
stakingParams, err := f.stakingKeeper.GetParams(ctx)
assert.NilError(t, err)
operatorAddr, valpubkey := valAddresses[0], pubkeys[0]
tstaking := stakingtestutil.NewHelper(t, ctx, f.stakingKeeper)
amt := tstaking.CreateValidatorWithValPower(operatorAddr, val, power, true)
amt := tstaking.CreateValidatorWithValPower(operatorAddr, valpubkey, power, true)
// execute end-blocker and verify validator attributes
_, err := f.stakingKeeper.EndBlocker(f.sdkCtx)
_, err = f.stakingKeeper.EndBlocker(f.sdkCtx)
assert.NilError(t, err)
assert.DeepEqual(t,
f.bankKeeper.GetAllBalances(ctx, sdk.AccAddress(operatorAddr)),
sdk.NewCoins(sdk.NewCoin(stakingParams.BondDenom, initAmt.Sub(amt))),
)
assert.DeepEqual(t, amt, f.stakingKeeper.Validator(ctx, operatorAddr).GetBondedTokens())
val, err := f.stakingKeeper.Validator(ctx, operatorAddr)
assert.NilError(t, err)
assert.DeepEqual(t, amt, val.GetBondedTokens())
nci := NewCometInfo(abci.RequestFinalizeBlock{
Misbehavior: []abci.Misbehavior{{
Validator: abci.Validator{Address: val.Address(), Power: power},
Validator: abci.Validator{Address: valpubkey.Address(), Power: power},
Type: abci.MisbehaviorType_DUPLICATE_VOTE,
Time: ctx.BlockTime(),
Height: 0,
@ -282,8 +294,10 @@ func TestHandleDoubleSign_TooOld(t *testing.T) {
assert.NilError(t, f.evidenceKeeper.BeginBlocker(ctx))
assert.Assert(t, f.stakingKeeper.Validator(ctx, operatorAddr).IsJailed() == false)
assert.Assert(t, f.slashingKeeper.IsTombstoned(ctx, sdk.ConsAddress(val.Address())) == false)
val, err = f.stakingKeeper.Validator(ctx, operatorAddr)
assert.NilError(t, err)
assert.Assert(t, val.IsJailed() == false)
assert.Assert(t, f.slashingKeeper.IsTombstoned(ctx, sdk.ConsAddress(valpubkey.Address())) == false)
}
func populateValidators(t assert.TestingT, f *fixture) {

View File

@ -87,7 +87,7 @@ func initFixture(t testing.TB) *fixture {
log.NewNopLogger(),
)
stakingKeeper := stakingkeeper.NewKeeper(cdc, keys[stakingtypes.StoreKey], accountKeeper, bankKeeper, authority.String())
stakingKeeper := stakingkeeper.NewKeeper(cdc, runtime.NewKVStoreService(keys[stakingtypes.StoreKey]), accountKeeper, bankKeeper, authority.String())
// set default staking params
stakingKeeper.SetParams(newCtx, stakingtypes.DefaultParams())

View File

@ -88,7 +88,7 @@ func initFixture(t testing.TB) *fixture {
log.NewNopLogger(),
)
stakingKeeper := stakingkeeper.NewKeeper(cdc, keys[stakingtypes.StoreKey], accountKeeper, bankKeeper, authority.String())
stakingKeeper := stakingkeeper.NewKeeper(cdc, runtime.NewKVStoreService(keys[stakingtypes.StoreKey]), accountKeeper, bankKeeper, authority.String())
slashingKeeper := slashingkeeper.NewKeeper(cdc, &codec.LegacyAmino{}, runtime.NewKVStoreService(keys[slashingtypes.StoreKey]), stakingKeeper, authority.String())
@ -133,7 +133,8 @@ func TestUnJailNotBonded(t *testing.T) {
t.Parallel()
f := initFixture(t)
p := f.stakingKeeper.GetParams(f.ctx)
p, err := f.stakingKeeper.GetParams(f.ctx)
assert.NilError(t, err)
p.MaxValidators = 5
f.stakingKeeper.SetParams(f.ctx, p)
@ -212,7 +213,7 @@ func TestHandleNewValidator(t *testing.T) {
f := initFixture(t)
pks := simtestutil.CreateTestPubKeys(1)
addr, val := f.valAddrs[0], pks[0]
addr, valpubkey := f.valAddrs[0], pks[0]
tstaking := stakingtestutil.NewHelper(t, f.ctx, f.stakingKeeper)
signedBlocksWindow, err := f.slashingKeeper.SignedBlocksWindow(f.ctx)
assert.NilError(t, err)
@ -220,27 +221,33 @@ func TestHandleNewValidator(t *testing.T) {
assert.NilError(t, f.slashingKeeper.AddPubkey(f.ctx, pks[0]))
info := slashingtypes.NewValidatorSigningInfo(sdk.ConsAddress(val.Address()), f.ctx.BlockHeight(), int64(0), time.Unix(0, 0), false, int64(0))
err = f.slashingKeeper.SetValidatorSigningInfo(f.ctx, sdk.ConsAddress(val.Address()), info)
assert.NilError(t, err)
info := slashingtypes.NewValidatorSigningInfo(sdk.ConsAddress(valpubkey.Address()), f.ctx.BlockHeight(), int64(0), time.Unix(0, 0), false, int64(0))
assert.NilError(t, f.slashingKeeper.SetValidatorSigningInfo(f.ctx, sdk.ConsAddress(valpubkey.Address()), info))
// Validator created
amt := tstaking.CreateValidatorWithValPower(addr, val, 100, true)
amt := tstaking.CreateValidatorWithValPower(addr, valpubkey, 100, true)
_, err = f.stakingKeeper.EndBlocker(f.ctx)
assert.NilError(t, err)
require.NoError(t, err)
bondDenom, err := f.stakingKeeper.BondDenom(f.ctx)
require.NoError(t, err)
assert.DeepEqual(
t, f.bankKeeper.GetAllBalances(f.ctx, sdk.AccAddress(addr)),
sdk.NewCoins(sdk.NewCoin(f.stakingKeeper.GetParams(f.ctx).BondDenom, testutil.InitTokens.Sub(amt))),
sdk.NewCoins(sdk.NewCoin(bondDenom, testutil.InitTokens.Sub(amt))),
)
assert.DeepEqual(t, amt, f.stakingKeeper.Validator(f.ctx, addr).GetBondedTokens())
val, err := f.stakingKeeper.Validator(f.ctx, addr)
require.NoError(t, err)
assert.DeepEqual(t, amt, val.GetBondedTokens())
// Now a validator, for two blocks
assert.NilError(t, f.slashingKeeper.HandleValidatorSignature(f.ctx, val.Address(), 100, comet.BlockIDFlagCommit))
assert.NilError(t, f.slashingKeeper.HandleValidatorSignature(f.ctx, valpubkey.Address(), 100, comet.BlockIDFlagCommit))
f.ctx = f.ctx.WithBlockHeight(signedBlocksWindow + 2)
assert.NilError(t, f.slashingKeeper.HandleValidatorSignature(f.ctx, val.Address(), 100, comet.BlockIDFlagAbsent))
assert.NilError(t, f.slashingKeeper.HandleValidatorSignature(f.ctx, valpubkey.Address(), 100, comet.BlockIDFlagAbsent))
info, found := f.slashingKeeper.GetValidatorSigningInfo(f.ctx, sdk.ConsAddress(val.Address()))
info, found := f.slashingKeeper.GetValidatorSigningInfo(f.ctx, sdk.ConsAddress(valpubkey.Address()))
assert.Assert(t, found)
assert.Equal(t, signedBlocksWindow+1, info.StartHeight)
assert.Equal(t, int64(2), info.IndexOffset)
@ -248,11 +255,11 @@ func TestHandleNewValidator(t *testing.T) {
assert.Equal(t, time.Unix(0, 0).UTC(), info.JailedUntil)
// validator should be bonded still, should not have been jailed or slashed
validator, _ := f.stakingKeeper.GetValidatorByConsAddr(f.ctx, sdk.GetConsAddress(val))
validator, _ := f.stakingKeeper.GetValidatorByConsAddr(f.ctx, sdk.GetConsAddress(valpubkey))
assert.Equal(t, stakingtypes.Bonded, validator.GetStatus())
bondPool := f.stakingKeeper.GetBondedPool(f.ctx)
expTokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 100)
assert.Assert(t, expTokens.Equal(f.bankKeeper.GetBalance(f.ctx, bondPool.GetAddress(), f.stakingKeeper.BondDenom(f.ctx)).Amount))
assert.Assert(t, expTokens.Equal(f.bankKeeper.GetBalance(f.ctx, bondPool.GetAddress(), bondDenom).Amount))
}
// Test a jailed validator being "down" twice
@ -326,7 +333,8 @@ func TestValidatorDippingInAndOut(t *testing.T) {
t.Parallel()
f := initFixture(t)
params := f.stakingKeeper.GetParams(f.ctx)
params, err := f.stakingKeeper.GetParams(f.ctx)
require.NoError(t, err)
params.MaxValidators = 1
f.stakingKeeper.SetParams(f.ctx, params)
power := int64(100)

View File

@ -71,12 +71,12 @@ func createValidators(t *testing.T, f *fixture, powers []int64) ([]sdk.AccAddres
val2 := testutil.NewValidator(t, valAddrs[1], pks[1])
vals := []types.Validator{val1, val2}
f.stakingKeeper.SetValidator(f.sdkCtx, val1)
f.stakingKeeper.SetValidator(f.sdkCtx, val2)
f.stakingKeeper.SetValidatorByConsAddr(f.sdkCtx, val1)
f.stakingKeeper.SetValidatorByConsAddr(f.sdkCtx, val2)
f.stakingKeeper.SetNewValidatorByPowerIndex(f.sdkCtx, val1)
f.stakingKeeper.SetNewValidatorByPowerIndex(f.sdkCtx, val2)
assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, val1))
assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, val2))
assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.sdkCtx, val1))
assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.sdkCtx, val2))
assert.NilError(t, f.stakingKeeper.SetNewValidatorByPowerIndex(f.sdkCtx, val1))
assert.NilError(t, f.stakingKeeper.SetNewValidatorByPowerIndex(f.sdkCtx, val2))
_, err := f.stakingKeeper.Delegate(f.sdkCtx, addrs[0], f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, powers[0]), types.Unbonded, val1, true)
assert.NilError(t, err)
@ -130,7 +130,7 @@ func initFixture(t testing.TB) *fixture {
log.NewNopLogger(),
)
stakingKeeper := stakingkeeper.NewKeeper(cdc, keys[types.StoreKey], accountKeeper, bankKeeper, authority.String())
stakingKeeper := stakingkeeper.NewKeeper(cdc, runtime.NewKVStoreService(keys[types.StoreKey]), accountKeeper, bankKeeper, authority.String())
authModule := auth.NewAppModule(cdc, accountKeeper, authsims.RandomGenesisAccounts, nil)
bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper, nil)
@ -145,7 +145,7 @@ func initFixture(t testing.TB) *fixture {
types.RegisterQueryServer(integrationApp.QueryHelper(), stakingkeeper.NewQuerier(stakingKeeper))
// set default staking params
stakingKeeper.SetParams(sdkCtx, types.DefaultParams())
assert.NilError(t, stakingKeeper.SetParams(sdkCtx, types.DefaultParams()))
f := fixture{
app: integrationApp,

View File

@ -21,23 +21,20 @@ func TestUnbondingDelegationsMaxEntries(t *testing.T) {
ctx := f.sdkCtx
initTokens := f.stakingKeeper.TokensFromConsensusPower(ctx, int64(1000))
f.bankKeeper.MintCoins(ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens)))
assert.NilError(t, f.bankKeeper.MintCoins(ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens))))
addrDel := sdk.AccAddress([]byte("addr"))
accAmt := sdk.NewInt(10000)
initCoins := sdk.NewCoins(sdk.NewCoin(f.stakingKeeper.BondDenom(ctx), accAmt))
if err := f.bankKeeper.MintCoins(ctx, types.ModuleName, initCoins); err != nil {
panic(err)
}
bondDenom, err := f.stakingKeeper.BondDenom(ctx)
assert.NilError(t, err)
if err := f.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, addrDel, initCoins); err != nil {
panic(err)
}
initCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, accAmt))
assert.NilError(t, f.bankKeeper.MintCoins(ctx, types.ModuleName, initCoins))
assert.NilError(t, f.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, addrDel, initCoins))
addrVal := sdk.ValAddress(addrDel)
startTokens := f.stakingKeeper.TokensFromConsensusPower(ctx, 10)
bondDenom := f.stakingKeeper.BondDenom(ctx)
notBondedPool := f.stakingKeeper.GetNotBondedPool(ctx)
assert.NilError(t, banktestutil.FundModuleAccount(ctx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens))))
@ -54,9 +51,10 @@ func TestUnbondingDelegationsMaxEntries(t *testing.T) {
assert.Assert(t, validator.IsBonded())
delegation := types.NewDelegation(addrDel, addrVal, issuedShares)
f.stakingKeeper.SetDelegation(ctx, delegation)
assert.NilError(t, f.stakingKeeper.SetDelegation(ctx, delegation))
maxEntries := f.stakingKeeper.MaxEntries(ctx)
maxEntries, err := f.stakingKeeper.MaxEntries(ctx)
assert.NilError(t, err)
oldBonded := f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount
oldNotBonded := f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount
@ -69,8 +67,8 @@ func TestUnbondingDelegationsMaxEntries(t *testing.T) {
ctx = ctx.WithBlockHeight(i)
var amount math.Int
completionTime, amount, err = f.stakingKeeper.Undelegate(ctx, addrDel, addrVal, math.LegacyNewDec(1))
totalUnbonded = totalUnbonded.Add(amount)
assert.NilError(t, err)
totalUnbonded = totalUnbonded.Add(amount)
}
newBonded := f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount
@ -84,7 +82,7 @@ func TestUnbondingDelegationsMaxEntries(t *testing.T) {
oldNotBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount
// an additional unbond should fail due to max entries
_, _, err := f.stakingKeeper.Undelegate(ctx, addrDel, addrVal, math.LegacyNewDec(1))
_, _, err = f.stakingKeeper.Undelegate(ctx, addrDel, addrVal, math.LegacyNewDec(1))
assert.Error(t, err, "too many unbonding delegation entries for (delegator, validator) tuple")
newBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount

View File

@ -102,7 +102,7 @@ func initDeterministicFixture(t *testing.T) *deterministicFixture {
log.NewNopLogger(),
)
stakingKeeper := stakingkeeper.NewKeeper(cdc, keys[stakingtypes.StoreKey], accountKeeper, bankKeeper, authority.String())
stakingKeeper := stakingkeeper.NewKeeper(cdc, runtime.NewKVStoreService(keys[stakingtypes.StoreKey]), accountKeeper, bankKeeper, authority.String())
authModule := auth.NewAppModule(cdc, accountKeeper, authsims.RandomGenesisAccounts, nil)
bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper, nil)
@ -110,34 +110,35 @@ func initDeterministicFixture(t *testing.T) *deterministicFixture {
integrationApp := integration.NewIntegrationApp(newCtx, logger, keys, cdc, authModule, bankModule, stakingModule)
sdkCtx := sdk.UnwrapSDKContext(integrationApp.Context())
ctx := integrationApp.Context()
// Register MsgServer and QueryServer
stakingtypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), stakingkeeper.NewMsgServerImpl(stakingKeeper))
stakingtypes.RegisterQueryServer(integrationApp.QueryHelper(), stakingkeeper.NewQuerier(stakingKeeper))
// set default staking params
stakingKeeper.SetParams(sdkCtx, stakingtypes.DefaultParams())
assert.NilError(t, stakingKeeper.SetParams(ctx, stakingtypes.DefaultParams()))
// set pools
startTokens := stakingKeeper.TokensFromConsensusPower(sdkCtx, 10)
bondDenom := stakingKeeper.BondDenom(sdkCtx)
notBondedPool := stakingKeeper.GetNotBondedPool(sdkCtx)
assert.NilError(t, banktestutil.FundModuleAccount(sdkCtx, bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens))))
accountKeeper.SetModuleAccount(sdkCtx, notBondedPool)
bondedPool := stakingKeeper.GetBondedPool(sdkCtx)
assert.NilError(t, banktestutil.FundModuleAccount(sdkCtx, bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens))))
accountKeeper.SetModuleAccount(sdkCtx, bondedPool)
startTokens := stakingKeeper.TokensFromConsensusPower(ctx, 10)
bondDenom, err := stakingKeeper.BondDenom(ctx)
assert.NilError(t, err)
notBondedPool := stakingKeeper.GetNotBondedPool(ctx)
assert.NilError(t, banktestutil.FundModuleAccount(ctx, bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens))))
accountKeeper.SetModuleAccount(ctx, notBondedPool)
bondedPool := stakingKeeper.GetBondedPool(ctx)
assert.NilError(t, banktestutil.FundModuleAccount(ctx, bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens))))
accountKeeper.SetModuleAccount(ctx, bondedPool)
qr := integrationApp.QueryHelper()
queryClient := stakingtypes.NewQueryClient(qr)
amt1 := stakingKeeper.TokensFromConsensusPower(sdkCtx, 101)
amt2 := stakingKeeper.TokensFromConsensusPower(sdkCtx, 102)
amt1 := stakingKeeper.TokensFromConsensusPower(ctx, 101)
amt2 := stakingKeeper.TokensFromConsensusPower(ctx, 102)
f := deterministicFixture{
app: integrationApp,
ctx: sdkCtx,
ctx: sdk.UnwrapSDKContext(ctx),
cdc: cdc,
keys: keys,
accountKeeper: accountKeeper,
@ -220,14 +221,14 @@ func createAndSetValidator(rt *rapid.T, f *deterministicFixture, t *testing.T) s
}
func setValidator(f *deterministicFixture, t *testing.T, validator stakingtypes.Validator) {
f.stakingKeeper.SetValidator(f.ctx, validator)
f.stakingKeeper.SetValidatorByPowerIndex(f.ctx, validator)
f.stakingKeeper.SetValidatorByConsAddr(f.ctx, validator)
assert.NilError(t, f.stakingKeeper.SetValidator(f.ctx, validator))
assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.ctx, validator))
assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.ctx, validator))
assert.NilError(t, f.stakingKeeper.Hooks().AfterValidatorCreated(f.ctx, validator.GetOperator()))
delegatorAddress := sdk.AccAddress(validator.GetOperator())
coins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, validator.BondedTokens()))
banktestutil.FundAccount(f.ctx, f.bankKeeper, delegatorAddress, coins)
assert.NilError(t, banktestutil.FundAccount(f.ctx, f.bankKeeper, delegatorAddress, coins))
_, err := f.stakingKeeper.Delegate(f.ctx, delegatorAddress, validator.BondedTokens(), stakingtypes.Unbonded, validator, true)
assert.NilError(t, err)
@ -312,7 +313,7 @@ func fundAccountAndDelegate(f *deterministicFixture, t *testing.T, delegator sdk
coins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, amt))
assert.NilError(t, f.bankKeeper.MintCoins(f.ctx, minttypes.ModuleName, coins))
banktestutil.FundAccount(f.ctx, f.bankKeeper, delegator, coins)
assert.NilError(t, banktestutil.FundAccount(f.ctx, f.bankKeeper, delegator, coins))
shares, err := f.stakingKeeper.Delegate(f.ctx, delegator, amt, stakingtypes.Unbonded, validator, true)
return shares, err
@ -651,11 +652,11 @@ func TestGRPCHistoricalInfo(t *testing.T) {
height := rapid.Int64Min(0).Draw(rt, "height")
f.stakingKeeper.SetHistoricalInfo(
assert.NilError(t, f.stakingKeeper.SetHistoricalInfo(
f.ctx,
height,
&historicalInfo,
)
))
req := &stakingtypes.QueryHistoricalInfoRequest{
Height: height,
@ -675,11 +676,11 @@ func TestGRPCHistoricalInfo(t *testing.T) {
height := int64(127)
f.stakingKeeper.SetHistoricalInfo(
assert.NilError(t, f.stakingKeeper.SetHistoricalInfo(
f.ctx,
height,
&historicalInfo,
)
))
req := &stakingtypes.QueryHistoricalInfoRequest{
Height: height,

View File

@ -40,10 +40,14 @@ func TestInitGenesis(t *testing.T) {
DelegatorShares: sdk.NewDecFromInt(valTokens),
Description: types.NewDescription("hoop", "", "", "", ""),
}
f.stakingKeeper.SetValidator(f.sdkCtx, bondedVal)
assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, bondedVal))
params, err := f.stakingKeeper.GetParams(f.sdkCtx)
assert.NilError(t, err)
validators, err := f.stakingKeeper.GetAllValidators(f.sdkCtx)
assert.NilError(t, err)
params := (f.stakingKeeper.GetParams(f.sdkCtx))
validators := (f.stakingKeeper.GetAllValidators(f.sdkCtx))
assert.Assert(t, len(validators) == 1)
var delegations []types.Delegation
@ -87,7 +91,8 @@ func TestInitGenesis(t *testing.T) {
),
)
genesisDelegations := (f.stakingKeeper.GetAllDelegations(f.sdkCtx))
genesisDelegations, err := f.stakingKeeper.GetAllDelegations(f.sdkCtx)
assert.NilError(t, err)
delegations = append(delegations, genesisDelegations...)
genesisState := types.NewGenesisState(params, validators, delegations)
@ -96,7 +101,10 @@ func TestInitGenesis(t *testing.T) {
actualGenesis := (f.stakingKeeper.ExportGenesis(f.sdkCtx))
assert.DeepEqual(t, genesisState.Params, actualGenesis.Params)
assert.DeepEqual(t, genesisState.Delegations, actualGenesis.Delegations)
assert.DeepEqual(t, (f.stakingKeeper.GetAllValidators(f.sdkCtx)), actualGenesis.Validators)
allvals, err := f.stakingKeeper.GetAllValidators(f.sdkCtx)
assert.NilError(t, err)
assert.DeepEqual(t, allvals, actualGenesis.Validators)
// Ensure validators have addresses.
vals2, err := staking.WriteValidators(f.sdkCtx, (f.stakingKeeper))
@ -175,14 +183,14 @@ func TestInitGenesisLargeValidatorSet(t *testing.T) {
assert.Assert(t, size > 100)
f, addrs := bootstrapGenesisTest(t, 200)
genesisValidators := f.stakingKeeper.GetAllValidators(f.sdkCtx)
genesisValidators, err := f.stakingKeeper.GetAllValidators(f.sdkCtx)
assert.NilError(t, err)
params := f.stakingKeeper.GetParams(f.sdkCtx)
params, err := f.stakingKeeper.GetParams(f.sdkCtx)
assert.NilError(t, err)
delegations := []types.Delegation{}
validators := make([]types.Validator, size)
var err error
bondedPoolAmt := math.ZeroInt()
for i := range validators {
validators[i], err = types.NewValidator(

View File

@ -27,7 +27,7 @@ func createValidatorAccs(t *testing.T, f *fixture) ([]sdk.AccAddress, []types.Va
sortedVals := make([]types.Validator, len(validators))
copy(sortedVals, validators)
hi := types.NewHistoricalInfo(header, sortedVals, f.stakingKeeper.PowerReduction(f.sdkCtx))
f.stakingKeeper.SetHistoricalInfo(f.sdkCtx, 5, &hi)
assert.NilError(t, f.stakingKeeper.SetHistoricalInfo(f.sdkCtx, 5, &hi))
return addrs, validators
}
@ -126,8 +126,10 @@ func TestGRPCQueryDelegatorValidators(t *testing.T) {
qr := f.app.QueryHelper()
queryClient := types.NewQueryClient(qr)
params := f.stakingKeeper.GetParams(ctx)
delValidators := f.stakingKeeper.GetDelegatorValidators(ctx, addrs[0], params.MaxValidators)
params, err := f.stakingKeeper.GetParams(ctx)
assert.NilError(t, err)
delValidators, err := f.stakingKeeper.GetDelegatorValidators(ctx, addrs[0], params.MaxValidators)
assert.NilError(t, err)
var req *types.QueryDelegatorValidatorsRequest
testCases := []struct {
msg string
@ -712,7 +714,9 @@ func TestGRPCQueryPoolParameters(t *testing.T) {
// Query Params
resp, err := queryClient.Params(gocontext.Background(), &types.QueryParamsRequest{})
assert.NilError(t, err)
assert.DeepEqual(t, f.stakingKeeper.GetParams(ctx), resp.Params)
params, err := f.stakingKeeper.GetParams(ctx)
assert.NilError(t, err)
assert.DeepEqual(t, params, resp.Params)
}
func TestGRPCQueryHistoricalInfo(t *testing.T) {

View File

@ -19,16 +19,17 @@ func TestCancelUnbondingDelegation(t *testing.T) {
ctx := f.sdkCtx
msgServer := keeper.NewMsgServerImpl(f.stakingKeeper)
bondDenom := f.stakingKeeper.BondDenom(ctx)
bondDenom, err := f.stakingKeeper.BondDenom(ctx)
assert.NilError(t, err)
// set the not bonded pool module account
notBondedPool := f.stakingKeeper.GetNotBondedPool(ctx)
startTokens := f.stakingKeeper.TokensFromConsensusPower(ctx, 5)
assert.NilError(t, testutil.FundModuleAccount(ctx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(f.stakingKeeper.BondDenom(ctx), startTokens))))
assert.NilError(t, testutil.FundModuleAccount(ctx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens))))
f.accountKeeper.SetModuleAccount(ctx, notBondedPool)
moduleBalance := f.bankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), f.stakingKeeper.BondDenom(ctx))
moduleBalance := f.bankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom)
assert.DeepEqual(t, sdk.NewInt64Coin(bondDenom, startTokens.Int64()), moduleBalance)
// accounts
@ -40,13 +41,13 @@ func TestCancelUnbondingDelegation(t *testing.T) {
validator, err := types.NewValidator(valAddr, PKs[0], types.NewDescription("Validator", "", "", "", ""))
validator.Status = types.Bonded
assert.NilError(t, err)
f.stakingKeeper.SetValidator(ctx, validator)
assert.NilError(t, f.stakingKeeper.SetValidator(ctx, validator))
validatorAddr, err := sdk.ValAddressFromBech32(validator.OperatorAddress)
assert.NilError(t, err)
// setting the ubd entry
unbondingAmount := sdk.NewInt64Coin(f.stakingKeeper.BondDenom(ctx), 5)
unbondingAmount := sdk.NewInt64Coin(bondDenom, 5)
ubd := types.NewUnbondingDelegation(
delegatorAddr, validatorAddr, 10,
ctx.BlockTime().Add(time.Minute*10),
@ -55,7 +56,7 @@ func TestCancelUnbondingDelegation(t *testing.T) {
)
// set and retrieve a record
f.stakingKeeper.SetUnbondingDelegation(ctx, ubd)
assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(ctx, ubd))
resUnbond, found := f.stakingKeeper.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr)
assert.Assert(t, found)
assert.DeepEqual(t, ubd, resUnbond)
@ -72,7 +73,7 @@ func TestCancelUnbondingDelegation(t *testing.T) {
req: types.MsgCancelUnbondingDelegation{
DelegatorAddress: resUnbond.DelegatorAddress,
ValidatorAddress: resUnbond.ValidatorAddress,
Amount: sdk.NewCoin(f.stakingKeeper.BondDenom(ctx), sdk.NewInt(4)),
Amount: sdk.NewCoin(bondDenom, sdk.NewInt(4)),
CreationHeight: 11,
},
expErrMsg: "unbonding delegation entry is not found at block height",
@ -83,7 +84,7 @@ func TestCancelUnbondingDelegation(t *testing.T) {
req: types.MsgCancelUnbondingDelegation{
DelegatorAddress: resUnbond.DelegatorAddress,
ValidatorAddress: resUnbond.ValidatorAddress,
Amount: sdk.NewCoin(f.stakingKeeper.BondDenom(ctx), sdk.NewInt(4)),
Amount: sdk.NewCoin(bondDenom, sdk.NewInt(4)),
CreationHeight: 0,
},
expErrMsg: "invalid height",

View File

@ -24,7 +24,9 @@ func bootstrapSlashTest(t *testing.T, power int64) (*fixture, []sdk.AccAddress,
addrDels, addrVals := generateAddresses(f, 100)
amt := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power)
totalSupply := sdk.NewCoins(sdk.NewCoin(f.stakingKeeper.BondDenom(f.sdkCtx), amt.MulRaw(int64(len(addrDels)))))
bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx)
require.NoError(t, err)
totalSupply := sdk.NewCoins(sdk.NewCoin(bondDenom, amt.MulRaw(int64(len(addrDels)))))
notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx)
assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), totalSupply))
@ -32,7 +34,7 @@ func bootstrapSlashTest(t *testing.T, power int64) (*fixture, []sdk.AccAddress,
f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool)
numVals := int64(3)
bondedCoins := sdk.NewCoins(sdk.NewCoin(f.stakingKeeper.BondDenom(f.sdkCtx), amt.MulRaw(numVals)))
bondedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, amt.MulRaw(numVals)))
bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx)
// set bonded pool balance
@ -43,7 +45,7 @@ func bootstrapSlashTest(t *testing.T, power int64) (*fixture, []sdk.AccAddress,
validator := testutil.NewValidator(t, addrVals[i], PKs[i])
validator, _ = validator.AddTokensFromDel(amt)
validator = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validator, true)
f.stakingKeeper.SetValidatorByConsAddr(f.sdkCtx, validator)
assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.sdkCtx, validator))
}
return f, addrDels, addrVals
@ -60,24 +62,27 @@ func TestSlashUnbondingDelegation(t *testing.T) {
ubd := types.NewUnbondingDelegation(addrDels[0], addrVals[0], 0,
time.Unix(5, 0), sdk.NewInt(10), 0)
f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubd)
assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubd))
// unbonding started prior to the infraction height, stakw didn't contribute
slashAmount := f.stakingKeeper.SlashUnbondingDelegation(f.sdkCtx, ubd, 1, fraction)
slashAmount, err := f.stakingKeeper.SlashUnbondingDelegation(f.sdkCtx, ubd, 1, fraction)
assert.NilError(t, err)
assert.Assert(t, slashAmount.Equal(sdk.NewInt(0)))
// after the expiration time, no longer eligible for slashing
f.sdkCtx = f.sdkCtx.WithBlockHeader(cmtproto.Header{Time: time.Unix(10, 0)})
f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubd)
slashAmount = f.stakingKeeper.SlashUnbondingDelegation(f.sdkCtx, ubd, 0, fraction)
assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubd))
slashAmount, err = f.stakingKeeper.SlashUnbondingDelegation(f.sdkCtx, ubd, 0, fraction)
assert.NilError(t, err)
assert.Assert(t, slashAmount.Equal(sdk.NewInt(0)))
// test valid slash, before expiration timestamp and to which stake contributed
notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx)
oldUnbondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, notBondedPool.GetAddress())
f.sdkCtx = f.sdkCtx.WithBlockHeader(cmtproto.Header{Time: time.Unix(0, 0)})
f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubd)
slashAmount = f.stakingKeeper.SlashUnbondingDelegation(f.sdkCtx, ubd, 0, fraction)
assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubd))
slashAmount, err = f.stakingKeeper.SlashUnbondingDelegation(f.sdkCtx, ubd, 0, fraction)
assert.NilError(t, err)
assert.Assert(t, slashAmount.Equal(sdk.NewInt(5)))
ubd, found := f.stakingKeeper.GetUnbondingDelegation(f.sdkCtx, addrDels[0], addrVals[0])
assert.Assert(t, found)
@ -90,7 +95,9 @@ func TestSlashUnbondingDelegation(t *testing.T) {
assert.DeepEqual(t, sdk.NewInt(5), ubd.Entries[0].Balance)
newUnbondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, notBondedPool.GetAddress())
diffTokens := oldUnbondedPoolBalances.Sub(newUnbondedPoolBalances...)
assert.Assert(t, diffTokens.AmountOf(f.stakingKeeper.BondDenom(f.sdkCtx)).Equal(sdk.NewInt(5)))
bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx)
assert.NilError(t, err)
assert.Assert(t, diffTokens.AmountOf(bondDenom).Equal(sdk.NewInt(5)))
}
// tests slashRedelegation
@ -98,8 +105,11 @@ func TestSlashRedelegation(t *testing.T) {
f, addrDels, addrVals := bootstrapSlashTest(t, 10)
fraction := sdk.NewDecWithPrec(5, 1)
bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx)
assert.NilError(t, err)
// add bonded tokens to pool for (re)delegations
startCoins := sdk.NewCoins(sdk.NewInt64Coin(f.stakingKeeper.BondDenom(f.sdkCtx), 15))
startCoins := sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 15))
bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx)
_ = f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress())
@ -111,34 +121,37 @@ func TestSlashRedelegation(t *testing.T) {
rd := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 0,
time.Unix(5, 0), sdk.NewInt(10), math.LegacyNewDec(10), 0)
f.stakingKeeper.SetRedelegation(f.sdkCtx, rd)
assert.NilError(t, f.stakingKeeper.SetRedelegation(f.sdkCtx, rd))
// set the associated delegation
del := types.NewDelegation(addrDels[0], addrVals[1], math.LegacyNewDec(10))
f.stakingKeeper.SetDelegation(f.sdkCtx, del)
assert.NilError(t, f.stakingKeeper.SetDelegation(f.sdkCtx, del))
// started redelegating prior to the current height, stake didn't contribute to infraction
validator, found := f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1])
assert.Assert(t, found)
slashAmount := f.stakingKeeper.SlashRedelegation(f.sdkCtx, validator, rd, 1, fraction)
slashAmount, err := f.stakingKeeper.SlashRedelegation(f.sdkCtx, validator, rd, 1, fraction)
assert.NilError(t, err)
assert.Assert(t, slashAmount.Equal(sdk.NewInt(0)))
// after the expiration time, no longer eligible for slashing
f.sdkCtx = f.sdkCtx.WithBlockHeader(cmtproto.Header{Time: time.Unix(10, 0)})
f.stakingKeeper.SetRedelegation(f.sdkCtx, rd)
assert.NilError(t, f.stakingKeeper.SetRedelegation(f.sdkCtx, rd))
validator, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1])
assert.Assert(t, found)
slashAmount = f.stakingKeeper.SlashRedelegation(f.sdkCtx, validator, rd, 0, fraction)
slashAmount, err = f.stakingKeeper.SlashRedelegation(f.sdkCtx, validator, rd, 0, fraction)
assert.NilError(t, err)
assert.Assert(t, slashAmount.Equal(sdk.NewInt(0)))
balances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress())
// test valid slash, before expiration timestamp and to which stake contributed
f.sdkCtx = f.sdkCtx.WithBlockHeader(cmtproto.Header{Time: time.Unix(0, 0)})
f.stakingKeeper.SetRedelegation(f.sdkCtx, rd)
assert.NilError(t, f.stakingKeeper.SetRedelegation(f.sdkCtx, rd))
validator, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1])
assert.Assert(t, found)
slashAmount = f.stakingKeeper.SlashRedelegation(f.sdkCtx, validator, rd, 0, fraction)
slashAmount, err = f.stakingKeeper.SlashRedelegation(f.sdkCtx, validator, rd, 0, fraction)
assert.NilError(t, err)
assert.Assert(t, slashAmount.Equal(sdk.NewInt(5)))
rd, found = f.stakingKeeper.GetRedelegation(f.sdkCtx, addrDels[0], addrVals[0], addrVals[1])
assert.Assert(t, found)
@ -156,7 +169,7 @@ func TestSlashRedelegation(t *testing.T) {
assert.Equal(t, int64(5), del.Shares.RoundInt64())
// pool bonded tokens should decrease
burnedCoins := sdk.NewCoins(sdk.NewCoin(f.stakingKeeper.BondDenom(f.sdkCtx), slashAmount))
burnedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, slashAmount))
assert.DeepEqual(t, balances.Sub(burnedCoins...), f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()))
}
@ -172,7 +185,8 @@ func TestSlashAtNegativeHeight(t *testing.T) {
_, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr)
assert.Assert(t, found)
f.stakingKeeper.Slash(f.sdkCtx, consAddr, -2, 10, fraction)
_, err := f.stakingKeeper.Slash(f.sdkCtx, consAddr, -2, 10, fraction)
assert.NilError(t, err)
// read updated state
validator, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr)
@ -186,9 +200,12 @@ func TestSlashAtNegativeHeight(t *testing.T) {
// power decreased
assert.Equal(t, int64(5), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx)))
bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx)
assert.NilError(t, err)
// pool bonded shares decreased
newBondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress())
diffTokens := oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(f.stakingKeeper.BondDenom(f.sdkCtx))
diffTokens := oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom)
assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 5).String(), diffTokens.String())
}
@ -198,12 +215,16 @@ func TestSlashValidatorAtCurrentHeight(t *testing.T) {
consAddr := sdk.ConsAddress(PKs[0].Address())
fraction := sdk.NewDecWithPrec(5, 1)
bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx)
assert.NilError(t, err)
bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx)
oldBondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress())
_, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr)
assert.Assert(t, found)
f.stakingKeeper.Slash(f.sdkCtx, consAddr, f.sdkCtx.BlockHeight(), 10, fraction)
_, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, f.sdkCtx.BlockHeight(), 10, fraction)
assert.NilError(t, err)
// read updated state
validator, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr)
@ -219,7 +240,7 @@ func TestSlashValidatorAtCurrentHeight(t *testing.T) {
// pool bonded shares decreased
newBondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress())
diffTokens := oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(f.stakingKeeper.BondDenom(f.sdkCtx))
diffTokens := oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom)
assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 5).String(), diffTokens.String())
}
@ -230,11 +251,14 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
consAddr := sdk.ConsAddress(PKs[0].Address())
fraction := sdk.NewDecWithPrec(5, 1)
bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx)
assert.NilError(t, err)
// set an unbonding delegation with expiration timestamp beyond which the
// unbonding delegation shouldn't be slashed
ubdTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 4)
ubd := types.NewUnbondingDelegation(addrDels[0], addrVals[0], 11, time.Unix(0, 0), ubdTokens, 0)
f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubd)
assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubd))
// slash validator for the first time
f.sdkCtx = f.sdkCtx.WithBlockHeight(12)
@ -243,7 +267,8 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
_, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr)
assert.Assert(t, found)
f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, fraction)
_, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, fraction)
assert.NilError(t, err)
// end block
applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1)
@ -258,7 +283,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
// bonded tokens burned
newBondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress())
diffTokens := oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(f.stakingKeeper.BondDenom(f.sdkCtx))
diffTokens := oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom)
assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 3), diffTokens)
// read updated validator
@ -273,7 +298,8 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
// slash validator again
f.sdkCtx = f.sdkCtx.WithBlockHeight(13)
f.stakingKeeper.Slash(f.sdkCtx, consAddr, 9, 10, fraction)
_, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 9, 10, fraction)
assert.NilError(t, err)
ubd, found = f.stakingKeeper.GetUnbondingDelegation(f.sdkCtx, addrDels[0], addrVals[0])
assert.Assert(t, found)
@ -284,7 +310,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
// bonded tokens burned again
newBondedPoolBalances = f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress())
diffTokens = oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(f.stakingKeeper.BondDenom(f.sdkCtx))
diffTokens = oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom)
assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 6), diffTokens)
// read updated validator
@ -299,7 +325,8 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
// on the unbonding delegation, but it will slash stake bonded since the infraction
// this may not be the desirable behavior, ref https://github.com/cosmos/cosmos-sdk/issues/1440
f.sdkCtx = f.sdkCtx.WithBlockHeight(13)
f.stakingKeeper.Slash(f.sdkCtx, consAddr, 9, 10, fraction)
_, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 9, 10, fraction)
assert.NilError(t, err)
ubd, found = f.stakingKeeper.GetUnbondingDelegation(f.sdkCtx, addrDels[0], addrVals[0])
assert.Assert(t, found)
@ -310,7 +337,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
// bonded tokens burned again
newBondedPoolBalances = f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress())
diffTokens = oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(f.stakingKeeper.BondDenom(f.sdkCtx))
diffTokens = oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom)
assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 9), diffTokens)
// read updated validator
@ -325,7 +352,8 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
// on the unbonding delegation, but it will slash stake bonded since the infraction
// this may not be the desirable behavior, ref https://github.com/cosmos/cosmos-sdk/issues/1440
f.sdkCtx = f.sdkCtx.WithBlockHeight(13)
f.stakingKeeper.Slash(f.sdkCtx, consAddr, 9, 10, fraction)
_, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 9, 10, fraction)
assert.NilError(t, err)
ubd, found = f.stakingKeeper.GetUnbondingDelegation(f.sdkCtx, addrDels[0], addrVals[0])
assert.Assert(t, found)
@ -336,7 +364,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
// just 1 bonded token burned again since that's all the validator now has
newBondedPoolBalances = f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress())
diffTokens = oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(f.stakingKeeper.BondDenom(f.sdkCtx))
diffTokens = oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom)
assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10), diffTokens)
// apply TM updates
@ -354,16 +382,17 @@ func TestSlashWithRedelegation(t *testing.T) {
f, addrDels, addrVals := bootstrapSlashTest(t, 10)
consAddr := sdk.ConsAddress(PKs[0].Address())
fraction := sdk.NewDecWithPrec(5, 1)
bondDenom := f.stakingKeeper.BondDenom(f.sdkCtx)
bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx)
assert.NilError(t, err)
// set a redelegation
rdTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 6)
rd := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 11, time.Unix(0, 0), rdTokens, sdk.NewDecFromInt(rdTokens), 0)
f.stakingKeeper.SetRedelegation(f.sdkCtx, rd)
assert.NilError(t, f.stakingKeeper.SetRedelegation(f.sdkCtx, rd))
// set the associated delegation
del := types.NewDelegation(addrDels[0], addrVals[1], sdk.NewDecFromInt(rdTokens))
f.stakingKeeper.SetDelegation(f.sdkCtx, del)
assert.NilError(t, f.stakingKeeper.SetDelegation(f.sdkCtx, del))
// update bonded tokens
bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx)
@ -382,9 +411,9 @@ func TestSlashWithRedelegation(t *testing.T) {
_, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr)
assert.Assert(t, found)
require.NotPanics(t, func() {
f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, fraction)
})
_, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, fraction)
assert.NilError(t, err)
burnAmount := sdk.NewDecFromInt(f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10)).Mul(fraction).TruncateInt()
bondedPool = f.stakingKeeper.GetBondedPool(f.sdkCtx)
@ -415,9 +444,8 @@ func TestSlashWithRedelegation(t *testing.T) {
_, found = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr)
assert.Assert(t, found)
require.NotPanics(t, func() {
f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, math.LegacyOneDec())
})
_, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, math.LegacyOneDec())
assert.NilError(t, err)
burnAmount = f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 7)
// read updated pool
@ -451,9 +479,8 @@ func TestSlashWithRedelegation(t *testing.T) {
_, found = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr)
assert.Assert(t, found)
require.NotPanics(t, func() {
f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, math.LegacyOneDec())
})
_, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, math.LegacyOneDec())
assert.NilError(t, err)
burnAmount = sdk.NewDecFromInt(f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10)).Mul(math.LegacyOneDec()).TruncateInt()
burnAmount = burnAmount.Sub(math.LegacyOneDec().MulInt(rdTokens).TruncateInt())
@ -486,9 +513,8 @@ func TestSlashWithRedelegation(t *testing.T) {
validator, _ = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr)
assert.Equal(t, validator.GetStatus(), types.Unbonding)
require.NotPanics(t, func() {
f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, math.LegacyOneDec())
})
_, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, math.LegacyOneDec())
assert.NilError(t, err)
// read updated pool
bondedPool = f.stakingKeeper.GetBondedPool(f.sdkCtx)
@ -513,24 +539,25 @@ func TestSlashWithRedelegation(t *testing.T) {
func TestSlashBoth(t *testing.T) {
f, addrDels, addrVals := bootstrapSlashTest(t, 10)
fraction := sdk.NewDecWithPrec(5, 1)
bondDenom := f.stakingKeeper.BondDenom(f.sdkCtx)
bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx)
assert.NilError(t, err)
// set a redelegation with expiration timestamp beyond which the
// redelegation shouldn't be slashed
rdATokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 6)
rdA := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 11, time.Unix(0, 0), rdATokens, sdk.NewDecFromInt(rdATokens), 0)
f.stakingKeeper.SetRedelegation(f.sdkCtx, rdA)
assert.NilError(t, f.stakingKeeper.SetRedelegation(f.sdkCtx, rdA))
// set the associated delegation
delA := types.NewDelegation(addrDels[0], addrVals[1], sdk.NewDecFromInt(rdATokens))
f.stakingKeeper.SetDelegation(f.sdkCtx, delA)
assert.NilError(t, f.stakingKeeper.SetDelegation(f.sdkCtx, delA))
// set an unbonding delegation with expiration timestamp (beyond which the
// unbonding delegation shouldn't be slashed)
ubdATokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 4)
ubdA := types.NewUnbondingDelegation(addrDels[0], addrVals[0], 11,
time.Unix(0, 0), ubdATokens, 0)
f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubdA)
assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubdA))
bondedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, rdATokens.MulRaw(2)))
notBondedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, ubdATokens))
@ -552,7 +579,8 @@ func TestSlashBoth(t *testing.T) {
_, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, sdk.GetConsAddress(PKs[0]))
assert.Assert(t, found)
consAddr0 := sdk.ConsAddress(PKs[0].Address())
f.stakingKeeper.Slash(f.sdkCtx, consAddr0, 10, 10, fraction)
_, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr0, 10, 10, fraction)
assert.NilError(t, err)
burnedNotBondedAmount := fraction.MulInt(ubdATokens).TruncateInt()
burnedBondAmount := sdk.NewDecFromInt(f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10)).Mul(fraction).TruncateInt()
@ -583,11 +611,13 @@ func TestSlashAmount(t *testing.T) {
f, _, _ := bootstrapSlashTest(t, 10)
consAddr := sdk.ConsAddress(PKs[0].Address())
fraction := sdk.NewDecWithPrec(5, 1)
burnedCoins := f.stakingKeeper.Slash(f.sdkCtx, consAddr, f.sdkCtx.BlockHeight(), 10, fraction)
burnedCoins, err := f.stakingKeeper.Slash(f.sdkCtx, consAddr, f.sdkCtx.BlockHeight(), 10, fraction)
assert.NilError(t, err)
assert.Assert(t, burnedCoins.GT(math.ZeroInt()))
// test the case where the validator was not found, which should return no coins
_, addrVals := generateAddresses(f, 100)
noBurned := f.stakingKeeper.Slash(f.sdkCtx, sdk.ConsAddress(addrVals[0]), f.sdkCtx.BlockHeight(), 10, fraction)
noBurned, err := f.stakingKeeper.Slash(f.sdkCtx, sdk.ConsAddress(addrVals[0]), f.sdkCtx.BlockHeight(), 10, fraction)
assert.NilError(t, err)
assert.Assert(t, sdk.NewInt(0).Equal(noBurned))
}

View File

@ -49,11 +49,11 @@ func SetupUnbondingTests(t *testing.T, f *fixture, hookCalled *bool, ubdeID *uin
valTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10)
startTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 20)
bondDenom = f.stakingKeeper.BondDenom(f.sdkCtx)
bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx)
assert.NilError(t, err)
notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx)
assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens))))
f.bankKeeper.SendCoinsFromModuleToModule(f.sdkCtx, types.BondedPoolName, types.NotBondedPoolName, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, startTokens)))
f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool)
// Create a validator
@ -67,7 +67,7 @@ func SetupUnbondingTests(t *testing.T, f *fixture, hookCalled *bool, ubdeID *uin
// Create a delegator
delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares1)
f.stakingKeeper.SetDelegation(f.sdkCtx, delegation)
assert.NilError(t, f.stakingKeeper.SetDelegation(f.sdkCtx, delegation))
// Create a validator to redelegate to
validator2 := testutil.NewValidator(t, addrVals[1], PKs[1])
@ -110,7 +110,8 @@ func doUnbondingDelegation(
assert.Assert(math.IntEq(t, notBondedAmt1.AddRaw(1), notBondedAmt2))
// Check that the unbonding happened- we look up the entry and see that it has the correct number of shares
unbondingDelegations := stakingKeeper.GetUnbondingDelegationsFromValidator(ctx, addrVals[0])
unbondingDelegations, err := stakingKeeper.GetUnbondingDelegationsFromValidator(ctx, addrVals[0])
assert.NilError(t, err)
assert.DeepEqual(t, math.NewInt(1), unbondingDelegations[0].Entries[0].Balance)
// check that our hook was called
@ -132,7 +133,8 @@ func doRedelegation(
assert.NilError(t, err)
// Check that the redelegation happened- we look up the entry and see that it has the correct number of shares
redelegations := stakingKeeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0])
redelegations, err := stakingKeeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0])
assert.NilError(t, err)
assert.Equal(t, 1, len(redelegations))
assert.DeepEqual(t, math.LegacyNewDec(1), redelegations[0].Entries[0].SharesDst)
@ -188,26 +190,28 @@ func TestValidatorUnbondingOnHold1(t *testing.T) {
assert.NilError(t, err)
// Try to unbond validator
f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx)
assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx))
// Check that validator unbonding is not complete (is not mature yet)
validator, found := f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[0])
assert.Assert(t, found)
assert.Equal(t, types.Unbonding, validator.Status)
unbondingVals := f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight)
unbondingVals, err := f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight)
assert.NilError(t, err)
assert.Equal(t, 1, len(unbondingVals))
assert.Equal(t, validator.OperatorAddress, unbondingVals[0])
// PROVIDER CHAIN'S UNBONDING PERIOD ENDS - BUT UNBONDING CANNOT COMPLETE
f.sdkCtx = f.sdkCtx.WithBlockTime(completionTime.Add(time.Duration(1)))
f.sdkCtx = f.sdkCtx.WithBlockHeight(completionHeight + 1)
f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx)
assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx))
// Check that validator unbonding is complete
validator, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[0])
assert.Assert(t, found)
assert.Equal(t, types.Unbonded, validator.Status)
unbondingVals = f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight)
unbondingVals, err = f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight)
assert.NilError(t, err)
assert.Equal(t, 0, len(unbondingVals))
}
@ -246,7 +250,7 @@ func TestValidatorUnbondingOnHold2(t *testing.T) {
// PROVIDER CHAIN'S UNBONDING PERIOD ENDS - BUT UNBONDING CANNOT COMPLETE
f.sdkCtx = f.sdkCtx.WithBlockTime(completionTime.Add(time.Duration(1)))
f.sdkCtx = f.sdkCtx.WithBlockHeight(completionHeight + 1)
f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx)
assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx))
// Check that unbonding is not complete for both validators
validator1, found := f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[0])
@ -255,17 +259,18 @@ func TestValidatorUnbondingOnHold2(t *testing.T) {
validator2, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1])
assert.Assert(t, found)
assert.Equal(t, types.Unbonding, validator2.Status)
unbondingVals := f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight)
unbondingVals, err := f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight)
assert.NilError(t, err)
assert.Equal(t, 2, len(unbondingVals))
assert.Equal(t, validator1.OperatorAddress, unbondingVals[0])
assert.Equal(t, validator2.OperatorAddress, unbondingVals[1])
// CONSUMER CHAIN'S UNBONDING PERIOD ENDS - STOPPED UNBONDING CAN NOW COMPLETE
err := f.stakingKeeper.UnbondingCanComplete(f.sdkCtx, ubdeIDs[0])
err = f.stakingKeeper.UnbondingCanComplete(f.sdkCtx, ubdeIDs[0])
assert.NilError(t, err)
// Try again to unbond validators
f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx)
assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx))
// Check that unbonding is complete for validator1, but not for validator2
validator1, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[0])
@ -274,7 +279,8 @@ func TestValidatorUnbondingOnHold2(t *testing.T) {
validator2, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1])
assert.Assert(t, found)
assert.Equal(t, types.Unbonding, validator2.Status)
unbondingVals = f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight)
unbondingVals, err = f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight)
assert.NilError(t, err)
assert.Equal(t, 1, len(unbondingVals))
assert.Equal(t, validator2.OperatorAddress, unbondingVals[0])
@ -283,13 +289,14 @@ func TestValidatorUnbondingOnHold2(t *testing.T) {
assert.NilError(t, err)
// Try again to unbond validators
f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx)
assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx))
// Check that unbonding is complete for validator2
validator2, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1])
assert.Assert(t, found)
assert.Equal(t, types.Unbonded, validator2.Status)
unbondingVals = f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight)
unbondingVals, err = f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight)
assert.NilError(t, err)
assert.Equal(t, 0, len(unbondingVals))
}
@ -311,7 +318,8 @@ func TestRedelegationOnHold1(t *testing.T) {
assert.NilError(t, err)
// Redelegation is not complete - still exists
redelegations := f.stakingKeeper.GetRedelegationsFromSrcValidator(f.sdkCtx, addrVals[0])
redelegations, err := f.stakingKeeper.GetRedelegationsFromSrcValidator(f.sdkCtx, addrVals[0])
assert.NilError(t, err)
assert.Equal(t, 1, len(redelegations))
// PROVIDER CHAIN'S UNBONDING PERIOD ENDS - STOPPED UNBONDING CAN NOW COMPLETE
@ -320,7 +328,8 @@ func TestRedelegationOnHold1(t *testing.T) {
assert.NilError(t, err)
// Redelegation is complete and record is gone
redelegations = f.stakingKeeper.GetRedelegationsFromSrcValidator(f.sdkCtx, addrVals[0])
redelegations, err = f.stakingKeeper.GetRedelegationsFromSrcValidator(f.sdkCtx, addrVals[0])
assert.NilError(t, err)
assert.Equal(t, 0, len(redelegations))
}
@ -343,7 +352,8 @@ func TestRedelegationOnHold2(t *testing.T) {
assert.NilError(t, err)
// Redelegation is not complete - still exists
redelegations := f.stakingKeeper.GetRedelegationsFromSrcValidator(f.sdkCtx, addrVals[0])
redelegations, err := f.stakingKeeper.GetRedelegationsFromSrcValidator(f.sdkCtx, addrVals[0])
assert.NilError(t, err)
assert.Equal(t, 1, len(redelegations))
// CONSUMER CHAIN'S UNBONDING PERIOD ENDS - STOPPED UNBONDING CAN NOW COMPLETE
@ -351,7 +361,8 @@ func TestRedelegationOnHold2(t *testing.T) {
assert.NilError(t, err)
// Redelegation is complete and record is gone
redelegations = f.stakingKeeper.GetRedelegationsFromSrcValidator(f.sdkCtx, addrVals[0])
redelegations, err = f.stakingKeeper.GetRedelegationsFromSrcValidator(f.sdkCtx, addrVals[0])
assert.NilError(t, err)
assert.Equal(t, 0, len(redelegations))
}

View File

@ -28,8 +28,11 @@ func bootstrapValidatorTest(t testing.TB, power int64, numAddrs int) (*fixture,
addrDels, addrVals := generateAddresses(f, numAddrs)
bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx)
assert.NilError(t, err)
amt := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power)
totalSupply := sdk.NewCoins(sdk.NewCoin(f.stakingKeeper.BondDenom(f.sdkCtx), amt.MulRaw(int64(len(addrDels)))))
totalSupply := sdk.NewCoins(sdk.NewCoin(bondDenom, amt.MulRaw(int64(len(addrDels)))))
notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx)
@ -65,13 +68,17 @@ func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) {
notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx)
// create keeper parameters
params := f.stakingKeeper.GetParams(f.sdkCtx)
params, err := f.stakingKeeper.GetParams(f.sdkCtx)
assert.NilError(t, err)
params.MaxValidators = uint32(maxVals)
f.stakingKeeper.SetParams(f.sdkCtx, params)
assert.NilError(t, f.stakingKeeper.SetParams(f.sdkCtx, params))
bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx)
assert.NilError(t, err)
// create a random pool
assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(f.stakingKeeper.BondDenom(f.sdkCtx), f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 1234)))))
assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(f.stakingKeeper.BondDenom(f.sdkCtx), f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10000)))))
assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 1234)))))
assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10000)))))
f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool)
f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool)
@ -124,8 +131,9 @@ func TestSlashToZeroPowerRemoved(t *testing.T) {
valTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 100)
bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx)
assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(f.stakingKeeper.BondDenom(f.sdkCtx), valTokens))))
bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx)
assert.NilError(t, err)
assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, valTokens))))
f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool)
@ -168,7 +176,8 @@ func TestGetValidatorSortingUnmixed(t *testing.T) {
}
// first make sure everything made it in to the gotValidator group
resValidators := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
assert.NilError(t, err)
assert.Equal(t, n, len(resValidators))
assert.DeepEqual(t, sdk.NewInt(400).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)), resValidators[0].BondedTokens())
assert.DeepEqual(t, sdk.NewInt(200).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)), resValidators[1].BondedTokens())
@ -184,14 +193,16 @@ func TestGetValidatorSortingUnmixed(t *testing.T) {
// test a basic increase in voting power
validators[3].Tokens = sdk.NewInt(500).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx))
keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true)
resValidators = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
assert.NilError(t, err)
assert.Equal(t, len(resValidators), n)
assert.Assert(ValEq(t, validators[3], resValidators[0]))
// test a decrease in voting power
validators[3].Tokens = sdk.NewInt(300).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx))
keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true)
resValidators = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
assert.NilError(t, err)
assert.Equal(t, len(resValidators), n)
assert.Assert(ValEq(t, validators[3], resValidators[0]))
assert.Assert(ValEq(t, validators[4], resValidators[1]))
@ -200,7 +211,8 @@ func TestGetValidatorSortingUnmixed(t *testing.T) {
validators[3].Tokens = sdk.NewInt(200).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx))
f.sdkCtx = f.sdkCtx.WithBlockHeight(10)
keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true)
resValidators = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
assert.NilError(t, err)
assert.Equal(t, len(resValidators), n)
assert.Assert(ValEq(t, validators[3], resValidators[0]))
assert.Assert(ValEq(t, validators[4], resValidators[1]))
@ -208,7 +220,8 @@ func TestGetValidatorSortingUnmixed(t *testing.T) {
// no change in voting power - no change in sort
f.sdkCtx = f.sdkCtx.WithBlockHeight(20)
keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[4], true)
resValidators = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
assert.NilError(t, err)
assert.Equal(t, len(resValidators), n)
assert.Assert(ValEq(t, validators[3], resValidators[0]))
assert.Assert(ValEq(t, validators[4], resValidators[1]))
@ -217,11 +230,13 @@ func TestGetValidatorSortingUnmixed(t *testing.T) {
validators[3].Tokens = sdk.NewInt(300).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx))
validators[4].Tokens = sdk.NewInt(300).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx))
keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true)
resValidators = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
assert.NilError(t, err)
assert.Equal(t, len(resValidators), n)
f.sdkCtx = f.sdkCtx.WithBlockHeight(30)
keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[4], true)
resValidators = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
assert.NilError(t, err)
assert.Equal(t, len(resValidators), n, "%v", resValidators)
assert.Assert(ValEq(t, validators[3], resValidators[0]))
assert.Assert(ValEq(t, validators[4], resValidators[1]))
@ -232,16 +247,20 @@ func TestGetValidatorSortingMixed(t *testing.T) {
bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx)
notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx)
assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(f.stakingKeeper.BondDenom(f.sdkCtx), f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 501)))))
assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(f.stakingKeeper.BondDenom(f.sdkCtx), f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 0)))))
bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx)
assert.NilError(t, err)
assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 501)))))
assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 0)))))
f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool)
f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool)
// now 2 max resValidators
params := f.stakingKeeper.GetParams(f.sdkCtx)
params, err := f.stakingKeeper.GetParams(f.sdkCtx)
assert.NilError(t, err)
params.MaxValidators = 2
f.stakingKeeper.SetParams(f.sdkCtx, params)
assert.NilError(t, f.stakingKeeper.SetParams(f.sdkCtx, params))
// initialize some validators into the state
amts := []math.Int{
@ -278,7 +297,8 @@ func TestGetValidatorSortingMixed(t *testing.T) {
assert.Equal(t, types.Bonded, val4.Status)
// first make sure everything made it in to the gotValidator group
resValidators := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
assert.NilError(t, err)
// The validators returned should match the max validators
assert.Equal(t, 2, len(resValidators))
assert.DeepEqual(t, sdk.NewInt(400).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)), resValidators[0].BondedTokens())
@ -292,7 +312,8 @@ func TestGetValidatorsEdgeCases(t *testing.T) {
f, addrs, _ := bootstrapValidatorTest(t, 1000, 20)
// set max validators to 2
params := f.stakingKeeper.GetParams(f.sdkCtx)
params, err := f.stakingKeeper.GetParams(f.sdkCtx)
assert.NilError(t, err)
nMax := uint32(2)
params.MaxValidators = nMax
f.stakingKeeper.SetParams(f.sdkCtx, params)
@ -314,7 +335,8 @@ func TestGetValidatorsEdgeCases(t *testing.T) {
}
// ensure that the first two bonded validators are the largest validators
resValidators := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
assert.NilError(t, err)
assert.Equal(t, nMax, uint32(len(resValidators)))
assert.Assert(ValEq(t, validators[2], resValidators[0]))
assert.Assert(ValEq(t, validators[3], resValidators[1]))
@ -334,7 +356,8 @@ func TestGetValidatorsEdgeCases(t *testing.T) {
// a) validator 0 with 500 tokens
// b) validator 2 with 400 tokens (delegated before validator 3)
validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], true)
resValidators = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
assert.NilError(t, err)
assert.Equal(t, nMax, uint32(len(resValidators)))
assert.Assert(ValEq(t, validators[0], resValidators[0]))
assert.Assert(ValEq(t, validators[2], resValidators[1]))
@ -351,9 +374,8 @@ func TestGetValidatorsEdgeCases(t *testing.T) {
// validator 3 enters bonded validator set
f.sdkCtx = f.sdkCtx.WithBlockHeight(40)
var found bool
validators[3], found = f.stakingKeeper.GetValidator(f.sdkCtx, validators[3].GetOperator())
assert.Assert(t, found)
validators[3], err = f.stakingKeeper.GetValidator(f.sdkCtx, validators[3].GetOperator())
assert.NilError(t, err)
f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[3])
validators[3], _ = validators[3].AddTokensFromDel(f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 1))
@ -363,7 +385,8 @@ func TestGetValidatorsEdgeCases(t *testing.T) {
f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool)
validators[3] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true)
resValidators = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
assert.NilError(t, err)
assert.Equal(t, nMax, uint32(len(resValidators)))
assert.Assert(ValEq(t, validators[0], resValidators[0]))
assert.Assert(ValEq(t, validators[3], resValidators[1]))
@ -378,7 +401,8 @@ func TestGetValidatorsEdgeCases(t *testing.T) {
f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool)
validators[3] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true)
resValidators = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
assert.NilError(t, err)
assert.Equal(t, nMax, uint32(len(resValidators)))
assert.Assert(ValEq(t, validators[0], resValidators[0]))
assert.Assert(ValEq(t, validators[2], resValidators[1]))
@ -392,7 +416,8 @@ func TestGetValidatorsEdgeCases(t *testing.T) {
f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool)
validators[3] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true)
resValidators = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
assert.NilError(t, err)
assert.Equal(t, nMax, uint32(len(resValidators)))
assert.Assert(ValEq(t, validators[0], resValidators[0]))
assert.Assert(ValEq(t, validators[2], resValidators[1]))
@ -404,7 +429,8 @@ func TestValidatorBondHeight(t *testing.T) {
f, addrs, _ := bootstrapValidatorTest(t, 1000, 20)
// now 2 max resValidators
params := f.stakingKeeper.GetParams(f.sdkCtx)
params, err := f.stakingKeeper.GetParams(f.sdkCtx)
assert.NilError(t, err)
params.MaxValidators = 2
f.stakingKeeper.SetParams(f.sdkCtx, params)
@ -429,7 +455,8 @@ func TestValidatorBondHeight(t *testing.T) {
validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], true)
validators[2] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[2], true)
resValidators := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
assert.NilError(t, err)
assert.Equal(t, uint32(len(resValidators)), params.MaxValidators)
assert.Assert(ValEq(t, validators[0], resValidators[0]))
@ -440,7 +467,8 @@ func TestValidatorBondHeight(t *testing.T) {
validators[1], _ = validators[1].AddTokensFromDel(delTokens)
validators[2], _ = validators[2].AddTokensFromDel(delTokens)
validators[2] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[2], true)
resValidators = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
assert.NilError(t, err)
assert.Equal(t, params.MaxValidators, uint32(len(resValidators)))
validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], true)
assert.Assert(ValEq(t, validators[0], resValidators[0]))
@ -449,10 +477,11 @@ func TestValidatorBondHeight(t *testing.T) {
func TestFullValidatorSetPowerChange(t *testing.T) {
f, addrs, _ := bootstrapValidatorTest(t, 1000, 20)
params := f.stakingKeeper.GetParams(f.sdkCtx)
params, err := f.stakingKeeper.GetParams(f.sdkCtx)
assert.NilError(t, err)
max := 2
params.MaxValidators = uint32(2)
f.stakingKeeper.SetParams(f.sdkCtx, params)
assert.NilError(t, f.stakingKeeper.SetParams(f.sdkCtx, params))
// initialize some validators into the state
powers := []int64{0, 100, 400, 400, 200}
@ -464,16 +493,16 @@ func TestFullValidatorSetPowerChange(t *testing.T) {
keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[i], true)
}
for i := range powers {
var found bool
validators[i], found = f.stakingKeeper.GetValidator(f.sdkCtx, validators[i].GetOperator())
assert.Assert(t, found)
validators[i], err = f.stakingKeeper.GetValidator(f.sdkCtx, validators[i].GetOperator())
assert.NilError(t, err)
}
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 := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
assert.NilError(t, err)
assert.Equal(t, max, len(resValidators))
assert.Assert(ValEq(t, validators[2], resValidators[0])) // in the order of txs
assert.Assert(ValEq(t, validators[3], resValidators[1]))
@ -483,7 +512,8 @@ func TestFullValidatorSetPowerChange(t *testing.T) {
tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 600)
validators[0], _ = validators[0].AddTokensFromDel(tokens)
validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], true)
resValidators = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx)
assert.NilError(t, err)
assert.Equal(t, max, len(resValidators))
assert.Assert(ValEq(t, validators[0], resValidators[0]))
assert.Assert(ValEq(t, validators[2], resValidators[1]))
@ -661,10 +691,11 @@ func TestApplyAndReturnValidatorSetUpdatesWithCliffValidator(t *testing.T) {
func TestApplyAndReturnValidatorSetUpdatesNewValidator(t *testing.T) {
f, _, _ := bootstrapValidatorTest(t, 1000, 20)
params := f.stakingKeeper.GetParams(f.sdkCtx)
params, err := f.stakingKeeper.GetParams(f.sdkCtx)
assert.NilError(t, err)
params.MaxValidators = uint32(3)
f.stakingKeeper.SetParams(f.sdkCtx, params)
assert.NilError(t, f.stakingKeeper.SetParams(f.sdkCtx, params))
powers := []int64{100, 100}
var validators [2]types.Validator
@ -739,10 +770,11 @@ func TestApplyAndReturnValidatorSetUpdatesNewValidator(t *testing.T) {
func TestApplyAndReturnValidatorSetUpdatesBondTransition(t *testing.T) {
f, _, _ := bootstrapValidatorTest(t, 1000, 20)
params := f.stakingKeeper.GetParams(f.sdkCtx)
params, err := f.stakingKeeper.GetParams(f.sdkCtx)
assert.NilError(t, err)
params.MaxValidators = uint32(2)
f.stakingKeeper.SetParams(f.sdkCtx, params)
assert.NilError(t, f.stakingKeeper.SetParams(f.sdkCtx, params))
powers := []int64{100, 200, 300}
var validators [3]types.Validator
@ -772,9 +804,8 @@ func TestApplyAndReturnValidatorSetUpdatesBondTransition(t *testing.T) {
// delegate to validator with lowest power but not enough to bond
f.sdkCtx = f.sdkCtx.WithBlockHeight(1)
var found bool
validators[0], found = f.stakingKeeper.GetValidator(f.sdkCtx, validators[0].GetOperator())
assert.Assert(t, found)
validators[0], err = f.stakingKeeper.GetValidator(f.sdkCtx, validators[0].GetOperator())
assert.NilError(t, err)
f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[0])
tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 1)
@ -789,8 +820,8 @@ func TestApplyAndReturnValidatorSetUpdatesBondTransition(t *testing.T) {
// lowest power in a single block context (height)
f.sdkCtx = f.sdkCtx.WithBlockHeight(2)
validators[1], found = f.stakingKeeper.GetValidator(f.sdkCtx, validators[1].GetOperator())
assert.Assert(t, found)
validators[1], err = f.stakingKeeper.GetValidator(f.sdkCtx, validators[1].GetOperator())
assert.NilError(t, err)
f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[0])
validators[0], _ = validators[0].RemoveDelShares(validators[0].DelegatorShares)

View File

@ -167,7 +167,8 @@ func (s *SimTestSuite) TestWeightedOperations() {
// Abonormal scenarios, where the message are created by an errors are not tested here.
func (s *SimTestSuite) TestSimulateMsgCreateValidator() {
require := s.Require()
s.app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: s.app.LastBlockHeight() + 1, Hash: s.app.LastCommitID().Hash})
_, err := s.app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: s.app.LastBlockHeight() + 1, Hash: s.app.LastCommitID().Hash})
require.NoError(err)
// execute operation
op := simulation.SimulateMsgCreateValidator(s.txConfig, s.accountKeeper, s.bankKeeper, s.stakingKeeper)
@ -201,17 +202,18 @@ func (s *SimTestSuite) TestSimulateMsgCancelUnbondingDelegation() {
validator0, issuedShares := validator0.AddTokensFromDel(delTokens)
delegator := s.accounts[2]
delegation := types.NewDelegation(delegator.Address, validator0.GetOperator(), issuedShares)
s.stakingKeeper.SetDelegation(ctx, delegation)
require.NoError(s.stakingKeeper.SetDelegation(ctx, delegation))
s.Require().NoError(s.distrKeeper.DelegatorStartingInfo.Set(ctx, collections.Join(validator0.GetOperator(), delegator.Address), distrtypes.NewDelegatorStartingInfo(2, math.LegacyOneDec(), 200)))
s.setupValidatorRewards(ctx, validator0.GetOperator())
// unbonding delegation
udb := types.NewUnbondingDelegation(delegator.Address, validator0.GetOperator(), s.app.LastBlockHeight()+1, blockTime.Add(2*time.Minute), delTokens, 0)
s.stakingKeeper.SetUnbondingDelegation(ctx, udb)
require.NoError(s.stakingKeeper.SetUnbondingDelegation(ctx, udb))
s.setupValidatorRewards(ctx, validator0.GetOperator())
s.app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: s.app.LastBlockHeight() + 1, Hash: s.app.LastCommitID().Hash, Time: blockTime})
_, err := s.app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: s.app.LastBlockHeight() + 1, Hash: s.app.LastCommitID().Hash, Time: blockTime})
require.NoError(err)
// execute operation
op := simulation.SimulateMsgCancelUnbondingDelegate(s.txConfig, s.accountKeeper, s.bankKeeper, s.stakingKeeper)
@ -239,7 +241,8 @@ func (s *SimTestSuite) TestSimulateMsgEditValidator() {
// setup accounts[0] as validator
_ = s.getTestingValidator0(ctx)
s.app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: s.app.LastBlockHeight() + 1, Hash: s.app.LastCommitID().Hash, Time: blockTime})
_, err := s.app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: s.app.LastBlockHeight() + 1, Hash: s.app.LastCommitID().Hash, Time: blockTime})
require.NoError(err)
// execute operation
op := simulation.SimulateMsgEditValidator(s.txConfig, s.accountKeeper, s.bankKeeper, s.stakingKeeper)
@ -293,12 +296,13 @@ func (s *SimTestSuite) TestSimulateMsgUndelegate() {
validator0, issuedShares := validator0.AddTokensFromDel(delTokens)
delegator := s.accounts[2]
delegation := types.NewDelegation(delegator.Address, validator0.GetOperator(), issuedShares)
s.stakingKeeper.SetDelegation(ctx, delegation)
require.NoError(s.stakingKeeper.SetDelegation(ctx, delegation))
s.Require().NoError(s.distrKeeper.DelegatorStartingInfo.Set(ctx, collections.Join(validator0.GetOperator(), delegator.Address), distrtypes.NewDelegatorStartingInfo(2, math.LegacyOneDec(), 200)))
s.setupValidatorRewards(ctx, validator0.GetOperator())
s.app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: s.app.LastBlockHeight() + 1, Hash: s.app.LastCommitID().Hash, Time: blockTime})
_, err := s.app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: s.app.LastBlockHeight() + 1, Hash: s.app.LastCommitID().Hash, Time: blockTime})
require.NoError(err)
// execute operation
op := simulation.SimulateMsgUndelegate(s.txConfig, s.accountKeeper, s.bankKeeper, s.stakingKeeper)
@ -334,14 +338,14 @@ func (s *SimTestSuite) TestSimulateMsgBeginRedelegate() {
// setup accounts[3] as delegator
delegator := s.accounts[3]
delegation := types.NewDelegation(delegator.Address, validator0.GetOperator(), issuedShares)
s.stakingKeeper.SetDelegation(ctx, delegation)
require.NoError(s.stakingKeeper.SetDelegation(ctx, delegation))
s.Require().NoError(s.distrKeeper.DelegatorStartingInfo.Set(ctx, collections.Join(validator0.GetOperator(), delegator.Address), distrtypes.NewDelegatorStartingInfo(2, math.LegacyOneDec(), 200)))
s.setupValidatorRewards(ctx, validator0.GetOperator())
s.setupValidatorRewards(ctx, validator1.GetOperator())
_, err := s.app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: s.app.LastBlockHeight() + 1, Hash: s.app.LastCommitID().Hash, Time: blockTime})
s.Require().NoError(err)
require.NoError(err)
// execute operation
op := simulation.SimulateMsgBeginRedelegate(s.txConfig, s.accountKeeper, s.bankKeeper, s.stakingKeeper)
@ -382,7 +386,7 @@ func (s *SimTestSuite) getTestingValidator(ctx sdk.Context, commission types.Com
validator.DelegatorShares = math.LegacyNewDec(100)
validator.Tokens = s.stakingKeeper.TokensFromConsensusPower(ctx, 100)
s.stakingKeeper.SetValidator(ctx, validator)
s.Require().NoError(s.stakingKeeper.SetValidator(ctx, validator))
return validator
}

View File

@ -2,6 +2,7 @@ package sims
import (
"bytes"
"context"
"encoding/hex"
"fmt"
"strconv"
@ -23,12 +24,16 @@ type GenerateAccountStrategy func(int) []sdk.AccAddress
// provides the staking bond denom. It is used in arguments in this package's
// functions so that a mock staking keeper can be passed instead of the real one.
type BondDenomProvider interface {
BondDenom(ctx sdk.Context) string
BondDenom(ctx context.Context) (string, error)
}
// AddTestAddrsFromPubKeys adds the addresses into the SimApp providing only the public keys.
func AddTestAddrsFromPubKeys(bankKeeper bankkeeper.Keeper, stakingKeeper BondDenomProvider, ctx sdk.Context, pubKeys []cryptotypes.PubKey, accAmt math.Int) {
initCoins := sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), accAmt))
bondDenom, err := stakingKeeper.BondDenom(ctx)
if err != nil {
panic(err)
}
initCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, accAmt))
for _, pk := range pubKeys {
initAccountWithCoins(bankKeeper, ctx, sdk.AccAddress(pk.Address()), initCoins)
@ -48,7 +53,11 @@ func AddTestAddrsIncremental(bankKeeper bankkeeper.Keeper, stakingKeeper BondDen
func addTestAddrs(bankKeeper bankkeeper.Keeper, stakingKeeper BondDenomProvider, ctx sdk.Context, accNum int, accAmt math.Int, strategy GenerateAccountStrategy) []sdk.AccAddress {
testAddrs := strategy(accNum)
initCoins := sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), accAmt))
bondDenom, err := stakingKeeper.BondDenom(ctx)
if err != nil {
panic(err)
}
initCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, accAmt))
for _, addr := range testAddrs {
initAccountWithCoins(bankKeeper, ctx, addr, initCoins)

View File

@ -19,13 +19,12 @@ func (k Keeper) AllocateTokens(ctx context.Context, totalPreviousPower int64, bo
// fetch and clear the collected fees for distribution, since this is
// called in BeginBlock, collected fees will be from the previous block
// (and distributed to the previous proposer)
sdkCtx := sdk.UnwrapSDKContext(ctx)
feeCollector := k.authKeeper.GetModuleAccount(ctx, k.feeCollectorName)
feesCollectedInt := k.bankKeeper.GetAllBalances(sdkCtx, feeCollector.GetAddress())
feesCollectedInt := k.bankKeeper.GetAllBalances(ctx, feeCollector.GetAddress())
feesCollected := sdk.NewDecCoinsFromCoins(feesCollectedInt...)
// transfer collected fees to the distribution module account
err := k.bankKeeper.SendCoinsFromModuleToModule(sdkCtx, k.feeCollectorName, types.ModuleName, feesCollectedInt)
err := k.bankKeeper.SendCoinsFromModuleToModule(ctx, k.feeCollectorName, types.ModuleName, feesCollectedInt)
if err != nil {
return err
}
@ -58,7 +57,10 @@ func (k Keeper) AllocateTokens(ctx context.Context, totalPreviousPower int64, bo
//
// Ref: https://github.com/cosmos/cosmos-sdk/pull/3099#discussion_r246276376
for _, vote := range bondedVotes {
validator := k.stakingKeeper.ValidatorByConsAddr(sdkCtx, vote.Validator.Address)
validator, err := k.stakingKeeper.ValidatorByConsAddr(ctx, vote.Validator.Address)
if err != nil {
return err
}
// TODO: Consider micro-slashing for missing votes.
//
@ -66,7 +68,7 @@ func (k Keeper) AllocateTokens(ctx context.Context, totalPreviousPower int64, bo
powerFraction := math.LegacyNewDec(vote.Validator.Power).QuoTruncate(math.LegacyNewDec(totalPreviousPower))
reward := feeMultiplier.MulDecTruncate(powerFraction)
err := k.AllocateTokensToValidator(ctx, validator, reward)
err = k.AllocateTokensToValidator(ctx, validator, reward)
if err != nil {
return err
}

View File

@ -53,7 +53,7 @@ func TestAllocateTokensToValidatorWithCommission(t *testing.T) {
val, err := distrtestutil.CreateValidator(valConsPk0, math.NewInt(100))
require.NoError(t, err)
val.Commission = stakingtypes.NewCommission(math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDec(0))
stakingKeeper.EXPECT().ValidatorByConsAddr(gomock.Any(), sdk.GetConsAddress(valConsPk0)).Return(val).AnyTimes()
stakingKeeper.EXPECT().ValidatorByConsAddr(gomock.Any(), sdk.GetConsAddress(valConsPk0)).Return(val, nil).AnyTimes()
// allocate tokens
tokens := sdk.DecCoins{
@ -111,14 +111,14 @@ func TestAllocateTokensToManyValidators(t *testing.T) {
val0, err := distrtestutil.CreateValidator(valConsPk0, math.NewInt(100))
require.NoError(t, err)
val0.Commission = stakingtypes.NewCommission(math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDec(0))
stakingKeeper.EXPECT().ValidatorByConsAddr(gomock.Any(), sdk.GetConsAddress(valConsPk0)).Return(val0).AnyTimes()
stakingKeeper.EXPECT().ValidatorByConsAddr(gomock.Any(), sdk.GetConsAddress(valConsPk0)).Return(val0, nil).AnyTimes()
// create second validator with 0% commission
valAddr1 := sdk.ValAddress(valConsAddr1)
val1, err := distrtestutil.CreateValidator(valConsPk1, math.NewInt(100))
require.NoError(t, err)
val1.Commission = stakingtypes.NewCommission(math.LegacyNewDec(0), math.LegacyNewDec(0), math.LegacyNewDec(0))
stakingKeeper.EXPECT().ValidatorByConsAddr(gomock.Any(), sdk.GetConsAddress(valConsPk1)).Return(val1).AnyTimes()
stakingKeeper.EXPECT().ValidatorByConsAddr(gomock.Any(), sdk.GetConsAddress(valConsPk1)).Return(val1, nil).AnyTimes()
abciValA := abci.Validator{
Address: valConsPk0.Address(),
@ -237,21 +237,21 @@ func TestAllocateTokensTruncation(t *testing.T) {
val0, err := distrtestutil.CreateValidator(valConsPk0, math.NewInt(100))
require.NoError(t, err)
val0.Commission = stakingtypes.NewCommission(math.LegacyNewDecWithPrec(1, 1), math.LegacyNewDecWithPrec(1, 1), math.LegacyNewDec(0))
stakingKeeper.EXPECT().ValidatorByConsAddr(gomock.Any(), sdk.GetConsAddress(valConsPk0)).Return(val0).AnyTimes()
stakingKeeper.EXPECT().ValidatorByConsAddr(gomock.Any(), sdk.GetConsAddress(valConsPk0)).Return(val0, nil).AnyTimes()
// create second validator with 10% commission
valAddr1 := sdk.ValAddress(valConsAddr1)
val1, err := distrtestutil.CreateValidator(valConsPk1, math.NewInt(100))
require.NoError(t, err)
val1.Commission = stakingtypes.NewCommission(math.LegacyNewDecWithPrec(1, 1), math.LegacyNewDecWithPrec(1, 1), math.LegacyNewDec(0))
stakingKeeper.EXPECT().ValidatorByConsAddr(gomock.Any(), sdk.GetConsAddress(valConsPk1)).Return(val1).AnyTimes()
stakingKeeper.EXPECT().ValidatorByConsAddr(gomock.Any(), sdk.GetConsAddress(valConsPk1)).Return(val1, nil).AnyTimes()
// create third validator with 10% commission
valAddr2 := sdk.ValAddress(valConsAddr2)
val2, err := stakingtypes.NewValidator(sdk.ValAddress(valConsAddr2), valConsPk1, stakingtypes.Description{})
require.NoError(t, err)
val2.Commission = stakingtypes.NewCommission(math.LegacyNewDecWithPrec(1, 1), math.LegacyNewDecWithPrec(1, 1), math.LegacyNewDec(0))
stakingKeeper.EXPECT().ValidatorByConsAddr(gomock.Any(), sdk.GetConsAddress(valConsPk2)).Return(val2).AnyTimes()
stakingKeeper.EXPECT().ValidatorByConsAddr(gomock.Any(), sdk.GetConsAddress(valConsPk2)).Return(val2, nil).AnyTimes()
abciValA := abci.Validator{
Address: valConsPk0.Address(),

View File

@ -23,16 +23,26 @@ func (k Keeper) initializeDelegation(ctx context.Context, val sdk.ValAddress, de
previousPeriod := valCurrentRewards.Period - 1
// increment reference count for the period we're going to track
k.incrementReferenceCount(ctx, val, previousPeriod)
err = k.incrementReferenceCount(ctx, val, previousPeriod)
if err != nil {
return err
}
sdkCtx := sdk.UnwrapSDKContext(ctx)
validator := k.stakingKeeper.Validator(sdkCtx, val)
delegation := k.stakingKeeper.Delegation(sdkCtx, del, val)
validator, err := k.stakingKeeper.Validator(ctx, val)
if err != nil {
return err
}
delegation, err := k.stakingKeeper.Delegation(ctx, del, val)
if err != nil {
return err
}
// calculate delegation stake in tokens
// we don't store directly, so multiply delegation shares * (tokens per share)
// note: necessary to truncate so we don't allow withdrawing more rewards than owed
stake := validator.TokensFromSharesTruncated(delegation.GetShares())
sdkCtx := sdk.UnwrapSDKContext(ctx)
return k.DelegatorStartingInfo.Set(ctx, collections.Join(val, del), types.NewDelegatorStartingInfo(previousPeriod, stake, uint64(sdkCtx.BlockHeight())))
}

View File

@ -59,8 +59,8 @@ func TestCalculateRewardsBasic(t *testing.T) {
// delegation mock
del := stakingtypes.NewDelegation(addr, valAddr, val.DelegatorShares)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val).Times(3)
stakingKeeper.EXPECT().Delegation(gomock.Any(), addr, valAddr).Return(del)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val, nil).Times(3)
stakingKeeper.EXPECT().Delegation(gomock.Any(), addr, valAddr).Return(del, nil)
// run the necessary hooks manually (given that we are not running an actual staking module)
err = distrtestutil.CallCreateValidatorHooks(ctx, distrKeeper, addr, valAddr)
@ -145,8 +145,8 @@ func TestCalculateRewardsAfterSlash(t *testing.T) {
del := stakingtypes.NewDelegation(addr, valAddr, val.DelegatorShares)
// set mock calls
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val).Times(4)
stakingKeeper.EXPECT().Delegation(gomock.Any(), addr, valAddr).Return(del)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val, nil).Times(4)
stakingKeeper.EXPECT().Delegation(gomock.Any(), addr, valAddr).Return(del, nil)
// run the necessary hooks manually (given that we are not running an actual staking module)
err = distrtestutil.CallCreateValidatorHooks(ctx, distrKeeper, addr, valAddr)
@ -244,8 +244,8 @@ func TestCalculateRewardsAfterManySlashes(t *testing.T) {
// delegation mocks
del := stakingtypes.NewDelegation(addr, valAddr, val.DelegatorShares)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val).Times(4)
stakingKeeper.EXPECT().Delegation(gomock.Any(), addr, valAddr).Return(del)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val, nil).Times(4)
stakingKeeper.EXPECT().Delegation(gomock.Any(), addr, valAddr).Return(del, nil)
// run the necessary hooks manually (given that we are not running an actual staking module)
err = distrtestutil.CallCreateValidatorHooks(ctx, distrKeeper, addr, valAddr)
@ -280,7 +280,7 @@ func TestCalculateRewardsAfterManySlashes(t *testing.T) {
require.True(t, slashedTokens.IsPositive(), "expected positive slashed tokens, got: %s", slashedTokens)
// expect a call for the next slash with the updated validator
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val).Times(1)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val, nil).Times(1)
// increase block height
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
@ -364,8 +364,8 @@ func TestCalculateRewardsMultiDelegator(t *testing.T) {
del0 := stakingtypes.NewDelegation(addr0, valAddr, val.DelegatorShares)
// set mock calls
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val).Times(4)
stakingKeeper.EXPECT().Delegation(gomock.Any(), addr0, valAddr).Return(del0).Times(1)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val, nil).Times(4)
stakingKeeper.EXPECT().Delegation(gomock.Any(), addr0, valAddr).Return(del0, nil).Times(1)
// run the necessary hooks manually (given that we are not running an actual staking module)
err = distrtestutil.CallCreateValidatorHooks(ctx, distrKeeper, addr0, valAddr)
@ -384,8 +384,8 @@ func TestCalculateRewardsMultiDelegator(t *testing.T) {
_, del1, err := distrtestutil.Delegate(ctx, distrKeeper, addr1, &val, math.NewInt(100), nil)
require.NoError(t, err)
stakingKeeper.EXPECT().Delegation(gomock.Any(), addr1, valAddr).Return(del1)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val).Times(1)
stakingKeeper.EXPECT().Delegation(gomock.Any(), addr1, valAddr).Return(del1, nil)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val, nil).Times(1)
// call necessary hooks to update a delegation
err = distrKeeper.Hooks().AfterDelegationModified(ctx, addr1, valAddr)
@ -458,8 +458,8 @@ func TestWithdrawDelegationRewardsBasic(t *testing.T) {
// delegation mock
del := stakingtypes.NewDelegation(addr, valAddr, val.DelegatorShares)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val).Times(5)
stakingKeeper.EXPECT().Delegation(gomock.Any(), addr, valAddr).Return(del).Times(3)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val, nil).Times(5)
stakingKeeper.EXPECT().Delegation(gomock.Any(), addr, valAddr).Return(del, nil).Times(3)
// run the necessary hooks manually (given that we are not running an actual staking module)
err = distrtestutil.CallCreateValidatorHooks(ctx, distrKeeper, addr, valAddr)
@ -531,8 +531,8 @@ func TestCalculateRewardsAfterManySlashesInSameBlock(t *testing.T) {
// delegation mock
del := stakingtypes.NewDelegation(addr, valAddr, val.DelegatorShares)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val).Times(5)
stakingKeeper.EXPECT().Delegation(gomock.Any(), addr, valAddr).Return(del)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val, nil).Times(5)
stakingKeeper.EXPECT().Delegation(gomock.Any(), addr, valAddr).Return(del, nil)
// run the necessary hooks manually (given that we are not running an actual staking module)
err = distrtestutil.CallCreateValidatorHooks(ctx, distrKeeper, addr, valAddr)
@ -644,13 +644,13 @@ func TestCalculateRewardsMultiDelegatorMultiSlash(t *testing.T) {
// validator and delegation mocks
del := stakingtypes.NewDelegation(addr, valAddr, val.DelegatorShares)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val).Times(3)
stakingKeeper.EXPECT().Delegation(gomock.Any(), addr, valAddr).Return(del)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val, nil).Times(3)
stakingKeeper.EXPECT().Delegation(gomock.Any(), addr, valAddr).Return(del, nil)
// run the necessary hooks manually (given that we are not running an actual staking module)
err = distrtestutil.CallCreateValidatorHooks(ctx, distrKeeper, addr, valAddr)
require.NoError(t, err)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val).Times(2)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val, nil).Times(2)
// next block
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
@ -674,7 +674,7 @@ func TestCalculateRewardsMultiDelegatorMultiSlash(t *testing.T) {
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
// update validator mock
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val).Times(1)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val, nil).Times(1)
// second delegation
_, del2, err := distrtestutil.Delegate(
@ -688,8 +688,8 @@ func TestCalculateRewardsMultiDelegatorMultiSlash(t *testing.T) {
require.NoError(t, err)
// new delegation mock and update validator mock
stakingKeeper.EXPECT().Delegation(gomock.Any(), sdk.AccAddress(valConsAddr1), valAddr).Return(del2)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val).Times(1)
stakingKeeper.EXPECT().Delegation(gomock.Any(), sdk.AccAddress(valConsAddr1), valAddr).Return(del2, nil)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val, nil).Times(1)
// call necessary hooks to update a delegation
err = distrKeeper.Hooks().AfterDelegationModified(ctx, sdk.AccAddress(valConsAddr1), valAddr)
@ -774,13 +774,13 @@ func TestCalculateRewardsMultiDelegatorMultWithdraw(t *testing.T) {
// validator and delegation mocks
del := stakingtypes.NewDelegation(addr, valAddr, val.DelegatorShares)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val).Times(3)
stakingKeeper.EXPECT().Delegation(gomock.Any(), addr, valAddr).Return(del).Times(5)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val, nil).Times(3)
stakingKeeper.EXPECT().Delegation(gomock.Any(), addr, valAddr).Return(del, nil).Times(5)
// run the necessary hooks manually (given that we are not running an actual staking module)
err = distrtestutil.CallCreateValidatorHooks(ctx, distrKeeper, addr, valAddr)
require.NoError(t, err)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val).Times(2)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val, nil).Times(2)
// next block
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
@ -805,8 +805,8 @@ func TestCalculateRewardsMultiDelegatorMultWithdraw(t *testing.T) {
require.NoError(t, err)
// new delegation mock and update validator mock
stakingKeeper.EXPECT().Delegation(gomock.Any(), sdk.AccAddress(valConsAddr1), valAddr).Return(del2).Times(3)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val).Times(6)
stakingKeeper.EXPECT().Delegation(gomock.Any(), sdk.AccAddress(valConsAddr1), valAddr).Return(del2, nil).Times(3)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val, nil).Times(6)
// call necessary hooks to update a delegation
err = distrKeeper.Hooks().AfterDelegationModified(ctx, sdk.AccAddress(valConsAddr1), valAddr)
@ -970,13 +970,13 @@ func Test100PercentCommissionReward(t *testing.T) {
// validator and delegation mocks
del := stakingtypes.NewDelegation(addr, valAddr, val.DelegatorShares)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val).Times(3)
stakingKeeper.EXPECT().Delegation(gomock.Any(), addr, valAddr).Return(del).Times(3)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val, nil).Times(3)
stakingKeeper.EXPECT().Delegation(gomock.Any(), addr, valAddr).Return(del, nil).Times(3)
// run the necessary hooks manually (given that we are not running an actual staking module)
err = distrtestutil.CallCreateValidatorHooks(ctx, distrKeeper, addr, valAddr)
require.NoError(t, err)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val).Times(2)
stakingKeeper.EXPECT().Validator(gomock.Any(), valAddr).Return(val, nil).Times(2)
// next block
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)

View File

@ -28,8 +28,8 @@ func NewQuerier(keeper Keeper) Querier {
}
// Params queries params of distribution module
func (k Querier) Params(c context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) {
params, err := k.Keeper.Params.Get(c)
func (k Querier) Params(ctx context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) {
params, err := k.Keeper.Params.Get(ctx)
if err != nil {
return nil, err
}
@ -38,7 +38,7 @@ func (k Querier) Params(c context.Context, req *types.QueryParamsRequest) (*type
}
// ValidatorDistributionInfo query validator's commission and self-delegation rewards
func (k Querier) ValidatorDistributionInfo(c context.Context, req *types.QueryValidatorDistributionInfoRequest) (*types.QueryValidatorDistributionInfoResponse, error) {
func (k Querier) ValidatorDistributionInfo(ctx context.Context, req *types.QueryValidatorDistributionInfoRequest) (*types.QueryValidatorDistributionInfoResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "invalid request")
}
@ -47,22 +47,28 @@ func (k Querier) ValidatorDistributionInfo(c context.Context, req *types.QueryVa
return nil, status.Error(codes.InvalidArgument, "empty validator address")
}
ctx := sdk.UnwrapSDKContext(c)
valAdr, err := sdk.ValAddressFromBech32(req.ValidatorAddress)
if err != nil {
return nil, err
}
// self-delegation rewards
val := k.stakingKeeper.Validator(ctx, valAdr)
val, err := k.stakingKeeper.Validator(ctx, valAdr)
if err != nil {
return nil, err
}
if val == nil {
return nil, errors.Wrap(types.ErrNoValidatorExists, req.ValidatorAddress)
}
delAdr := sdk.AccAddress(valAdr)
del := k.stakingKeeper.Delegation(ctx, delAdr, valAdr)
del, err := k.stakingKeeper.Delegation(ctx, delAdr, valAdr)
if err != nil {
return nil, err
}
if del == nil {
return nil, types.ErrNoDelegationExists
}
@ -91,7 +97,7 @@ func (k Querier) ValidatorDistributionInfo(c context.Context, req *types.QueryVa
}
// ValidatorOutstandingRewards queries rewards of a validator address
func (k Querier) ValidatorOutstandingRewards(c context.Context, req *types.QueryValidatorOutstandingRewardsRequest) (*types.QueryValidatorOutstandingRewardsResponse, error) {
func (k Querier) ValidatorOutstandingRewards(ctx context.Context, req *types.QueryValidatorOutstandingRewardsRequest) (*types.QueryValidatorOutstandingRewardsResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "invalid request")
}
@ -100,14 +106,16 @@ func (k Querier) ValidatorOutstandingRewards(c context.Context, req *types.Query
return nil, status.Error(codes.InvalidArgument, "empty validator address")
}
ctx := sdk.UnwrapSDKContext(c)
valAdr, err := sdk.ValAddressFromBech32(req.ValidatorAddress)
if err != nil {
return nil, err
}
validator := k.stakingKeeper.Validator(ctx, valAdr)
validator, err := k.stakingKeeper.Validator(ctx, valAdr)
if err != nil {
return nil, err
}
if validator == nil {
return nil, errors.Wrapf(types.ErrNoValidatorExists, valAdr.String())
}
@ -121,7 +129,7 @@ func (k Querier) ValidatorOutstandingRewards(c context.Context, req *types.Query
}
// ValidatorCommission queries accumulated commission for a validator
func (k Querier) ValidatorCommission(c context.Context, req *types.QueryValidatorCommissionRequest) (*types.QueryValidatorCommissionResponse, error) {
func (k Querier) ValidatorCommission(ctx context.Context, req *types.QueryValidatorCommissionRequest) (*types.QueryValidatorCommissionResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "invalid request")
}
@ -130,14 +138,16 @@ func (k Querier) ValidatorCommission(c context.Context, req *types.QueryValidato
return nil, status.Error(codes.InvalidArgument, "empty validator address")
}
ctx := sdk.UnwrapSDKContext(c)
valAdr, err := sdk.ValAddressFromBech32(req.ValidatorAddress)
if err != nil {
return nil, err
}
validator := k.stakingKeeper.Validator(ctx, valAdr)
validator, err := k.stakingKeeper.Validator(ctx, valAdr)
if err != nil {
return nil, err
}
if validator == nil {
return nil, errors.Wrapf(types.ErrNoValidatorExists, valAdr.String())
}
@ -150,7 +160,7 @@ func (k Querier) ValidatorCommission(c context.Context, req *types.QueryValidato
}
// ValidatorSlashes queries slash events of a validator
func (k Querier) ValidatorSlashes(c context.Context, req *types.QueryValidatorSlashesRequest) (*types.QueryValidatorSlashesResponse, error) {
func (k Querier) ValidatorSlashes(ctx context.Context, req *types.QueryValidatorSlashesRequest) (*types.QueryValidatorSlashesResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "invalid request")
}
@ -168,7 +178,7 @@ func (k Querier) ValidatorSlashes(c context.Context, req *types.QueryValidatorSl
return nil, status.Errorf(codes.InvalidArgument, "invalid validator address")
}
store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(c))
store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
slashesStore := prefix.NewStore(store, types.GetValidatorSlashEventPrefix(valAddr))
events, pageRes, err := query.GenericFilteredPaginate(k.cdc, slashesStore, req.Pagination, func(key []byte, result *types.ValidatorSlashEvent) (*types.ValidatorSlashEvent, error) {
@ -193,7 +203,7 @@ func (k Querier) ValidatorSlashes(c context.Context, req *types.QueryValidatorSl
}
// DelegationRewards the total rewards accrued by a delegation
func (k Querier) DelegationRewards(c context.Context, req *types.QueryDelegationRewardsRequest) (*types.QueryDelegationRewardsResponse, error) {
func (k Querier) DelegationRewards(ctx context.Context, req *types.QueryDelegationRewardsRequest) (*types.QueryDelegationRewardsResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "invalid request")
}
@ -206,14 +216,16 @@ func (k Querier) DelegationRewards(c context.Context, req *types.QueryDelegation
return nil, status.Error(codes.InvalidArgument, "empty validator address")
}
ctx := sdk.UnwrapSDKContext(c)
valAdr, err := sdk.ValAddressFromBech32(req.ValidatorAddress)
if err != nil {
return nil, err
}
val := k.stakingKeeper.Validator(ctx, valAdr)
val, err := k.stakingKeeper.Validator(ctx, valAdr)
if err != nil {
return nil, err
}
if val == nil {
return nil, errors.Wrap(types.ErrNoValidatorExists, req.ValidatorAddress)
}
@ -222,7 +234,11 @@ func (k Querier) DelegationRewards(c context.Context, req *types.QueryDelegation
if err != nil {
return nil, err
}
del := k.stakingKeeper.Delegation(ctx, delAdr, valAdr)
del, err := k.stakingKeeper.Delegation(ctx, delAdr, valAdr)
if err != nil {
return nil, err
}
if del == nil {
return nil, types.ErrNoDelegationExists
}
@ -241,7 +257,7 @@ func (k Querier) DelegationRewards(c context.Context, req *types.QueryDelegation
}
// DelegationTotalRewards the total rewards accrued by a each validator
func (k Querier) DelegationTotalRewards(c context.Context, req *types.QueryDelegationTotalRewardsRequest) (*types.QueryDelegationTotalRewardsResponse, error) {
func (k Querier) DelegationTotalRewards(ctx context.Context, req *types.QueryDelegationTotalRewardsRequest) (*types.QueryDelegationTotalRewardsResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "invalid request")
}
@ -250,8 +266,6 @@ func (k Querier) DelegationTotalRewards(c context.Context, req *types.QueryDeleg
return nil, status.Error(codes.InvalidArgument, "empty delegator address")
}
ctx := sdk.UnwrapSDKContext(c)
total := sdk.DecCoins{}
var delRewards []types.DelegationDelegatorReward
@ -260,11 +274,15 @@ func (k Querier) DelegationTotalRewards(c context.Context, req *types.QueryDeleg
return nil, err
}
k.stakingKeeper.IterateDelegations(
err = k.stakingKeeper.IterateDelegations(
ctx, delAdr,
func(_ int64, del stakingtypes.DelegationI) (stop bool) {
valAddr := del.GetValidatorAddr()
val := k.stakingKeeper.Validator(ctx, valAddr)
val, err := k.stakingKeeper.Validator(ctx, valAddr)
if err != nil {
panic(err)
}
endingPeriod, err := k.IncrementValidatorPeriod(ctx, val)
if err != nil {
panic(err)
@ -280,12 +298,15 @@ func (k Querier) DelegationTotalRewards(c context.Context, req *types.QueryDeleg
return false
},
)
if err != nil {
return nil, err
}
return &types.QueryDelegationTotalRewardsResponse{Rewards: delRewards, Total: total}, nil
}
// DelegatorValidators queries the validators list of a delegator
func (k Querier) DelegatorValidators(c context.Context, req *types.QueryDelegatorValidatorsRequest) (*types.QueryDelegatorValidatorsResponse, error) {
func (k Querier) DelegatorValidators(ctx context.Context, req *types.QueryDelegatorValidatorsRequest) (*types.QueryDelegatorValidatorsResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "invalid request")
}
@ -294,14 +315,13 @@ func (k Querier) DelegatorValidators(c context.Context, req *types.QueryDelegato
return nil, status.Error(codes.InvalidArgument, "empty delegator address")
}
ctx := sdk.UnwrapSDKContext(c)
delAdr, err := k.authKeeper.AddressCodec().StringToBytes(req.DelegatorAddress)
if err != nil {
return nil, err
}
var validators []string
k.stakingKeeper.IterateDelegations(
err = k.stakingKeeper.IterateDelegations(
ctx, delAdr,
func(_ int64, del stakingtypes.DelegationI) (stop bool) {
validators = append(validators, del.GetValidatorAddr().String())
@ -309,11 +329,15 @@ func (k Querier) DelegatorValidators(c context.Context, req *types.QueryDelegato
},
)
if err != nil {
return nil, err
}
return &types.QueryDelegatorValidatorsResponse{Validators: validators}, nil
}
// DelegatorWithdrawAddress queries Query/delegatorWithdrawAddress
func (k Querier) DelegatorWithdrawAddress(c context.Context, req *types.QueryDelegatorWithdrawAddressRequest) (*types.QueryDelegatorWithdrawAddressResponse, error) {
func (k Querier) DelegatorWithdrawAddress(ctx context.Context, req *types.QueryDelegatorWithdrawAddressRequest) (*types.QueryDelegatorWithdrawAddressResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "invalid request")
}
@ -326,7 +350,7 @@ func (k Querier) DelegatorWithdrawAddress(c context.Context, req *types.QueryDel
return nil, err
}
withdrawAddr, err := k.GetDelegatorWithdrawAddr(c, delAdr)
withdrawAddr, err := k.GetDelegatorWithdrawAddr(ctx, delAdr)
if err != nil {
return nil, err
}
@ -335,8 +359,8 @@ func (k Querier) DelegatorWithdrawAddress(c context.Context, req *types.QueryDel
}
// CommunityPool queries the community pool coins
func (k Querier) CommunityPool(c context.Context, req *types.QueryCommunityPoolRequest) (*types.QueryCommunityPoolResponse, error) {
pool, err := k.FeePool.Get(c)
func (k Querier) CommunityPool(ctx context.Context, req *types.QueryCommunityPoolRequest) (*types.QueryCommunityPoolResponse, error) {
pool, err := k.FeePool.Get(ctx)
if err != nil {
return nil, err
}

View File

@ -1,6 +1,7 @@
package keeper
import (
"context"
"errors"
"cosmossdk.io/collections"
@ -24,13 +25,16 @@ func (k Keeper) Hooks() Hooks {
}
// initialize validator distribution record
func (h Hooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) error {
val := h.k.stakingKeeper.Validator(ctx, valAddr)
func (h Hooks) AfterValidatorCreated(ctx context.Context, valAddr sdk.ValAddress) error {
val, err := h.k.stakingKeeper.Validator(ctx, valAddr)
if err != nil {
return err
}
return h.k.initializeValidator(ctx, val)
}
// AfterValidatorRemoved performs clean up after a validator is removed
func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, _ sdk.ConsAddress, valAddr sdk.ValAddress) error {
func (h Hooks) AfterValidatorRemoved(ctx context.Context, _ sdk.ConsAddress, valAddr sdk.ValAddress) error {
// fetch outstanding
outstanding, err := h.k.GetValidatorOutstandingRewardsCoins(ctx, valAddr)
if err != nil {
@ -120,16 +124,27 @@ func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, _ sdk.ConsAddress, valAddr
}
// increment period
func (h Hooks) BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error {
val := h.k.stakingKeeper.Validator(ctx, valAddr)
_, err := h.k.IncrementValidatorPeriod(ctx, val)
func (h Hooks) BeforeDelegationCreated(ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error {
val, err := h.k.stakingKeeper.Validator(ctx, valAddr)
if err != nil {
return err
}
_, err = h.k.IncrementValidatorPeriod(ctx, val)
return err
}
// withdraw delegation rewards (which also increments period)
func (h Hooks) BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error {
val := h.k.stakingKeeper.Validator(ctx, valAddr)
del := h.k.stakingKeeper.Delegation(ctx, delAddr, valAddr)
func (h Hooks) BeforeDelegationSharesModified(ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error {
val, err := h.k.stakingKeeper.Validator(ctx, valAddr)
if err != nil {
return err
}
del, err := h.k.stakingKeeper.Delegation(ctx, delAddr, valAddr)
if err != nil {
return err
}
if _, err := h.k.withdrawDelegationRewards(ctx, val, del); err != nil {
return err
@ -139,32 +154,32 @@ func (h Hooks) BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAd
}
// create new delegation period record
func (h Hooks) AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error {
func (h Hooks) AfterDelegationModified(ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error {
return h.k.initializeDelegation(ctx, valAddr, delAddr)
}
// record the slash event
func (h Hooks) BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, fraction sdkmath.LegacyDec) error {
func (h Hooks) BeforeValidatorSlashed(ctx context.Context, valAddr sdk.ValAddress, fraction sdkmath.LegacyDec) error {
h.k.updateValidatorSlashFraction(ctx, valAddr, fraction)
return nil
}
func (h Hooks) BeforeValidatorModified(_ sdk.Context, _ sdk.ValAddress) error {
func (h Hooks) BeforeValidatorModified(_ context.Context, _ sdk.ValAddress) error {
return nil
}
func (h Hooks) AfterValidatorBonded(_ sdk.Context, _ sdk.ConsAddress, _ sdk.ValAddress) error {
func (h Hooks) AfterValidatorBonded(_ context.Context, _ sdk.ConsAddress, _ sdk.ValAddress) error {
return nil
}
func (h Hooks) AfterValidatorBeginUnbonding(_ sdk.Context, _ sdk.ConsAddress, _ sdk.ValAddress) error {
func (h Hooks) AfterValidatorBeginUnbonding(_ context.Context, _ sdk.ConsAddress, _ sdk.ValAddress) error {
return nil
}
func (h Hooks) BeforeDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) error {
func (h Hooks) BeforeDelegationRemoved(_ context.Context, _ sdk.AccAddress, _ sdk.ValAddress) error {
return nil
}
func (h Hooks) AfterUnbondingInitiated(_ sdk.Context, _ uint64) error {
func (h Hooks) AfterUnbondingInitiated(_ context.Context, _ uint64) error {
return nil
}

View File

@ -75,13 +75,18 @@ func CanWithdrawInvariant(k Keeper) sdk.Invariant {
var remaining sdk.DecCoins
valDelegationAddrs := make(map[string][]sdk.AccAddress)
for _, del := range k.stakingKeeper.GetAllSDKDelegations(ctx) {
allDelegations, err := k.stakingKeeper.GetAllSDKDelegations(ctx)
if err != nil {
panic(err)
}
for _, del := range allDelegations {
valAddr := del.GetValidatorAddr().String()
valDelegationAddrs[valAddr] = append(valDelegationAddrs[valAddr], del.GetDelegatorAddr())
}
// iterate over all validators
k.stakingKeeper.IterateValidators(ctx, func(_ int64, val stakingtypes.ValidatorI) (stop bool) {
err = k.stakingKeeper.IterateValidators(ctx, func(_ int64, val stakingtypes.ValidatorI) (stop bool) {
_, _ = k.WithdrawValidatorCommission(ctx, val.GetOperator())
delegationAddrs, ok := valDelegationAddrs[val.GetOperator().String()]
@ -105,6 +110,9 @@ func CanWithdrawInvariant(k Keeper) sdk.Invariant {
return false
})
if err != nil {
panic(err)
}
broken := len(remaining) > 0 && remaining[0].Amount.IsNegative()
return sdk.FormatInvariant(types.ModuleName, "can withdraw",
@ -116,11 +124,19 @@ func CanWithdrawInvariant(k Keeper) sdk.Invariant {
func ReferenceCountInvariant(k Keeper) sdk.Invariant {
return func(ctx sdk.Context) (string, bool) {
valCount := uint64(0)
k.stakingKeeper.IterateValidators(ctx, func(_ int64, val stakingtypes.ValidatorI) (stop bool) {
err := k.stakingKeeper.IterateValidators(ctx, func(_ int64, val stakingtypes.ValidatorI) (stop bool) {
valCount++
return false
})
dels := k.stakingKeeper.GetAllSDKDelegations(ctx)
if err != nil {
panic(err)
}
dels, err := k.stakingKeeper.GetAllSDKDelegations(ctx)
if err != nil {
panic(err)
}
slashCount := uint64(0)
k.IterateValidatorSlashEvents(ctx,
func(_ sdk.ValAddress, _ uint64, _ types.ValidatorSlashEvent) (stop bool) {

View File

@ -146,25 +146,32 @@ func (k Keeper) SetWithdrawAddr(ctx context.Context, delegatorAddr, withdrawAddr
// withdraw rewards from a delegation
func (k Keeper) WithdrawDelegationRewards(ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) (sdk.Coins, error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
val := k.stakingKeeper.Validator(sdkCtx, valAddr)
val, err := k.stakingKeeper.Validator(ctx, valAddr)
if err != nil {
return nil, err
}
if val == nil {
return nil, types.ErrNoValidatorDistInfo
}
del := k.stakingKeeper.Delegation(sdkCtx, delAddr, valAddr)
del, err := k.stakingKeeper.Delegation(ctx, delAddr, valAddr)
if err != nil {
return nil, err
}
if del == nil {
return nil, types.ErrEmptyDelegationDistInfo
}
// withdraw rewards
rewards, err := k.withdrawDelegationRewards(sdkCtx, val, del)
rewards, err := k.withdrawDelegationRewards(ctx, val, del)
if err != nil {
return nil, err
}
// reinitialize the delegation
err = k.initializeDelegation(sdkCtx, valAddr, delAddr)
err = k.initializeDelegation(ctx, valAddr, delAddr)
if err != nil {
return nil, err
}

View File

@ -183,8 +183,11 @@ func (k msgServer) DepositValidatorRewardsPool(ctx context.Context, msg *types.M
return nil, err
}
sdkCtx := sdk.UnwrapSDKContext(ctx)
validator := k.stakingKeeper.Validator(sdkCtx, valAddr)
validator, err := k.stakingKeeper.Validator(ctx, valAddr)
if err != nil {
return nil, err
}
if validator == nil {
return nil, errors.Wrapf(types.ErrNoValidatorExists, valAddr.String())
}

View File

@ -147,7 +147,10 @@ func (k Keeper) updateValidatorSlashFraction(ctx context.Context, valAddr sdk.Va
}
sdkCtx := sdk.UnwrapSDKContext(ctx)
val := k.stakingKeeper.Validator(sdkCtx, valAddr)
val, err := k.stakingKeeper.Validator(ctx, valAddr)
if err != nil {
return err
}
// increment current period
newPeriod, err := k.IncrementValidatorPeriod(ctx, val)

View File

@ -126,14 +126,20 @@ func SimulateMsgWithdrawDelegatorReward(txConfig client.TxConfig, ak types.Accou
r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string,
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
simAccount, _ := simtypes.RandomAcc(r, accs)
delegations := sk.GetAllDelegatorDelegations(ctx, simAccount.Address)
delegations, err := sk.GetAllDelegatorDelegations(ctx, simAccount.Address)
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawDelegatorReward{}), "error getting delegations"), nil, err
}
if len(delegations) == 0 {
return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawDelegatorReward{}), "number of delegators equal 0"), nil, nil
}
delegation := delegations[r.Intn(len(delegations))]
validator := sk.Validator(ctx, delegation.GetValidatorAddr())
validator, err := sk.Validator(ctx, delegation.GetValidatorAddr())
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawDelegatorReward{}), "error getting validator"), nil, err
}
if validator == nil {
return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawDelegatorReward{}), "validator is nil"), nil, fmt.Errorf("validator %s not found", delegation.GetValidatorAddr())
}
@ -168,7 +174,12 @@ func SimulateMsgWithdrawValidatorCommission(txConfig client.TxConfig, ak types.A
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
msgType := sdk.MsgTypeURL(&types.MsgWithdrawValidatorCommission{})
validator, ok := testutil.RandSliceElem(r, sk.GetAllValidators(ctx))
allVals, err := sk.GetAllValidators(ctx)
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting all validators"), nil, err
}
validator, ok := testutil.RandSliceElem(r, allVals)
if !ok {
return simtypes.NoOpMsg(types.ModuleName, msgType, "random validator is not ok"), nil, nil
}

View File

@ -267,7 +267,8 @@ func (suite *SimTestSuite) SetupTest() {
suite.ctx = suite.app.BaseApp.NewContext(false)
genesisVals := suite.stakingKeeper.GetAllValidators(suite.ctx)
genesisVals, err := suite.stakingKeeper.GetAllValidators(suite.ctx)
suite.Require().NoError(err)
suite.Require().Len(genesisVals, 1)
suite.genesisVals = genesisVals
}

View File

@ -236,11 +236,12 @@ func (m *MockStakingKeeper) EXPECT() *MockStakingKeeperMockRecorder {
}
// Delegation mocks base method.
func (m *MockStakingKeeper) Delegation(arg0 types.Context, arg1 types.AccAddress, arg2 types.ValAddress) types0.DelegationI {
func (m *MockStakingKeeper) Delegation(arg0 context.Context, arg1 types.AccAddress, arg2 types.ValAddress) (types0.DelegationI, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Delegation", arg0, arg1, arg2)
ret0, _ := ret[0].(types0.DelegationI)
return ret0
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Delegation indicates an expected call of Delegation.
@ -250,11 +251,12 @@ func (mr *MockStakingKeeperMockRecorder) Delegation(arg0, arg1, arg2 interface{}
}
// GetAllDelegatorDelegations mocks base method.
func (m *MockStakingKeeper) GetAllDelegatorDelegations(ctx types.Context, delegator types.AccAddress) []types0.Delegation {
func (m *MockStakingKeeper) GetAllDelegatorDelegations(ctx context.Context, delegator types.AccAddress) ([]types0.Delegation, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetAllDelegatorDelegations", ctx, delegator)
ret0, _ := ret[0].([]types0.Delegation)
return ret0
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetAllDelegatorDelegations indicates an expected call of GetAllDelegatorDelegations.
@ -264,11 +266,12 @@ func (mr *MockStakingKeeperMockRecorder) GetAllDelegatorDelegations(ctx, delegat
}
// GetAllSDKDelegations mocks base method.
func (m *MockStakingKeeper) GetAllSDKDelegations(ctx types.Context) []types0.Delegation {
func (m *MockStakingKeeper) GetAllSDKDelegations(ctx context.Context) ([]types0.Delegation, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetAllSDKDelegations", ctx)
ret0, _ := ret[0].([]types0.Delegation)
return ret0
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetAllSDKDelegations indicates an expected call of GetAllSDKDelegations.
@ -278,11 +281,12 @@ func (mr *MockStakingKeeperMockRecorder) GetAllSDKDelegations(ctx interface{}) *
}
// GetAllValidators mocks base method.
func (m *MockStakingKeeper) GetAllValidators(ctx types.Context) []types0.Validator {
func (m *MockStakingKeeper) GetAllValidators(ctx context.Context) ([]types0.Validator, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetAllValidators", ctx)
ret0, _ := ret[0].([]types0.Validator)
return ret0
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetAllValidators indicates an expected call of GetAllValidators.
@ -292,9 +296,11 @@ func (mr *MockStakingKeeperMockRecorder) GetAllValidators(ctx interface{}) *gomo
}
// IterateDelegations mocks base method.
func (m *MockStakingKeeper) IterateDelegations(ctx types.Context, delegator types.AccAddress, fn func(int64, types0.DelegationI) bool) {
func (m *MockStakingKeeper) IterateDelegations(ctx context.Context, delegator types.AccAddress, fn func(int64, types0.DelegationI) bool) error {
m.ctrl.T.Helper()
m.ctrl.Call(m, "IterateDelegations", ctx, delegator, fn)
ret := m.ctrl.Call(m, "IterateDelegations", ctx, delegator, fn)
ret0, _ := ret[0].(error)
return ret0
}
// IterateDelegations indicates an expected call of IterateDelegations.
@ -304,9 +310,11 @@ func (mr *MockStakingKeeperMockRecorder) IterateDelegations(ctx, delegator, fn i
}
// IterateValidators mocks base method.
func (m *MockStakingKeeper) IterateValidators(arg0 types.Context, arg1 func(int64, types0.ValidatorI) bool) {
func (m *MockStakingKeeper) IterateValidators(arg0 context.Context, arg1 func(int64, types0.ValidatorI) bool) error {
m.ctrl.T.Helper()
m.ctrl.Call(m, "IterateValidators", arg0, arg1)
ret := m.ctrl.Call(m, "IterateValidators", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// IterateValidators indicates an expected call of IterateValidators.
@ -316,11 +324,12 @@ func (mr *MockStakingKeeperMockRecorder) IterateValidators(arg0, arg1 interface{
}
// Validator mocks base method.
func (m *MockStakingKeeper) Validator(arg0 types.Context, arg1 types.ValAddress) types0.ValidatorI {
func (m *MockStakingKeeper) Validator(arg0 context.Context, arg1 types.ValAddress) (types0.ValidatorI, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Validator", arg0, arg1)
ret0, _ := ret[0].(types0.ValidatorI)
return ret0
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Validator indicates an expected call of Validator.
@ -330,11 +339,12 @@ func (mr *MockStakingKeeperMockRecorder) Validator(arg0, arg1 interface{}) *gomo
}
// ValidatorByConsAddr mocks base method.
func (m *MockStakingKeeper) ValidatorByConsAddr(arg0 types.Context, arg1 types.ConsAddress) types0.ValidatorI {
func (m *MockStakingKeeper) ValidatorByConsAddr(arg0 context.Context, arg1 types.ConsAddress) (types0.ValidatorI, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ValidatorByConsAddr", arg0, arg1)
ret0, _ := ret[0].(types0.ValidatorI)
return ret0
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ValidatorByConsAddr indicates an expected call of ValidatorByConsAddr.
@ -367,9 +377,11 @@ func (m *MockStakingHooks) EXPECT() *MockStakingHooksMockRecorder {
}
// AfterDelegationModified mocks base method.
func (m *MockStakingHooks) AfterDelegationModified(ctx types.Context, delAddr types.AccAddress, valAddr types.ValAddress) {
func (m *MockStakingHooks) AfterDelegationModified(ctx context.Context, delAddr types.AccAddress, valAddr types.ValAddress) error {
m.ctrl.T.Helper()
m.ctrl.Call(m, "AfterDelegationModified", ctx, delAddr, valAddr)
ret := m.ctrl.Call(m, "AfterDelegationModified", ctx, delAddr, valAddr)
ret0, _ := ret[0].(error)
return ret0
}
// AfterDelegationModified indicates an expected call of AfterDelegationModified.
@ -379,9 +391,11 @@ func (mr *MockStakingHooksMockRecorder) AfterDelegationModified(ctx, delAddr, va
}
// AfterValidatorCreated mocks base method.
func (m *MockStakingHooks) AfterValidatorCreated(ctx types.Context, valAddr types.ValAddress) {
func (m *MockStakingHooks) AfterValidatorCreated(ctx context.Context, valAddr types.ValAddress) error {
m.ctrl.T.Helper()
m.ctrl.Call(m, "AfterValidatorCreated", ctx, valAddr)
ret := m.ctrl.Call(m, "AfterValidatorCreated", ctx, valAddr)
ret0, _ := ret[0].(error)
return ret0
}
// AfterValidatorCreated indicates an expected call of AfterValidatorCreated.

View File

@ -35,26 +35,26 @@ type BankKeeper interface {
// StakingKeeper expected staking keeper (noalias)
type StakingKeeper interface {
// iterate through validators by operator address, execute func for each validator
IterateValidators(sdk.Context,
func(index int64, validator stakingtypes.ValidatorI) (stop bool))
IterateValidators(context.Context,
func(index int64, validator stakingtypes.ValidatorI) (stop bool)) error
Validator(sdk.Context, sdk.ValAddress) stakingtypes.ValidatorI // get a particular validator by operator address
ValidatorByConsAddr(sdk.Context, sdk.ConsAddress) stakingtypes.ValidatorI // get a particular validator by consensus address
Validator(context.Context, sdk.ValAddress) (stakingtypes.ValidatorI, error) // get a particular validator by operator address
ValidatorByConsAddr(context.Context, sdk.ConsAddress) (stakingtypes.ValidatorI, error) // get a particular validator by consensus address
// Delegation allows for getting a particular delegation for a given validator
// and delegator outside the scope of the staking module.
Delegation(sdk.Context, sdk.AccAddress, sdk.ValAddress) stakingtypes.DelegationI
Delegation(context.Context, sdk.AccAddress, sdk.ValAddress) (stakingtypes.DelegationI, error)
IterateDelegations(ctx sdk.Context, delegator sdk.AccAddress,
fn func(index int64, delegation stakingtypes.DelegationI) (stop bool))
IterateDelegations(ctx context.Context, delegator sdk.AccAddress,
fn func(index int64, delegation stakingtypes.DelegationI) (stop bool)) error
GetAllSDKDelegations(ctx sdk.Context) []stakingtypes.Delegation
GetAllValidators(ctx sdk.Context) (validators []stakingtypes.Validator)
GetAllDelegatorDelegations(ctx sdk.Context, delegator sdk.AccAddress) []stakingtypes.Delegation
GetAllSDKDelegations(ctx context.Context) ([]stakingtypes.Delegation, error)
GetAllValidators(ctx context.Context) ([]stakingtypes.Validator, error)
GetAllDelegatorDelegations(ctx context.Context, delegator sdk.AccAddress) ([]stakingtypes.Delegation, error)
}
// StakingHooks event hooks for staking validator object (noalias)
type StakingHooks interface {
AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) // Must be called when a validator is created
AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress)
AfterValidatorCreated(ctx context.Context, valAddr sdk.ValAddress) error // Must be called when a validator is created
AfterDelegationModified(ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error
}

View File

@ -13,7 +13,7 @@ require (
cosmossdk.io/store v0.1.0-alpha.1.0.20230606190835-3e18f4088b2c
github.com/cometbft/cometbft v0.38.0-rc1
github.com/cosmos/cosmos-proto v1.0.0-beta.3
github.com/cosmos/cosmos-sdk v0.46.0-beta2.0.20230614103911-b3da8bb4e801
github.com/cosmos/cosmos-sdk v0.46.0-beta2.0.20230616095813-1111e0b51118
github.com/cosmos/gogoproto v1.4.10
github.com/golang/mock v1.6.0
github.com/golang/protobuf v1.5.3

View File

@ -177,6 +177,8 @@ github.com/cosmos/cosmos-proto v1.0.0-beta.3 h1:VitvZ1lPORTVxkmF2fAp3IiA61xVwArQ
github.com/cosmos/cosmos-proto v1.0.0-beta.3/go.mod h1:t8IASdLaAq+bbHbjq4p960BvcTqtwuAxid3b/2rOD6I=
github.com/cosmos/cosmos-sdk v0.46.0-beta2.0.20230614103911-b3da8bb4e801 h1:Qg0EgcEYtN0RWmxaFWTTCeMDfnbHB6UEzHucafy14i8=
github.com/cosmos/cosmos-sdk v0.46.0-beta2.0.20230614103911-b3da8bb4e801/go.mod h1:VwFzgpv4z/Mrx+0sQpWwURCHx4h/iAalMdKIe3VEyBw=
github.com/cosmos/cosmos-sdk v0.46.0-beta2.0.20230616095813-1111e0b51118 h1:XIBDrJ25Sv4nnO6LspwXQkiMYnlo7j52XCl2KzBMjoQ=
github.com/cosmos/cosmos-sdk v0.46.0-beta2.0.20230616095813-1111e0b51118/go.mod h1:dtE3e607fUxLeDcDwSzKycM0lat8U5BbK/wsAmFk7HI=
github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY=
github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw=
github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE=

View File

@ -26,10 +26,13 @@ import (
// in the case of a lunatic attack.
func (k Keeper) handleEquivocationEvidence(ctx context.Context, evidence *types.Equivocation) error {
sdkCtx := sdk.UnwrapSDKContext(ctx)
logger := k.Logger(sdkCtx)
logger := k.Logger(ctx)
consAddr := evidence.GetConsensusAddress()
validator := k.stakingKeeper.ValidatorByConsAddr(sdkCtx, consAddr)
validator, err := k.stakingKeeper.ValidatorByConsAddr(ctx, consAddr)
if err != nil {
return err
}
if validator == nil || validator.IsUnbonded() {
// Defensive: Simulation doesn't take unbonding periods into account, and
// CometBFT might break this assumption at some point.

View File

@ -41,11 +41,12 @@ func (m *MockStakingKeeper) EXPECT() *MockStakingKeeperMockRecorder {
}
// GetParams mocks base method.
func (m *MockStakingKeeper) GetParams(ctx types0.Context) types1.Params {
func (m *MockStakingKeeper) GetParams(ctx context.Context) (types1.Params, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetParams", ctx)
ret0, _ := ret[0].(types1.Params)
return ret0
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetParams indicates an expected call of GetParams.
@ -55,11 +56,12 @@ func (mr *MockStakingKeeperMockRecorder) GetParams(ctx interface{}) *gomock.Call
}
// ValidatorByConsAddr mocks base method.
func (m *MockStakingKeeper) ValidatorByConsAddr(arg0 types0.Context, arg1 types0.ConsAddress) types1.ValidatorI {
func (m *MockStakingKeeper) ValidatorByConsAddr(arg0 context.Context, arg1 types0.ConsAddress) (types1.ValidatorI, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ValidatorByConsAddr", arg0, arg1)
ret0, _ := ret[0].(types1.ValidatorI)
return ret0
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ValidatorByConsAddr indicates an expected call of ValidatorByConsAddr.

View File

@ -16,8 +16,8 @@ type (
// StakingKeeper defines the staking module interface contract needed by the
// evidence module.
StakingKeeper interface {
ValidatorByConsAddr(sdk.Context, sdk.ConsAddress) stakingtypes.ValidatorI
GetParams(ctx sdk.Context) (params stakingtypes.Params)
ValidatorByConsAddr(context.Context, sdk.ConsAddress) (stakingtypes.ValidatorI, error)
GetParams(ctx context.Context) (params stakingtypes.Params, err error)
}
// SlashingKeeper defines the slashing module interface contract needed by the

View File

@ -40,7 +40,7 @@ func (m *MockStakingKeeper) EXPECT() *MockStakingKeeperMockRecorder {
}
// ApplyAndReturnValidatorSetUpdates mocks base method.
func (m *MockStakingKeeper) ApplyAndReturnValidatorSetUpdates(arg0 types0.Context) ([]types.ValidatorUpdate, error) {
func (m *MockStakingKeeper) ApplyAndReturnValidatorSetUpdates(arg0 context.Context) ([]types.ValidatorUpdate, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ApplyAndReturnValidatorSetUpdates", arg0)
ret0, _ := ret[0].([]types.ValidatorUpdate)

View File

@ -13,7 +13,7 @@ import (
// StakingKeeper defines the expected staking keeper (noalias)
type StakingKeeper interface {
ApplyAndReturnValidatorSetUpdates(sdk.Context) (updates []abci.ValidatorUpdate, err error)
ApplyAndReturnValidatorSetUpdates(context.Context) (updates []abci.ValidatorUpdate, err error)
}
// AccountKeeper defines the expected account keeper (noalias)

View File

@ -95,10 +95,10 @@ func setupGovKeeper(t *testing.T) (
return sdk.TokensFromConsensusPower(power, math.NewIntFromUint64(1000000))
}).AnyTimes()
stakingKeeper.EXPECT().BondDenom(ctx).Return("stake").AnyTimes()
stakingKeeper.EXPECT().BondDenom(ctx).Return("stake", nil).AnyTimes()
stakingKeeper.EXPECT().IterateBondedValidatorsByPower(gomock.Any(), gomock.Any()).AnyTimes()
stakingKeeper.EXPECT().IterateDelegations(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
stakingKeeper.EXPECT().TotalBondedTokens(gomock.Any()).Return(math.NewInt(10000000)).AnyTimes()
stakingKeeper.EXPECT().TotalBondedTokens(gomock.Any()).Return(math.NewInt(10000000), nil).AnyTimes()
distributionKeeper.EXPECT().FundCommunityPool(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
// Gov keeper initializations

View File

@ -28,8 +28,7 @@ func (keeper Keeper) Tally(ctx context.Context, proposal v1.Proposal) (passes, b
currValidators := make(map[string]v1.ValidatorGovInfo)
// fetch all the bonded validators, insert them into currValidators
sdkCtx := sdk.UnwrapSDKContext(ctx)
keeper.sk.IterateBondedValidatorsByPower(sdkCtx, func(index int64, validator stakingtypes.ValidatorI) (stop bool) {
err = keeper.sk.IterateBondedValidatorsByPower(ctx, func(index int64, validator stakingtypes.ValidatorI) (stop bool) {
currValidators[validator.GetOperator().String()] = v1.NewValidatorGovInfo(
validator.GetOperator(),
validator.GetBondedTokens(),
@ -40,6 +39,10 @@ func (keeper Keeper) Tally(ctx context.Context, proposal v1.Proposal) (passes, b
return false
})
if err != nil {
return false, false, tallyResults, err
}
rng := collections.NewPrefixedPairRange[uint64, sdk.AccAddress](proposal.Id)
err = keeper.Votes.Walk(ctx, rng, func(key collections.Pair[uint64, sdk.AccAddress], vote v1.Vote) (bool, error) {
// if validator, just record it in the map
@ -55,7 +58,7 @@ func (keeper Keeper) Tally(ctx context.Context, proposal v1.Proposal) (passes, b
}
// iterate over all delegations from voter, deduct from any delegated-to validators
keeper.sk.IterateDelegations(sdkCtx, voter, func(index int64, delegation stakingtypes.DelegationI) (stop bool) {
err = keeper.sk.IterateDelegations(ctx, voter, func(index int64, delegation stakingtypes.DelegationI) (stop bool) {
valAddrStr := delegation.GetValidatorAddr().String()
if val, ok := currValidators[valAddrStr]; ok {
@ -77,6 +80,9 @@ func (keeper Keeper) Tally(ctx context.Context, proposal v1.Proposal) (passes, b
return false
})
if err != nil {
return false, err
}
return false, keeper.Votes.Remove(ctx, collections.Join(vote.ProposalId, sdk.AccAddress(voter)))
})
@ -110,12 +116,17 @@ func (keeper Keeper) Tally(ctx context.Context, proposal v1.Proposal) (passes, b
// TODO: Upgrade the spec to cover all of these cases & remove pseudocode.
// If there is no staked coins, the proposal fails
if keeper.sk.TotalBondedTokens(sdkCtx).IsZero() {
totalBonded, err := keeper.sk.TotalBondedTokens(ctx)
if err != nil {
return false, false, tallyResults, err
}
if totalBonded.IsZero() {
return false, false, tallyResults, nil
}
// If there is not enough quorum of votes, the proposal fails
percentVoting := totalVotingPower.Quo(math.LegacyNewDecFromInt(keeper.sk.TotalBondedTokens(sdkCtx)))
percentVoting := totalVotingPower.Quo(math.LegacyNewDecFromInt(totalBonded))
quorum, _ := math.LegacyNewDecFromStr(params.Quorum)
if percentVoting.LT(quorum) {
return false, params.BurnVoteQuorum, tallyResults, nil

View File

@ -31,8 +31,8 @@ type BankKeeper interface {
type StakingKeeper interface {
types.StakingKeeper
BondDenom(ctx sdk.Context) string
TokensFromConsensusPower(ctx sdk.Context, power int64) math.Int
BondDenom(ctx context.Context) (string, error)
TokensFromConsensusPower(ctx context.Context, power int64) math.Int
}
// DistributionKeeper defines the expected distribution keeper

View File

@ -985,11 +985,12 @@ func (m *MockStakingKeeper) EXPECT() *MockStakingKeeperMockRecorder {
}
// BondDenom mocks base method.
func (m *MockStakingKeeper) BondDenom(ctx types.Context) string {
func (m *MockStakingKeeper) BondDenom(ctx context.Context) (string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "BondDenom", ctx)
ret0, _ := ret[0].(string)
return ret0
ret1, _ := ret[1].(error)
return ret0, ret1
}
// BondDenom indicates an expected call of BondDenom.
@ -999,9 +1000,11 @@ func (mr *MockStakingKeeperMockRecorder) BondDenom(ctx interface{}) *gomock.Call
}
// IterateBondedValidatorsByPower mocks base method.
func (m *MockStakingKeeper) IterateBondedValidatorsByPower(arg0 types.Context, arg1 func(int64, types1.ValidatorI) bool) {
func (m *MockStakingKeeper) IterateBondedValidatorsByPower(arg0 context.Context, arg1 func(int64, types1.ValidatorI) bool) error {
m.ctrl.T.Helper()
m.ctrl.Call(m, "IterateBondedValidatorsByPower", arg0, arg1)
ret := m.ctrl.Call(m, "IterateBondedValidatorsByPower", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// IterateBondedValidatorsByPower indicates an expected call of IterateBondedValidatorsByPower.
@ -1011,9 +1014,11 @@ func (mr *MockStakingKeeperMockRecorder) IterateBondedValidatorsByPower(arg0, ar
}
// IterateDelegations mocks base method.
func (m *MockStakingKeeper) IterateDelegations(ctx types.Context, delegator types.AccAddress, fn func(int64, types1.DelegationI) bool) {
func (m *MockStakingKeeper) IterateDelegations(ctx context.Context, delegator types.AccAddress, fn func(int64, types1.DelegationI) bool) error {
m.ctrl.T.Helper()
m.ctrl.Call(m, "IterateDelegations", ctx, delegator, fn)
ret := m.ctrl.Call(m, "IterateDelegations", ctx, delegator, fn)
ret0, _ := ret[0].(error)
return ret0
}
// IterateDelegations indicates an expected call of IterateDelegations.
@ -1023,7 +1028,7 @@ func (mr *MockStakingKeeperMockRecorder) IterateDelegations(ctx, delegator, fn i
}
// TokensFromConsensusPower mocks base method.
func (m *MockStakingKeeper) TokensFromConsensusPower(ctx types.Context, power int64) math.Int {
func (m *MockStakingKeeper) TokensFromConsensusPower(ctx context.Context, power int64) math.Int {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "TokensFromConsensusPower", ctx, power)
ret0, _ := ret[0].(math.Int)
@ -1037,11 +1042,12 @@ func (mr *MockStakingKeeperMockRecorder) TokensFromConsensusPower(ctx, power int
}
// TotalBondedTokens mocks base method.
func (m *MockStakingKeeper) TotalBondedTokens(arg0 types.Context) math.Int {
func (m *MockStakingKeeper) TotalBondedTokens(arg0 context.Context) (math.Int, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "TotalBondedTokens", arg0)
ret0, _ := ret[0].(math.Int)
return ret0
ret1, _ := ret[1].(error)
return ret0, ret1
}
// TotalBondedTokens indicates an expected call of TotalBondedTokens.

View File

@ -20,14 +20,14 @@ type ParamSubspace interface {
type StakingKeeper interface {
// iterate through bonded validators by operator address, execute func for each validator
IterateBondedValidatorsByPower(
sdk.Context, func(index int64, validator stakingtypes.ValidatorI) (stop bool),
)
context.Context, func(index int64, validator stakingtypes.ValidatorI) (stop bool),
) error
TotalBondedTokens(sdk.Context) math.Int // total bonded tokens within the validator set
TotalBondedTokens(context.Context) (math.Int, error) // total bonded tokens within the validator set
IterateDelegations(
ctx sdk.Context, delegator sdk.AccAddress,
ctx context.Context, delegator sdk.AccAddress,
fn func(index int64, delegation stakingtypes.DelegationI) (stop bool),
)
) error
}
// DistributionKeeper defines the expected distribution keeper (noalias)

View File

@ -26,12 +26,19 @@ func BeginBlocker(ctx context.Context, k keeper.Keeper, ic types.InflationCalcul
}
// recalculate inflation rate
totalStakingSupply := k.StakingTokenSupply(ctx)
bondedRatio := k.BondedRatio(ctx)
totalStakingSupply, err := k.StakingTokenSupply(ctx)
if err != nil {
return err
}
bondedRatio, err := k.BondedRatio(ctx)
if err != nil {
return err
}
minter.Inflation = ic(ctx, minter, params, bondedRatio)
minter.AnnualProvisions = minter.NextAnnualProvisions(params, totalStakingSupply)
err = k.Minter.Set(ctx, minter)
if err != nil {
if err = k.Minter.Set(ctx, minter); err != nil {
return err
}

View File

@ -80,16 +80,14 @@ func (k Keeper) Logger(ctx context.Context) log.Logger {
// StakingTokenSupply implements an alias call to the underlying staking keeper's
// StakingTokenSupply to be used in BeginBlocker.
func (k Keeper) StakingTokenSupply(ctx context.Context) math.Int {
sdkCtx := sdk.UnwrapSDKContext(ctx)
return k.stakingKeeper.StakingTokenSupply(sdkCtx)
func (k Keeper) StakingTokenSupply(ctx context.Context) (math.Int, error) {
return k.stakingKeeper.StakingTokenSupply(ctx)
}
// BondedRatio implements an alias call to the underlying staking keeper's
// BondedRatio to be used in BeginBlocker.
func (k Keeper) BondedRatio(ctx context.Context) math.LegacyDec {
sdkCtx := sdk.UnwrapSDKContext(ctx)
return k.stakingKeeper.BondedRatio(sdkCtx)
func (k Keeper) BondedRatio(ctx context.Context) (math.LegacyDec, error) {
return k.stakingKeeper.BondedRatio(ctx)
}
// MintCoins implements an alias call to the underlying supply keeper's

View File

@ -73,12 +73,16 @@ func (s *IntegrationTestSuite) SetupTest() {
func (s *IntegrationTestSuite) TestAliasFunctions() {
stakingTokenSupply := math.NewIntFromUint64(100000000000)
s.stakingKeeper.EXPECT().StakingTokenSupply(s.ctx).Return(stakingTokenSupply)
s.Require().Equal(s.mintKeeper.StakingTokenSupply(s.ctx), stakingTokenSupply)
s.stakingKeeper.EXPECT().StakingTokenSupply(s.ctx).Return(stakingTokenSupply, nil)
tokenSupply, err := s.mintKeeper.StakingTokenSupply(s.ctx)
s.Require().NoError(err)
s.Require().Equal(tokenSupply, stakingTokenSupply)
bondedRatio := math.LegacyNewDecWithPrec(15, 2)
s.stakingKeeper.EXPECT().BondedRatio(s.ctx).Return(bondedRatio)
s.Require().Equal(s.mintKeeper.BondedRatio(s.ctx), bondedRatio)
s.stakingKeeper.EXPECT().BondedRatio(s.ctx).Return(bondedRatio, nil)
ratio, err := s.mintKeeper.BondedRatio(s.ctx)
s.Require().NoError(err)
s.Require().Equal(ratio, bondedRatio)
coins := sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000000)))
s.bankKeeper.EXPECT().MintCoins(s.ctx, types.ModuleName, coins).Return(nil)

View File

@ -37,11 +37,12 @@ func (m *MockStakingKeeper) EXPECT() *MockStakingKeeperMockRecorder {
}
// BondedRatio mocks base method.
func (m *MockStakingKeeper) BondedRatio(ctx types.Context) math.LegacyDec {
func (m *MockStakingKeeper) BondedRatio(ctx context.Context) (math.LegacyDec, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "BondedRatio", ctx)
ret0, _ := ret[0].(math.LegacyDec)
return ret0
ret1, _ := ret[1].(error)
return ret0, ret1
}
// BondedRatio indicates an expected call of BondedRatio.
@ -51,11 +52,12 @@ func (mr *MockStakingKeeperMockRecorder) BondedRatio(ctx interface{}) *gomock.Ca
}
// StakingTokenSupply mocks base method.
func (m *MockStakingKeeper) StakingTokenSupply(ctx types.Context) math.Int {
func (m *MockStakingKeeper) StakingTokenSupply(ctx context.Context) (math.Int, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "StakingTokenSupply", ctx)
ret0, _ := ret[0].(math.Int)
return ret0
ret1, _ := ret[1].(error)
return ret0, ret1
}
// StakingTokenSupply indicates an expected call of StakingTokenSupply.

View File

@ -10,8 +10,8 @@ import (
// StakingKeeper defines the expected staking keeper
type StakingKeeper interface {
StakingTokenSupply(ctx sdk.Context) math.Int
BondedRatio(ctx sdk.Context) math.LegacyDec
StakingTokenSupply(ctx context.Context) (math.Int, error)
BondedRatio(ctx context.Context) (math.LegacyDec, error)
}
// AccountKeeper defines the contract required for account APIs.

View File

@ -1,6 +1,7 @@
package params_test
import (
"context"
"testing"
"github.com/golang/mock/gomock"
@ -22,7 +23,7 @@ import (
// StakingKeeper defines the expected staking keeper
type StakingKeeper interface {
MaxValidators(ctx sdk.Context) (res uint32)
MaxValidators(ctx context.Context) (res uint32, err error)
}
type HandlerTestSuite struct {
@ -43,7 +44,7 @@ func (suite *HandlerTestSuite) SetupTest() {
paramsKeeper.Subspace("staking").WithKeyTable(stakingtypes.ParamKeyTable()) //nolint:staticcheck // TODO: depreacte this test case
ctrl := gomock.NewController(suite.T())
stakingKeeper := paramstestutil.NewMockStakingKeeper(ctrl)
stakingKeeper.EXPECT().MaxValidators(ctx).Return(uint32(1))
stakingKeeper.EXPECT().MaxValidators(ctx).Return(uint32(1), nil)
suite.govHandler = params.NewParamChangeProposalHandler(paramsKeeper)
suite.stakingKeeper = stakingKeeper
@ -69,7 +70,8 @@ func (suite *HandlerTestSuite) TestProposalHandler() {
"all fields",
testProposal(proposal.NewParamChange(stakingtypes.ModuleName, string(stakingtypes.KeyMaxValidators), "1")),
func() {
maxVals := suite.stakingKeeper.MaxValidators(suite.ctx)
maxVals, err := suite.stakingKeeper.MaxValidators(suite.ctx)
suite.Require().NoError(err)
suite.Require().Equal(uint32(1), maxVals)
},
false,

View File

@ -5,9 +5,9 @@
package testutil
import (
context "context"
reflect "reflect"
types "github.com/cosmos/cosmos-sdk/types"
gomock "github.com/golang/mock/gomock"
)
@ -35,11 +35,12 @@ func (m *MockStakingKeeper) EXPECT() *MockStakingKeeperMockRecorder {
}
// MaxValidators mocks base method.
func (m *MockStakingKeeper) MaxValidators(ctx types.Context) uint32 {
func (m *MockStakingKeeper) MaxValidators(ctx context.Context) (uint32, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MaxValidators", ctx)
ret0, _ := ret[0].(uint32)
return ret0
ret1, _ := ret[1].(error)
return ret0, ret1
}
// MaxValidators indicates an expected call of MaxValidators.

View File

@ -51,19 +51,23 @@ func TestBeginBlocker(t *testing.T) {
power := int64(100)
amt := tstaking.CreateValidatorWithValPower(addr, pk, power, true)
stakingKeeper.EndBlocker(ctx)
bondDenom, err := stakingKeeper.BondDenom(ctx)
require.NoError(t, err)
require.Equal(
t, bankKeeper.GetAllBalances(ctx, sdk.AccAddress(addr)),
sdk.NewCoins(sdk.NewCoin(stakingKeeper.GetParams(ctx).BondDenom, testutil.InitTokens.Sub(amt))),
sdk.NewCoins(sdk.NewCoin(bondDenom, testutil.InitTokens.Sub(amt))),
)
require.Equal(t, amt, stakingKeeper.Validator(ctx, addr).GetBondedTokens())
val, err := stakingKeeper.Validator(ctx, addr)
require.NoError(t, err)
require.Equal(t, amt, val.GetBondedTokens())
val := abci.Validator{
abciVal := abci.Validator{
Address: pk.Address(),
Power: power,
}
ctx = ctx.WithVoteInfos([]abci.VoteInfo{{
Validator: val,
Validator: abciVal,
BlockIdFlag: cmtproto.BlockIDFlagCommit,
}})
@ -85,7 +89,7 @@ func TestBeginBlocker(t *testing.T) {
for ; height < signedBlocksWindow; height++ {
ctx = ctx.WithBlockHeight(height).
WithVoteInfos([]abci.VoteInfo{{
Validator: val,
Validator: abciVal,
BlockIdFlag: cmtproto.BlockIDFlagCommit,
}})
@ -99,7 +103,7 @@ func TestBeginBlocker(t *testing.T) {
for ; height < ((signedBlocksWindow * 2) - minSignedPerWindow + 1); height++ {
ctx = ctx.WithBlockHeight(height).
WithVoteInfos([]abci.VoteInfo{{
Validator: val,
Validator: abciVal,
BlockIdFlag: cmtproto.BlockIDFlagAbsent,
}})
@ -112,7 +116,7 @@ func TestBeginBlocker(t *testing.T) {
require.NoError(t, err)
// validator should be jailed
validator, found := stakingKeeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(pk))
require.True(t, found)
validator, err := stakingKeeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(pk))
require.NoError(t, err)
require.Equal(t, stakingtypes.Unbonding, validator.GetStatus())
}

View File

@ -94,8 +94,9 @@ func TestSlashingMsgs(t *testing.T) {
app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: app.LastBlockHeight() + 1})
ctxCheck = baseApp.NewContext(true)
validator, found := stakingKeeper.GetValidator(ctxCheck, sdk.ValAddress(addr1))
require.True(t, found)
validator, err := stakingKeeper.GetValidator(ctxCheck, sdk.ValAddress(addr1))
require.NoError(t, err)
require.Equal(t, sdk.ValAddress(addr1).String(), validator.OperatorAddress)
require.Equal(t, stakingtypes.Bonded, validator.Status)
require.True(math.IntEq(t, bondTokens, validator.BondedTokens()))

View File

@ -45,7 +45,7 @@ func (s *KeeperTestSuite) TestExportAndInitGenesis() {
require.NotEqual(info1, newInfo1)
// Initialize genesis with genesis state before tombstone
s.stakingKeeper.EXPECT().IterateValidators(ctx, gomock.Any()).Return()
s.stakingKeeper.EXPECT().IterateValidators(ctx, gomock.Any()).Return(nil)
keeper.InitGenesis(ctx, s.stakingKeeper, genesisState)
// Validator isTombstoned should return false as GenesisState is initialized

View File

@ -1,6 +1,7 @@
package keeper
import (
"context"
"time"
sdkmath "cosmossdk.io/math"
@ -23,14 +24,15 @@ func (k Keeper) Hooks() Hooks {
}
// AfterValidatorBonded updates the signing info start height or create a new signing info
func (h Hooks) AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error {
func (h Hooks) AfterValidatorBonded(ctx context.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error {
sdkCtx := sdk.UnwrapSDKContext(ctx)
signingInfo, err := h.k.GetValidatorSigningInfo(ctx, consAddr)
if err == nil {
signingInfo.StartHeight = ctx.BlockHeight()
signingInfo.StartHeight = sdkCtx.BlockHeight()
} else {
signingInfo = types.NewValidatorSigningInfo(
consAddr,
ctx.BlockHeight(),
sdkCtx.BlockHeight(),
0,
time.Unix(0, 0),
false,
@ -42,49 +44,54 @@ func (h Hooks) AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, v
}
// AfterValidatorRemoved deletes the address-pubkey relation when a validator is removed,
func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, _ sdk.ValAddress) error {
func (h Hooks) AfterValidatorRemoved(ctx context.Context, consAddr sdk.ConsAddress, _ sdk.ValAddress) error {
return h.k.deleteAddrPubkeyRelation(ctx, crypto.Address(consAddr))
}
// AfterValidatorCreated adds the address-pubkey relation when a validator is created.
func (h Hooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) error {
validator := h.k.sk.Validator(ctx, valAddr)
func (h Hooks) AfterValidatorCreated(ctx context.Context, valAddr sdk.ValAddress) error {
sdkCtx := sdk.UnwrapSDKContext(ctx)
validator, err := h.k.sk.Validator(ctx, valAddr)
if err != nil {
return err
}
consPk, err := validator.ConsPubKey()
if err != nil {
return err
}
return h.k.AddPubkey(ctx, consPk)
return h.k.AddPubkey(sdkCtx, consPk)
}
func (h Hooks) AfterValidatorBeginUnbonding(_ sdk.Context, _ sdk.ConsAddress, _ sdk.ValAddress) error {
func (h Hooks) AfterValidatorBeginUnbonding(_ context.Context, _ sdk.ConsAddress, _ sdk.ValAddress) error {
return nil
}
func (h Hooks) BeforeValidatorModified(_ sdk.Context, _ sdk.ValAddress) error {
func (h Hooks) BeforeValidatorModified(_ context.Context, _ sdk.ValAddress) error {
return nil
}
func (h Hooks) BeforeDelegationCreated(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) error {
func (h Hooks) BeforeDelegationCreated(_ context.Context, _ sdk.AccAddress, _ sdk.ValAddress) error {
return nil
}
func (h Hooks) BeforeDelegationSharesModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) error {
func (h Hooks) BeforeDelegationSharesModified(_ context.Context, _ sdk.AccAddress, _ sdk.ValAddress) error {
return nil
}
func (h Hooks) BeforeDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) error {
func (h Hooks) BeforeDelegationRemoved(_ context.Context, _ sdk.AccAddress, _ sdk.ValAddress) error {
return nil
}
func (h Hooks) AfterDelegationModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) error {
func (h Hooks) AfterDelegationModified(_ context.Context, _ sdk.AccAddress, _ sdk.ValAddress) error {
return nil
}
func (h Hooks) BeforeValidatorSlashed(_ sdk.Context, _ sdk.ValAddress, _ sdkmath.LegacyDec) error {
func (h Hooks) BeforeValidatorSlashed(_ context.Context, _ sdk.ValAddress, _ sdkmath.LegacyDec) error {
return nil
}
func (h Hooks) AfterUnbondingInitiated(_ sdk.Context, _ uint64) error {
func (h Hooks) AfterUnbondingInitiated(_ context.Context, _ uint64) error {
return nil
}

View File

@ -27,7 +27,7 @@ func (s *KeeperTestSuite) TestAfterValidatorCreatedOrRemoved() {
validator, err := stakingtypes.NewValidator(sdk.ValAddress(addr), pubKey, stakingtypes.Description{})
require.NoError(err)
s.stakingKeeper.EXPECT().Validator(ctx, valAddr).Return(validator)
s.stakingKeeper.EXPECT().Validator(ctx, valAddr).Return(validator, nil)
err = keeper.Hooks().AfterValidatorCreated(ctx, valAddr)
require.NoError(err)

View File

@ -23,7 +23,12 @@ func (k Keeper) HandleValidatorSignature(ctx context.Context, addr cryptotypes.A
consAddr := sdk.ConsAddress(addr)
// don't update missed blocks when validator's jailed
if k.sk.IsValidatorJailed(sdkCtx, consAddr) {
isJailed, err := k.sk.IsValidatorJailed(ctx, consAddr)
if err != nil {
return err
}
if isJailed {
return nil
}
@ -105,7 +110,10 @@ func (k Keeper) HandleValidatorSignature(ctx context.Context, addr cryptotypes.A
// if we are past the minimum height and the validator has missed too many blocks, punish them
if height > minHeight && signInfo.MissedBlocksCounter > maxMissed {
validator := k.sk.ValidatorByConsAddr(sdkCtx, consAddr)
validator, err := k.sk.ValidatorByConsAddr(ctx, consAddr)
if err != nil {
return err
}
if validator != nil && !validator.IsJailed() {
// Downtime confirmed: slash and jail the validator
// We need to retrieve the stake distribution which signed the block, so we subtract ValidatorUpdateDelay from the evidence height,
@ -120,7 +128,11 @@ func (k Keeper) HandleValidatorSignature(ctx context.Context, addr cryptotypes.A
return err
}
coinsBurned := k.sk.SlashWithInfractionReason(sdkCtx, consAddr, distributionHeight, power, slashFractionDowntime, stakingtypes.Infraction_INFRACTION_DOWNTIME)
coinsBurned, err := k.sk.SlashWithInfractionReason(ctx, consAddr, distributionHeight, power, slashFractionDowntime, stakingtypes.Infraction_INFRACTION_DOWNTIME)
if err != nil {
return err
}
sdkCtx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeSlash,

View File

@ -84,8 +84,12 @@ func (k Keeper) Slash(ctx context.Context, consAddr sdk.ConsAddress, fraction sd
// SlashWithInfractionReason attempts to slash a validator. The slash is delegated to the staking
// module to make the necessary validator changes. It specifies an intraction reason.
func (k Keeper) SlashWithInfractionReason(ctx context.Context, consAddr sdk.ConsAddress, fraction sdkmath.LegacyDec, power, distributionHeight int64, infraction stakingtypes.Infraction) error {
coinsBurned, err := k.sk.SlashWithInfractionReason(ctx, consAddr, distributionHeight, power, fraction, infraction)
if err != nil {
return err
}
sdkCtx := sdk.UnwrapSDKContext(ctx)
coinsBurned := k.sk.SlashWithInfractionReason(sdkCtx, consAddr, distributionHeight, power, fraction, infraction)
sdkCtx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeSlash,

View File

@ -90,7 +90,7 @@ func (s *KeeperTestSuite) TestJailAndSlash() {
sdk.TokensToConsensusPower(sdkmath.NewInt(1), sdk.DefaultPowerReduction),
slashFractionDoubleSign,
stakingtypes.Infraction_INFRACTION_UNSPECIFIED,
).Return(sdkmath.NewInt(0))
).Return(sdkmath.NewInt(0), nil)
s.slashingKeeper.Slash(
s.ctx,
@ -100,7 +100,7 @@ func (s *KeeperTestSuite) TestJailAndSlash() {
s.ctx.BlockHeight(),
)
s.stakingKeeper.EXPECT().Jail(s.ctx, consAddr).Return()
s.stakingKeeper.EXPECT().Jail(s.ctx, consAddr).Return(nil)
s.slashingKeeper.Jail(s.ctx, consAddr)
}
@ -114,7 +114,7 @@ func (s *KeeperTestSuite) TestJailAndSlashWithInfractionReason() {
sdk.TokensToConsensusPower(sdkmath.NewInt(1), sdk.DefaultPowerReduction),
slashFractionDoubleSign,
stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN,
).Return(sdkmath.NewInt(0))
).Return(sdkmath.NewInt(0), nil)
s.slashingKeeper.SlashWithInfractionReason(
s.ctx,
@ -125,7 +125,7 @@ func (s *KeeperTestSuite) TestJailAndSlashWithInfractionReason() {
stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN,
)
s.stakingKeeper.EXPECT().Jail(s.ctx, consAddr).Return()
s.stakingKeeper.EXPECT().Jail(s.ctx, consAddr).Return(nil)
s.slashingKeeper.Jail(s.ctx, consAddr)
}

View File

@ -170,8 +170,8 @@ func (s *KeeperTestSuite) TestUnjail() {
val, err := types.NewValidator(valAddr, pubKey, types.Description{Moniker: "test"})
s.Require().NoError(err)
s.stakingKeeper.EXPECT().Validator(s.ctx, valAddr).Return(val)
s.stakingKeeper.EXPECT().Delegation(s.ctx, addr, valAddr).Return(nil)
s.stakingKeeper.EXPECT().Validator(s.ctx, valAddr).Return(val, nil)
s.stakingKeeper.EXPECT().Delegation(s.ctx, addr, valAddr).Return(nil, nil)
return &slashingtypes.MsgUnjail{
ValidatorAddr: sdk.ValAddress(addr).String(),
@ -186,7 +186,7 @@ func (s *KeeperTestSuite) TestUnjail() {
_, _, addr := testdata.KeyTestPubAddr()
valAddr := sdk.ValAddress(addr)
s.stakingKeeper.EXPECT().Validator(s.ctx, valAddr).Return(nil)
s.stakingKeeper.EXPECT().Validator(s.ctx, valAddr).Return(nil, nil)
return &slashingtypes.MsgUnjail{
ValidatorAddr: valAddr.String(),
@ -213,10 +213,10 @@ func (s *KeeperTestSuite) TestUnjail() {
s.slashingKeeper.SetValidatorSigningInfo(s.ctx, sdk.ConsAddress(addr), info)
s.stakingKeeper.EXPECT().Validator(s.ctx, valAddr).Return(val)
s.stakingKeeper.EXPECT().Validator(s.ctx, valAddr).Return(val, nil)
del := types.NewDelegation(addr, valAddr, sdkmath.LegacyNewDec(100))
s.stakingKeeper.EXPECT().Delegation(s.ctx, addr, valAddr).Return(del)
s.stakingKeeper.EXPECT().Delegation(s.ctx, addr, valAddr).Return(del, nil)
return &slashingtypes.MsgUnjail{
ValidatorAddr: sdk.ValAddress(addr).String(),
@ -243,10 +243,10 @@ func (s *KeeperTestSuite) TestUnjail() {
s.slashingKeeper.SetValidatorSigningInfo(s.ctx, sdk.ConsAddress(addr), info)
s.stakingKeeper.EXPECT().Validator(s.ctx, valAddr).Return(val)
s.stakingKeeper.EXPECT().Validator(s.ctx, valAddr).Return(val, nil)
del := types.NewDelegation(addr, valAddr, sdkmath.LegacyNewDec(100))
s.stakingKeeper.EXPECT().Delegation(s.ctx, addr, valAddr).Return(del)
s.stakingKeeper.EXPECT().Delegation(s.ctx, addr, valAddr).Return(del, nil)
return &slashingtypes.MsgUnjail{
ValidatorAddr: sdk.ValAddress(addr).String(),
@ -273,10 +273,10 @@ func (s *KeeperTestSuite) TestUnjail() {
s.slashingKeeper.SetValidatorSigningInfo(s.ctx, sdk.ConsAddress(addr), info)
s.stakingKeeper.EXPECT().Validator(s.ctx, valAddr).Return(val)
s.stakingKeeper.EXPECT().Validator(s.ctx, valAddr).Return(val, nil)
del := types.NewDelegation(addr, valAddr, sdkmath.LegacyNewDec(10000))
s.stakingKeeper.EXPECT().Delegation(s.ctx, addr, valAddr).Return(del)
s.stakingKeeper.EXPECT().Delegation(s.ctx, addr, valAddr).Return(del, nil)
return &slashingtypes.MsgUnjail{
ValidatorAddr: sdk.ValAddress(addr).String(),
@ -303,11 +303,11 @@ func (s *KeeperTestSuite) TestUnjail() {
s.slashingKeeper.SetValidatorSigningInfo(s.ctx, sdk.ConsAddress(addr), info)
s.stakingKeeper.EXPECT().Validator(s.ctx, valAddr).Return(val)
s.stakingKeeper.EXPECT().Validator(s.ctx, valAddr).Return(val, nil)
del := types.NewDelegation(addr, valAddr, sdkmath.LegacyNewDec(100))
s.stakingKeeper.EXPECT().Delegation(s.ctx, addr, valAddr).Return(del)
s.stakingKeeper.EXPECT().Unjail(s.ctx, sdk.ConsAddress(addr)).Return()
s.stakingKeeper.EXPECT().Delegation(s.ctx, addr, valAddr).Return(del, nil)
s.stakingKeeper.EXPECT().Unjail(s.ctx, sdk.ConsAddress(addr)).Return(nil)
return &slashingtypes.MsgUnjail{
ValidatorAddr: sdk.ValAddress(addr).String(),

View File

@ -12,14 +12,20 @@ import (
// Unjail calls the staking Unjail function to unjail a validator if the
// jailed period has concluded
func (k Keeper) Unjail(ctx context.Context, validatorAddr sdk.ValAddress) error {
sdkCtx := sdk.UnwrapSDKContext(ctx)
validator := k.sk.Validator(sdkCtx, validatorAddr)
validator, err := k.sk.Validator(ctx, validatorAddr)
if err != nil {
return err
}
if validator == nil {
return types.ErrNoValidatorForAddress
}
// cannot be unjailed if no self-delegation exists
selfDel := k.sk.Delegation(sdkCtx, sdk.AccAddress(validatorAddr), validatorAddr)
selfDel, err := k.sk.Delegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr)
if err != nil {
return err
}
if selfDel == nil {
return types.ErrMissingSelfDelegation
}
@ -57,11 +63,11 @@ func (k Keeper) Unjail(ctx context.Context, validatorAddr sdk.ValAddress) error
}
// cannot be unjailed until out of jail
sdkCtx := sdk.UnwrapSDKContext(ctx)
if sdkCtx.BlockHeader().Time.Before(info.JailedUntil) {
return types.ErrValidatorJailed
}
}
k.sk.Unjail(sdkCtx, consAddr)
return nil
return k.sk.Unjail(ctx, consAddr)
}

View File

@ -63,7 +63,12 @@ func SimulateMsgUnjail(
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
msgType := sdk.MsgTypeURL(&types.MsgUnjail{})
validator, ok := testutil.RandSliceElem(r, sk.GetAllValidators(ctx))
allVals, err := sk.GetAllValidators(ctx)
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to get all validators"), nil, err
}
validator, ok := testutil.RandSliceElem(r, allVals)
if !ok {
return simtypes.NoOpMsg(types.ModuleName, msgType, "validator is not ok"), nil, nil // skip
}
@ -87,7 +92,11 @@ func SimulateMsgUnjail(
return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to find validator signing info"), nil, err // skip
}
selfDel := sk.Delegation(ctx, simAccount.Address, validator.GetOperator())
selfDel, err := sk.Delegation(ctx, simAccount.Address, validator.GetOperator())
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to get self delegation"), nil, err
}
if selfDel == nil {
return simtypes.NoOpMsg(types.ModuleName, msgType, "self delegation is nil"), nil, nil // skip
}

View File

@ -254,11 +254,12 @@ func (m *MockStakingKeeper) EXPECT() *MockStakingKeeperMockRecorder {
}
// Delegation mocks base method.
func (m *MockStakingKeeper) Delegation(arg0 types.Context, arg1 types.AccAddress, arg2 types.ValAddress) types1.DelegationI {
func (m *MockStakingKeeper) Delegation(arg0 context.Context, arg1 types.AccAddress, arg2 types.ValAddress) (types1.DelegationI, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Delegation", arg0, arg1, arg2)
ret0, _ := ret[0].(types1.DelegationI)
return ret0
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Delegation indicates an expected call of Delegation.
@ -268,11 +269,12 @@ func (mr *MockStakingKeeperMockRecorder) Delegation(arg0, arg1, arg2 interface{}
}
// GetAllValidators mocks base method.
func (m *MockStakingKeeper) GetAllValidators(ctx types.Context) []types1.Validator {
func (m *MockStakingKeeper) GetAllValidators(ctx context.Context) ([]types1.Validator, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetAllValidators", ctx)
ret0, _ := ret[0].([]types1.Validator)
return ret0
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetAllValidators indicates an expected call of GetAllValidators.
@ -282,11 +284,12 @@ func (mr *MockStakingKeeperMockRecorder) GetAllValidators(ctx interface{}) *gomo
}
// IsValidatorJailed mocks base method.
func (m *MockStakingKeeper) IsValidatorJailed(ctx types.Context, addr types.ConsAddress) bool {
func (m *MockStakingKeeper) IsValidatorJailed(ctx context.Context, addr types.ConsAddress) (bool, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "IsValidatorJailed", ctx, addr)
ret0, _ := ret[0].(bool)
return ret0
ret1, _ := ret[1].(error)
return ret0, ret1
}
// IsValidatorJailed indicates an expected call of IsValidatorJailed.
@ -296,9 +299,11 @@ func (mr *MockStakingKeeperMockRecorder) IsValidatorJailed(ctx, addr interface{}
}
// IterateValidators mocks base method.
func (m *MockStakingKeeper) IterateValidators(arg0 types.Context, arg1 func(int64, types1.ValidatorI) bool) {
func (m *MockStakingKeeper) IterateValidators(arg0 context.Context, arg1 func(int64, types1.ValidatorI) bool) error {
m.ctrl.T.Helper()
m.ctrl.Call(m, "IterateValidators", arg0, arg1)
ret := m.ctrl.Call(m, "IterateValidators", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// IterateValidators indicates an expected call of IterateValidators.
@ -308,9 +313,11 @@ func (mr *MockStakingKeeperMockRecorder) IterateValidators(arg0, arg1 interface{
}
// Jail mocks base method.
func (m *MockStakingKeeper) Jail(arg0 types.Context, arg1 types.ConsAddress) {
func (m *MockStakingKeeper) Jail(arg0 context.Context, arg1 types.ConsAddress) error {
m.ctrl.T.Helper()
m.ctrl.Call(m, "Jail", arg0, arg1)
ret := m.ctrl.Call(m, "Jail", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// Jail indicates an expected call of Jail.
@ -320,11 +327,12 @@ func (mr *MockStakingKeeperMockRecorder) Jail(arg0, arg1 interface{}) *gomock.Ca
}
// MaxValidators mocks base method.
func (m *MockStakingKeeper) MaxValidators(arg0 types.Context) uint32 {
func (m *MockStakingKeeper) MaxValidators(arg0 context.Context) (uint32, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MaxValidators", arg0)
ret0, _ := ret[0].(uint32)
return ret0
ret1, _ := ret[1].(error)
return ret0, ret1
}
// MaxValidators indicates an expected call of MaxValidators.
@ -334,11 +342,12 @@ func (mr *MockStakingKeeperMockRecorder) MaxValidators(arg0 interface{}) *gomock
}
// Slash mocks base method.
func (m *MockStakingKeeper) Slash(arg0 types.Context, arg1 types.ConsAddress, arg2, arg3 int64, arg4 math.LegacyDec) math.Int {
func (m *MockStakingKeeper) Slash(arg0 context.Context, arg1 types.ConsAddress, arg2, arg3 int64, arg4 math.LegacyDec) (math.Int, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Slash", arg0, arg1, arg2, arg3, arg4)
ret0, _ := ret[0].(math.Int)
return ret0
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Slash indicates an expected call of Slash.
@ -348,11 +357,12 @@ func (mr *MockStakingKeeperMockRecorder) Slash(arg0, arg1, arg2, arg3, arg4 inte
}
// SlashWithInfractionReason mocks base method.
func (m *MockStakingKeeper) SlashWithInfractionReason(arg0 types.Context, arg1 types.ConsAddress, arg2, arg3 int64, arg4 math.LegacyDec, arg5 types1.Infraction) math.Int {
func (m *MockStakingKeeper) SlashWithInfractionReason(arg0 context.Context, arg1 types.ConsAddress, arg2, arg3 int64, arg4 math.LegacyDec, arg5 types1.Infraction) (math.Int, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SlashWithInfractionReason", arg0, arg1, arg2, arg3, arg4, arg5)
ret0, _ := ret[0].(math.Int)
return ret0
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SlashWithInfractionReason indicates an expected call of SlashWithInfractionReason.
@ -362,9 +372,11 @@ func (mr *MockStakingKeeperMockRecorder) SlashWithInfractionReason(arg0, arg1, a
}
// Unjail mocks base method.
func (m *MockStakingKeeper) Unjail(arg0 types.Context, arg1 types.ConsAddress) {
func (m *MockStakingKeeper) Unjail(arg0 context.Context, arg1 types.ConsAddress) error {
m.ctrl.T.Helper()
m.ctrl.Call(m, "Unjail", arg0, arg1)
ret := m.ctrl.Call(m, "Unjail", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// Unjail indicates an expected call of Unjail.
@ -374,11 +386,12 @@ func (mr *MockStakingKeeperMockRecorder) Unjail(arg0, arg1 interface{}) *gomock.
}
// Validator mocks base method.
func (m *MockStakingKeeper) Validator(arg0 types.Context, arg1 types.ValAddress) types1.ValidatorI {
func (m *MockStakingKeeper) Validator(arg0 context.Context, arg1 types.ValAddress) (types1.ValidatorI, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Validator", arg0, arg1)
ret0, _ := ret[0].(types1.ValidatorI)
return ret0
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Validator indicates an expected call of Validator.
@ -388,11 +401,12 @@ func (mr *MockStakingKeeperMockRecorder) Validator(arg0, arg1 interface{}) *gomo
}
// ValidatorByConsAddr mocks base method.
func (m *MockStakingKeeper) ValidatorByConsAddr(arg0 types.Context, arg1 types.ConsAddress) types1.ValidatorI {
func (m *MockStakingKeeper) ValidatorByConsAddr(arg0 context.Context, arg1 types.ConsAddress) (types1.ValidatorI, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ValidatorByConsAddr", arg0, arg1)
ret0, _ := ret[0].(types1.ValidatorI)
return ret0
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ValidatorByConsAddr indicates an expected call of ValidatorByConsAddr.
@ -425,7 +439,7 @@ func (m *MockStakingHooks) EXPECT() *MockStakingHooksMockRecorder {
}
// AfterDelegationModified mocks base method.
func (m *MockStakingHooks) AfterDelegationModified(ctx types.Context, delAddr types.AccAddress, valAddr types.ValAddress) error {
func (m *MockStakingHooks) AfterDelegationModified(ctx context.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)
@ -439,7 +453,7 @@ func (mr *MockStakingHooksMockRecorder) AfterDelegationModified(ctx, delAddr, va
}
// AfterValidatorBeginUnbonding mocks base method.
func (m *MockStakingHooks) AfterValidatorBeginUnbonding(ctx types.Context, consAddr types.ConsAddress, valAddr types.ValAddress) error {
func (m *MockStakingHooks) AfterValidatorBeginUnbonding(ctx context.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)
@ -453,7 +467,7 @@ func (mr *MockStakingHooksMockRecorder) AfterValidatorBeginUnbonding(ctx, consAd
}
// AfterValidatorBonded mocks base method.
func (m *MockStakingHooks) AfterValidatorBonded(ctx types.Context, consAddr types.ConsAddress, valAddr types.ValAddress) error {
func (m *MockStakingHooks) AfterValidatorBonded(ctx context.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)
@ -467,7 +481,7 @@ func (mr *MockStakingHooksMockRecorder) AfterValidatorBonded(ctx, consAddr, valA
}
// AfterValidatorCreated mocks base method.
func (m *MockStakingHooks) AfterValidatorCreated(ctx types.Context, valAddr types.ValAddress) error {
func (m *MockStakingHooks) AfterValidatorCreated(ctx context.Context, valAddr types.ValAddress) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AfterValidatorCreated", ctx, valAddr)
ret0, _ := ret[0].(error)
@ -481,7 +495,7 @@ func (mr *MockStakingHooksMockRecorder) AfterValidatorCreated(ctx, valAddr inter
}
// AfterValidatorRemoved mocks base method.
func (m *MockStakingHooks) AfterValidatorRemoved(ctx types.Context, consAddr types.ConsAddress, valAddr types.ValAddress) error {
func (m *MockStakingHooks) AfterValidatorRemoved(ctx context.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)
@ -495,7 +509,7 @@ func (mr *MockStakingHooksMockRecorder) AfterValidatorRemoved(ctx, consAddr, val
}
// BeforeDelegationCreated mocks base method.
func (m *MockStakingHooks) BeforeDelegationCreated(ctx types.Context, delAddr types.AccAddress, valAddr types.ValAddress) error {
func (m *MockStakingHooks) BeforeDelegationCreated(ctx context.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)
@ -509,7 +523,7 @@ func (mr *MockStakingHooksMockRecorder) BeforeDelegationCreated(ctx, delAddr, va
}
// BeforeDelegationRemoved mocks base method.
func (m *MockStakingHooks) BeforeDelegationRemoved(ctx types.Context, delAddr types.AccAddress, valAddr types.ValAddress) error {
func (m *MockStakingHooks) BeforeDelegationRemoved(ctx context.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)
@ -523,7 +537,7 @@ func (mr *MockStakingHooksMockRecorder) BeforeDelegationRemoved(ctx, delAddr, va
}
// BeforeDelegationSharesModified mocks base method.
func (m *MockStakingHooks) BeforeDelegationSharesModified(ctx types.Context, delAddr types.AccAddress, valAddr types.ValAddress) error {
func (m *MockStakingHooks) BeforeDelegationSharesModified(ctx context.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)
@ -537,7 +551,7 @@ func (mr *MockStakingHooksMockRecorder) BeforeDelegationSharesModified(ctx, delA
}
// BeforeValidatorModified mocks base method.
func (m *MockStakingHooks) BeforeValidatorModified(ctx types.Context, valAddr types.ValAddress) error {
func (m *MockStakingHooks) BeforeValidatorModified(ctx context.Context, valAddr types.ValAddress) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "BeforeValidatorModified", ctx, valAddr)
ret0, _ := ret[0].(error)
@ -551,7 +565,7 @@ func (mr *MockStakingHooksMockRecorder) BeforeValidatorModified(ctx, valAddr int
}
// BeforeValidatorSlashed mocks base method.
func (m *MockStakingHooks) BeforeValidatorSlashed(ctx types.Context, valAddr types.ValAddress, fraction math.LegacyDec) error {
func (m *MockStakingHooks) BeforeValidatorSlashed(ctx context.Context, valAddr types.ValAddress, fraction math.LegacyDec) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "BeforeValidatorSlashed", ctx, valAddr, fraction)
ret0, _ := ret[0].(error)

View File

@ -36,42 +36,42 @@ type ParamSubspace interface {
// StakingKeeper expected staking keeper
type StakingKeeper interface {
// iterate through validators by operator address, execute func for each validator
IterateValidators(sdk.Context,
func(index int64, validator stakingtypes.ValidatorI) (stop bool))
IterateValidators(context.Context,
func(index int64, validator stakingtypes.ValidatorI) (stop bool)) error
Validator(sdk.Context, sdk.ValAddress) stakingtypes.ValidatorI // get a particular validator by operator address
ValidatorByConsAddr(sdk.Context, sdk.ConsAddress) stakingtypes.ValidatorI // get a particular validator by consensus address
Validator(context.Context, sdk.ValAddress) (stakingtypes.ValidatorI, error) // get a particular validator by operator address
ValidatorByConsAddr(context.Context, sdk.ConsAddress) (stakingtypes.ValidatorI, error) // get a particular validator by consensus address
// slash the validator and delegators of the validator, specifying offense height, offense power, and slash fraction
Slash(sdk.Context, sdk.ConsAddress, int64, int64, math.LegacyDec) math.Int
SlashWithInfractionReason(sdk.Context, sdk.ConsAddress, int64, int64, math.LegacyDec, stakingtypes.Infraction) math.Int
Jail(sdk.Context, sdk.ConsAddress) // jail a validator
Unjail(sdk.Context, sdk.ConsAddress) // unjail a validator
Slash(context.Context, sdk.ConsAddress, int64, int64, math.LegacyDec) (math.Int, error)
SlashWithInfractionReason(context.Context, sdk.ConsAddress, int64, int64, math.LegacyDec, stakingtypes.Infraction) (math.Int, error)
Jail(context.Context, sdk.ConsAddress) error // jail a validator
Unjail(context.Context, sdk.ConsAddress) error // unjail a validator
// Delegation allows for getting a particular delegation for a given validator
// and delegator outside the scope of the staking module.
Delegation(sdk.Context, sdk.AccAddress, sdk.ValAddress) stakingtypes.DelegationI
GetAllValidators(ctx sdk.Context) (validators []stakingtypes.Validator)
Delegation(context.Context, sdk.AccAddress, sdk.ValAddress) (stakingtypes.DelegationI, error)
GetAllValidators(ctx context.Context) ([]stakingtypes.Validator, error)
// MaxValidators returns the maximum amount of bonded validators
MaxValidators(sdk.Context) uint32
MaxValidators(context.Context) (uint32, error)
// IsValidatorJailed returns if the validator is jailed.
IsValidatorJailed(ctx sdk.Context, addr sdk.ConsAddress) bool
IsValidatorJailed(ctx context.Context, addr sdk.ConsAddress) (bool, error)
}
// StakingHooks event hooks for staking validator object (noalias)
type StakingHooks interface {
AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) error // Must be called when a validator is created
BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) error // Must be called when a validator's state changes
AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error // Must be called when a validator is deleted
AfterValidatorCreated(ctx context.Context, valAddr sdk.ValAddress) error // Must be called when a validator is created
BeforeValidatorModified(ctx context.Context, valAddr sdk.ValAddress) error // Must be called when a validator's state changes
AfterValidatorRemoved(ctx context.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error // Must be called when a validator is deleted
AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error // Must be called when a validator is bonded
AfterValidatorBeginUnbonding(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error // Must be called when a validator begins unbonding
AfterValidatorBonded(ctx context.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error // Must be called when a validator is bonded
AfterValidatorBeginUnbonding(ctx context.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error // Must be called when a validator begins unbonding
BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error // Must be called when a delegation is created
BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error // Must be called when a delegation's shares are modified
BeforeDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error // Must be called when a delegation is removed
AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error
BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, fraction math.LegacyDec) error
BeforeDelegationCreated(ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error // Must be called when a delegation is created
BeforeDelegationSharesModified(ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error // Must be called when a delegation's shares are modified
BeforeDelegationRemoved(ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error // Must be called when a delegation is removed
AfterDelegationModified(ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error
BeforeValidatorSlashed(ctx context.Context, valAddr sdk.ValAddress, fraction math.LegacyDec) error
}

View File

@ -82,15 +82,18 @@ func TestStakingMsgs(t *testing.T) {
require.NoError(t, err)
require.True(t, sdk.Coins{genCoin.Sub(bondCoin)}.Equal(bankKeeper.GetAllBalances(ctxCheck, addr1)))
app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: app.LastBlockHeight() + 1})
_, err = app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: app.LastBlockHeight() + 1})
require.NoError(t, err)
ctxCheck = app.BaseApp.NewContext(true)
validator, found := stakingKeeper.GetValidator(ctxCheck, sdk.ValAddress(addr1))
require.True(t, found)
validator, err := stakingKeeper.GetValidator(ctxCheck, sdk.ValAddress(addr1))
require.NoError(t, err)
require.Equal(t, sdk.ValAddress(addr1).String(), validator.OperatorAddress)
require.Equal(t, types.Bonded, validator.Status)
require.True(math.IntEq(t, bondTokens, validator.BondedTokens()))
app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: app.LastBlockHeight() + 1})
_, err = app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: app.LastBlockHeight() + 1})
require.NoError(t, err)
// edit the validator
description = types.NewDescription("bar_moniker", "", "", "", "")
@ -101,8 +104,8 @@ func TestStakingMsgs(t *testing.T) {
require.NoError(t, err)
ctxCheck = app.BaseApp.NewContext(true)
validator, found = stakingKeeper.GetValidator(ctxCheck, sdk.ValAddress(addr1))
require.True(t, found)
validator, err = stakingKeeper.GetValidator(ctxCheck, sdk.ValAddress(addr1))
require.NoError(t, err)
require.Equal(t, description, validator.Description)
// delegate
@ -115,8 +118,8 @@ func TestStakingMsgs(t *testing.T) {
ctxCheck = app.BaseApp.NewContext(true)
require.True(t, sdk.Coins{genCoin.Sub(bondCoin)}.Equal(bankKeeper.GetAllBalances(ctxCheck, addr2)))
_, found = stakingKeeper.GetDelegation(ctxCheck, addr2, sdk.ValAddress(addr1))
require.True(t, found)
_, err = stakingKeeper.GetDelegation(ctxCheck, addr2, sdk.ValAddress(addr1))
require.NoError(t, err)
// begin unbonding
beginUnbondingMsg := types.NewMsgUndelegate(addr2, sdk.ValAddress(addr1), bondCoin)
@ -126,8 +129,8 @@ func TestStakingMsgs(t *testing.T) {
// delegation should exist anymore
ctxCheck = app.BaseApp.NewContext(true)
_, found = stakingKeeper.GetDelegation(ctxCheck, addr2, sdk.ValAddress(addr1))
require.False(t, found)
_, err = stakingKeeper.GetDelegation(ctxCheck, addr2, sdk.ValAddress(addr1))
require.ErrorIs(t, err, types.ErrNoDelegation)
// balance should be the same because bonding not yet complete
require.True(t, sdk.Coins{genCoin.Sub(bondCoin)}.Equal(bankKeeper.GetAllBalances(ctxCheck, addr2)))

View File

@ -8,7 +8,6 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
rpcclientmock "github.com/cometbft/cometbft/rpc/client/mock"
"github.com/spf13/pflag"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"github.com/cosmos/cosmos-sdk/client"
@ -78,6 +77,7 @@ func (s *CLITestSuite) TestPrepareConfigForTxCreateValidator() {
privKey := ed25519.GenPrivKey()
valPubKey := privKey.PubKey()
moniker := "DefaultMoniker"
require := s.Require()
mkTxValCfg := func(amount, commission, commissionMax, commissionMaxChange, minSelfDelegation string) cli.TxCreateValidatorConfig {
return cli.TxCreateValidatorConfig{
IP: ip,
@ -107,35 +107,35 @@ func (s *CLITestSuite) TestPrepareConfigForTxCreateValidator() {
{
name: "Custom amount",
fsModify: func(fs *pflag.FlagSet) {
fs.Set(cli.FlagAmount, "2000stake")
require.NoError(fs.Set(cli.FlagAmount, "2000stake"))
},
expectedCfg: mkTxValCfg("2000stake", "0.1", "0.2", "0.01", "1"),
},
{
name: "Custom commission rate",
fsModify: func(fs *pflag.FlagSet) {
fs.Set(cli.FlagCommissionRate, "0.54")
require.NoError(fs.Set(cli.FlagCommissionRate, "0.54"))
},
expectedCfg: mkTxValCfg(cli.DefaultTokens.String()+sdk.DefaultBondDenom, "0.54", "0.2", "0.01", "1"),
},
{
name: "Custom commission max rate",
fsModify: func(fs *pflag.FlagSet) {
fs.Set(cli.FlagCommissionMaxRate, "0.89")
require.NoError(fs.Set(cli.FlagCommissionMaxRate, "0.89"))
},
expectedCfg: mkTxValCfg(cli.DefaultTokens.String()+sdk.DefaultBondDenom, "0.1", "0.89", "0.01", "1"),
},
{
name: "Custom commission max change rate",
fsModify: func(fs *pflag.FlagSet) {
fs.Set(cli.FlagCommissionMaxChangeRate, "0.55")
require.NoError(fs.Set(cli.FlagCommissionMaxChangeRate, "0.55"))
},
expectedCfg: mkTxValCfg(cli.DefaultTokens.String()+sdk.DefaultBondDenom, "0.1", "0.2", "0.55", "1"),
},
{
name: "Custom min self delegations",
fsModify: func(fs *pflag.FlagSet) {
fs.Set(cli.FlagMinSelfDelegation, "0.33")
require.NoError(fs.Set(cli.FlagMinSelfDelegation, "0.33"))
},
expectedCfg: mkTxValCfg(cli.DefaultTokens.String()+sdk.DefaultBondDenom, "0.1", "0.2", "0.01", "0.33"),
},
@ -150,9 +150,9 @@ func (s *CLITestSuite) TestPrepareConfigForTxCreateValidator() {
tc.fsModify(fs)
cvCfg, err := cli.PrepareConfigForTxCreateValidator(fs, moniker, nodeID, chainID, valPubKey)
require.NoError(s.T(), err)
require.NoError(err)
require.Equal(s.T(), tc.expectedCfg, cvCfg)
require.Equal(tc.expectedCfg, cvCfg)
})
}
}

View File

@ -13,7 +13,7 @@ import (
// WriteValidators returns a slice of bonded genesis validators.
func WriteValidators(ctx sdk.Context, keeper *keeper.Keeper) (vals []cmttypes.GenesisValidator, returnErr error) {
keeper.IterateLastValidators(ctx, func(_ int64, validator types.ValidatorI) (stop bool) {
err := keeper.IterateLastValidators(ctx, func(_ int64, validator types.ValidatorI) (stop bool) {
pk, err := validator.ConsPubKey()
if err != nil {
returnErr = err
@ -34,6 +34,9 @@ func WriteValidators(ctx sdk.Context, keeper *keeper.Keeper) (vals []cmttypes.Ge
return false
})
if err != nil {
return nil, err
}
return
}

View File

@ -7,21 +7,18 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
// BeginBlocker will persist the current header and validator set as a historical entry
// and prune the oldest entry based on the HistoricalEntries parameter
func (k *Keeper) BeginBlocker(ctx sdk.Context) {
func (k *Keeper) BeginBlocker(ctx context.Context) error {
defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyBeginBlocker)
k.TrackHistoricalInfo(ctx)
return k.TrackHistoricalInfo(ctx)
}
// Called every block, update validator set
func (k *Keeper) EndBlocker(ctx context.Context) ([]abci.ValidatorUpdate, error) {
defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyEndBlocker)
return k.BlockValidatorUpdates(sdk.UnwrapSDKContext(ctx)), nil
return k.BlockValidatorUpdates(ctx)
}

View File

@ -1,7 +1,7 @@
package keeper
import (
"fmt"
"context"
storetypes "cosmossdk.io/store/types"
@ -12,16 +12,21 @@ import (
// Validator Set
// iterate through the validator set and perform the provided function
func (k Keeper) IterateValidators(ctx sdk.Context, fn func(index int64, validator types.ValidatorI) (stop bool)) {
store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, types.ValidatorsKey)
func (k Keeper) IterateValidators(ctx context.Context, fn func(index int64, validator types.ValidatorI) (stop bool)) error {
store := k.storeService.OpenKVStore(ctx)
iterator, err := store.Iterator(types.ValidatorsKey, storetypes.PrefixEndBytes(types.ValidatorsKey))
if err != nil {
return err
}
defer iterator.Close()
i := int64(0)
for ; iterator.Valid(); iterator.Next() {
validator := types.MustUnmarshalValidator(k.cdc, iterator.Value())
validator, err := types.UnmarshalValidator(k.cdc, iterator.Value())
if err != nil {
return err
}
stop := fn(i, validator) // XXX is this safe will the validator unexposed fields be able to get written to?
if stop {
@ -29,14 +34,22 @@ func (k Keeper) IterateValidators(ctx sdk.Context, fn func(index int64, validato
}
i++
}
return nil
}
// iterate through the bonded validator set and perform the provided function
func (k Keeper) IterateBondedValidatorsByPower(ctx sdk.Context, fn func(index int64, validator types.ValidatorI) (stop bool)) {
store := ctx.KVStore(k.storeKey)
maxValidators := k.MaxValidators(ctx)
func (k Keeper) IterateBondedValidatorsByPower(ctx context.Context, fn func(index int64, validator types.ValidatorI) (stop bool)) error {
store := k.storeService.OpenKVStore(ctx)
maxValidators, err := k.MaxValidators(ctx)
if err != nil {
return err
}
iterator := storetypes.KVStoreReversePrefixIterator(store, types.ValidatorsByPowerIndexKey)
iterator, err := store.ReverseIterator(types.ValidatorsByPowerIndexKey, storetypes.PrefixEndBytes(types.ValidatorsByPowerIndexKey))
if err != nil {
return err
}
defer iterator.Close()
i := int64(0)
@ -52,11 +65,16 @@ func (k Keeper) IterateBondedValidatorsByPower(ctx sdk.Context, fn func(index in
i++
}
}
return nil
}
// iterate through the active validator set and perform the provided function
func (k Keeper) IterateLastValidators(ctx sdk.Context, fn func(index int64, validator types.ValidatorI) (stop bool)) {
iterator := k.LastValidatorsIterator(ctx)
func (k Keeper) IterateLastValidators(ctx context.Context, fn func(index int64, validator types.ValidatorI) (stop bool)) error {
iterator, err := k.LastValidatorsIterator(ctx)
if err != nil {
return err
}
defer iterator.Close()
i := int64(0)
@ -64,9 +82,9 @@ func (k Keeper) IterateLastValidators(ctx sdk.Context, fn func(index int64, vali
for ; iterator.Valid(); iterator.Next() {
address := types.AddressFromLastValidatorPowerKey(iterator.Key())
validator, found := k.GetValidator(ctx, address)
if !found {
panic(fmt.Sprintf("validator record not found for address: %v\n", address))
validator, err := k.GetValidator(ctx, address)
if err != nil {
return err
}
stop := fn(i, validator) // XXX is this safe will the validator unexposed fields be able to get written to?
@ -75,26 +93,17 @@ func (k Keeper) IterateLastValidators(ctx sdk.Context, fn func(index int64, vali
}
i++
}
return nil
}
// Validator gets the Validator interface for a particular address
func (k Keeper) Validator(ctx sdk.Context, address sdk.ValAddress) types.ValidatorI {
val, found := k.GetValidator(ctx, address)
if !found {
return nil
}
return val
func (k Keeper) Validator(ctx context.Context, address sdk.ValAddress) (types.ValidatorI, error) {
return k.GetValidator(ctx, address)
}
// ValidatorByConsAddr gets the validator interface for a particular pubkey
func (k Keeper) ValidatorByConsAddr(ctx sdk.Context, addr sdk.ConsAddress) types.ValidatorI {
val, found := k.GetValidatorByConsAddr(ctx, addr)
if !found {
return nil
}
return val
func (k Keeper) ValidatorByConsAddr(ctx context.Context, addr sdk.ConsAddress) (types.ValidatorI, error) {
return k.GetValidatorByConsAddr(ctx, addr)
}
// Delegation Set
@ -105,27 +114,32 @@ func (k Keeper) GetValidatorSet() types.ValidatorSet {
}
// Delegation get the delegation interface for a particular set of delegator and validator addresses
func (k Keeper) Delegation(ctx sdk.Context, addrDel sdk.AccAddress, addrVal sdk.ValAddress) types.DelegationI {
bond, ok := k.GetDelegation(ctx, addrDel, addrVal)
if !ok {
return nil
func (k Keeper) Delegation(ctx context.Context, addrDel sdk.AccAddress, addrVal sdk.ValAddress) (types.DelegationI, error) {
bond, err := k.GetDelegation(ctx, addrDel, addrVal)
if err != nil {
return nil, err
}
return bond
return bond, nil
}
// iterate through all of the delegations from a delegator
func (k Keeper) IterateDelegations(ctx sdk.Context, delAddr sdk.AccAddress,
func (k Keeper) IterateDelegations(ctx context.Context, delAddr sdk.AccAddress,
fn func(index int64, del types.DelegationI) (stop bool),
) {
store := ctx.KVStore(k.storeKey)
) error {
store := k.storeService.OpenKVStore(ctx)
delegatorPrefixKey := types.GetDelegationsKey(delAddr)
iterator := storetypes.KVStorePrefixIterator(store, delegatorPrefixKey) // smallest to largest
iterator, err := store.Iterator(delegatorPrefixKey, storetypes.PrefixEndBytes(delegatorPrefixKey))
if err != nil {
return err
}
defer iterator.Close()
for i := int64(0); iterator.Valid(); iterator.Next() {
del := types.MustUnmarshalDelegation(k.cdc, iterator.Value())
del, err := types.UnmarshalDelegation(k.cdc, iterator.Value())
if err != nil {
return err
}
stop := fn(i, del)
if stop {
@ -133,18 +147,25 @@ func (k Keeper) IterateDelegations(ctx sdk.Context, delAddr sdk.AccAddress,
}
i++
}
return nil
}
// return all delegations used during genesis dump
// TODO: remove this func, change all usage for iterate functionality
func (k Keeper) GetAllSDKDelegations(ctx sdk.Context) (delegations []types.Delegation) {
store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, types.DelegationKey)
func (k Keeper) GetAllSDKDelegations(ctx context.Context) (delegations []types.Delegation, err error) {
store := k.storeService.OpenKVStore(ctx)
iterator, err := store.Iterator(types.DelegationKey, storetypes.PrefixEndBytes(types.DelegationKey))
if err != nil {
return delegations, err
}
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Value())
delegation, err := types.UnmarshalDelegation(k.cdc, iterator.Value())
if err != nil {
return delegations, err
}
delegations = append(delegations, delegation)
}

File diff suppressed because it is too large Load Diff

View File

@ -44,20 +44,20 @@ func (s *KeeperTestSuite) TestDelegation() {
bond1to1 := stakingtypes.NewDelegation(addrDels[0], valAddrs[0], math.LegacyNewDec(9))
// check the empty keeper first
_, found := keeper.GetDelegation(ctx, addrDels[0], valAddrs[0])
require.False(found)
_, err := keeper.GetDelegation(ctx, addrDels[0], valAddrs[0])
require.ErrorIs(err, stakingtypes.ErrNoDelegation)
// set and retrieve a record
keeper.SetDelegation(ctx, bond1to1)
resBond, found := keeper.GetDelegation(ctx, addrDels[0], valAddrs[0])
require.True(found)
require.NoError(keeper.SetDelegation(ctx, bond1to1))
resBond, err := keeper.GetDelegation(ctx, addrDels[0], valAddrs[0])
require.NoError(err)
require.Equal(bond1to1, resBond)
// modify a records, save, and retrieve
bond1to1.Shares = math.LegacyNewDec(99)
keeper.SetDelegation(ctx, bond1to1)
resBond, found = keeper.GetDelegation(ctx, addrDels[0], valAddrs[0])
require.True(found)
require.NoError(keeper.SetDelegation(ctx, bond1to1))
resBond, err = keeper.GetDelegation(ctx, addrDels[0], valAddrs[0])
require.NoError(err)
require.Equal(bond1to1, resBond)
// add some more records
@ -66,28 +66,33 @@ func (s *KeeperTestSuite) TestDelegation() {
bond2to1 := stakingtypes.NewDelegation(addrDels[1], valAddrs[0], math.LegacyNewDec(9))
bond2to2 := stakingtypes.NewDelegation(addrDels[1], valAddrs[1], math.LegacyNewDec(9))
bond2to3 := stakingtypes.NewDelegation(addrDels[1], valAddrs[2], math.LegacyNewDec(9))
keeper.SetDelegation(ctx, bond1to2)
keeper.SetDelegation(ctx, bond1to3)
keeper.SetDelegation(ctx, bond2to1)
keeper.SetDelegation(ctx, bond2to2)
keeper.SetDelegation(ctx, bond2to3)
require.NoError(keeper.SetDelegation(ctx, bond1to2))
require.NoError(keeper.SetDelegation(ctx, bond1to3))
require.NoError(keeper.SetDelegation(ctx, bond2to1))
require.NoError(keeper.SetDelegation(ctx, bond2to2))
require.NoError(keeper.SetDelegation(ctx, bond2to3))
// test all bond retrieve capabilities
resBonds := keeper.GetDelegatorDelegations(ctx, addrDels[0], 5)
resBonds, err := keeper.GetDelegatorDelegations(ctx, addrDels[0], 5)
require.NoError(err)
require.Equal(3, len(resBonds))
require.Equal(bond1to1, resBonds[0])
require.Equal(bond1to2, resBonds[1])
require.Equal(bond1to3, resBonds[2])
resBonds = keeper.GetAllDelegatorDelegations(ctx, addrDels[0])
resBonds, err = keeper.GetAllDelegatorDelegations(ctx, addrDels[0])
require.NoError(err)
require.Equal(3, len(resBonds))
resBonds = keeper.GetDelegatorDelegations(ctx, addrDels[0], 2)
resBonds, err = keeper.GetDelegatorDelegations(ctx, addrDels[0], 2)
require.NoError(err)
require.Equal(2, len(resBonds))
resBonds = keeper.GetDelegatorDelegations(ctx, addrDels[1], 5)
resBonds, err = keeper.GetDelegatorDelegations(ctx, addrDels[1], 5)
require.NoError(err)
require.Equal(3, len(resBonds))
require.Equal(bond2to1, resBonds[0])
require.Equal(bond2to2, resBonds[1])
require.Equal(bond2to3, resBonds[2])
allBonds := keeper.GetAllDelegations(ctx)
allBonds, err := keeper.GetAllDelegations(ctx)
require.NoError(err)
require.Equal(6, len(allBonds))
require.Equal(bond1to1, allBonds[0])
require.Equal(bond1to2, allBonds[1])
@ -96,9 +101,11 @@ func (s *KeeperTestSuite) TestDelegation() {
require.Equal(bond2to2, allBonds[4])
require.Equal(bond2to3, allBonds[5])
resVals := keeper.GetDelegatorValidators(ctx, addrDels[0], 3)
resVals, err := keeper.GetDelegatorValidators(ctx, addrDels[0], 3)
require.NoError(err)
require.Equal(3, len(resVals))
resVals = keeper.GetDelegatorValidators(ctx, addrDels[1], 4)
resVals, err = keeper.GetDelegatorValidators(ctx, addrDels[1], 4)
require.NoError(err)
require.Equal(3, len(resVals))
for i := 0; i < 3; i++ {
@ -110,35 +117,40 @@ func (s *KeeperTestSuite) TestDelegation() {
require.Nil(err)
require.Equal(valAddrs[i], resVal.GetOperator())
resDels := keeper.GetValidatorDelegations(ctx, valAddrs[i])
resDels, err := keeper.GetValidatorDelegations(ctx, valAddrs[i])
require.NoError(err)
require.Len(resDels, 2)
}
// test total bonded for single delegator
expBonded := bond1to1.Shares.Add(bond2to1.Shares).Add(bond1to3.Shares)
resDelBond := keeper.GetDelegatorBonded(ctx, addrDels[0])
resDelBond, err := keeper.GetDelegatorBonded(ctx, addrDels[0])
require.NoError(err)
require.Equal(expBonded, math.LegacyNewDecFromInt(resDelBond))
// delete a record
keeper.RemoveDelegation(ctx, bond2to3)
_, found = keeper.GetDelegation(ctx, addrDels[1], valAddrs[2])
require.False(found)
resBonds = keeper.GetDelegatorDelegations(ctx, addrDels[1], 5)
require.NoError(keeper.RemoveDelegation(ctx, bond2to3))
_, err = keeper.GetDelegation(ctx, addrDels[1], valAddrs[2])
require.ErrorIs(err, stakingtypes.ErrNoDelegation)
resBonds, err = keeper.GetDelegatorDelegations(ctx, addrDels[1], 5)
require.NoError(err)
require.Equal(2, len(resBonds))
require.Equal(bond2to1, resBonds[0])
require.Equal(bond2to2, resBonds[1])
resBonds = keeper.GetAllDelegatorDelegations(ctx, addrDels[1])
resBonds, err = keeper.GetAllDelegatorDelegations(ctx, addrDels[1])
require.NoError(err)
require.Equal(2, len(resBonds))
// delete all the records from delegator 2
keeper.RemoveDelegation(ctx, bond2to1)
keeper.RemoveDelegation(ctx, bond2to2)
_, found = keeper.GetDelegation(ctx, addrDels[1], valAddrs[0])
require.False(found)
_, found = keeper.GetDelegation(ctx, addrDels[1], valAddrs[1])
require.False(found)
resBonds = keeper.GetDelegatorDelegations(ctx, addrDels[1], 5)
require.NoError(keeper.RemoveDelegation(ctx, bond2to1))
require.NoError(keeper.RemoveDelegation(ctx, bond2to2))
_, err = keeper.GetDelegation(ctx, addrDels[1], valAddrs[0])
require.ErrorIs(err, stakingtypes.ErrNoDelegation)
_, err = keeper.GetDelegation(ctx, addrDels[1], valAddrs[1])
require.ErrorIs(err, stakingtypes.ErrNoDelegation)
resBonds, err = keeper.GetDelegatorDelegations(ctx, addrDels[1], 5)
require.NoError(err)
require.Equal(0, len(resBonds))
}
@ -169,7 +181,8 @@ func (s *KeeperTestSuite) TestDelegationsByValIndex() {
_, err := s.msgServer.Delegate(ctx, stakingtypes.NewMsgDelegate(addrDels[0], valAddrs[0], sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(2))))
require.NoError(err)
dels := s.stakingKeeper.GetValidatorDelegations(ctx, valAddrs[0])
dels, err := s.stakingKeeper.GetValidatorDelegations(ctx, valAddrs[0])
require.NoError(err)
require.Len(dels, 1)
// delegate 4 tokens
@ -178,7 +191,8 @@ func (s *KeeperTestSuite) TestDelegationsByValIndex() {
_, err = s.msgServer.Delegate(ctx, stakingtypes.NewMsgDelegate(addrDels[1], valAddrs[0], sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(4))))
require.NoError(err)
dels = s.stakingKeeper.GetValidatorDelegations(ctx, valAddrs[0])
dels, err = s.stakingKeeper.GetValidatorDelegations(ctx, valAddrs[0])
require.NoError(err)
require.Len(dels, 2)
// undelegate 1 token from del1
@ -187,7 +201,8 @@ func (s *KeeperTestSuite) TestDelegationsByValIndex() {
_, err = s.msgServer.Undelegate(ctx, stakingtypes.NewMsgUndelegate(addrDels[0], valAddrs[0], sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1))))
require.NoError(err)
dels = s.stakingKeeper.GetValidatorDelegations(ctx, valAddrs[0])
dels, err = s.stakingKeeper.GetValidatorDelegations(ctx, valAddrs[0])
require.NoError(err)
require.Len(dels, 2)
// undelegate 1 token from del1
@ -196,7 +211,8 @@ func (s *KeeperTestSuite) TestDelegationsByValIndex() {
_, err = s.msgServer.Undelegate(ctx, stakingtypes.NewMsgUndelegate(addrDels[0], valAddrs[0], sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1))))
require.NoError(err)
dels = s.stakingKeeper.GetValidatorDelegations(ctx, valAddrs[0])
dels, err = s.stakingKeeper.GetValidatorDelegations(ctx, valAddrs[0])
require.NoError(err)
require.Len(dels, 1)
// undelegate 2 tokens from del2
@ -205,7 +221,8 @@ func (s *KeeperTestSuite) TestDelegationsByValIndex() {
_, err = s.msgServer.Undelegate(ctx, stakingtypes.NewMsgUndelegate(addrDels[1], valAddrs[0], sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(2))))
require.NoError(err)
dels = s.stakingKeeper.GetValidatorDelegations(ctx, valAddrs[0])
dels, err = s.stakingKeeper.GetValidatorDelegations(ctx, valAddrs[0])
require.NoError(err)
require.Len(dels, 1)
// undelegate 2 tokens from del2
@ -214,7 +231,8 @@ func (s *KeeperTestSuite) TestDelegationsByValIndex() {
_, err = s.msgServer.Undelegate(ctx, stakingtypes.NewMsgUndelegate(addrDels[1], valAddrs[0], sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(2))))
require.NoError(err)
dels = s.stakingKeeper.GetValidatorDelegations(ctx, valAddrs[0])
dels, err = s.stakingKeeper.GetValidatorDelegations(ctx, valAddrs[0])
require.NoError(err)
require.Len(dels, 0)
}
@ -237,38 +255,43 @@ func (s *KeeperTestSuite) TestUnbondingDelegation() {
)
// set and retrieve a record
keeper.SetUnbondingDelegation(ctx, ubd)
resUnbond, found := keeper.GetUnbondingDelegation(ctx, delAddrs[0], valAddrs[0])
require.True(found)
require.NoError(keeper.SetUnbondingDelegation(ctx, ubd))
resUnbond, err := keeper.GetUnbondingDelegation(ctx, delAddrs[0], valAddrs[0])
require.NoError(err)
require.Equal(ubd, resUnbond)
// modify a records, save, and retrieve
expUnbond := math.NewInt(21)
ubd.Entries[0].Balance = expUnbond
keeper.SetUnbondingDelegation(ctx, ubd)
require.NoError(keeper.SetUnbondingDelegation(ctx, ubd))
resUnbonds := keeper.GetUnbondingDelegations(ctx, delAddrs[0], 5)
resUnbonds, err := keeper.GetUnbondingDelegations(ctx, delAddrs[0], 5)
require.NoError(err)
require.Equal(1, len(resUnbonds))
resUnbonds = keeper.GetAllUnbondingDelegations(ctx, delAddrs[0])
resUnbonds, err = keeper.GetAllUnbondingDelegations(ctx, delAddrs[0])
require.NoError(err)
require.Equal(1, len(resUnbonds))
resUnbond, found = keeper.GetUnbondingDelegation(ctx, delAddrs[0], valAddrs[0])
require.True(found)
resUnbond, err = keeper.GetUnbondingDelegation(ctx, delAddrs[0], valAddrs[0])
require.NoError(err)
require.Equal(ubd, resUnbond)
resDelUnbond := keeper.GetDelegatorUnbonding(ctx, delAddrs[0])
resDelUnbond, err := keeper.GetDelegatorUnbonding(ctx, delAddrs[0])
require.NoError(err)
require.Equal(expUnbond, resDelUnbond)
// delete a record
keeper.RemoveUnbondingDelegation(ctx, ubd)
_, found = keeper.GetUnbondingDelegation(ctx, delAddrs[0], valAddrs[0])
require.False(found)
require.NoError(keeper.RemoveUnbondingDelegation(ctx, ubd))
_, err = keeper.GetUnbondingDelegation(ctx, delAddrs[0], valAddrs[0])
require.ErrorIs(err, stakingtypes.ErrNoUnbondingDelegation)
resUnbonds = keeper.GetUnbondingDelegations(ctx, delAddrs[0], 5)
resUnbonds, err = keeper.GetUnbondingDelegations(ctx, delAddrs[0], 5)
require.NoError(err)
require.Equal(0, len(resUnbonds))
resUnbonds = keeper.GetAllUnbondingDelegations(ctx, delAddrs[0])
resUnbonds, err = keeper.GetAllUnbondingDelegations(ctx, delAddrs[0])
require.NoError(err)
require.Equal(0, len(resUnbonds))
}
@ -288,44 +311,51 @@ func (s *KeeperTestSuite) TestUnbondingDelegationsFromValidator() {
)
// set and retrieve a record
keeper.SetUnbondingDelegation(ctx, ubd)
resUnbond, found := keeper.GetUnbondingDelegation(ctx, delAddrs[0], valAddrs[0])
require.True(found)
require.NoError(keeper.SetUnbondingDelegation(ctx, ubd))
resUnbond, err := keeper.GetUnbondingDelegation(ctx, delAddrs[0], valAddrs[0])
require.NoError(err)
require.Equal(ubd, resUnbond)
// modify a records, save, and retrieve
expUnbond := sdk.NewInt(21)
ubd.Entries[0].Balance = expUnbond
keeper.SetUnbondingDelegation(ctx, ubd)
require.NoError(keeper.SetUnbondingDelegation(ctx, ubd))
resUnbonds := keeper.GetUnbondingDelegations(ctx, delAddrs[0], 5)
resUnbonds, err := keeper.GetUnbondingDelegations(ctx, delAddrs[0], 5)
require.NoError(err)
require.Equal(1, len(resUnbonds))
resUnbonds = keeper.GetAllUnbondingDelegations(ctx, delAddrs[0])
resUnbonds, err = keeper.GetAllUnbondingDelegations(ctx, delAddrs[0])
require.NoError(err)
require.Equal(1, len(resUnbonds))
resUnbonds = keeper.GetUnbondingDelegationsFromValidator(ctx, valAddrs[0])
resUnbonds, err = keeper.GetUnbondingDelegationsFromValidator(ctx, valAddrs[0])
require.NoError(err)
require.Equal(1, len(resUnbonds))
resUnbond, found = keeper.GetUnbondingDelegation(ctx, delAddrs[0], valAddrs[0])
require.True(found)
resUnbond, err = keeper.GetUnbondingDelegation(ctx, delAddrs[0], valAddrs[0])
require.NoError(err)
require.Equal(ubd, resUnbond)
resDelUnbond := keeper.GetDelegatorUnbonding(ctx, delAddrs[0])
resDelUnbond, err := keeper.GetDelegatorUnbonding(ctx, delAddrs[0])
require.NoError(err)
require.Equal(expUnbond, resDelUnbond)
// delete a record
keeper.RemoveUnbondingDelegation(ctx, ubd)
_, found = keeper.GetUnbondingDelegation(ctx, delAddrs[0], valAddrs[0])
require.False(found)
require.NoError(keeper.RemoveUnbondingDelegation(ctx, ubd))
_, err = keeper.GetUnbondingDelegation(ctx, delAddrs[0], valAddrs[0])
require.ErrorIs(err, stakingtypes.ErrNoUnbondingDelegation)
resUnbonds = keeper.GetUnbondingDelegations(ctx, delAddrs[0], 5)
resUnbonds, err = keeper.GetUnbondingDelegations(ctx, delAddrs[0], 5)
require.NoError(err)
require.Equal(0, len(resUnbonds))
resUnbonds = keeper.GetAllUnbondingDelegations(ctx, delAddrs[0])
resUnbonds, err = keeper.GetAllUnbondingDelegations(ctx, delAddrs[0])
require.NoError(err)
require.Equal(0, len(resUnbonds))
resUnbonds = keeper.GetUnbondingDelegationsFromValidator(ctx, valAddrs[0])
resUnbonds, err = keeper.GetUnbondingDelegationsFromValidator(ctx, valAddrs[0])
require.NoError(err)
require.Equal(0, len(resUnbonds))
}
@ -345,17 +375,17 @@ func (s *KeeperTestSuite) TestUnbondDelegation() {
_ = stakingkeeper.TestingUpdateValidator(keeper, ctx, validator, true)
delegation := stakingtypes.NewDelegation(delAddrs[0], valAddrs[0], issuedShares)
keeper.SetDelegation(ctx, delegation)
require.NoError(keeper.SetDelegation(ctx, delegation))
bondTokens := keeper.TokensFromConsensusPower(ctx, 6)
amount, err := keeper.Unbond(ctx, delAddrs[0], valAddrs[0], math.LegacyNewDecFromInt(bondTokens))
require.NoError(err)
require.Equal(bondTokens, amount) // shares to be added to an unbonding delegation
delegation, found := keeper.GetDelegation(ctx, delAddrs[0], valAddrs[0])
require.True(found)
validator, found = keeper.GetValidator(ctx, valAddrs[0])
require.True(found)
delegation, err = keeper.GetDelegation(ctx, delAddrs[0], valAddrs[0])
require.NoError(err)
validator, err = keeper.GetValidator(ctx, valAddrs[0])
require.NoError(err)
remainingTokens := startTokens.Sub(bondTokens)
@ -381,21 +411,21 @@ func (s *KeeperTestSuite) TestUndelegateSelfDelegationBelowMinSelfDelegation() {
s.bankKeeper.EXPECT().SendCoinsFromModuleToModule(gomock.Any(), stakingtypes.NotBondedPoolName, stakingtypes.BondedPoolName, gomock.Any())
validator = stakingkeeper.TestingUpdateValidator(keeper, ctx, validator, true)
keeper.SetValidatorByConsAddr(ctx, validator)
require.NoError(keeper.SetValidatorByConsAddr(ctx, validator))
require.True(validator.IsBonded())
selfDelegation := stakingtypes.NewDelegation(sdk.AccAddress(addrVals[0].Bytes()), addrVals[0], issuedShares)
keeper.SetDelegation(ctx, selfDelegation)
require.NoError(keeper.SetDelegation(ctx, selfDelegation))
// create a second delegation to this validator
keeper.DeleteValidatorByPowerIndex(ctx, validator)
require.NoError(keeper.DeleteValidatorByPowerIndex(ctx, validator))
validator, issuedShares = validator.AddTokensFromDel(delTokens)
require.True(validator.IsBonded())
require.Equal(delTokens, issuedShares.RoundInt())
validator = stakingkeeper.TestingUpdateValidator(keeper, ctx, validator, true)
delegation := stakingtypes.NewDelegation(addrDels[0], addrVals[0], issuedShares)
keeper.SetDelegation(ctx, delegation)
require.NoError(keeper.SetDelegation(ctx, delegation))
val0AccAddr := sdk.AccAddress(addrVals[0].Bytes())
s.bankKeeper.EXPECT().SendCoinsFromModuleToModule(gomock.Any(), stakingtypes.BondedPoolName, stakingtypes.NotBondedPoolName, gomock.Any())
@ -406,8 +436,8 @@ func (s *KeeperTestSuite) TestUndelegateSelfDelegationBelowMinSelfDelegation() {
s.bankKeeper.EXPECT().SendCoinsFromModuleToModule(gomock.Any(), stakingtypes.BondedPoolName, stakingtypes.NotBondedPoolName, gomock.Any())
s.applyValidatorSetUpdates(ctx, keeper, 1)
validator, found := keeper.GetValidator(ctx, addrVals[0])
require.True(found)
validator, err = keeper.GetValidator(ctx, addrVals[0])
require.NoError(err)
require.Equal(keeper.TokensFromConsensusPower(ctx, 14), validator.Tokens)
require.Equal(stakingtypes.Unbonding, validator.Status)
require.True(validator.Jailed)
@ -422,7 +452,7 @@ func (s *KeeperTestSuite) TestUndelegateFromUnbondingValidator() {
// create a validator with a self-delegation
validator := testutil.NewValidator(s.T(), addrVals[0], PKs[0])
keeper.SetValidatorByConsAddr(ctx, validator)
require.NoError(keeper.SetValidatorByConsAddr(ctx, validator))
validator, issuedShares := validator.AddTokensFromDel(delTokens)
require.Equal(delTokens, issuedShares.RoundInt())
@ -432,17 +462,17 @@ func (s *KeeperTestSuite) TestUndelegateFromUnbondingValidator() {
require.True(validator.IsBonded())
selfDelegation := stakingtypes.NewDelegation(addrVals[0].Bytes(), addrVals[0], issuedShares)
keeper.SetDelegation(ctx, selfDelegation)
require.NoError(keeper.SetDelegation(ctx, selfDelegation))
// create a second delegation to this validator
keeper.DeleteValidatorByPowerIndex(ctx, validator)
require.NoError(keeper.DeleteValidatorByPowerIndex(ctx, validator))
validator, issuedShares = validator.AddTokensFromDel(delTokens)
require.Equal(delTokens, issuedShares.RoundInt())
stakingkeeper.TestingUpdateValidator(keeper, ctx, validator, true)
delegation := stakingtypes.NewDelegation(addrDels[1], addrVals[0], issuedShares)
keeper.SetDelegation(ctx, delegation)
require.NoError(keeper.SetDelegation(ctx, delegation))
header := ctx.BlockHeader()
blockHeight := int64(10)
@ -462,10 +492,11 @@ func (s *KeeperTestSuite) TestUndelegateFromUnbondingValidator() {
s.bankKeeper.EXPECT().SendCoinsFromModuleToModule(gomock.Any(), stakingtypes.BondedPoolName, stakingtypes.NotBondedPoolName, gomock.Any())
s.applyValidatorSetUpdates(ctx, keeper, 1)
validator, found := keeper.GetValidator(ctx, addrVals[0])
require.True(found)
validator, err = keeper.GetValidator(ctx, addrVals[0])
require.NoError(err)
require.Equal(blockHeight, validator.UnbondingHeight)
params := keeper.GetParams(ctx)
params, err := keeper.GetParams(ctx)
require.NoError(err)
require.True(blockTime.Add(params.UnbondingTime).Equal(validator.UnbondingTime))
blockHeight2 := int64(20)
@ -480,8 +511,8 @@ func (s *KeeperTestSuite) TestUndelegateFromUnbondingValidator() {
require.Equal(math.LegacyNewDecFromInt(undelegatedAmount), undelegateAmount)
// retrieve the unbonding delegation
ubd, found := keeper.GetUnbondingDelegation(ctx, addrDels[1], addrVals[0])
require.True(found)
ubd, err := keeper.GetUnbondingDelegation(ctx, addrDels[1], addrVals[0])
require.NoError(err)
require.Len(ubd.Entries, 1)
require.True(ubd.Entries[0].Balance.Equal(math.NewInt(6)))
require.Equal(blockHeight2, ubd.Entries[0].CreationHeight)
@ -497,7 +528,7 @@ func (s *KeeperTestSuite) TestUndelegateFromUnbondedValidator() {
// create a validator with a self-delegation
validator := testutil.NewValidator(s.T(), addrVals[0], PKs[0])
keeper.SetValidatorByConsAddr(ctx, validator)
require.NoError(keeper.SetValidatorByConsAddr(ctx, validator))
valTokens := keeper.TokensFromConsensusPower(ctx, 10)
validator, issuedShares := validator.AddTokensFromDel(valTokens)
@ -508,16 +539,16 @@ func (s *KeeperTestSuite) TestUndelegateFromUnbondedValidator() {
val0AccAddr := sdk.AccAddress(addrVals[0])
selfDelegation := stakingtypes.NewDelegation(val0AccAddr, addrVals[0], issuedShares)
keeper.SetDelegation(ctx, selfDelegation)
require.NoError(keeper.SetDelegation(ctx, selfDelegation))
// create a second delegation to this validator
keeper.DeleteValidatorByPowerIndex(ctx, validator)
require.NoError(keeper.DeleteValidatorByPowerIndex(ctx, validator))
validator, issuedShares = validator.AddTokensFromDel(delTokens)
require.Equal(delTokens, issuedShares.RoundInt())
validator = stakingkeeper.TestingUpdateValidator(keeper, ctx, validator, true)
require.True(validator.IsBonded())
delegation := stakingtypes.NewDelegation(addrDels[1], addrVals[0], issuedShares)
keeper.SetDelegation(ctx, delegation)
require.NoError(keeper.SetDelegation(ctx, delegation))
ctx = ctx.WithBlockHeight(10)
ctx = ctx.WithBlockTime(time.Unix(333, 0))
@ -532,19 +563,21 @@ func (s *KeeperTestSuite) TestUndelegateFromUnbondedValidator() {
s.bankKeeper.EXPECT().SendCoinsFromModuleToModule(gomock.Any(), stakingtypes.BondedPoolName, stakingtypes.NotBondedPoolName, gomock.Any())
s.applyValidatorSetUpdates(ctx, keeper, 1)
validator, found := keeper.GetValidator(ctx, addrVals[0])
require.True(found)
validator, err = keeper.GetValidator(ctx, addrVals[0])
require.NoError(err)
require.Equal(ctx.BlockHeight(), validator.UnbondingHeight)
params := keeper.GetParams(ctx)
params, err := keeper.GetParams(ctx)
require.NoError(err)
require.True(ctx.BlockHeader().Time.Add(params.UnbondingTime).Equal(validator.UnbondingTime))
// unbond the validator
ctx = ctx.WithBlockTime(validator.UnbondingTime)
keeper.UnbondAllMatureValidators(ctx)
err = keeper.UnbondAllMatureValidators(ctx)
require.NoError(err)
// Make sure validator is still in state because there is still an outstanding delegation
validator, found = keeper.GetValidator(ctx, addrVals[0])
require.True(found)
validator, err = keeper.GetValidator(ctx, addrVals[0])
require.NoError(err)
require.Equal(validator.Status, stakingtypes.Unbonded)
// unbond some of the other delegation's shares
@ -560,8 +593,8 @@ func (s *KeeperTestSuite) TestUndelegateFromUnbondedValidator() {
require.Equal(amount3, remainingTokens)
// now validator should be deleted from state
validator, found = keeper.GetValidator(ctx, addrVals[0])
require.False(found, "%v", validator)
validator, err = keeper.GetValidator(ctx, addrVals[0])
require.ErrorIs(err, stakingtypes.ErrNoValidatorFound)
}
func (s *KeeperTestSuite) TestUnbondingAllDelegationFromValidator() {
@ -573,7 +606,7 @@ func (s *KeeperTestSuite) TestUnbondingAllDelegationFromValidator() {
// create a validator with a self-delegation
validator := testutil.NewValidator(s.T(), addrVals[0], PKs[0])
keeper.SetValidatorByConsAddr(ctx, validator)
require.NoError(keeper.SetValidatorByConsAddr(ctx, validator))
valTokens := keeper.TokensFromConsensusPower(ctx, 10)
validator, issuedShares := validator.AddTokensFromDel(valTokens)
@ -585,10 +618,10 @@ func (s *KeeperTestSuite) TestUnbondingAllDelegationFromValidator() {
val0AccAddr := sdk.AccAddress(addrVals[0].Bytes())
selfDelegation := stakingtypes.NewDelegation(val0AccAddr, addrVals[0], issuedShares)
keeper.SetDelegation(ctx, selfDelegation)
require.NoError(keeper.SetDelegation(ctx, selfDelegation))
// create a second delegation to this validator
keeper.DeleteValidatorByPowerIndex(ctx, validator)
require.NoError(keeper.DeleteValidatorByPowerIndex(ctx, validator))
validator, issuedShares = validator.AddTokensFromDel(delTokens)
require.Equal(delTokens, issuedShares.RoundInt())
@ -596,7 +629,7 @@ func (s *KeeperTestSuite) TestUnbondingAllDelegationFromValidator() {
require.True(validator.IsBonded())
delegation := stakingtypes.NewDelegation(addrDels[1], addrVals[0], issuedShares)
keeper.SetDelegation(ctx, delegation)
require.NoError(keeper.SetDelegation(ctx, delegation))
ctx = ctx.WithBlockHeight(10)
ctx = ctx.WithBlockTime(time.Unix(333, 0))
@ -617,17 +650,18 @@ func (s *KeeperTestSuite) TestUnbondingAllDelegationFromValidator() {
require.Equal(amount2, delTokens)
// validator should still be in state and still be in unbonding state
validator, found := keeper.GetValidator(ctx, addrVals[0])
require.True(found)
validator, err = keeper.GetValidator(ctx, addrVals[0])
require.NoError(err)
require.Equal(validator.Status, stakingtypes.Unbonding)
// unbond the validator
ctx = ctx.WithBlockTime(validator.UnbondingTime)
keeper.UnbondAllMatureValidators(ctx)
err = keeper.UnbondAllMatureValidators(ctx)
require.NoError(err)
// validator should now be deleted from state
_, found = keeper.GetValidator(ctx, addrVals[0])
require.False(found)
_, err = keeper.GetValidator(ctx, addrVals[0])
require.ErrorIs(err, stakingtypes.ErrNoValidatorFound)
}
// Make sure that that the retrieving the delegations doesn't affect the state
@ -642,17 +676,20 @@ func (s *KeeperTestSuite) TestGetRedelegationsFromSrcValidator() {
math.LegacyNewDec(5), 0)
// set and retrieve a record
keeper.SetRedelegation(ctx, rd)
resBond, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
require.True(found)
err := keeper.SetRedelegation(ctx, rd)
require.NoError(err)
resBond, err := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
require.NoError(err)
// get the redelegations one time
redelegations := keeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0])
redelegations, err := keeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0])
require.NoError(err)
require.Equal(1, len(redelegations))
require.Equal(redelegations[0], resBond)
// get the redelegations a second time, should be exactly the same
redelegations = keeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0])
redelegations, err = keeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0])
require.NoError(err)
require.Equal(1, len(redelegations))
require.Equal(redelegations[0], resBond)
}
@ -669,55 +706,67 @@ func (s *KeeperTestSuite) TestRedelegation() {
math.LegacyNewDec(5), 0)
// test shouldn't have and redelegations
has := keeper.HasReceivingRedelegation(ctx, addrDels[0], addrVals[1])
has, err := keeper.HasReceivingRedelegation(ctx, addrDels[0], addrVals[1])
require.NoError(err)
require.False(has)
// set and retrieve a record
keeper.SetRedelegation(ctx, rd)
resRed, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
require.True(found)
err = keeper.SetRedelegation(ctx, rd)
require.NoError(err)
resRed, err := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
require.NoError(err)
redelegations := keeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0])
redelegations, err := keeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0])
require.NoError(err)
require.Equal(1, len(redelegations))
require.Equal(redelegations[0], resRed)
redelegations = keeper.GetRedelegations(ctx, addrDels[0], 5)
redelegations, err = keeper.GetRedelegations(ctx, addrDels[0], 5)
require.NoError(err)
require.Equal(1, len(redelegations))
require.Equal(redelegations[0], resRed)
redelegations = keeper.GetAllRedelegations(ctx, addrDels[0], nil, nil)
redelegations, err = keeper.GetAllRedelegations(ctx, addrDels[0], nil, nil)
require.NoError(err)
require.Equal(1, len(redelegations))
require.Equal(redelegations[0], resRed)
// check if has the redelegation
has = keeper.HasReceivingRedelegation(ctx, addrDels[0], addrVals[1])
has, err = keeper.HasReceivingRedelegation(ctx, addrDels[0], addrVals[1])
require.NoError(err)
require.True(has)
// modify a records, save, and retrieve
rd.Entries[0].SharesDst = math.LegacyNewDec(21)
keeper.SetRedelegation(ctx, rd)
err = keeper.SetRedelegation(ctx, rd)
require.NoError(err)
resRed, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
require.True(found)
resRed, err = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
require.NoError(err)
require.Equal(rd, resRed)
redelegations = keeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0])
redelegations, err = keeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0])
require.NoError(err)
require.Equal(1, len(redelegations))
require.Equal(redelegations[0], resRed)
redelegations = keeper.GetRedelegations(ctx, addrDels[0], 5)
redelegations, err = keeper.GetRedelegations(ctx, addrDels[0], 5)
require.NoError(err)
require.Equal(1, len(redelegations))
require.Equal(redelegations[0], resRed)
// delete a record
keeper.RemoveRedelegation(ctx, rd)
_, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
require.False(found)
err = keeper.RemoveRedelegation(ctx, rd)
require.NoError(err)
_, err = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
require.ErrorIs(err, stakingtypes.ErrNoRedelegation)
redelegations = keeper.GetRedelegations(ctx, addrDels[0], 5)
redelegations, err = keeper.GetRedelegations(ctx, addrDels[0], 5)
require.NoError(err)
require.Equal(0, len(redelegations))
redelegations = keeper.GetAllRedelegations(ctx, addrDels[0], nil, nil)
redelegations, err = keeper.GetAllRedelegations(ctx, addrDels[0], nil, nil)
require.NoError(err)
require.Equal(0, len(redelegations))
}
@ -740,7 +789,7 @@ func (s *KeeperTestSuite) TestRedelegateToSameValidator() {
val0AccAddr := sdk.AccAddress(addrVals[0].Bytes())
selfDelegation := stakingtypes.NewDelegation(val0AccAddr, addrVals[0], issuedShares)
keeper.SetDelegation(ctx, selfDelegation)
require.NoError(keeper.SetDelegation(ctx, selfDelegation))
_, err := keeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[0], math.LegacyNewDec(5))
require.Error(err)
@ -762,7 +811,7 @@ func (s *KeeperTestSuite) TestRedelegationMaxEntries() {
_ = stakingkeeper.TestingUpdateValidator(keeper, ctx, validator, true)
val0AccAddr := sdk.AccAddress(addrVals[0].Bytes())
selfDelegation := stakingtypes.NewDelegation(val0AccAddr, addrVals[0], issuedShares)
keeper.SetDelegation(ctx, selfDelegation)
require.NoError(keeper.SetDelegation(ctx, selfDelegation))
// create a second validator
validator2 := testutil.NewValidator(s.T(), addrVals[1], PKs[1])
@ -773,7 +822,8 @@ func (s *KeeperTestSuite) TestRedelegationMaxEntries() {
validator2 = stakingkeeper.TestingUpdateValidator(keeper, ctx, validator2, true)
require.Equal(stakingtypes.Bonded, validator2.Status)
maxEntries := keeper.MaxEntries(ctx)
maxEntries, err := keeper.MaxEntries(ctx)
require.NoError(err)
// redelegations should pass
var completionTime time.Time
@ -784,7 +834,7 @@ func (s *KeeperTestSuite) TestRedelegationMaxEntries() {
}
// an additional redelegation should fail due to max entries
_, err := keeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1], math.LegacyNewDec(1))
_, err = keeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1], math.LegacyNewDec(1))
require.Error(err)
// mature redelegations
@ -805,7 +855,7 @@ func (s *KeeperTestSuite) TestRedelegateSelfDelegation() {
// create a validator with a self-delegation
validator := testutil.NewValidator(s.T(), addrVals[0], PKs[0])
keeper.SetValidatorByConsAddr(ctx, validator)
require.NoError(keeper.SetValidatorByConsAddr(ctx, validator))
valTokens := keeper.TokensFromConsensusPower(ctx, 10)
validator, issuedShares := validator.AddTokensFromDel(valTokens)
@ -816,7 +866,7 @@ func (s *KeeperTestSuite) TestRedelegateSelfDelegation() {
val0AccAddr := sdk.AccAddress(addrVals[0])
selfDelegation := stakingtypes.NewDelegation(val0AccAddr, addrVals[0], issuedShares)
keeper.SetDelegation(ctx, selfDelegation)
require.NoError(keeper.SetDelegation(ctx, selfDelegation))
// create a second validator
validator2 := testutil.NewValidator(s.T(), addrVals[1], PKs[1])
@ -833,7 +883,7 @@ func (s *KeeperTestSuite) TestRedelegateSelfDelegation() {
stakingkeeper.TestingUpdateValidator(keeper, ctx, validator, true)
delegation := stakingtypes.NewDelegation(addrDels[0], addrVals[0], issuedShares)
keeper.SetDelegation(ctx, delegation)
require.NoError(keeper.SetDelegation(ctx, delegation))
_, err := keeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1], math.LegacyNewDecFromInt(delTokens))
require.NoError(err)
@ -842,8 +892,8 @@ func (s *KeeperTestSuite) TestRedelegateSelfDelegation() {
s.bankKeeper.EXPECT().SendCoinsFromModuleToModule(gomock.Any(), stakingtypes.BondedPoolName, stakingtypes.NotBondedPoolName, gomock.Any())
s.applyValidatorSetUpdates(ctx, keeper, 2)
validator, found := keeper.GetValidator(ctx, addrVals[0])
require.True(found)
validator, err = keeper.GetValidator(ctx, addrVals[0])
require.NoError(err)
require.Equal(valTokens, validator.Tokens)
require.Equal(stakingtypes.Unbonding, validator.Status)
}
@ -856,7 +906,7 @@ func (s *KeeperTestSuite) TestRedelegateFromUnbondingValidator() {
// create a validator with a self-delegation
validator := testutil.NewValidator(s.T(), addrVals[0], PKs[0])
keeper.SetValidatorByConsAddr(ctx, validator)
require.NoError(keeper.SetValidatorByConsAddr(ctx, validator))
valTokens := keeper.TokensFromConsensusPower(ctx, 10)
validator, issuedShares := validator.AddTokensFromDel(valTokens)
@ -865,16 +915,16 @@ func (s *KeeperTestSuite) TestRedelegateFromUnbondingValidator() {
validator = stakingkeeper.TestingUpdateValidator(keeper, ctx, validator, true)
val0AccAddr := sdk.AccAddress(addrVals[0].Bytes())
selfDelegation := stakingtypes.NewDelegation(val0AccAddr, addrVals[0], issuedShares)
keeper.SetDelegation(ctx, selfDelegation)
require.NoError(keeper.SetDelegation(ctx, selfDelegation))
// create a second delegation to this validator
keeper.DeleteValidatorByPowerIndex(ctx, validator)
require.NoError(keeper.DeleteValidatorByPowerIndex(ctx, validator))
delTokens := keeper.TokensFromConsensusPower(ctx, 10)
validator, issuedShares = validator.AddTokensFromDel(delTokens)
require.Equal(delTokens, issuedShares.RoundInt())
stakingkeeper.TestingUpdateValidator(keeper, ctx, validator, true)
delegation := stakingtypes.NewDelegation(addrDels[1], addrVals[0], issuedShares)
keeper.SetDelegation(ctx, delegation)
require.NoError(keeper.SetDelegation(ctx, delegation))
// create a second validator
validator2 := testutil.NewValidator(s.T(), addrVals[1], PKs[1])
@ -900,10 +950,11 @@ func (s *KeeperTestSuite) TestRedelegateFromUnbondingValidator() {
s.bankKeeper.EXPECT().SendCoinsFromModuleToModule(gomock.Any(), stakingtypes.BondedPoolName, stakingtypes.NotBondedPoolName, gomock.Any())
s.applyValidatorSetUpdates(ctx, keeper, 1)
validator, found := keeper.GetValidator(ctx, addrVals[0])
require.True(found)
validator, err = keeper.GetValidator(ctx, addrVals[0])
require.NoError(err)
require.Equal(blockHeight, validator.UnbondingHeight)
params := keeper.GetParams(ctx)
params, err := keeper.GetParams(ctx)
require.NoError(err)
require.True(blockTime.Add(params.UnbondingTime).Equal(validator.UnbondingTime))
// change the context
@ -921,8 +972,8 @@ func (s *KeeperTestSuite) TestRedelegateFromUnbondingValidator() {
require.NoError(err)
// retrieve the unbonding delegation
ubd, found := keeper.GetRedelegation(ctx, addrDels[1], addrVals[0], addrVals[1])
require.True(found)
ubd, err := keeper.GetRedelegation(ctx, addrDels[1], addrVals[0], addrVals[1])
require.NoError(err)
require.Len(ubd.Entries, 1)
require.Equal(blockHeight, ubd.Entries[0].CreationHeight)
require.True(blockTime.Add(params.UnbondingTime).Equal(ubd.Entries[0].CompletionTime))
@ -936,7 +987,7 @@ func (s *KeeperTestSuite) TestRedelegateFromUnbondedValidator() {
// create a validator with a self-delegation
validator := testutil.NewValidator(s.T(), addrVals[0], PKs[0])
keeper.SetValidatorByConsAddr(ctx, validator)
require.NoError(keeper.SetValidatorByConsAddr(ctx, validator))
valTokens := keeper.TokensFromConsensusPower(ctx, 10)
validator, issuedShares := validator.AddTokensFromDel(valTokens)
@ -945,16 +996,16 @@ func (s *KeeperTestSuite) TestRedelegateFromUnbondedValidator() {
validator = stakingkeeper.TestingUpdateValidator(keeper, ctx, validator, true)
val0AccAddr := sdk.AccAddress(addrVals[0].Bytes())
selfDelegation := stakingtypes.NewDelegation(val0AccAddr, addrVals[0], issuedShares)
keeper.SetDelegation(ctx, selfDelegation)
require.NoError(keeper.SetDelegation(ctx, selfDelegation))
// create a second delegation to this validator
keeper.DeleteValidatorByPowerIndex(ctx, validator)
require.NoError(keeper.DeleteValidatorByPowerIndex(ctx, validator))
delTokens := keeper.TokensFromConsensusPower(ctx, 10)
validator, issuedShares = validator.AddTokensFromDel(delTokens)
require.Equal(delTokens, issuedShares.RoundInt())
stakingkeeper.TestingUpdateValidator(keeper, ctx, validator, true)
delegation := stakingtypes.NewDelegation(addrDels[1], addrVals[0], issuedShares)
keeper.SetDelegation(ctx, delegation)
require.NoError(keeper.SetDelegation(ctx, delegation))
// create a second validator
validator2 := testutil.NewValidator(s.T(), addrVals[1], PKs[1])
@ -977,14 +1028,16 @@ func (s *KeeperTestSuite) TestRedelegateFromUnbondedValidator() {
s.bankKeeper.EXPECT().SendCoinsFromModuleToModule(gomock.Any(), stakingtypes.BondedPoolName, stakingtypes.NotBondedPoolName, gomock.Any())
s.applyValidatorSetUpdates(ctx, keeper, 1)
validator, found := keeper.GetValidator(ctx, addrVals[0])
require.True(found)
validator, err = keeper.GetValidator(ctx, addrVals[0])
require.NoError(err)
require.Equal(ctx.BlockHeight(), validator.UnbondingHeight)
params := keeper.GetParams(ctx)
params, err := keeper.GetParams(ctx)
require.NoError(err)
require.True(ctx.BlockHeader().Time.Add(params.UnbondingTime).Equal(validator.UnbondingTime))
// unbond the validator
keeper.UnbondingToUnbonded(ctx, validator)
_, err = keeper.UnbondingToUnbonded(ctx, validator)
require.NoError(err)
// redelegate some of the delegation's shares
redelegationTokens := keeper.TokensFromConsensusPower(ctx, 6)
@ -993,8 +1046,8 @@ func (s *KeeperTestSuite) TestRedelegateFromUnbondedValidator() {
require.NoError(err)
// no red should have been found
red, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
require.False(found, "%v", red)
red, err := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
require.ErrorIs(err, stakingtypes.ErrNoRedelegation, "%v", red)
}
func (s *KeeperTestSuite) TestUnbondingDelegationAddEntry() {
@ -1056,9 +1109,9 @@ func (s *KeeperTestSuite) TestSetUnbondingDelegationEntry() {
)
// set and retrieve a record
keeper.SetUnbondingDelegation(ctx, ubd)
resUnbond, found := keeper.GetUnbondingDelegation(ctx, delAddr, valAddr)
require.True(found)
require.NoError(keeper.SetUnbondingDelegation(ctx, ubd))
resUnbond, err := keeper.GetUnbondingDelegation(ctx, delAddr, valAddr)
require.NoError(err)
require.Equal(ubd, resUnbond)
initialEntries := ubd.Entries
@ -1068,7 +1121,7 @@ func (s *KeeperTestSuite) TestSetUnbondingDelegationEntry() {
// set unbonding delegation entry for existing creationHeight
// entries are expected to be merged
keeper.SetUnbondingDelegationEntry(
_, err = keeper.SetUnbondingDelegationEntry(
ctx,
delAddr,
valAddr,
@ -1076,8 +1129,9 @@ func (s *KeeperTestSuite) TestSetUnbondingDelegationEntry() {
time.Unix(0, 0).UTC(),
math.NewInt(5),
)
resUnbonding, found := keeper.GetUnbondingDelegation(ctx, delAddr, valAddr)
require.True(found)
require.NoError(err)
resUnbonding, err := keeper.GetUnbondingDelegation(ctx, delAddr, valAddr)
require.NoError(err)
require.Len(resUnbonding.Entries, 1)
require.NotEqual(initialEntries, resUnbonding.Entries)
require.Equal(creationHeight, resUnbonding.Entries[0].CreationHeight)
@ -1087,7 +1141,7 @@ func (s *KeeperTestSuite) TestSetUnbondingDelegationEntry() {
// set unbonding delegation entry for newCreationHeight
// new entry is expected to be appended to the existing entries
newCreationHeight := int64(1)
keeper.SetUnbondingDelegationEntry(
_, err = keeper.SetUnbondingDelegationEntry(
ctx,
delAddr,
valAddr,
@ -1095,8 +1149,9 @@ func (s *KeeperTestSuite) TestSetUnbondingDelegationEntry() {
time.Unix(1, 0).UTC(),
math.NewInt(10),
)
resUnbonding, found = keeper.GetUnbondingDelegation(ctx, delAddr, valAddr)
require.True(found)
require.NoError(err)
resUnbonding, err = keeper.GetUnbondingDelegation(ctx, delAddr, valAddr)
require.NoError(err)
require.Len(resUnbonding.Entries, 2)
require.NotEqual(initialEntries, resUnbonding.Entries)
require.NotEqual(resUnbonding.Entries[0], resUnbonding.Entries[1])

View File

@ -1,6 +1,7 @@
package keeper
import (
"context"
"fmt"
abci "github.com/cometbft/cometbft/abci/types"
@ -16,7 +17,7 @@ import (
// setting the indexes. In addition, it also sets any delegations found in
// data. Finally, it updates the bonded validators.
// Returns final validator set after applying all declaration and delegations
func (k Keeper) InitGenesis(ctx sdk.Context, data *types.GenesisState) (res []abci.ValidatorUpdate) {
func (k Keeper) InitGenesis(ctx context.Context, data *types.GenesisState) (res []abci.ValidatorUpdate) {
bondedTokens := math.ZeroInt()
notBondedTokens := math.ZeroInt()
@ -25,19 +26,31 @@ func (k Keeper) InitGenesis(ctx sdk.Context, data *types.GenesisState) (res []ab
// initialized for the validator set e.g. with a one-block offset - the
// first TM block is at height 1, so state updates applied from
// genesis.json are in block 0.
ctx = ctx.WithBlockHeight(1 - sdk.ValidatorUpdateDelay)
sdkCtx := sdk.UnwrapSDKContext(ctx)
sdkCtx = sdkCtx.WithBlockHeight(1 - sdk.ValidatorUpdateDelay)
ctx = sdkCtx
if err := k.SetParams(ctx, data.Params); err != nil {
panic(err)
}
k.SetLastTotalPower(ctx, data.LastTotalPower)
if err := k.SetLastTotalPower(ctx, data.LastTotalPower); err != nil {
panic(err)
}
for _, validator := range data.Validators {
k.SetValidator(ctx, validator)
if err := k.SetValidator(ctx, validator); err != nil {
panic(err)
}
// Manually set indices for the first time
k.SetValidatorByConsAddr(ctx, validator)
k.SetValidatorByPowerIndex(ctx, validator)
if err := k.SetValidatorByConsAddr(ctx, validator); err != nil {
panic(err)
}
if err := k.SetValidatorByPowerIndex(ctx, validator); err != nil {
panic(err)
}
// Call the creation hook if not exported
if !data.Exported {
@ -48,7 +61,9 @@ func (k Keeper) InitGenesis(ctx sdk.Context, data *types.GenesisState) (res []ab
// update timeslice if necessary
if validator.IsUnbonding() {
k.InsertUnbondingValidatorQueue(ctx, validator)
if err := k.InsertUnbondingValidatorQueue(ctx, validator); err != nil {
panic(err)
}
}
switch validator.GetStatus() {
@ -76,7 +91,9 @@ func (k Keeper) InitGenesis(ctx sdk.Context, data *types.GenesisState) (res []ab
}
}
k.SetDelegation(ctx, delegation)
if err := k.SetDelegation(ctx, delegation); err != nil {
panic(err)
}
// Call the after-modification hook if not exported
if !data.Exported {
@ -87,19 +104,27 @@ func (k Keeper) InitGenesis(ctx sdk.Context, data *types.GenesisState) (res []ab
}
for _, ubd := range data.UnbondingDelegations {
k.SetUnbondingDelegation(ctx, ubd)
if err := k.SetUnbondingDelegation(ctx, ubd); err != nil {
panic(err)
}
for _, entry := range ubd.Entries {
k.InsertUBDQueue(ctx, ubd, entry.CompletionTime)
if err := k.InsertUBDQueue(ctx, ubd, entry.CompletionTime); err != nil {
panic(err)
}
notBondedTokens = notBondedTokens.Add(entry.Balance)
}
}
for _, red := range data.Redelegations {
k.SetRedelegation(ctx, red)
if err := k.SetRedelegation(ctx, red); err != nil {
panic(err)
}
for _, entry := range red.Entries {
k.InsertRedelegationQueue(ctx, red, entry.CompletionTime)
if err := k.InsertRedelegationQueue(ctx, red, entry.CompletionTime); err != nil {
panic(err)
}
}
}
@ -148,10 +173,13 @@ func (k Keeper) InitGenesis(ctx sdk.Context, data *types.GenesisState) (res []ab
panic(err)
}
k.SetLastValidatorPower(ctx, valAddr, lv.Power)
validator, found := k.GetValidator(ctx, valAddr)
err = k.SetLastValidatorPower(ctx, valAddr, lv.Power)
if err != nil {
panic(err)
}
if !found {
validator, err := k.GetValidator(ctx, valAddr)
if err != nil {
panic(fmt.Sprintf("validator %s not found", lv.Address))
}
@ -177,31 +205,60 @@ func (k Keeper) InitGenesis(ctx sdk.Context, data *types.GenesisState) (res []ab
func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState {
var unbondingDelegations []types.UnbondingDelegation
k.IterateUnbondingDelegations(ctx, func(_ int64, ubd types.UnbondingDelegation) (stop bool) {
err := k.IterateUnbondingDelegations(ctx, func(_ int64, ubd types.UnbondingDelegation) (stop bool) {
unbondingDelegations = append(unbondingDelegations, ubd)
return false
})
if err != nil {
panic(err)
}
var redelegations []types.Redelegation
k.IterateRedelegations(ctx, func(_ int64, red types.Redelegation) (stop bool) {
err = k.IterateRedelegations(ctx, func(_ int64, red types.Redelegation) (stop bool) {
redelegations = append(redelegations, red)
return false
})
if err != nil {
panic(err)
}
var lastValidatorPowers []types.LastValidatorPower
k.IterateLastValidatorPowers(ctx, func(addr sdk.ValAddress, power int64) (stop bool) {
err = k.IterateLastValidatorPowers(ctx, func(addr sdk.ValAddress, power int64) (stop bool) {
lastValidatorPowers = append(lastValidatorPowers, types.LastValidatorPower{Address: addr.String(), Power: power})
return false
})
if err != nil {
panic(err)
}
params, err := k.GetParams(ctx)
if err != nil {
panic(err)
}
totalPower, err := k.GetLastTotalPower(ctx)
if err != nil {
panic(err)
}
allDelegations, err := k.GetAllDelegations(ctx)
if err != nil {
panic(err)
}
allValidators, err := k.GetAllValidators(ctx)
if err != nil {
panic(err)
}
return &types.GenesisState{
Params: k.GetParams(ctx),
LastTotalPower: k.GetLastTotalPower(ctx),
Params: params,
LastTotalPower: totalPower,
LastValidatorPowers: lastValidatorPowers,
Validators: k.GetAllValidators(ctx),
Delegations: k.GetAllDelegations(ctx),
Validators: allValidators,
Delegations: allDelegations,
UnbondingDelegations: unbondingDelegations,
Redelegations: redelegations,
Exported: true,

View File

@ -10,6 +10,7 @@ import (
"cosmossdk.io/store/prefix"
storetypes "cosmossdk.io/store/types"
"github.com/cosmos/cosmos-sdk/runtime"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/query"
"github.com/cosmos/cosmos-sdk/x/staking/types"
@ -27,7 +28,7 @@ func NewQuerier(keeper *Keeper) Querier {
}
// Validators queries all validators that match the given status
func (k Querier) Validators(c context.Context, req *types.QueryValidatorsRequest) (*types.QueryValidatorsResponse, error) {
func (k Querier) Validators(ctx context.Context, req *types.QueryValidatorsRequest) (*types.QueryValidatorsResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
@ -37,9 +38,7 @@ func (k Querier) Validators(c context.Context, req *types.QueryValidatorsRequest
return nil, status.Errorf(codes.InvalidArgument, "invalid validator status %s", req.Status)
}
ctx := sdk.UnwrapSDKContext(c)
store := ctx.KVStore(k.storeKey)
store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
valStore := prefix.NewStore(store, types.ValidatorsKey)
validators, pageRes, err := query.GenericFilteredPaginate(k.cdc, valStore, req.Pagination, func(key []byte, val *types.Validator) (*types.Validator, error) {
@ -64,7 +63,7 @@ func (k Querier) Validators(c context.Context, req *types.QueryValidatorsRequest
}
// Validator queries validator info for given validator address
func (k Querier) Validator(c context.Context, req *types.QueryValidatorRequest) (*types.QueryValidatorResponse, error) {
func (k Querier) Validator(ctx context.Context, req *types.QueryValidatorRequest) (*types.QueryValidatorResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
@ -78,9 +77,8 @@ func (k Querier) Validator(c context.Context, req *types.QueryValidatorRequest)
return nil, err
}
ctx := sdk.UnwrapSDKContext(c)
validator, found := k.GetValidator(ctx, valAddr)
if !found {
validator, err := k.GetValidator(ctx, valAddr)
if err != nil {
return nil, status.Errorf(codes.NotFound, "validator %s not found", req.ValidatorAddr)
}
@ -88,7 +86,7 @@ func (k Querier) Validator(c context.Context, req *types.QueryValidatorRequest)
}
// ValidatorDelegations queries delegate info for given validator
func (k Querier) ValidatorDelegations(c context.Context, req *types.QueryValidatorDelegationsRequest) (*types.QueryValidatorDelegationsResponse, error) {
func (k Querier) ValidatorDelegations(ctx context.Context, req *types.QueryValidatorDelegationsRequest) (*types.QueryValidatorDelegationsResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
@ -101,9 +99,8 @@ func (k Querier) ValidatorDelegations(c context.Context, req *types.QueryValidat
if err != nil {
return nil, err
}
ctx := sdk.UnwrapSDKContext(c)
store := ctx.KVStore(k.storeKey)
store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
delStore := prefix.NewStore(store, types.GetDelegationsByValPrefixKey(valAddr))
var (
@ -146,8 +143,8 @@ func (k Querier) ValidatorDelegations(c context.Context, req *types.QueryValidat
}, nil
}
func (k Querier) getValidatorDelegationsLegacy(ctx sdk.Context, req *types.QueryValidatorDelegationsRequest) ([]*types.Delegation, *query.PageResponse, error) {
store := ctx.KVStore(k.storeKey)
func (k Querier) getValidatorDelegationsLegacy(ctx context.Context, req *types.QueryValidatorDelegationsRequest) ([]*types.Delegation, *query.PageResponse, error) {
store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
valStore := prefix.NewStore(store, types.DelegationKey)
return query.GenericFilteredPaginate(k.cdc, valStore, req.Pagination, func(key []byte, delegation *types.Delegation) (*types.Delegation, error) {
@ -167,7 +164,7 @@ func (k Querier) getValidatorDelegationsLegacy(ctx sdk.Context, req *types.Query
}
// ValidatorUnbondingDelegations queries unbonding delegations of a validator
func (k Querier) ValidatorUnbondingDelegations(c context.Context, req *types.QueryValidatorUnbondingDelegationsRequest) (*types.QueryValidatorUnbondingDelegationsResponse, error) {
func (k Querier) ValidatorUnbondingDelegations(ctx context.Context, req *types.QueryValidatorUnbondingDelegationsRequest) (*types.QueryValidatorUnbondingDelegationsResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
@ -176,15 +173,13 @@ func (k Querier) ValidatorUnbondingDelegations(c context.Context, req *types.Que
return nil, status.Error(codes.InvalidArgument, "validator address cannot be empty")
}
var ubds types.UnbondingDelegations
ctx := sdk.UnwrapSDKContext(c)
store := ctx.KVStore(k.storeKey)
valAddr, err := sdk.ValAddressFromBech32(req.ValidatorAddr)
if err != nil {
return nil, err
}
store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
srcValPrefix := types.GetUBDsByValIndexKey(valAddr)
ubdStore := prefix.NewStore(store, srcValPrefix)
pageRes, err := query.Paginate(ubdStore, req.Pagination, func(key, value []byte) error {
@ -209,7 +204,7 @@ func (k Querier) ValidatorUnbondingDelegations(c context.Context, req *types.Que
}
// Delegation queries delegate info for given validator delegator pair
func (k Querier) Delegation(c context.Context, req *types.QueryDelegationRequest) (*types.QueryDelegationResponse, error) {
func (k Querier) Delegation(ctx context.Context, req *types.QueryDelegationRequest) (*types.QueryDelegationResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
@ -221,7 +216,6 @@ func (k Querier) Delegation(c context.Context, req *types.QueryDelegationRequest
return nil, status.Error(codes.InvalidArgument, "validator address cannot be empty")
}
ctx := sdk.UnwrapSDKContext(c)
delAddr, err := k.authKeeper.AddressCodec().StringToBytes(req.DelegatorAddr)
if err != nil {
return nil, err
@ -232,8 +226,8 @@ func (k Querier) Delegation(c context.Context, req *types.QueryDelegationRequest
return nil, err
}
delegation, found := k.GetDelegation(ctx, delAddr, valAddr)
if !found {
delegation, err := k.GetDelegation(ctx, delAddr, valAddr)
if err != nil {
return nil, status.Errorf(
codes.NotFound,
"delegation with delegator %s not found for validator %s",
@ -249,7 +243,7 @@ func (k Querier) Delegation(c context.Context, req *types.QueryDelegationRequest
}
// UnbondingDelegation queries unbonding info for give validator delegator pair
func (k Querier) UnbondingDelegation(c context.Context, req *types.QueryUnbondingDelegationRequest) (*types.QueryUnbondingDelegationResponse, error) {
func (k Querier) UnbondingDelegation(ctx context.Context, req *types.QueryUnbondingDelegationRequest) (*types.QueryUnbondingDelegationResponse, error) {
if req == nil {
return nil, status.Errorf(codes.InvalidArgument, "empty request")
}
@ -261,8 +255,6 @@ func (k Querier) UnbondingDelegation(c context.Context, req *types.QueryUnbondin
return nil, status.Errorf(codes.InvalidArgument, "validator address cannot be empty")
}
ctx := sdk.UnwrapSDKContext(c)
delAddr, err := k.authKeeper.AddressCodec().StringToBytes(req.DelegatorAddr)
if err != nil {
return nil, err
@ -273,8 +265,8 @@ func (k Querier) UnbondingDelegation(c context.Context, req *types.QueryUnbondin
return nil, err
}
unbond, found := k.GetUnbondingDelegation(ctx, delAddr, valAddr)
if !found {
unbond, err := k.GetUnbondingDelegation(ctx, delAddr, valAddr)
if err != nil {
return nil, status.Errorf(
codes.NotFound,
"unbonding delegation with delegator %s not found for validator %s",
@ -285,7 +277,7 @@ func (k Querier) UnbondingDelegation(c context.Context, req *types.QueryUnbondin
}
// DelegatorDelegations queries all delegations of a give delegator address
func (k Querier) DelegatorDelegations(c context.Context, req *types.QueryDelegatorDelegationsRequest) (*types.QueryDelegatorDelegationsResponse, error) {
func (k Querier) DelegatorDelegations(ctx context.Context, req *types.QueryDelegatorDelegationsRequest) (*types.QueryDelegatorDelegationsResponse, error) {
if req == nil {
return nil, status.Errorf(codes.InvalidArgument, "empty request")
}
@ -294,14 +286,13 @@ func (k Querier) DelegatorDelegations(c context.Context, req *types.QueryDelegat
return nil, status.Error(codes.InvalidArgument, "delegator address cannot be empty")
}
var delegations types.Delegations
ctx := sdk.UnwrapSDKContext(c)
delAddr, err := k.authKeeper.AddressCodec().StringToBytes(req.DelegatorAddr)
if err != nil {
return nil, err
}
store := ctx.KVStore(k.storeKey)
store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
delStore := prefix.NewStore(store, types.GetDelegationsKey(delAddr))
pageRes, err := query.Paginate(delStore, req.Pagination, func(key, value []byte) error {
delegation, err := types.UnmarshalDelegation(k.cdc, value)
@ -324,7 +315,7 @@ func (k Querier) DelegatorDelegations(c context.Context, req *types.QueryDelegat
}
// DelegatorValidator queries validator info for given delegator validator pair
func (k Querier) DelegatorValidator(c context.Context, req *types.QueryDelegatorValidatorRequest) (*types.QueryDelegatorValidatorResponse, error) {
func (k Querier) DelegatorValidator(ctx context.Context, req *types.QueryDelegatorValidatorRequest) (*types.QueryDelegatorValidatorResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
@ -336,7 +327,6 @@ func (k Querier) DelegatorValidator(c context.Context, req *types.QueryDelegator
return nil, status.Error(codes.InvalidArgument, "validator address cannot be empty")
}
ctx := sdk.UnwrapSDKContext(c)
delAddr, err := k.authKeeper.AddressCodec().StringToBytes(req.DelegatorAddr)
if err != nil {
return nil, err
@ -356,7 +346,7 @@ func (k Querier) DelegatorValidator(c context.Context, req *types.QueryDelegator
}
// DelegatorUnbondingDelegations queries all unbonding delegations of a given delegator address
func (k Querier) DelegatorUnbondingDelegations(c context.Context, req *types.QueryDelegatorUnbondingDelegationsRequest) (*types.QueryDelegatorUnbondingDelegationsResponse, error) {
func (k Querier) DelegatorUnbondingDelegations(ctx context.Context, req *types.QueryDelegatorUnbondingDelegationsRequest) (*types.QueryDelegatorUnbondingDelegationsResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
@ -365,14 +355,13 @@ func (k Querier) DelegatorUnbondingDelegations(c context.Context, req *types.Que
return nil, status.Error(codes.InvalidArgument, "delegator address cannot be empty")
}
var unbondingDelegations types.UnbondingDelegations
ctx := sdk.UnwrapSDKContext(c)
store := ctx.KVStore(k.storeKey)
delAddr, err := k.authKeeper.AddressCodec().StringToBytes(req.DelegatorAddr)
if err != nil {
return nil, err
}
store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
unbStore := prefix.NewStore(store, types.GetUBDsKey(delAddr))
pageRes, err := query.Paginate(unbStore, req.Pagination, func(key, value []byte) error {
unbond, err := types.UnmarshalUBD(k.cdc, value)
@ -392,7 +381,7 @@ func (k Querier) DelegatorUnbondingDelegations(c context.Context, req *types.Que
}
// HistoricalInfo queries the historical info for given height
func (k Querier) HistoricalInfo(c context.Context, req *types.QueryHistoricalInfoRequest) (*types.QueryHistoricalInfoResponse, error) {
func (k Querier) HistoricalInfo(ctx context.Context, req *types.QueryHistoricalInfoRequest) (*types.QueryHistoricalInfoResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
@ -400,9 +389,9 @@ func (k Querier) HistoricalInfo(c context.Context, req *types.QueryHistoricalInf
if req.Height < 0 {
return nil, status.Error(codes.InvalidArgument, "height cannot be negative")
}
ctx := sdk.UnwrapSDKContext(c)
hi, found := k.GetHistoricalInfo(ctx, req.Height)
if !found {
hi, err := k.GetHistoricalInfo(ctx, req.Height)
if err != nil {
return nil, status.Errorf(codes.NotFound, "historical info for height %d not found", req.Height)
}
@ -410,7 +399,7 @@ func (k Querier) HistoricalInfo(c context.Context, req *types.QueryHistoricalInf
}
// Redelegations queries redelegations of given address
func (k Querier) Redelegations(c context.Context, req *types.QueryRedelegationsRequest) (*types.QueryRedelegationsResponse, error) {
func (k Querier) Redelegations(ctx context.Context, req *types.QueryRedelegationsRequest) (*types.QueryRedelegationsResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
@ -419,8 +408,7 @@ func (k Querier) Redelegations(c context.Context, req *types.QueryRedelegationsR
var pageRes *query.PageResponse
var err error
ctx := sdk.UnwrapSDKContext(c)
store := ctx.KVStore(k.storeKey)
store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
switch {
case req.DelegatorAddr != "" && req.SrcValidatorAddr != "" && req.DstValidatorAddr != "":
redels, err = queryRedelegation(ctx, k, req)
@ -441,7 +429,7 @@ func (k Querier) Redelegations(c context.Context, req *types.QueryRedelegationsR
}
// DelegatorValidators queries all validators info for given delegator address
func (k Querier) DelegatorValidators(c context.Context, req *types.QueryDelegatorValidatorsRequest) (*types.QueryDelegatorValidatorsResponse, error) {
func (k Querier) DelegatorValidators(ctx context.Context, req *types.QueryDelegatorValidatorsRequest) (*types.QueryDelegatorValidatorsResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
@ -450,9 +438,8 @@ func (k Querier) DelegatorValidators(c context.Context, req *types.QueryDelegato
return nil, status.Error(codes.InvalidArgument, "delegator address cannot be empty")
}
var validators types.Validators
ctx := sdk.UnwrapSDKContext(c)
store := ctx.KVStore(k.storeKey)
store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
delAddr, err := k.authKeeper.AddressCodec().StringToBytes(req.DelegatorAddr)
if err != nil {
return nil, err
@ -465,9 +452,9 @@ func (k Querier) DelegatorValidators(c context.Context, req *types.QueryDelegato
return err
}
validator, found := k.GetValidator(ctx, delegation.GetValidatorAddr())
if !found {
return types.ErrNoValidatorFound
validator, err := k.GetValidator(ctx, delegation.GetValidatorAddr())
if err != nil {
return err
}
validators = append(validators, validator)
@ -481,9 +468,11 @@ func (k Querier) DelegatorValidators(c context.Context, req *types.QueryDelegato
}
// Pool queries the pool info
func (k Querier) Pool(c context.Context, _ *types.QueryPoolRequest) (*types.QueryPoolResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
bondDenom := k.BondDenom(ctx)
func (k Querier) Pool(ctx context.Context, _ *types.QueryPoolRequest) (*types.QueryPoolResponse, error) {
bondDenom, err := k.BondDenom(ctx)
if err != nil {
return nil, err
}
bondedPool := k.GetBondedPool(ctx)
notBondedPool := k.GetNotBondedPool(ctx)
@ -496,14 +485,15 @@ func (k Querier) Pool(c context.Context, _ *types.QueryPoolRequest) (*types.Quer
}
// Params queries the staking parameters
func (k Querier) Params(c context.Context, _ *types.QueryParamsRequest) (*types.QueryParamsResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
params := k.GetParams(ctx)
func (k Querier) Params(ctx context.Context, _ *types.QueryParamsRequest) (*types.QueryParamsResponse, error) {
params, err := k.GetParams(ctx)
if err != nil {
return nil, err
}
return &types.QueryParamsResponse{Params: params}, nil
}
func queryRedelegation(ctx sdk.Context, k Querier, req *types.QueryRedelegationsRequest) (redels types.Redelegations, err error) {
func queryRedelegation(ctx context.Context, k Querier, req *types.QueryRedelegationsRequest) (redels types.Redelegations, err error) {
delAddr, err := k.authKeeper.AddressCodec().StringToBytes(req.DelegatorAddr)
if err != nil {
return nil, err
@ -519,8 +509,8 @@ func queryRedelegation(ctx sdk.Context, k Querier, req *types.QueryRedelegations
return nil, err
}
redel, found := k.GetRedelegation(ctx, delAddr, srcValAddr, dstValAddr)
if !found {
redel, err := k.GetRedelegation(ctx, delAddr, srcValAddr, dstValAddr)
if err != nil {
return nil, status.Errorf(
codes.NotFound,
"redelegation not found for delegator address %s from validator address %s",
@ -528,7 +518,7 @@ func queryRedelegation(ctx sdk.Context, k Querier, req *types.QueryRedelegations
}
redels = []types.Redelegation{redel}
return redels, err
return redels, nil
}
func queryRedelegationsFromSrcValidator(store storetypes.KVStore, k Querier, req *types.QueryRedelegationsRequest) (redels types.Redelegations, res *query.PageResponse, err error) {
@ -574,10 +564,10 @@ func queryAllRedelegations(store storetypes.KVStore, k Querier, req *types.Query
// util
func DelegationToDelegationResponse(ctx sdk.Context, k *Keeper, del types.Delegation) (types.DelegationResponse, error) {
val, found := k.GetValidator(ctx, del.GetValidatorAddr())
if !found {
return types.DelegationResponse{}, types.ErrNoValidatorFound
func DelegationToDelegationResponse(ctx context.Context, k *Keeper, del types.Delegation) (types.DelegationResponse, error) {
val, err := k.GetValidator(ctx, del.GetValidatorAddr())
if err != nil {
return types.DelegationResponse{}, err
}
delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(del.DelegatorAddress)
@ -585,15 +575,20 @@ func DelegationToDelegationResponse(ctx sdk.Context, k *Keeper, del types.Delega
return types.DelegationResponse{}, err
}
bondDenom, err := k.BondDenom(ctx)
if err != nil {
return types.DelegationResponse{}, err
}
return types.NewDelegationResp(
delegatorAddress,
del.GetValidatorAddr(),
del.Shares,
sdk.NewCoin(k.BondDenom(ctx), val.TokensFromShares(del.Shares).TruncateInt()),
sdk.NewCoin(bondDenom, val.TokensFromShares(del.Shares).TruncateInt()),
), nil
}
func DelegationsToDelegationResponses(ctx sdk.Context, k *Keeper, delegations types.Delegations) (types.DelegationResponses, error) {
func DelegationsToDelegationResponses(ctx context.Context, k *Keeper, delegations types.Delegations) (types.DelegationResponses, error) {
resp := make(types.DelegationResponses, len(delegations))
for i, del := range delegations {
@ -608,7 +603,7 @@ func DelegationsToDelegationResponses(ctx sdk.Context, k *Keeper, delegations ty
return resp, nil
}
func RedelegationsToRedelegationResponses(ctx sdk.Context, k *Keeper, redels types.Redelegations) (types.RedelegationResponses, error) {
func RedelegationsToRedelegationResponses(ctx context.Context, k *Keeper, redels types.Redelegations) (types.RedelegationResponses, error) {
resp := make(types.RedelegationResponses, len(redels))
for i, redel := range redels {
@ -626,9 +621,9 @@ func RedelegationsToRedelegationResponses(ctx sdk.Context, k *Keeper, redels typ
return nil, err
}
val, found := k.GetValidator(ctx, valDstAddr)
if !found {
return nil, types.ErrNoValidatorFound
val, err := k.GetValidator(ctx, valDstAddr)
if err != nil {
return nil, err
}
entryResponses := make([]types.RedelegationEntryResponse, len(redel.Entries))

View File

@ -14,7 +14,7 @@ func (s *KeeperTestSuite) TestGRPCQueryValidator() {
require := s.Require()
validator := testutil.NewValidator(s.T(), sdk.ValAddress(PKs[0].Address().Bytes()), PKs[0])
keeper.SetValidator(ctx, validator)
require.NoError(keeper.SetValidator(ctx, validator))
var req *types.QueryValidatorRequest
testCases := []struct {
msg string

View File

@ -1,6 +1,9 @@
package keeper
import (
"context"
"errors"
storetypes "cosmossdk.io/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -8,32 +11,39 @@ import (
)
// GetHistoricalInfo gets the historical info at a given height
func (k Keeper) GetHistoricalInfo(ctx sdk.Context, height int64) (types.HistoricalInfo, bool) {
store := ctx.KVStore(k.storeKey)
func (k Keeper) GetHistoricalInfo(ctx context.Context, height int64) (types.HistoricalInfo, error) {
store := k.storeService.OpenKVStore(ctx)
key := types.GetHistoricalInfoKey(height)
value := store.Get(key)
if value == nil {
return types.HistoricalInfo{}, false
value, err := store.Get(key)
if err != nil {
return types.HistoricalInfo{}, err
}
return types.MustUnmarshalHistoricalInfo(k.cdc, value), true
if value == nil {
return types.HistoricalInfo{}, types.ErrNoHistoricalInfo
}
return types.UnmarshalHistoricalInfo(k.cdc, value)
}
// SetHistoricalInfo sets the historical info at a given height
func (k Keeper) SetHistoricalInfo(ctx sdk.Context, height int64, hi *types.HistoricalInfo) {
store := ctx.KVStore(k.storeKey)
func (k Keeper) SetHistoricalInfo(ctx context.Context, height int64, hi *types.HistoricalInfo) error {
store := k.storeService.OpenKVStore(ctx)
key := types.GetHistoricalInfoKey(height)
value := k.cdc.MustMarshal(hi)
store.Set(key, value)
value, err := k.cdc.Marshal(hi)
if err != nil {
return err
}
return store.Set(key, value)
}
// DeleteHistoricalInfo deletes the historical info at a given height
func (k Keeper) DeleteHistoricalInfo(ctx sdk.Context, height int64) {
store := ctx.KVStore(k.storeKey)
func (k Keeper) DeleteHistoricalInfo(ctx context.Context, height int64) error {
store := k.storeService.OpenKVStore(ctx)
key := types.GetHistoricalInfoKey(height)
store.Delete(key)
return store.Delete(key)
}
// IterateHistoricalInfo provides an interator over all stored HistoricalInfo
@ -41,36 +51,47 @@ func (k Keeper) DeleteHistoricalInfo(ctx sdk.Context, height int64) {
// objects. For each HistoricalInfo object, cb will be called. If the cb returns
//
// true, the iterator will close and stop.
func (k Keeper) IterateHistoricalInfo(ctx sdk.Context, cb func(types.HistoricalInfo) bool) {
store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, types.HistoricalInfoKey)
func (k Keeper) IterateHistoricalInfo(ctx context.Context, cb func(types.HistoricalInfo) bool) error {
store := k.storeService.OpenKVStore(ctx)
iterator, err := store.Iterator(types.HistoricalInfoKey, storetypes.PrefixEndBytes(types.HistoricalInfoKey))
if err != nil {
return err
}
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
histInfo := types.MustUnmarshalHistoricalInfo(k.cdc, iterator.Value())
histInfo, err := types.UnmarshalHistoricalInfo(k.cdc, iterator.Value())
if err != nil {
return err
}
if cb(histInfo) {
break
}
}
return nil
}
// GetAllHistoricalInfo returns all stored HistoricalInfo objects.
func (k Keeper) GetAllHistoricalInfo(ctx sdk.Context) []types.HistoricalInfo {
func (k Keeper) GetAllHistoricalInfo(ctx context.Context) ([]types.HistoricalInfo, error) {
var infos []types.HistoricalInfo
k.IterateHistoricalInfo(ctx, func(histInfo types.HistoricalInfo) bool {
err := k.IterateHistoricalInfo(ctx, func(histInfo types.HistoricalInfo) bool {
infos = append(infos, histInfo)
return false
})
return infos
return infos, err
}
// TrackHistoricalInfo saves the latest historical-info and deletes the oldest
// heights that are below pruning height
func (k Keeper) TrackHistoricalInfo(ctx sdk.Context) {
entryNum := k.HistoricalEntries(ctx)
func (k Keeper) TrackHistoricalInfo(ctx context.Context) error {
entryNum, err := k.HistoricalEntries(ctx)
if err != nil {
return err
}
sdkCtx := sdk.UnwrapSDKContext(ctx)
// Prune store to ensure we only have parameter-defined historical entries.
// In most cases, this will involve removing a single historical entry.
@ -79,24 +100,32 @@ func (k Keeper) TrackHistoricalInfo(ctx sdk.Context) {
// Since the entries to be deleted are always in a continuous range, we can iterate
// over the historical entries starting from the most recent version to be pruned
// and then return at the first empty entry.
for i := ctx.BlockHeight() - int64(entryNum); i >= 0; i-- {
_, found := k.GetHistoricalInfo(ctx, i)
if found {
k.DeleteHistoricalInfo(ctx, i)
} else {
break
for i := sdkCtx.BlockHeight() - int64(entryNum); i >= 0; i-- {
_, err := k.GetHistoricalInfo(ctx, i)
if err != nil {
if errors.Is(err, types.ErrNoHistoricalInfo) {
break
}
return err
}
if err = k.DeleteHistoricalInfo(ctx, i); err != nil {
return err
}
}
// if there is no need to persist historicalInfo, return
if entryNum == 0 {
return
return nil
}
// Create HistoricalInfo struct
lastVals := k.GetLastValidators(ctx)
historicalEntry := types.NewHistoricalInfo(ctx.BlockHeader(), lastVals, k.PowerReduction(ctx))
lastVals, err := k.GetLastValidators(ctx)
if err != nil {
return err
}
historicalEntry := types.NewHistoricalInfo(sdkCtx.BlockHeader(), lastVals, k.PowerReduction(ctx))
// Set latest HistoricalInfo at current height
k.SetHistoricalInfo(ctx, ctx.BlockHeight(), &historicalEntry)
return k.SetHistoricalInfo(ctx, sdkCtx.BlockHeight(), &historicalEntry)
}

View File

@ -33,17 +33,17 @@ func (s *KeeperTestSuite) TestHistoricalInfo() {
}
hi := stakingtypes.NewHistoricalInfo(ctx.BlockHeader(), validators, keeper.PowerReduction(ctx))
keeper.SetHistoricalInfo(ctx, 2, &hi)
require.NoError(keeper.SetHistoricalInfo(ctx, 2, &hi))
recv, found := keeper.GetHistoricalInfo(ctx, 2)
require.True(found, "HistoricalInfo not found after set")
recv, err := keeper.GetHistoricalInfo(ctx, 2)
require.NoError(err, "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")
keeper.DeleteHistoricalInfo(ctx, 2)
require.NoError(keeper.DeleteHistoricalInfo(ctx, 2))
recv, found = keeper.GetHistoricalInfo(ctx, 2)
require.False(found, "HistoricalInfo found after delete")
recv, err = keeper.GetHistoricalInfo(ctx, 2)
require.ErrorIs(err, stakingtypes.ErrNoHistoricalInfo, "HistoricalInfo found after delete")
require.Equal(stakingtypes.HistoricalInfo{}, recv, "HistoricalInfo is not empty")
}
@ -56,7 +56,7 @@ func (s *KeeperTestSuite) TestTrackHistoricalInfo() {
// set historical entries in params to 5
params := stakingtypes.DefaultParams()
params.HistoricalEntries = 5
keeper.SetParams(ctx, params)
require.NoError(keeper.SetParams(ctx, params))
// set historical info at 5, 4 which should be pruned
// and check that it has been stored
@ -74,26 +74,26 @@ func (s *KeeperTestSuite) TestTrackHistoricalInfo() {
}
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.NoError(keeper.SetHistoricalInfo(ctx, 4, &hi4))
require.NoError(keeper.SetHistoricalInfo(ctx, 5, &hi5))
recv, err := keeper.GetHistoricalInfo(ctx, 4)
require.NoError(err)
require.Equal(hi4, recv)
recv, found = keeper.GetHistoricalInfo(ctx, 5)
require.True(found)
recv, err = keeper.GetHistoricalInfo(ctx, 5)
require.NoError(err)
require.Equal(hi5, recv)
// Set bonded validators in keeper
val1 := testutil.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)
require.NoError(keeper.SetValidator(ctx, val1))
require.NoError(keeper.SetLastValidatorPower(ctx, val1.GetOperator(), 10))
val2 := testutil.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)
require.NoError(keeper.SetValidator(ctx, val2))
require.NoError(keeper.SetLastValidatorPower(ctx, val2.GetOperator(), 80))
vals := []stakingtypes.Validator{val1, val2}
require.True(IsValSetSorted(vals, keeper.PowerReduction(ctx)))
@ -105,23 +105,23 @@ func (s *KeeperTestSuite) TestTrackHistoricalInfo() {
}
ctx = ctx.WithBlockHeader(header)
keeper.TrackHistoricalInfo(ctx)
require.NoError(keeper.TrackHistoricalInfo(ctx))
// Check HistoricalInfo at height 10 is persisted
expected := stakingtypes.HistoricalInfo{
Header: header,
Valset: vals,
}
recv, found = keeper.GetHistoricalInfo(ctx, 10)
require.True(found, "GetHistoricalInfo failed after BeginBlock")
recv, err = keeper.GetHistoricalInfo(ctx, 10)
require.NoError(err, "GetHistoricalInfo failed after BeginBlock")
require.Equal(expected, recv, "GetHistoricalInfo returned unexpected result")
// Check HistoricalInfo at height 5, 4 is pruned
recv, found = keeper.GetHistoricalInfo(ctx, 4)
require.False(found, "GetHistoricalInfo did not prune earlier height")
recv, err = keeper.GetHistoricalInfo(ctx, 4)
require.ErrorIs(err, stakingtypes.ErrNoHistoricalInfo, "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")
recv, err = keeper.GetHistoricalInfo(ctx, 5)
require.ErrorIs(err, stakingtypes.ErrNoHistoricalInfo, "GetHistoricalInfo did not prune first prune height")
require.Equal(stakingtypes.HistoricalInfo{}, recv, "GetHistoricalInfo at height 5 is not empty after prune")
}
@ -147,9 +147,10 @@ func (s *KeeperTestSuite) TestGetAllHistoricalInfo() {
expHistInfos := []stakingtypes.HistoricalInfo{hist1, hist2, hist3}
for i, hi := range expHistInfos {
keeper.SetHistoricalInfo(ctx, int64(9+i), &hi) //nolint:gosec // G601: Implicit memory aliasing in for loop.
require.NoError(keeper.SetHistoricalInfo(ctx, int64(9+i), &hi)) //nolint:gosec // G601: Implicit memory aliasing in for loop.
}
infos := keeper.GetAllHistoricalInfo(ctx)
infos, err := keeper.GetAllHistoricalInfo(ctx)
require.NoError(err)
require.Equal(expHistInfos, infos)
}

View File

@ -5,6 +5,7 @@ import (
"fmt"
"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
@ -51,9 +52,12 @@ func ModuleAccountInvariants(k *Keeper) sdk.Invariant {
notBonded := math.ZeroInt()
bondedPool := k.GetBondedPool(ctx)
notBondedPool := k.GetNotBondedPool(ctx)
bondDenom := k.BondDenom(ctx)
bondDenom, err := k.BondDenom(ctx)
if err != nil {
panic(err)
}
k.IterateValidators(ctx, func(_ int64, validator types.ValidatorI) bool {
err = k.IterateValidators(ctx, func(_ int64, validator types.ValidatorI) bool {
switch validator.GetStatus() {
case types.Bonded:
bonded = bonded.Add(validator.GetTokens())
@ -64,13 +68,19 @@ func ModuleAccountInvariants(k *Keeper) sdk.Invariant {
}
return false
})
if err != nil {
panic(err)
}
k.IterateUnbondingDelegations(ctx, func(_ int64, ubd types.UnbondingDelegation) bool {
err = k.IterateUnbondingDelegations(ctx, func(_ int64, ubd types.UnbondingDelegation) bool {
for _, entry := range ubd.Entries {
notBonded = notBonded.Add(entry.Balance)
}
return false
})
if err != nil {
panic(err)
}
poolBonded := k.bankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom)
poolNotBonded := k.bankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom)
@ -99,10 +109,13 @@ func NonNegativePowerInvariant(k *Keeper) sdk.Invariant {
broken bool
)
iterator := k.ValidatorsPowerStoreIterator(ctx)
iterator, err := k.ValidatorsPowerStoreIterator(ctx)
if err != nil {
panic(err)
}
for ; iterator.Valid(); iterator.Next() {
validator, found := k.GetValidator(ctx, iterator.Value())
if !found {
validator, err := k.GetValidator(ctx, iterator.Value())
if err != nil {
panic(fmt.Sprintf("validator record not found for address: %X\n", iterator.Value()))
}
@ -134,7 +147,10 @@ func PositiveDelegationInvariant(k *Keeper) sdk.Invariant {
count int
)
delegations := k.GetAllDelegations(ctx)
delegations, err := k.GetAllDelegations(ctx)
if err != nil {
panic(err)
}
for _, delegation := range delegations {
if delegation.Shares.IsNegative() {
count++
@ -164,7 +180,11 @@ func DelegatorSharesInvariant(k *Keeper) sdk.Invariant {
broken bool
)
validators := k.GetAllValidators(ctx)
validators, err := k.GetAllValidators(ctx)
if err != nil {
panic(err)
}
validatorsDelegationShares := map[string]math.LegacyDec{}
// initialize a map: validator -> its delegation shares
@ -173,7 +193,11 @@ func DelegatorSharesInvariant(k *Keeper) sdk.Invariant {
}
// iterate through all the delegations to calculate the total delegation shares for each validator
delegations := k.GetAllDelegations(ctx)
delegations, err := k.GetAllDelegations(ctx)
if err != nil {
panic(err)
}
for _, delegation := range delegations {
delegationValidatorAddr := delegation.GetValidatorAddr().String()
validatorDelegationShares := validatorsDelegationShares[delegationValidatorAddr]

View File

@ -1,13 +1,15 @@
package keeper
import (
"context"
"fmt"
"cosmossdk.io/log"
"cosmossdk.io/math"
abci "github.com/cometbft/cometbft/abci/types"
storetypes "cosmossdk.io/store/types"
storetypes "cosmossdk.io/core/store"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/staking/types"
@ -21,18 +23,18 @@ var _ types.DelegationSet = Keeper{}
// Keeper of the x/staking store
type Keeper struct {
storeKey storetypes.StoreKey
cdc codec.BinaryCodec
authKeeper types.AccountKeeper
bankKeeper types.BankKeeper
hooks types.StakingHooks
authority string
storeService storetypes.KVStoreService
cdc codec.BinaryCodec
authKeeper types.AccountKeeper
bankKeeper types.BankKeeper
hooks types.StakingHooks
authority string
}
// NewKeeper creates a new staking Keeper instance
func NewKeeper(
cdc codec.BinaryCodec,
key storetypes.StoreKey,
storeService storetypes.KVStoreService,
ak types.AccountKeeper,
bk types.BankKeeper,
authority string,
@ -52,18 +54,19 @@ func NewKeeper(
}
return &Keeper{
storeKey: key,
cdc: cdc,
authKeeper: ak,
bankKeeper: bk,
hooks: nil,
authority: authority,
storeService: storeService,
cdc: cdc,
authKeeper: ak,
bankKeeper: bk,
hooks: nil,
authority: authority,
}
}
// Logger returns a module-specific logger.
func (k Keeper) Logger(ctx sdk.Context) log.Logger {
return ctx.Logger().With("module", "x/"+types.ModuleName)
func (k Keeper) Logger(ctx context.Context) log.Logger {
sdkCtx := sdk.UnwrapSDKContext(ctx)
return sdkCtx.Logger().With("module", "x/"+types.ModuleName)
}
// Hooks gets the hooks for staking *Keeper {
@ -87,25 +90,34 @@ func (k *Keeper) SetHooks(sh types.StakingHooks) {
}
// GetLastTotalPower Load the last total validator power.
func (k Keeper) GetLastTotalPower(ctx sdk.Context) math.Int {
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.LastTotalPowerKey)
func (k Keeper) GetLastTotalPower(ctx context.Context) (math.Int, error) {
store := k.storeService.OpenKVStore(ctx)
bz, err := store.Get(types.LastTotalPowerKey)
if err != nil {
return math.ZeroInt(), err
}
if bz == nil {
return math.ZeroInt()
return math.ZeroInt(), nil
}
ip := sdk.IntProto{}
k.cdc.MustUnmarshal(bz, &ip)
err = k.cdc.Unmarshal(bz, &ip)
if err != nil {
return math.ZeroInt(), err
}
return ip.Int
return ip.Int, nil
}
// SetLastTotalPower Set the last total validator power.
func (k Keeper) SetLastTotalPower(ctx sdk.Context, power math.Int) {
store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshal(&sdk.IntProto{Int: power})
store.Set(types.LastTotalPowerKey, bz)
func (k Keeper) SetLastTotalPower(ctx context.Context, power math.Int) error {
store := k.storeService.OpenKVStore(ctx)
bz, err := k.cdc.Marshal(&sdk.IntProto{Int: power})
if err != nil {
return err
}
return store.Set(types.LastTotalPowerKey, bz)
}
// GetAuthority returns the x/staking module's authority.
@ -114,19 +126,28 @@ func (k Keeper) GetAuthority() string {
}
// SetValidatorUpdates sets the ABCI validator power updates for the current block.
func (k Keeper) SetValidatorUpdates(ctx sdk.Context, valUpdates []abci.ValidatorUpdate) {
store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshal(&types.ValidatorUpdates{Updates: valUpdates})
store.Set(types.ValidatorUpdatesKey, bz)
func (k Keeper) SetValidatorUpdates(ctx context.Context, valUpdates []abci.ValidatorUpdate) error {
store := k.storeService.OpenKVStore(ctx)
bz, err := k.cdc.Marshal(&types.ValidatorUpdates{Updates: valUpdates})
if err != nil {
return err
}
return store.Set(types.ValidatorUpdatesKey, bz)
}
// GetValidatorUpdates returns the ABCI validator power updates within the current block.
func (k Keeper) GetValidatorUpdates(ctx sdk.Context) []abci.ValidatorUpdate {
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.ValidatorUpdatesKey)
func (k Keeper) GetValidatorUpdates(ctx context.Context) ([]abci.ValidatorUpdate, error) {
store := k.storeService.OpenKVStore(ctx)
bz, err := store.Get(types.ValidatorUpdatesKey)
if err != nil {
return nil, err
}
var valUpdates types.ValidatorUpdates
k.cdc.MustUnmarshal(bz, &valUpdates)
err = k.cdc.Unmarshal(bz, &valUpdates)
if err != nil {
return nil, err
}
return valUpdates.Updates
return valUpdates.Updates, nil
}

View File

@ -13,6 +13,7 @@ import (
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec/address"
"github.com/cosmos/cosmos-sdk/runtime"
"github.com/cosmos/cosmos-sdk/testutil"
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -41,7 +42,9 @@ type KeeperTestSuite struct {
}
func (s *KeeperTestSuite) SetupTest() {
require := s.Require()
key := storetypes.NewKVStoreKey(stakingtypes.StoreKey)
storeService := runtime.NewKVStoreService(key)
testCtx := testutil.DefaultContextWithDB(s.T(), key, storetypes.NewTransientStoreKey("transient_test"))
ctx := testCtx.Ctx.WithBlockHeader(cmtproto.Header{Time: cmttime.Now()})
encCfg := moduletestutil.MakeTestEncodingConfig()
@ -56,12 +59,12 @@ func (s *KeeperTestSuite) SetupTest() {
keeper := stakingkeeper.NewKeeper(
encCfg.Codec,
key,
storeService,
accountKeeper,
bankKeeper,
authtypes.NewModuleAddress(stakingtypes.GovModuleName).String(),
)
keeper.SetParams(ctx, stakingtypes.DefaultParams())
require.NoError(keeper.SetParams(ctx, stakingtypes.DefaultParams()))
s.ctx = ctx
s.stakingKeeper = keeper
@ -81,13 +84,15 @@ func (s *KeeperTestSuite) TestParams() {
expParams := stakingtypes.DefaultParams()
// check that the empty keeper loads the default
resParams := keeper.GetParams(ctx)
resParams, err := keeper.GetParams(ctx)
require.NoError(err)
require.Equal(expParams, resParams)
expParams.MaxValidators = 555
expParams.MaxEntries = 111
keeper.SetParams(ctx, expParams)
resParams = keeper.GetParams(ctx)
require.NoError(keeper.SetParams(ctx, expParams))
resParams, err = keeper.GetParams(ctx)
require.NoError(err)
require.True(expParams.Equal(resParams))
}
@ -96,8 +101,9 @@ func (s *KeeperTestSuite) TestLastTotalPower() {
require := s.Require()
expTotalPower := math.NewInt(10 ^ 9)
keeper.SetLastTotalPower(ctx, expTotalPower)
resTotalPower := keeper.GetLastTotalPower(ctx)
require.NoError(keeper.SetLastTotalPower(ctx, expTotalPower))
resTotalPower, err := keeper.GetLastTotalPower(ctx)
require.NoError(err)
require.True(expTotalPower.Equal(resTotalPower))
}

View File

@ -1,6 +1,7 @@
package keeper
import (
"github.com/cosmos/cosmos-sdk/runtime"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/staking/exported"
v2 "github.com/cosmos/cosmos-sdk/x/staking/migrations/v2"
@ -25,20 +26,24 @@ func NewMigrator(keeper *Keeper, legacySubspace exported.Subspace) Migrator {
// Migrate1to2 migrates from version 1 to 2.
func (m Migrator) Migrate1to2(ctx sdk.Context) error {
return v2.MigrateStore(ctx, m.keeper.storeKey)
store := runtime.KVStoreAdapter(m.keeper.storeService.OpenKVStore(ctx))
return v2.MigrateStore(ctx, store)
}
// Migrate2to3 migrates x/staking state from consensus version 2 to 3.
func (m Migrator) Migrate2to3(ctx sdk.Context) error {
return v3.MigrateStore(ctx, m.keeper.storeKey, m.keeper.cdc, m.legacySubspace)
store := runtime.KVStoreAdapter(m.keeper.storeService.OpenKVStore(ctx))
return v3.MigrateStore(ctx, store, m.keeper.cdc, m.legacySubspace)
}
// Migrate3to4 migrates x/staking state from consensus version 3 to 4.
func (m Migrator) Migrate3to4(ctx sdk.Context) error {
return v4.MigrateStore(ctx, m.keeper.storeKey, m.keeper.cdc, m.legacySubspace)
store := runtime.KVStoreAdapter(m.keeper.storeService.OpenKVStore(ctx))
return v4.MigrateStore(ctx, store, m.keeper.cdc, m.legacySubspace)
}
// Migrate4to5 migrates x/staking state from consensus version 4 to 5.
func (m Migrator) Migrate4to5(ctx sdk.Context) error {
return v5.MigrateStore(ctx, m.keeper.storeKey, m.keeper.cdc)
store := runtime.KVStoreAdapter(m.keeper.storeService.OpenKVStore(ctx))
return v5.MigrateStore(ctx, store, m.keeper.cdc)
}

View File

@ -32,7 +32,7 @@ func NewMsgServerImpl(keeper *Keeper) types.MsgServer {
var _ types.MsgServer = msgServer{}
// CreateValidator defines a method for creating a new validator
func (k msgServer) CreateValidator(goCtx context.Context, msg *types.MsgCreateValidator) (*types.MsgCreateValidatorResponse, error) {
func (k msgServer) CreateValidator(ctx context.Context, msg *types.MsgCreateValidator) (*types.MsgCreateValidatorResponse, error) {
valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddress)
if err != nil {
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid validator address: %s", err)
@ -42,14 +42,17 @@ func (k msgServer) CreateValidator(goCtx context.Context, msg *types.MsgCreateVa
return nil, err
}
ctx := sdk.UnwrapSDKContext(goCtx)
minCommRate, err := k.MinCommissionRate(ctx)
if err != nil {
return nil, err
}
if msg.Commission.Rate.LT(k.MinCommissionRate(ctx)) {
return nil, errorsmod.Wrapf(types.ErrCommissionLTMinRate, "cannot set validator commission to less than minimum rate of %s", k.MinCommissionRate(ctx))
if msg.Commission.Rate.LT(minCommRate) {
return nil, errorsmod.Wrapf(types.ErrCommissionLTMinRate, "cannot set validator commission to less than minimum rate of %s", minCommRate)
}
// check to see if the pubkey or sender has been registered before
if _, found := k.GetValidator(ctx, valAddr); found {
if _, err := k.GetValidator(ctx, valAddr); err == nil {
return nil, types.ErrValidatorOwnerExists
}
@ -58,11 +61,15 @@ func (k msgServer) CreateValidator(goCtx context.Context, msg *types.MsgCreateVa
return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidType, "Expecting cryptotypes.PubKey, got %T", pk)
}
if _, found := k.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(pk)); found {
if _, err := k.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(pk)); err == nil {
return nil, types.ErrValidatorPubKeyExists
}
bondDenom := k.BondDenom(ctx)
bondDenom, err := k.BondDenom(ctx)
if err != nil {
return nil, err
}
if msg.Value.Denom != bondDenom {
return nil, errorsmod.Wrapf(
sdkerrors.ErrInvalidRequest, "invalid coin denomination: got %s, expected %s", msg.Value.Denom, bondDenom,
@ -73,7 +80,8 @@ func (k msgServer) CreateValidator(goCtx context.Context, msg *types.MsgCreateVa
return nil, err
}
cp := ctx.ConsensusParams()
sdkCtx := sdk.UnwrapSDKContext(ctx)
cp := sdkCtx.ConsensusParams()
if cp.Validator != nil {
pkType := pk.Type()
hasKeyType := false
@ -98,7 +106,7 @@ func (k msgServer) CreateValidator(goCtx context.Context, msg *types.MsgCreateVa
commission := types.NewCommissionWithTime(
msg.Commission.Rate, msg.Commission.MaxRate,
msg.Commission.MaxChangeRate, ctx.BlockHeader().Time,
msg.Commission.MaxChangeRate, sdkCtx.BlockHeader().Time,
)
validator, err = validator.SetInitialCommission(commission)
@ -108,9 +116,20 @@ func (k msgServer) CreateValidator(goCtx context.Context, msg *types.MsgCreateVa
validator.MinSelfDelegation = msg.MinSelfDelegation
k.SetValidator(ctx, validator)
k.SetValidatorByConsAddr(ctx, validator)
k.SetNewValidatorByPowerIndex(ctx, validator)
err = k.SetValidator(ctx, validator)
if err != nil {
return nil, err
}
err = k.SetValidatorByConsAddr(ctx, validator)
if err != nil {
return nil, err
}
err = k.SetNewValidatorByPowerIndex(ctx, validator)
if err != nil {
return nil, err
}
// call the after-creation hook
if err := k.Hooks().AfterValidatorCreated(ctx, validator.GetOperator()); err != nil {
@ -125,7 +144,7 @@ func (k msgServer) CreateValidator(goCtx context.Context, msg *types.MsgCreateVa
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdkCtx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeCreateValidator,
sdk.NewAttribute(types.AttributeKeyValidator, msg.ValidatorAddress),
@ -137,7 +156,7 @@ func (k msgServer) CreateValidator(goCtx context.Context, msg *types.MsgCreateVa
}
// EditValidator defines a method for editing an existing validator
func (k msgServer) EditValidator(goCtx context.Context, msg *types.MsgEditValidator) (*types.MsgEditValidatorResponse, error) {
func (k msgServer) EditValidator(ctx context.Context, msg *types.MsgEditValidator) (*types.MsgEditValidatorResponse, error) {
valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddress)
if err != nil {
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid validator address: %s", err)
@ -160,12 +179,10 @@ func (k msgServer) EditValidator(goCtx context.Context, msg *types.MsgEditValida
}
}
ctx := sdk.UnwrapSDKContext(goCtx)
// validator must already be registered
validator, found := k.GetValidator(ctx, valAddr)
if !found {
return nil, types.ErrNoValidatorFound
validator, err := k.GetValidator(ctx, valAddr)
if err != nil {
return nil, err
}
// replace all editable fields (clients should autofill existing values)
@ -202,9 +219,13 @@ func (k msgServer) EditValidator(goCtx context.Context, msg *types.MsgEditValida
validator.MinSelfDelegation = *msg.MinSelfDelegation
}
k.SetValidator(ctx, validator)
err = k.SetValidator(ctx, validator)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdkCtx := sdk.UnwrapSDKContext(ctx)
sdkCtx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeEditValidator,
sdk.NewAttribute(types.AttributeKeyCommissionRate, validator.Commission.String()),
@ -216,7 +237,7 @@ func (k msgServer) EditValidator(goCtx context.Context, msg *types.MsgEditValida
}
// Delegate defines a method for performing a delegation of coins from a delegator to a validator
func (k msgServer) Delegate(goCtx context.Context, msg *types.MsgDelegate) (*types.MsgDelegateResponse, error) {
func (k msgServer) Delegate(ctx context.Context, msg *types.MsgDelegate) (*types.MsgDelegateResponse, error) {
valAddr, valErr := sdk.ValAddressFromBech32(msg.ValidatorAddress)
if valErr != nil {
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid validator address: %s", valErr)
@ -234,14 +255,16 @@ func (k msgServer) Delegate(goCtx context.Context, msg *types.MsgDelegate) (*typ
)
}
ctx := sdk.UnwrapSDKContext(goCtx)
validator, found := k.GetValidator(ctx, valAddr)
if !found {
return nil, types.ErrNoValidatorFound
validator, err := k.GetValidator(ctx, valAddr)
if err != nil {
return nil, err
}
bondDenom, err := k.BondDenom(ctx)
if err != nil {
return nil, err
}
bondDenom := k.BondDenom(ctx)
if msg.Amount.Denom != bondDenom {
return nil, errorsmod.Wrapf(
sdkerrors.ErrInvalidRequest, "invalid coin denomination: got %s, expected %s", msg.Amount.Denom, bondDenom,
@ -265,7 +288,8 @@ func (k msgServer) Delegate(goCtx context.Context, msg *types.MsgDelegate) (*typ
}()
}
ctx.EventManager().EmitEvents(sdk.Events{
sdkCtx := sdk.UnwrapSDKContext(ctx)
sdkCtx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeDelegate,
sdk.NewAttribute(types.AttributeKeyValidator, msg.ValidatorAddress),
@ -278,7 +302,7 @@ func (k msgServer) Delegate(goCtx context.Context, msg *types.MsgDelegate) (*typ
}
// BeginRedelegate defines a method for performing a redelegation of coins from a delegator and source validator to a destination validator
func (k msgServer) BeginRedelegate(goCtx context.Context, msg *types.MsgBeginRedelegate) (*types.MsgBeginRedelegateResponse, error) {
func (k msgServer) BeginRedelegate(ctx context.Context, msg *types.MsgBeginRedelegate) (*types.MsgBeginRedelegateResponse, error) {
valSrcAddr, err := sdk.ValAddressFromBech32(msg.ValidatorSrcAddress)
if err != nil {
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid source validator address: %s", err)
@ -301,8 +325,6 @@ func (k msgServer) BeginRedelegate(goCtx context.Context, msg *types.MsgBeginRed
)
}
ctx := sdk.UnwrapSDKContext(goCtx)
shares, err := k.ValidateUnbondAmount(
ctx, delegatorAddress, valSrcAddr, msg.Amount.Amount,
)
@ -310,7 +332,11 @@ func (k msgServer) BeginRedelegate(goCtx context.Context, msg *types.MsgBeginRed
return nil, err
}
bondDenom := k.BondDenom(ctx)
bondDenom, err := k.BondDenom(ctx)
if err != nil {
return nil, err
}
if msg.Amount.Denom != bondDenom {
return nil, errorsmod.Wrapf(
sdkerrors.ErrInvalidRequest, "invalid coin denomination: got %s, expected %s", msg.Amount.Denom, bondDenom,
@ -335,7 +361,8 @@ func (k msgServer) BeginRedelegate(goCtx context.Context, msg *types.MsgBeginRed
}()
}
ctx.EventManager().EmitEvents(sdk.Events{
sdkCtx := sdk.UnwrapSDKContext(ctx)
sdkCtx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeRedelegate,
sdk.NewAttribute(types.AttributeKeySrcValidator, msg.ValidatorSrcAddress),
@ -351,7 +378,7 @@ func (k msgServer) BeginRedelegate(goCtx context.Context, msg *types.MsgBeginRed
}
// Undelegate defines a method for performing an undelegation from a delegate and a validator
func (k msgServer) Undelegate(goCtx context.Context, msg *types.MsgUndelegate) (*types.MsgUndelegateResponse, error) {
func (k msgServer) Undelegate(ctx context.Context, msg *types.MsgUndelegate) (*types.MsgUndelegateResponse, error) {
addr, err := sdk.ValAddressFromBech32(msg.ValidatorAddress)
if err != nil {
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid validator address: %s", err)
@ -369,8 +396,6 @@ func (k msgServer) Undelegate(goCtx context.Context, msg *types.MsgUndelegate) (
)
}
ctx := sdk.UnwrapSDKContext(goCtx)
shares, err := k.ValidateUnbondAmount(
ctx, delegatorAddress, addr, msg.Amount.Amount,
)
@ -378,7 +403,11 @@ func (k msgServer) Undelegate(goCtx context.Context, msg *types.MsgUndelegate) (
return nil, err
}
bondDenom := k.BondDenom(ctx)
bondDenom, err := k.BondDenom(ctx)
if err != nil {
return nil, err
}
if msg.Amount.Denom != bondDenom {
return nil, errorsmod.Wrapf(
sdkerrors.ErrInvalidRequest, "invalid coin denomination: got %s, expected %s", msg.Amount.Denom, bondDenom,
@ -403,7 +432,8 @@ func (k msgServer) Undelegate(goCtx context.Context, msg *types.MsgUndelegate) (
}()
}
ctx.EventManager().EmitEvents(sdk.Events{
sdkCtx := sdk.UnwrapSDKContext(ctx)
sdkCtx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeUnbond,
sdk.NewAttribute(types.AttributeKeyValidator, msg.ValidatorAddress),
@ -420,7 +450,7 @@ func (k msgServer) Undelegate(goCtx context.Context, msg *types.MsgUndelegate) (
// CancelUnbondingDelegation defines a method for canceling the unbonding delegation
// and delegate back to the validator.
func (k msgServer) CancelUnbondingDelegation(goCtx context.Context, msg *types.MsgCancelUnbondingDelegation) (*types.MsgCancelUnbondingDelegationResponse, error) {
func (k msgServer) CancelUnbondingDelegation(ctx context.Context, msg *types.MsgCancelUnbondingDelegation) (*types.MsgCancelUnbondingDelegationResponse, error) {
valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddress)
if err != nil {
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid validator address: %s", err)
@ -445,18 +475,20 @@ func (k msgServer) CancelUnbondingDelegation(goCtx context.Context, msg *types.M
)
}
ctx := sdk.UnwrapSDKContext(goCtx)
bondDenom, err := k.BondDenom(ctx)
if err != nil {
return nil, err
}
bondDenom := k.BondDenom(ctx)
if msg.Amount.Denom != bondDenom {
return nil, errorsmod.Wrapf(
sdkerrors.ErrInvalidRequest, "invalid coin denomination: got %s, expected %s", msg.Amount.Denom, bondDenom,
)
}
validator, found := k.GetValidator(ctx, valAddr)
if !found {
return nil, types.ErrNoValidatorFound
validator, err := k.GetValidator(ctx, valAddr)
if err != nil {
return nil, err
}
// In some situations, the exchange rate becomes invalid, e.g. if
@ -470,8 +502,8 @@ func (k msgServer) CancelUnbondingDelegation(goCtx context.Context, msg *types.M
return nil, types.ErrValidatorJailed
}
ubd, found := k.GetUnbondingDelegation(ctx, delegatorAddress, valAddr)
if !found {
ubd, err := k.GetUnbondingDelegation(ctx, delegatorAddress, valAddr)
if err != nil {
return nil, status.Errorf(
codes.NotFound,
"unbonding delegation with delegator %s not found for validator %s",
@ -499,7 +531,8 @@ func (k msgServer) CancelUnbondingDelegation(goCtx context.Context, msg *types.M
return nil, sdkerrors.ErrInvalidRequest.Wrap("amount is greater than the unbonding delegation entry balance")
}
if unbondEntry.CompletionTime.Before(ctx.BlockTime()) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
if unbondEntry.CompletionTime.Before(sdkCtx.BlockTime()) {
return nil, sdkerrors.ErrInvalidRequest.Wrap("unbonding delegation is already processed")
}
@ -521,12 +554,16 @@ func (k msgServer) CancelUnbondingDelegation(goCtx context.Context, msg *types.M
// set the unbonding delegation or remove it if there are no more entries
if len(ubd.Entries) == 0 {
k.RemoveUnbondingDelegation(ctx, ubd)
err = k.RemoveUnbondingDelegation(ctx, ubd)
} else {
k.SetUnbondingDelegation(ctx, ubd)
err = k.SetUnbondingDelegation(ctx, ubd)
}
ctx.EventManager().EmitEvent(
if err != nil {
return nil, err
}
sdkCtx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeCancelUnbondingDelegation,
sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Amount.String()),
@ -539,7 +576,7 @@ func (k msgServer) CancelUnbondingDelegation(goCtx context.Context, msg *types.M
return &types.MsgCancelUnbondingDelegationResponse{}, nil
}
func (k msgServer) UpdateParams(goCtx context.Context, msg *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) {
func (k msgServer) UpdateParams(ctx context.Context, msg *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) {
if k.authority != msg.Authority {
return nil, errorsmod.Wrapf(types.ErrInvalidSigner, "invalid authority; expected %s, got %s", k.authority, msg.Authority)
}
@ -548,8 +585,6 @@ func (k msgServer) UpdateParams(goCtx context.Context, msg *types.MsgUpdateParam
return nil, err
}
ctx := sdk.UnwrapSDKContext(goCtx)
// store params
if err := k.SetParams(ctx, msg.Params); err != nil {
return nil, err

View File

@ -567,9 +567,9 @@ func (s *KeeperTestSuite) TestMsgBeginRedelegate() {
shares := math.LegacyNewDec(100)
del := stakingtypes.NewDelegation(Addr, srcValAddr, shares)
keeper.SetDelegation(ctx, del)
_, found := keeper.GetDelegation(ctx, Addr, srcValAddr)
require.True(found)
require.NoError(keeper.SetDelegation(ctx, del))
_, err = keeper.GetDelegation(ctx, Addr, srcValAddr)
require.NoError(err)
testCases := []struct {
name string
@ -721,9 +721,9 @@ func (s *KeeperTestSuite) TestMsgUndelegate() {
shares := math.LegacyNewDec(100)
del := stakingtypes.NewDelegation(Addr, ValAddr, shares)
keeper.SetDelegation(ctx, del)
_, found := keeper.GetDelegation(ctx, Addr, ValAddr)
require.True(found)
require.NoError(keeper.SetDelegation(ctx, del))
_, err = keeper.GetDelegation(ctx, Addr, ValAddr)
require.NoError(err)
testCases := []struct {
name string
@ -846,15 +846,15 @@ func (s *KeeperTestSuite) TestMsgCancelUnbondingDelegation() {
shares := math.LegacyNewDec(100)
del := stakingtypes.NewDelegation(Addr, ValAddr, shares)
keeper.SetDelegation(ctx, del)
resDel, found := keeper.GetDelegation(ctx, Addr, ValAddr)
require.True(found)
require.NoError(keeper.SetDelegation(ctx, del))
resDel, err := keeper.GetDelegation(ctx, Addr, ValAddr)
require.NoError(err)
require.Equal(del, resDel)
ubd := stakingtypes.NewUnbondingDelegation(Addr, ValAddr, 10, ctx.BlockTime().Add(time.Minute*10), shares.RoundInt(), 0)
keeper.SetUnbondingDelegation(ctx, ubd)
resUnbond, found := keeper.GetUnbondingDelegation(ctx, Addr, ValAddr)
require.True(found)
require.NoError(keeper.SetUnbondingDelegation(ctx, ubd))
resUnbond, err := keeper.GetUnbondingDelegation(ctx, Addr, ValAddr)
require.NoError(err)
require.Equal(ubd, resUnbond)
testCases := []struct {

View File

@ -1,6 +1,7 @@
package keeper
import (
"context"
"time"
"cosmossdk.io/math"
@ -10,66 +11,74 @@ import (
)
// UnbondingTime - The time duration for unbonding
func (k Keeper) UnbondingTime(ctx sdk.Context) time.Duration {
return k.GetParams(ctx).UnbondingTime
func (k Keeper) UnbondingTime(ctx context.Context) (time.Duration, error) {
params, err := k.GetParams(ctx)
return params.UnbondingTime, err
}
// MaxValidators - Maximum number of validators
func (k Keeper) MaxValidators(ctx sdk.Context) uint32 {
return k.GetParams(ctx).MaxValidators
func (k Keeper) MaxValidators(ctx context.Context) (uint32, error) {
params, err := k.GetParams(ctx)
return params.MaxValidators, err
}
// MaxEntries - Maximum number of simultaneous unbonding
// delegations or redelegations (per pair/trio)
func (k Keeper) MaxEntries(ctx sdk.Context) uint32 {
return k.GetParams(ctx).MaxEntries
func (k Keeper) MaxEntries(ctx context.Context) (uint32, error) {
params, err := k.GetParams(ctx)
return params.MaxEntries, err
}
// HistoricalEntries = number of historical info entries
// to persist in store
func (k Keeper) HistoricalEntries(ctx sdk.Context) uint32 {
return k.GetParams(ctx).HistoricalEntries
func (k Keeper) HistoricalEntries(ctx context.Context) (uint32, error) {
params, err := k.GetParams(ctx)
return params.HistoricalEntries, err
}
// BondDenom - Bondable coin denomination
func (k Keeper) BondDenom(ctx sdk.Context) string {
return k.GetParams(ctx).BondDenom
func (k Keeper) BondDenom(ctx context.Context) (string, error) {
params, err := k.GetParams(ctx)
return params.BondDenom, err
}
// PowerReduction - is the amount of staking tokens required for 1 unit of consensus-engine power.
// Currently, this returns a global variable that the app developer can tweak.
// TODO: we might turn this into an on-chain param:
// https://github.com/cosmos/cosmos-sdk/issues/8365
func (k Keeper) PowerReduction(ctx sdk.Context) math.Int {
func (k Keeper) PowerReduction(ctx context.Context) math.Int {
return sdk.DefaultPowerReduction
}
// MinCommissionRate - Minimum validator commission rate
func (k Keeper) MinCommissionRate(ctx sdk.Context) math.LegacyDec {
return k.GetParams(ctx).MinCommissionRate
func (k Keeper) MinCommissionRate(ctx context.Context) (math.LegacyDec, error) {
params, err := k.GetParams(ctx)
return params.MinCommissionRate, err
}
// SetParams sets the x/staking module parameters.
// CONTRACT: This method performs no validation of the parameters.
func (k Keeper) SetParams(ctx sdk.Context, params types.Params) error {
store := ctx.KVStore(k.storeKey)
func (k Keeper) SetParams(ctx context.Context, params types.Params) error {
store := k.storeService.OpenKVStore(ctx)
bz, err := k.cdc.Marshal(&params)
if err != nil {
return err
}
store.Set(types.ParamsKey, bz)
return nil
return store.Set(types.ParamsKey, bz)
}
// GetParams sets the x/staking module parameters.
func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.ParamsKey)
if bz == nil {
return params
func (k Keeper) GetParams(ctx context.Context) (params types.Params, err error) {
store := k.storeService.OpenKVStore(ctx)
bz, err := store.Get(types.ParamsKey)
if err != nil {
return params, err
}
k.cdc.MustUnmarshal(bz, &params)
return params
if bz == nil {
return params, nil
}
err = k.cdc.Unmarshal(bz, &params)
return params, err
}

View File

@ -1,6 +1,8 @@
package keeper
import (
"context"
"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -8,72 +10,104 @@ import (
)
// GetBondedPool returns the bonded tokens pool's module account
func (k Keeper) GetBondedPool(ctx sdk.Context) (bondedPool sdk.ModuleAccountI) {
func (k Keeper) GetBondedPool(ctx context.Context) (bondedPool sdk.ModuleAccountI) {
return k.authKeeper.GetModuleAccount(ctx, types.BondedPoolName)
}
// GetNotBondedPool returns the not bonded tokens pool's module account
func (k Keeper) GetNotBondedPool(ctx sdk.Context) (notBondedPool sdk.ModuleAccountI) {
func (k Keeper) GetNotBondedPool(ctx context.Context) (notBondedPool sdk.ModuleAccountI) {
return k.authKeeper.GetModuleAccount(ctx, types.NotBondedPoolName)
}
// bondedTokensToNotBonded transfers coins from the bonded to the not bonded pool within staking
func (k Keeper) bondedTokensToNotBonded(ctx sdk.Context, tokens math.Int) {
coins := sdk.NewCoins(sdk.NewCoin(k.BondDenom(ctx), tokens))
if err := k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.BondedPoolName, types.NotBondedPoolName, coins); err != nil {
panic(err)
func (k Keeper) bondedTokensToNotBonded(ctx context.Context, tokens math.Int) error {
bondDenom, err := k.BondDenom(ctx)
if err != nil {
return err
}
coins := sdk.NewCoins(sdk.NewCoin(bondDenom, tokens))
return k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.BondedPoolName, types.NotBondedPoolName, coins)
}
// notBondedTokensToBonded transfers coins from the not bonded to the bonded pool within staking
func (k Keeper) notBondedTokensToBonded(ctx sdk.Context, tokens math.Int) {
coins := sdk.NewCoins(sdk.NewCoin(k.BondDenom(ctx), tokens))
if err := k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.NotBondedPoolName, types.BondedPoolName, coins); err != nil {
panic(err)
func (k Keeper) notBondedTokensToBonded(ctx context.Context, tokens math.Int) error {
bondDenom, err := k.BondDenom(ctx)
if err != nil {
return err
}
coins := sdk.NewCoins(sdk.NewCoin(bondDenom, tokens))
return k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.NotBondedPoolName, types.BondedPoolName, coins)
}
// burnBondedTokens removes coins from the bonded pool module account
func (k Keeper) burnBondedTokens(ctx sdk.Context, amt math.Int) error {
func (k Keeper) burnBondedTokens(ctx context.Context, amt math.Int) error {
if !amt.IsPositive() {
// skip as no coins need to be burned
return nil
}
coins := sdk.NewCoins(sdk.NewCoin(k.BondDenom(ctx), amt))
bondDenom, err := k.BondDenom(ctx)
if err != nil {
return err
}
coins := sdk.NewCoins(sdk.NewCoin(bondDenom, amt))
return k.bankKeeper.BurnCoins(ctx, types.BondedPoolName, coins)
}
// burnNotBondedTokens removes coins from the not bonded pool module account
func (k Keeper) burnNotBondedTokens(ctx sdk.Context, amt math.Int) error {
func (k Keeper) burnNotBondedTokens(ctx context.Context, amt math.Int) error {
if !amt.IsPositive() {
// skip as no coins need to be burned
return nil
}
coins := sdk.NewCoins(sdk.NewCoin(k.BondDenom(ctx), amt))
bondDenom, err := k.BondDenom(ctx)
if err != nil {
return err
}
coins := sdk.NewCoins(sdk.NewCoin(bondDenom, amt))
return k.bankKeeper.BurnCoins(ctx, types.NotBondedPoolName, coins)
}
// TotalBondedTokens total staking tokens supply which is bonded
func (k Keeper) TotalBondedTokens(ctx sdk.Context) math.Int {
func (k Keeper) TotalBondedTokens(ctx context.Context) (math.Int, error) {
bondedPool := k.GetBondedPool(ctx)
return k.bankKeeper.GetBalance(ctx, bondedPool.GetAddress(), k.BondDenom(ctx)).Amount
bondDenom, err := k.BondDenom(ctx)
if err != nil {
return math.ZeroInt(), err
}
return k.bankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount, nil
}
// StakingTokenSupply staking tokens from the total supply
func (k Keeper) StakingTokenSupply(ctx sdk.Context) math.Int {
return k.bankKeeper.GetSupply(ctx, k.BondDenom(ctx)).Amount
func (k Keeper) StakingTokenSupply(ctx context.Context) (math.Int, error) {
bondDenom, err := k.BondDenom(ctx)
if err != nil {
return math.ZeroInt(), err
}
return k.bankKeeper.GetSupply(ctx, bondDenom).Amount, nil
}
// BondedRatio the fraction of the staking tokens which are currently bonded
func (k Keeper) BondedRatio(ctx sdk.Context) math.LegacyDec {
stakeSupply := k.StakingTokenSupply(ctx)
if stakeSupply.IsPositive() {
return math.LegacyNewDecFromInt(k.TotalBondedTokens(ctx)).QuoInt(stakeSupply)
func (k Keeper) BondedRatio(ctx context.Context) (math.LegacyDec, error) {
stakeSupply, err := k.StakingTokenSupply(ctx)
if err != nil {
return math.LegacyZeroDec(), err
}
return math.LegacyZeroDec()
if stakeSupply.IsPositive() {
totalBonded, err := k.TotalBondedTokens(ctx)
if err != nil {
return math.LegacyZeroDec(), err
}
return math.LegacyNewDecFromInt(totalBonded).QuoInt(stakeSupply), nil
}
return math.LegacyZeroDec(), nil
}

View File

@ -1,16 +1,19 @@
package keeper
import (
"context"
"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// TokensToConsensusPower - convert input tokens to potential consensus-engine power
func (k Keeper) TokensToConsensusPower(ctx sdk.Context, tokens math.Int) int64 {
func (k Keeper) TokensToConsensusPower(ctx context.Context, tokens math.Int) int64 {
return sdk.TokensToConsensusPower(tokens, k.PowerReduction(ctx))
}
// TokensFromConsensusPower - convert input power to tokens
func (k Keeper) TokensFromConsensusPower(ctx sdk.Context, power int64) math.Int {
func (k Keeper) TokensFromConsensusPower(ctx context.Context, power int64) math.Int {
return sdk.TokensFromConsensusPower(power, k.PowerReduction(ctx))
}

View File

@ -1,6 +1,8 @@
package keeper
import (
"context"
storetypes "cosmossdk.io/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -9,97 +11,107 @@ import (
// Return all validators that a delegator is bonded to. If maxRetrieve is supplied, the respective amount will be returned.
func (k Keeper) GetDelegatorValidators(
ctx sdk.Context, delegatorAddr sdk.AccAddress, maxRetrieve uint32,
) types.Validators {
ctx context.Context, delegatorAddr sdk.AccAddress, maxRetrieve uint32,
) (types.Validators, error) {
validators := make([]types.Validator, maxRetrieve)
store := ctx.KVStore(k.storeKey)
store := k.storeService.OpenKVStore(ctx)
delegatorPrefixKey := types.GetDelegationsKey(delegatorAddr)
iterator := storetypes.KVStorePrefixIterator(store, delegatorPrefixKey) // smallest to largest
iterator, err := store.Iterator(delegatorPrefixKey, storetypes.PrefixEndBytes(delegatorPrefixKey)) // smallest to largest
if err != nil {
return nil, err
}
defer iterator.Close()
i := 0
for ; iterator.Valid() && i < int(maxRetrieve); iterator.Next() {
delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Value())
validator, found := k.GetValidator(ctx, delegation.GetValidatorAddr())
if !found {
panic(types.ErrNoValidatorFound)
validator, err := k.GetValidator(ctx, delegation.GetValidatorAddr())
if err != nil {
return nil, err
}
validators[i] = validator
i++
}
return validators[:i] // trim
return validators[:i], nil // trim
}
// return a validator that a delegator is bonded to
func (k Keeper) GetDelegatorValidator(
ctx sdk.Context, delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress,
ctx context.Context, delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress,
) (validator types.Validator, err error) {
delegation, found := k.GetDelegation(ctx, delegatorAddr, validatorAddr)
if !found {
return validator, types.ErrNoDelegation
delegation, err := k.GetDelegation(ctx, delegatorAddr, validatorAddr)
if err != nil {
return validator, err
}
validator, found = k.GetValidator(ctx, delegation.GetValidatorAddr())
if !found {
panic(types.ErrNoValidatorFound)
}
return validator, nil
return k.GetValidator(ctx, delegation.GetValidatorAddr())
}
// return all delegations for a delegator
func (k Keeper) GetAllDelegatorDelegations(ctx sdk.Context, delegator sdk.AccAddress) []types.Delegation {
func (k Keeper) GetAllDelegatorDelegations(ctx context.Context, delegator sdk.AccAddress) ([]types.Delegation, error) {
delegations := make([]types.Delegation, 0)
store := ctx.KVStore(k.storeKey)
store := k.storeService.OpenKVStore(ctx)
delegatorPrefixKey := types.GetDelegationsKey(delegator)
iterator := storetypes.KVStorePrefixIterator(store, delegatorPrefixKey) // smallest to largest
iterator, err := store.Iterator(delegatorPrefixKey, storetypes.PrefixEndBytes(delegatorPrefixKey)) // smallest to largest
if err != nil {
return nil, err
}
defer iterator.Close()
i := 0
for ; iterator.Valid(); iterator.Next() {
delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Value())
for i := 0; iterator.Valid(); iterator.Next() {
delegation, err := types.UnmarshalDelegation(k.cdc, iterator.Value())
if err != nil {
return nil, err
}
delegations = append(delegations, delegation)
i++
}
return delegations
return delegations, nil
}
// return all unbonding-delegations for a delegator
func (k Keeper) GetAllUnbondingDelegations(ctx sdk.Context, delegator sdk.AccAddress) []types.UnbondingDelegation {
func (k Keeper) GetAllUnbondingDelegations(ctx context.Context, delegator sdk.AccAddress) ([]types.UnbondingDelegation, error) {
unbondingDelegations := make([]types.UnbondingDelegation, 0)
store := ctx.KVStore(k.storeKey)
store := k.storeService.OpenKVStore(ctx)
delegatorPrefixKey := types.GetUBDsKey(delegator)
iterator := storetypes.KVStorePrefixIterator(store, delegatorPrefixKey) // smallest to largest
iterator, err := store.Iterator(delegatorPrefixKey, storetypes.PrefixEndBytes(delegatorPrefixKey)) // smallest to largest
if err != nil {
return nil, err
}
defer iterator.Close()
for i := 0; iterator.Valid(); iterator.Next() {
unbondingDelegation := types.MustUnmarshalUBD(k.cdc, iterator.Value())
unbondingDelegation, err := types.UnmarshalUBD(k.cdc, iterator.Value())
if err != nil {
return nil, err
}
unbondingDelegations = append(unbondingDelegations, unbondingDelegation)
i++
}
return unbondingDelegations
return unbondingDelegations, nil
}
// return all redelegations for a delegator
func (k Keeper) GetAllRedelegations(
ctx sdk.Context, delegator sdk.AccAddress, srcValAddress, dstValAddress sdk.ValAddress,
) []types.Redelegation {
store := ctx.KVStore(k.storeKey)
ctx context.Context, delegator sdk.AccAddress, srcValAddress, dstValAddress sdk.ValAddress,
) ([]types.Redelegation, error) {
store := k.storeService.OpenKVStore(ctx)
delegatorPrefixKey := types.GetREDsKey(delegator)
iterator := storetypes.KVStorePrefixIterator(store, delegatorPrefixKey) // smallest to largest
iterator, err := store.Iterator(delegatorPrefixKey, storetypes.PrefixEndBytes(delegatorPrefixKey)) // smallest to largest
if err != nil {
return nil, err
}
defer iterator.Close()
srcValFilter := !(srcValAddress.Empty())
@ -111,11 +123,11 @@ func (k Keeper) GetAllRedelegations(
redelegation := types.MustUnmarshalRED(k.cdc, iterator.Value())
valSrcAddr, err := sdk.ValAddressFromBech32(redelegation.ValidatorSrcAddress)
if err != nil {
panic(err)
return nil, err
}
valDstAddr, err := sdk.ValAddressFromBech32(redelegation.ValidatorDstAddress)
if err != nil {
panic(err)
return nil, err
}
if srcValFilter && !(srcValAddress.Equals(valSrcAddr)) {
continue
@ -128,5 +140,5 @@ func (k Keeper) GetAllRedelegations(
redelegations = append(redelegations, redelegation)
}
return redelegations
return redelegations, nil
}

View File

@ -1,6 +1,8 @@
package keeper
import (
"context"
"errors"
"fmt"
"cosmossdk.io/math"
@ -30,11 +32,12 @@ import (
//
// Infraction was committed at the current height or at a past height,
// not at a height in the future
func (k Keeper) Slash(ctx sdk.Context, consAddr sdk.ConsAddress, infractionHeight, power int64, slashFactor math.LegacyDec) math.Int {
func (k Keeper) Slash(ctx context.Context, consAddr sdk.ConsAddress, infractionHeight, power int64, slashFactor math.LegacyDec) (math.Int, error) {
logger := k.Logger(ctx)
sdkCtx := sdk.UnwrapSDKContext(ctx)
if slashFactor.IsNegative() {
panic(fmt.Errorf("attempted to slash with a negative slash factor: %v", slashFactor))
return math.NewInt(0), fmt.Errorf("attempted to slash with a negative slash factor: %v", slashFactor)
}
// Amount of slashing = slash slashFactor * power at time of infraction
@ -44,8 +47,8 @@ func (k Keeper) Slash(ctx sdk.Context, consAddr sdk.ConsAddress, infractionHeigh
// ref https://github.com/cosmos/cosmos-sdk/issues/1348
validator, found := k.GetValidatorByConsAddr(ctx, consAddr)
if !found {
validator, err := k.GetValidatorByConsAddr(ctx, consAddr)
if errors.Is(err, types.ErrNoValidatorFound) {
// If not found, the validator must have been overslashed and removed - so we don't need to do anything
// NOTE: Correctness dependent on invariant that unbonding delegations / redelegations must also have been completely
// slashed in this case - which we don't explicitly check, but should be true.
@ -54,12 +57,14 @@ func (k Keeper) Slash(ctx sdk.Context, consAddr sdk.ConsAddress, infractionHeigh
"WARNING: ignored attempt to slash a nonexistent validator; we recommend you investigate immediately",
"validator", consAddr.String(),
)
return math.NewInt(0)
return math.NewInt(0), nil
} else if err != nil {
return math.NewInt(0), err
}
// should not be slashing an unbonded validator
if validator.IsUnbonded() {
panic(fmt.Sprintf("should not be slashing unbonded validator: %s", validator.GetOperator()))
return math.NewInt(0), fmt.Errorf("should not be slashing unbonded validator: %s", validator.GetOperator())
}
operatorAddress := validator.GetOperator()
@ -75,13 +80,13 @@ func (k Keeper) Slash(ctx sdk.Context, consAddr sdk.ConsAddress, infractionHeigh
remainingSlashAmount := slashAmount
switch {
case infractionHeight > ctx.BlockHeight():
case infractionHeight > sdkCtx.BlockHeight():
// Can't slash infractions in the future
panic(fmt.Sprintf(
return math.NewInt(0), fmt.Errorf(
"impossible attempt to slash future infraction at height %d but we are at height %d",
infractionHeight, ctx.BlockHeight()))
infractionHeight, sdkCtx.BlockHeight())
case infractionHeight == ctx.BlockHeight():
case infractionHeight == sdkCtx.BlockHeight():
// Special-case slash at current height for efficiency - we don't need to
// look through unbonding delegations or redelegations.
logger.Info(
@ -89,11 +94,18 @@ func (k Keeper) Slash(ctx sdk.Context, consAddr sdk.ConsAddress, infractionHeigh
"height", infractionHeight,
)
case infractionHeight < ctx.BlockHeight():
case infractionHeight < sdkCtx.BlockHeight():
// Iterate through unbonding delegations from slashed validator
unbondingDelegations := k.GetUnbondingDelegationsFromValidator(ctx, operatorAddress)
unbondingDelegations, err := k.GetUnbondingDelegationsFromValidator(ctx, operatorAddress)
if err != nil {
return math.NewInt(0), err
}
for _, unbondingDelegation := range unbondingDelegations {
amountSlashed := k.SlashUnbondingDelegation(ctx, unbondingDelegation, infractionHeight, slashFactor)
amountSlashed, err := k.SlashUnbondingDelegation(ctx, unbondingDelegation, infractionHeight, slashFactor)
if err != nil {
return math.ZeroInt(), err
}
if amountSlashed.IsZero() {
continue
}
@ -102,9 +114,17 @@ func (k Keeper) Slash(ctx sdk.Context, consAddr sdk.ConsAddress, infractionHeigh
}
// Iterate through redelegations from slashed source validator
redelegations := k.GetRedelegationsFromSrcValidator(ctx, operatorAddress)
redelegations, err := k.GetRedelegationsFromSrcValidator(ctx, operatorAddress)
if err != nil {
return math.NewInt(0), err
}
for _, redelegation := range redelegations {
amountSlashed := k.SlashRedelegation(ctx, validator, redelegation, infractionHeight, slashFactor)
amountSlashed, err := k.SlashRedelegation(ctx, validator, redelegation, infractionHeight, slashFactor)
if err != nil {
return math.NewInt(0), err
}
if amountSlashed.IsZero() {
continue
}
@ -132,16 +152,19 @@ func (k Keeper) Slash(ctx sdk.Context, consAddr sdk.ConsAddress, infractionHeigh
// Deduct from validator's bonded tokens and update the validator.
// Burn the slashed tokens from the pool account and decrease the total supply.
validator = k.RemoveValidatorTokens(ctx, validator, tokensToBurn)
validator, err = k.RemoveValidatorTokens(ctx, validator, tokensToBurn)
if err != nil {
return math.NewInt(0), err
}
switch validator.GetStatus() {
case types.Bonded:
if err := k.burnBondedTokens(ctx, tokensToBurn); err != nil {
panic(err)
return math.NewInt(0), err
}
case types.Unbonding, types.Unbonded:
if err := k.burnNotBondedTokens(ctx, tokensToBurn); err != nil {
panic(err)
return math.NewInt(0), err
}
default:
panic("invalid validator status")
@ -153,28 +176,35 @@ func (k Keeper) Slash(ctx sdk.Context, consAddr sdk.ConsAddress, infractionHeigh
"slash_factor", slashFactor.String(),
"burned", tokensToBurn,
)
return tokensToBurn
return tokensToBurn, nil
}
// SlashWithInfractionReason implementation doesn't require the infraction (types.Infraction) to work but is required by Interchain Security.
func (k Keeper) SlashWithInfractionReason(ctx sdk.Context, consAddr sdk.ConsAddress, infractionHeight, power int64, slashFactor math.LegacyDec, _ types.Infraction) math.Int {
func (k Keeper) SlashWithInfractionReason(ctx context.Context, consAddr sdk.ConsAddress, infractionHeight, power int64, slashFactor math.LegacyDec, _ types.Infraction) (math.Int, error) {
return k.Slash(ctx, consAddr, infractionHeight, power, slashFactor)
}
// jail a validator
func (k Keeper) Jail(ctx sdk.Context, consAddr sdk.ConsAddress) {
func (k Keeper) Jail(ctx context.Context, consAddr sdk.ConsAddress) error {
validator := k.mustGetValidatorByConsAddr(ctx, consAddr)
k.jailValidator(ctx, validator)
if err := k.jailValidator(ctx, validator); err != nil {
return err
}
logger := k.Logger(ctx)
logger.Info("validator jailed", "validator", consAddr)
return nil
}
// unjail a validator
func (k Keeper) Unjail(ctx sdk.Context, consAddr sdk.ConsAddress) {
func (k Keeper) Unjail(ctx context.Context, consAddr sdk.ConsAddress) error {
validator := k.mustGetValidatorByConsAddr(ctx, consAddr)
k.unjailValidator(ctx, validator)
if err := k.unjailValidator(ctx, validator); err != nil {
return err
}
logger := k.Logger(ctx)
logger.Info("validator un-jailed", "validator", consAddr)
return nil
}
// slash an unbonding delegation and update the pool
@ -182,10 +212,11 @@ func (k Keeper) Unjail(ctx sdk.Context, consAddr sdk.ConsAddress) {
// the unbonding delegation had enough stake to slash
// (the amount actually slashed may be less if there's
// insufficient stake remaining)
func (k Keeper) SlashUnbondingDelegation(ctx sdk.Context, unbondingDelegation types.UnbondingDelegation,
func (k Keeper) SlashUnbondingDelegation(ctx context.Context, unbondingDelegation types.UnbondingDelegation,
infractionHeight int64, slashFactor math.LegacyDec,
) (totalSlashAmount math.Int) {
now := ctx.BlockHeader().Time
) (totalSlashAmount math.Int, err error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
now := sdkCtx.BlockHeader().Time
totalSlashAmount = math.ZeroInt()
burnedAmount := math.ZeroInt()
@ -220,14 +251,16 @@ func (k Keeper) SlashUnbondingDelegation(ctx sdk.Context, unbondingDelegation ty
burnedAmount = burnedAmount.Add(unbondingSlashAmount)
entry.Balance = entry.Balance.Sub(unbondingSlashAmount)
unbondingDelegation.Entries[i] = entry
k.SetUnbondingDelegation(ctx, unbondingDelegation)
if err = k.SetUnbondingDelegation(ctx, unbondingDelegation); err != nil {
return math.ZeroInt(), err
}
}
if err := k.burnNotBondedTokens(ctx, burnedAmount); err != nil {
panic(err)
return math.ZeroInt(), err
}
return totalSlashAmount
return totalSlashAmount, nil
}
// slash a redelegation and update the pool
@ -236,10 +269,11 @@ func (k Keeper) SlashUnbondingDelegation(ctx sdk.Context, unbondingDelegation ty
// (the amount actually slashed may be less if there's
// insufficient stake remaining)
// NOTE this is only slashing for prior infractions from the source validator
func (k Keeper) SlashRedelegation(ctx sdk.Context, srcValidator types.Validator, redelegation types.Redelegation,
func (k Keeper) SlashRedelegation(ctx context.Context, srcValidator types.Validator, redelegation types.Redelegation,
infractionHeight int64, slashFactor math.LegacyDec,
) (totalSlashAmount math.Int) {
now := ctx.BlockHeader().Time
) (totalSlashAmount math.Int, err error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
now := sdkCtx.BlockHeader().Time
totalSlashAmount = math.ZeroInt()
bondedBurnedAmount, notBondedBurnedAmount := math.ZeroInt(), math.ZeroInt()
@ -276,8 +310,8 @@ func (k Keeper) SlashRedelegation(ctx sdk.Context, srcValidator types.Validator,
panic(err)
}
delegation, found := k.GetDelegation(ctx, delegatorAddress, valDstAddr)
if !found {
delegation, err := k.GetDelegation(ctx, delegatorAddress, valDstAddr)
if err != nil {
// If deleted, delegation has zero shares, and we can't unbond any more
continue
}
@ -288,12 +322,12 @@ func (k Keeper) SlashRedelegation(ctx sdk.Context, srcValidator types.Validator,
tokensToBurn, err := k.Unbond(ctx, delegatorAddress, valDstAddr, sharesToUnbond)
if err != nil {
panic(fmt.Errorf("error unbonding delegator: %v", err))
return math.ZeroInt(), err
}
dstValidator, found := k.GetValidator(ctx, valDstAddr)
if !found {
panic("destination validator not found")
dstValidator, err := k.GetValidator(ctx, valDstAddr)
if err != nil {
return math.ZeroInt(), err
}
// tokens of a redelegation currently live in the destination validator
@ -309,12 +343,12 @@ func (k Keeper) SlashRedelegation(ctx sdk.Context, srcValidator types.Validator,
}
if err := k.burnBondedTokens(ctx, bondedBurnedAmount); err != nil {
panic(err)
return math.ZeroInt(), err
}
if err := k.burnNotBondedTokens(ctx, notBondedBurnedAmount); err != nil {
panic(err)
return math.ZeroInt(), err
}
return totalSlashAmount
return totalSlashAmount, nil
}

View File

@ -15,36 +15,36 @@ func (s *KeeperTestSuite) TestRevocation() {
validator := testutil.NewValidator(s.T(), valAddr, PKs[0])
// initial state
keeper.SetValidator(ctx, validator)
keeper.SetValidatorByConsAddr(ctx, validator)
val, found := keeper.GetValidator(ctx, valAddr)
require.True(found)
require.NoError(keeper.SetValidator(ctx, validator))
require.NoError(keeper.SetValidatorByConsAddr(ctx, validator))
val, err := keeper.GetValidator(ctx, valAddr)
require.NoError(err)
require.False(val.IsJailed())
// test jail
keeper.Jail(ctx, consAddr)
val, found = keeper.GetValidator(ctx, valAddr)
require.True(found)
require.NoError(keeper.Jail(ctx, consAddr))
val, err = keeper.GetValidator(ctx, valAddr)
require.NoError(err)
require.True(val.IsJailed())
// test unjail
keeper.Unjail(ctx, consAddr)
val, found = keeper.GetValidator(ctx, valAddr)
require.True(found)
require.NoError(keeper.Unjail(ctx, consAddr))
val, err = keeper.GetValidator(ctx, valAddr)
require.NoError(err)
require.False(val.IsJailed())
}
// tests Slash at a future height (must panic)
// tests Slash at a future height (must error)
func (s *KeeperTestSuite) TestSlashAtFutureHeight() {
ctx, keeper := s.ctx, s.stakingKeeper
require := s.Require()
consAddr := sdk.ConsAddress(PKs[0].Address())
validator := testutil.NewValidator(s.T(), sdk.ValAddress(PKs[0].Address().Bytes()), PKs[0])
keeper.SetValidator(ctx, validator)
err := keeper.SetValidatorByConsAddr(ctx, validator)
require.NoError(err)
require.NoError(keeper.SetValidator(ctx, validator))
require.NoError(keeper.SetValidatorByConsAddr(ctx, validator))
fraction := sdk.NewDecWithPrec(5, 1)
require.Panics(func() { keeper.Slash(ctx, consAddr, 1, 10, fraction) })
_, err := keeper.Slash(ctx, consAddr, 1, 10, fraction)
require.Error(err)
}

View File

@ -2,6 +2,7 @@ package keeper // noalias
import (
"bytes"
"context"
storetypes "cosmossdk.io/store/types"
@ -10,20 +11,30 @@ import (
)
// does a certain by-power index record exist
func ValidatorByPowerIndexExists(ctx sdk.Context, keeper *Keeper, power []byte) bool {
store := ctx.KVStore(keeper.storeKey)
return store.Has(power)
func ValidatorByPowerIndexExists(ctx context.Context, keeper *Keeper, power []byte) bool {
store := keeper.storeService.OpenKVStore(ctx)
has, err := store.Has(power)
if err != nil {
panic(err)
}
return has
}
// update validator for testing
func TestingUpdateValidator(keeper *Keeper, ctx sdk.Context, validator types.Validator, apply bool) types.Validator {
keeper.SetValidator(ctx, validator)
err := keeper.SetValidator(ctx, validator)
if err != nil {
panic(err)
}
// Remove any existing power key for validator.
store := ctx.KVStore(keeper.storeKey)
store := keeper.storeService.OpenKVStore(ctx)
deleted := false
iterator := storetypes.KVStorePrefixIterator(store, types.ValidatorsByPowerIndexKey)
iterator, err := store.Iterator(types.ValidatorsByPowerIndexKey, storetypes.PrefixEndBytes(types.ValidatorsByPowerIndexKey))
if err != nil {
panic(err)
}
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
@ -35,23 +46,27 @@ func TestingUpdateValidator(keeper *Keeper, ctx sdk.Context, validator types.Val
deleted = true
}
store.Delete(iterator.Key())
if err = store.Delete(iterator.Key()); err != nil {
panic(err)
}
}
}
keeper.SetValidatorByPowerIndex(ctx, validator)
if err = keeper.SetValidatorByPowerIndex(ctx, validator); err != nil {
panic(err)
}
if !apply {
ctx, _ = ctx.CacheContext()
}
_, err := keeper.ApplyAndReturnValidatorSetUpdates(ctx)
_, err = keeper.ApplyAndReturnValidatorSetUpdates(ctx)
if err != nil {
panic(err)
}
validator, found := keeper.GetValidator(ctx, validator.GetOperator())
if !found {
panic("validator expected but not found")
validator, err = keeper.GetValidator(ctx, validator.GetOperator())
if err != nil {
panic(err)
}
return validator

View File

@ -1,6 +1,7 @@
package keeper
import (
"context"
"encoding/binary"
errorsmod "cosmossdk.io/errors"
@ -10,9 +11,13 @@ import (
)
// IncrementUnbondingID increments and returns a unique ID for an unbonding operation
func (k Keeper) IncrementUnbondingID(ctx sdk.Context) (unbondingID uint64) {
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.UnbondingIDKey)
func (k Keeper) IncrementUnbondingID(ctx context.Context) (unbondingID uint64, err error) {
store := k.storeService.OpenKVStore(ctx)
bz, err := store.Get(types.UnbondingIDKey)
if err != nil {
return 0, err
}
if bz != nil {
unbondingID = binary.BigEndian.Uint64(bz)
}
@ -23,203 +28,239 @@ func (k Keeper) IncrementUnbondingID(ctx sdk.Context) (unbondingID uint64) {
bz = make([]byte, 8)
binary.BigEndian.PutUint64(bz, unbondingID)
store.Set(types.UnbondingIDKey, bz)
if err = store.Set(types.UnbondingIDKey, bz); err != nil {
return 0, err
}
return unbondingID
return unbondingID, err
}
// DeleteUnbondingIndex removes a mapping from UnbondingId to unbonding operation
func (k Keeper) DeleteUnbondingIndex(ctx sdk.Context, id uint64) {
store := ctx.KVStore(k.storeKey)
store.Delete(types.GetUnbondingIndexKey(id))
func (k Keeper) DeleteUnbondingIndex(ctx context.Context, id uint64) error {
store := k.storeService.OpenKVStore(ctx)
return store.Delete(types.GetUnbondingIndexKey(id))
}
func (k Keeper) GetUnbondingType(ctx sdk.Context, id uint64) (unbondingType types.UnbondingType, found bool) {
store := ctx.KVStore(k.storeKey)
func (k Keeper) GetUnbondingType(ctx context.Context, id uint64) (unbondingType types.UnbondingType, err error) {
store := k.storeService.OpenKVStore(ctx)
bz := store.Get(types.GetUnbondingTypeKey(id))
if bz == nil {
return unbondingType, false
bz, err := store.Get(types.GetUnbondingTypeKey(id))
if err != nil {
return unbondingType, err
}
return types.UnbondingType(binary.BigEndian.Uint64(bz)), true
if bz == nil {
return unbondingType, types.ErrNoUnbondingType
}
return types.UnbondingType(binary.BigEndian.Uint64(bz)), nil
}
func (k Keeper) SetUnbondingType(ctx sdk.Context, id uint64, unbondingType types.UnbondingType) {
store := ctx.KVStore(k.storeKey)
func (k Keeper) SetUnbondingType(ctx context.Context, id uint64, unbondingType types.UnbondingType) error {
store := k.storeService.OpenKVStore(ctx)
// Convert into bytes for storage
bz := make([]byte, 8)
binary.BigEndian.PutUint64(bz, uint64(unbondingType))
store.Set(types.GetUnbondingTypeKey(id), bz)
return store.Set(types.GetUnbondingTypeKey(id), bz)
}
// GetUnbondingDelegationByUnbondingID returns a unbonding delegation that has an unbonding delegation entry with a certain ID
func (k Keeper) GetUnbondingDelegationByUnbondingID(ctx sdk.Context, id uint64) (ubd types.UnbondingDelegation, found bool) {
store := ctx.KVStore(k.storeKey)
func (k Keeper) GetUnbondingDelegationByUnbondingID(ctx context.Context, id uint64) (ubd types.UnbondingDelegation, err error) {
store := k.storeService.OpenKVStore(ctx)
ubdKey, err := store.Get(types.GetUnbondingIndexKey(id))
if err != nil {
return types.UnbondingDelegation{}, err
}
ubdKey := store.Get(types.GetUnbondingIndexKey(id))
if ubdKey == nil {
return types.UnbondingDelegation{}, false
return types.UnbondingDelegation{}, types.ErrNoUnbondingDelegation
}
value, err := store.Get(ubdKey)
if err != nil {
return types.UnbondingDelegation{}, err
}
value := store.Get(ubdKey)
if value == nil {
return types.UnbondingDelegation{}, false
return types.UnbondingDelegation{}, types.ErrNoUnbondingDelegation
}
ubd, err := types.UnmarshalUBD(k.cdc, value)
ubd, err = types.UnmarshalUBD(k.cdc, value)
// An error here means that what we got wasn't the right type
if err != nil {
return types.UnbondingDelegation{}, false
return types.UnbondingDelegation{}, err
}
return ubd, true
return ubd, nil
}
// GetRedelegationByUnbondingID returns a unbonding delegation that has an unbonding delegation entry with a certain ID
func (k Keeper) GetRedelegationByUnbondingID(ctx sdk.Context, id uint64) (red types.Redelegation, found bool) {
store := ctx.KVStore(k.storeKey)
func (k Keeper) GetRedelegationByUnbondingID(ctx context.Context, id uint64) (red types.Redelegation, err error) {
store := k.storeService.OpenKVStore(ctx)
redKey, err := store.Get(types.GetUnbondingIndexKey(id))
if err != nil {
return types.Redelegation{}, err
}
redKey := store.Get(types.GetUnbondingIndexKey(id))
if redKey == nil {
return types.Redelegation{}, false
return types.Redelegation{}, types.ErrNoRedelegation
}
value, err := store.Get(redKey)
if err != nil {
return types.Redelegation{}, err
}
value := store.Get(redKey)
if value == nil {
return types.Redelegation{}, false
return types.Redelegation{}, types.ErrNoRedelegation
}
red, err := types.UnmarshalRED(k.cdc, value)
red, err = types.UnmarshalRED(k.cdc, value)
// An error here means that what we got wasn't the right type
if err != nil {
return types.Redelegation{}, false
return types.Redelegation{}, err
}
return red, true
return red, nil
}
// GetValidatorByUnbondingID returns the validator that is unbonding with a certain unbonding op ID
func (k Keeper) GetValidatorByUnbondingID(ctx sdk.Context, id uint64) (val types.Validator, found bool) {
store := ctx.KVStore(k.storeKey)
func (k Keeper) GetValidatorByUnbondingID(ctx context.Context, id uint64) (val types.Validator, err error) {
store := k.storeService.OpenKVStore(ctx)
valKey, err := store.Get(types.GetUnbondingIndexKey(id))
if err != nil {
return types.Validator{}, err
}
valKey := store.Get(types.GetUnbondingIndexKey(id))
if valKey == nil {
return types.Validator{}, false
return types.Validator{}, types.ErrNoValidatorFound
}
value, err := store.Get(valKey)
if err != nil {
return types.Validator{}, err
}
value := store.Get(valKey)
if value == nil {
return types.Validator{}, false
return types.Validator{}, types.ErrNoValidatorFound
}
val, err := types.UnmarshalValidator(k.cdc, value)
val, err = types.UnmarshalValidator(k.cdc, value)
// An error here means that what we got wasn't the right type
if err != nil {
return types.Validator{}, false
return types.Validator{}, err
}
return val, true
return val, nil
}
// SetUnbondingDelegationByUnbondingID sets an index to look up an UnbondingDelegation by the unbondingID of an UnbondingDelegationEntry that it contains
// Note, it does not set the unbonding delegation itself, use SetUnbondingDelegation(ctx, ubd) for that
func (k Keeper) SetUnbondingDelegationByUnbondingID(ctx sdk.Context, ubd types.UnbondingDelegation, id uint64) {
store := ctx.KVStore(k.storeKey)
func (k Keeper) SetUnbondingDelegationByUnbondingID(ctx context.Context, ubd types.UnbondingDelegation, id uint64) error {
store := k.storeService.OpenKVStore(ctx)
delAddr, err := k.authKeeper.AddressCodec().StringToBytes(ubd.DelegatorAddress)
if err != nil {
panic(err)
return err
}
valAddr, err := sdk.ValAddressFromBech32(ubd.ValidatorAddress)
if err != nil {
panic(err)
return err
}
ubdKey := types.GetUBDKey(delAddr, valAddr)
store.Set(types.GetUnbondingIndexKey(id), ubdKey)
if err = store.Set(types.GetUnbondingIndexKey(id), ubdKey); err != nil {
return err
}
// Set unbonding type so that we know how to deserialize it later
k.SetUnbondingType(ctx, id, types.UnbondingType_UnbondingDelegation)
return k.SetUnbondingType(ctx, id, types.UnbondingType_UnbondingDelegation)
}
// SetRedelegationByUnbondingID sets an index to look up an Redelegation by the unbondingID of an RedelegationEntry that it contains
// Note, it does not set the redelegation itself, use SetRedelegation(ctx, red) for that
func (k Keeper) SetRedelegationByUnbondingID(ctx sdk.Context, red types.Redelegation, id uint64) {
store := ctx.KVStore(k.storeKey)
func (k Keeper) SetRedelegationByUnbondingID(ctx context.Context, red types.Redelegation, id uint64) error {
store := k.storeService.OpenKVStore(ctx)
delAddr, err := k.authKeeper.AddressCodec().StringToBytes(red.DelegatorAddress)
if err != nil {
panic(err)
return err
}
valSrcAddr, err := sdk.ValAddressFromBech32(red.ValidatorSrcAddress)
if err != nil {
panic(err)
return err
}
valDstAddr, err := sdk.ValAddressFromBech32(red.ValidatorDstAddress)
if err != nil {
panic(err)
return err
}
redKey := types.GetREDKey(delAddr, valSrcAddr, valDstAddr)
store.Set(types.GetUnbondingIndexKey(id), redKey)
if err = store.Set(types.GetUnbondingIndexKey(id), redKey); err != nil {
return err
}
// Set unbonding type so that we know how to deserialize it later
k.SetUnbondingType(ctx, id, types.UnbondingType_Redelegation)
return k.SetUnbondingType(ctx, id, types.UnbondingType_Redelegation)
}
// SetValidatorByUnbondingID sets an index to look up a Validator by the unbondingID corresponding to its current unbonding
// Note, it does not set the validator itself, use SetValidator(ctx, val) for that
func (k Keeper) SetValidatorByUnbondingID(ctx sdk.Context, val types.Validator, id uint64) {
store := ctx.KVStore(k.storeKey)
func (k Keeper) SetValidatorByUnbondingID(ctx context.Context, val types.Validator, id uint64) error {
store := k.storeService.OpenKVStore(ctx)
valAddr, err := sdk.ValAddressFromBech32(val.OperatorAddress)
if err != nil {
panic(err)
return err
}
valKey := types.GetValidatorKey(valAddr)
store.Set(types.GetUnbondingIndexKey(id), valKey)
if err = store.Set(types.GetUnbondingIndexKey(id), valKey); err != nil {
return err
}
// Set unbonding type so that we know how to deserialize it later
k.SetUnbondingType(ctx, id, types.UnbondingType_ValidatorUnbonding)
return k.SetUnbondingType(ctx, id, types.UnbondingType_ValidatorUnbonding)
}
// unbondingDelegationEntryArrayIndex and redelegationEntryArrayIndex are utilities to find
// at which position in the Entries array the entry with a given id is
func unbondingDelegationEntryArrayIndex(ubd types.UnbondingDelegation, id uint64) (index int, found bool) {
func unbondingDelegationEntryArrayIndex(ubd types.UnbondingDelegation, id uint64) (index int, err error) {
for i, entry := range ubd.Entries {
// we find the entry with the right ID
if entry.UnbondingId == id {
return i, true
return i, nil
}
}
return 0, false
return 0, types.ErrNoUnbondingDelegation
}
func redelegationEntryArrayIndex(red types.Redelegation, id uint64) (index int, found bool) {
func redelegationEntryArrayIndex(red types.Redelegation, id uint64) (index int, err error) {
for i, entry := range red.Entries {
// we find the entry with the right ID
if entry.UnbondingId == id {
return i, true
return i, nil
}
}
return 0, false
return 0, types.ErrNoRedelegation
}
// UnbondingCanComplete allows a stopped unbonding operation, such as an
// unbonding delegation, a redelegation, or a validator unbonding to complete.
// In order for the unbonding operation with `id` to eventually complete, every call
// to PutUnbondingOnHold(id) must be matched by a call to UnbondingCanComplete(id).
func (k Keeper) UnbondingCanComplete(ctx sdk.Context, id uint64) error {
unbondingType, found := k.GetUnbondingType(ctx, id)
if !found {
return types.ErrUnbondingNotFound
func (k Keeper) UnbondingCanComplete(ctx context.Context, id uint64) error {
unbondingType, err := k.GetUnbondingType(ctx, id)
if err != nil {
return err
}
switch unbondingType {
@ -242,15 +283,15 @@ func (k Keeper) UnbondingCanComplete(ctx sdk.Context, id uint64) error {
return nil
}
func (k Keeper) unbondingDelegationEntryCanComplete(ctx sdk.Context, id uint64) error {
ubd, found := k.GetUnbondingDelegationByUnbondingID(ctx, id)
if !found {
return types.ErrUnbondingNotFound
func (k Keeper) unbondingDelegationEntryCanComplete(ctx context.Context, id uint64) error {
ubd, err := k.GetUnbondingDelegationByUnbondingID(ctx, id)
if err != nil {
return err
}
i, found := unbondingDelegationEntryArrayIndex(ubd, id)
if !found {
return types.ErrUnbondingNotFound
i, err := unbondingDelegationEntryArrayIndex(ubd, id)
if err != nil {
return err
}
// The entry must be on hold
@ -263,15 +304,19 @@ func (k Keeper) unbondingDelegationEntryCanComplete(ctx sdk.Context, id uint64)
}
ubd.Entries[i].UnbondingOnHoldRefCount--
sdkCtx := sdk.UnwrapSDKContext(ctx)
// Check if entry is matured.
if !ubd.Entries[i].OnHold() && ubd.Entries[i].IsMature(ctx.BlockHeader().Time) {
if !ubd.Entries[i].OnHold() && ubd.Entries[i].IsMature(sdkCtx.BlockHeader().Time) {
// If matured, complete it.
delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(ubd.DelegatorAddress)
if err != nil {
return err
}
bondDenom := k.GetParams(ctx).BondDenom
bondDenom, err := k.BondDenom(ctx)
if err != nil {
return err
}
// track undelegation only when remaining or truncated shares are non-zero
if !ubd.Entries[i].Balance.IsZero() {
@ -286,29 +331,30 @@ func (k Keeper) unbondingDelegationEntryCanComplete(ctx sdk.Context, id uint64)
// Remove entry
ubd.RemoveEntry(int64(i))
// Remove from the UnbondingIndex
k.DeleteUnbondingIndex(ctx, id)
err = k.DeleteUnbondingIndex(ctx, id)
if err != nil {
return err
}
}
// set the unbonding delegation or remove it if there are no more entries
if len(ubd.Entries) == 0 {
k.RemoveUnbondingDelegation(ctx, ubd)
} else {
k.SetUnbondingDelegation(ctx, ubd)
return k.RemoveUnbondingDelegation(ctx, ubd)
}
// Successfully completed unbonding
return nil
return k.SetUnbondingDelegation(ctx, ubd)
}
func (k Keeper) redelegationEntryCanComplete(ctx sdk.Context, id uint64) error {
red, found := k.GetRedelegationByUnbondingID(ctx, id)
if !found {
return types.ErrUnbondingNotFound
func (k Keeper) redelegationEntryCanComplete(ctx context.Context, id uint64) error {
red, err := k.GetRedelegationByUnbondingID(ctx, id)
if err != nil {
return err
}
i, found := redelegationEntryArrayIndex(red, id)
if !found {
return types.ErrUnbondingNotFound
i, err := redelegationEntryArrayIndex(red, id)
if err != nil {
return err
}
// The entry must be on hold
@ -321,29 +367,29 @@ func (k Keeper) redelegationEntryCanComplete(ctx sdk.Context, id uint64) error {
}
red.Entries[i].UnbondingOnHoldRefCount--
if !red.Entries[i].OnHold() && red.Entries[i].IsMature(ctx.BlockHeader().Time) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
if !red.Entries[i].OnHold() && red.Entries[i].IsMature(sdkCtx.BlockHeader().Time) {
// If matured, complete it.
// Remove entry
red.RemoveEntry(int64(i))
// Remove from the Unbonding index
k.DeleteUnbondingIndex(ctx, id)
if err = k.DeleteUnbondingIndex(ctx, id); err != nil {
return err
}
}
// set the redelegation or remove it if there are no more entries
if len(red.Entries) == 0 {
k.RemoveRedelegation(ctx, red)
} else {
k.SetRedelegation(ctx, red)
return k.RemoveRedelegation(ctx, red)
}
// Successfully completed unbonding
return nil
return k.SetRedelegation(ctx, red)
}
func (k Keeper) validatorUnbondingCanComplete(ctx sdk.Context, id uint64) error {
val, found := k.GetValidatorByUnbondingID(ctx, id)
if !found {
return types.ErrUnbondingNotFound
func (k Keeper) validatorUnbondingCanComplete(ctx context.Context, id uint64) error {
val, err := k.GetValidatorByUnbondingID(ctx, id)
if err != nil {
return err
}
if val.UnbondingOnHoldRefCount <= 0 {
@ -354,19 +400,17 @@ func (k Keeper) validatorUnbondingCanComplete(ctx sdk.Context, id uint64) error
)
}
val.UnbondingOnHoldRefCount--
k.SetValidator(ctx, val)
return nil
return k.SetValidator(ctx, val)
}
// PutUnbondingOnHold allows an external module to stop an unbonding operation,
// such as an unbonding delegation, a redelegation, or a validator unbonding.
// In order for the unbonding operation with `id` to eventually complete, every call
// to PutUnbondingOnHold(id) must be matched by a call to UnbondingCanComplete(id).
func (k Keeper) PutUnbondingOnHold(ctx sdk.Context, id uint64) error {
unbondingType, found := k.GetUnbondingType(ctx, id)
if !found {
return types.ErrUnbondingNotFound
func (k Keeper) PutUnbondingOnHold(ctx context.Context, id uint64) error {
unbondingType, err := k.GetUnbondingType(ctx, id)
if err != nil {
return err
}
switch unbondingType {
case types.UnbondingType_UnbondingDelegation:
@ -388,48 +432,42 @@ func (k Keeper) PutUnbondingOnHold(ctx sdk.Context, id uint64) error {
return nil
}
func (k Keeper) putUnbondingDelegationEntryOnHold(ctx sdk.Context, id uint64) error {
ubd, found := k.GetUnbondingDelegationByUnbondingID(ctx, id)
if !found {
return types.ErrUnbondingNotFound
func (k Keeper) putUnbondingDelegationEntryOnHold(ctx context.Context, id uint64) error {
ubd, err := k.GetUnbondingDelegationByUnbondingID(ctx, id)
if err != nil {
return err
}
i, found := unbondingDelegationEntryArrayIndex(ubd, id)
if !found {
return types.ErrUnbondingNotFound
i, err := unbondingDelegationEntryArrayIndex(ubd, id)
if err != nil {
return err
}
ubd.Entries[i].UnbondingOnHoldRefCount++
k.SetUnbondingDelegation(ctx, ubd)
return nil
return k.SetUnbondingDelegation(ctx, ubd)
}
func (k Keeper) putRedelegationEntryOnHold(ctx sdk.Context, id uint64) error {
red, found := k.GetRedelegationByUnbondingID(ctx, id)
if !found {
return types.ErrUnbondingNotFound
func (k Keeper) putRedelegationEntryOnHold(ctx context.Context, id uint64) error {
red, err := k.GetRedelegationByUnbondingID(ctx, id)
if err != nil {
return err
}
i, found := redelegationEntryArrayIndex(red, id)
if !found {
return types.ErrUnbondingNotFound
i, err := redelegationEntryArrayIndex(red, id)
if err != nil {
return err
}
red.Entries[i].UnbondingOnHoldRefCount++
k.SetRedelegation(ctx, red)
return nil
return k.SetRedelegation(ctx, red)
}
func (k Keeper) putValidatorOnHold(ctx sdk.Context, id uint64) error {
val, found := k.GetValidatorByUnbondingID(ctx, id)
if !found {
return types.ErrUnbondingNotFound
func (k Keeper) putValidatorOnHold(ctx context.Context, id uint64) error {
val, err := k.GetValidatorByUnbondingID(ctx, id)
if err != nil {
return err
}
val.UnbondingOnHoldRefCount++
k.SetValidator(ctx, val)
return nil
return k.SetValidator(ctx, val)
}

View File

@ -4,6 +4,7 @@ import (
"time"
"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/staking/testutil"
"github.com/cosmos/cosmos-sdk/x/staking/types"
@ -11,11 +12,14 @@ import (
func (s *KeeperTestSuite) TestIncrementUnbondingID() {
for i := 1; i < 10; i++ {
s.Require().Equal(uint64(i), s.stakingKeeper.IncrementUnbondingID(s.ctx))
id, err := s.stakingKeeper.IncrementUnbondingID(s.ctx)
s.Require().NoError(err)
s.Require().Equal(uint64(i), id)
}
}
func (s *KeeperTestSuite) TestUnbondingTypeAccessors() {
require := s.Require()
cases := []struct {
exists bool
name string
@ -40,15 +44,15 @@ func (s *KeeperTestSuite) TestUnbondingTypeAccessors() {
for i, tc := range cases {
s.Run(tc.name, func() {
if tc.exists {
s.stakingKeeper.SetUnbondingType(s.ctx, uint64(i), tc.expected)
require.NoError(s.stakingKeeper.SetUnbondingType(s.ctx, uint64(i), tc.expected))
}
unbondingType, found := s.stakingKeeper.GetUnbondingType(s.ctx, uint64(i))
unbondingType, err := s.stakingKeeper.GetUnbondingType(s.ctx, uint64(i))
if tc.exists {
s.Require().True(found)
s.Require().Equal(tc.expected, unbondingType)
require.NoError(err)
require.Equal(tc.expected, unbondingType)
} else {
s.Require().False(found)
require.ErrorIs(err, types.ErrNoUnbondingType)
}
})
}
@ -56,6 +60,7 @@ func (s *KeeperTestSuite) TestUnbondingTypeAccessors() {
func (s *KeeperTestSuite) TestUnbondingDelegationByUnbondingIDAccessors() {
delAddrs, valAddrs := createValAddrs(2)
require := s.Require()
type exists struct {
setUnbondingDelegation bool
@ -108,19 +113,19 @@ func (s *KeeperTestSuite) TestUnbondingDelegationByUnbondingIDAccessors() {
for i, tc := range cases {
s.Run(tc.name, func() {
if tc.exists.setUnbondingDelegation {
s.stakingKeeper.SetUnbondingDelegation(s.ctx, tc.expected)
require.NoError(s.stakingKeeper.SetUnbondingDelegation(s.ctx, tc.expected))
}
if tc.exists.setUnbondingDelegationByUnbondingID {
s.stakingKeeper.SetUnbondingDelegationByUnbondingID(s.ctx, tc.expected, uint64(i))
require.NoError(s.stakingKeeper.SetUnbondingDelegationByUnbondingID(s.ctx, tc.expected, uint64(i)))
}
ubd, found := s.stakingKeeper.GetUnbondingDelegationByUnbondingID(s.ctx, uint64(i))
ubd, err := s.stakingKeeper.GetUnbondingDelegationByUnbondingID(s.ctx, uint64(i))
if tc.exists.setUnbondingDelegation && tc.exists.setUnbondingDelegationByUnbondingID {
s.Require().True(found)
s.Require().Equal(tc.expected, ubd)
require.NoError(err)
require.Equal(tc.expected, ubd)
} else {
s.Require().False(found)
require.ErrorIs(err, types.ErrNoUnbondingDelegation)
}
})
}
@ -128,6 +133,7 @@ func (s *KeeperTestSuite) TestUnbondingDelegationByUnbondingIDAccessors() {
func (s *KeeperTestSuite) TestRedelegationByUnbondingIDAccessors() {
delAddrs, valAddrs := createValAddrs(2)
require := s.Require()
type exists struct {
setRedelegation bool
@ -186,19 +192,19 @@ func (s *KeeperTestSuite) TestRedelegationByUnbondingIDAccessors() {
for i, tc := range cases {
s.Run(tc.name, func() {
if tc.exists.setRedelegation {
s.stakingKeeper.SetRedelegation(s.ctx, tc.expected)
require.NoError(s.stakingKeeper.SetRedelegation(s.ctx, tc.expected))
}
if tc.exists.setRedelegationByUnbondingID {
s.stakingKeeper.SetRedelegationByUnbondingID(s.ctx, tc.expected, uint64(i))
require.NoError(s.stakingKeeper.SetRedelegationByUnbondingID(s.ctx, tc.expected, uint64(i)))
}
red, found := s.stakingKeeper.GetRedelegationByUnbondingID(s.ctx, uint64(i))
red, err := s.stakingKeeper.GetRedelegationByUnbondingID(s.ctx, uint64(i))
if tc.exists.setRedelegation && tc.exists.setRedelegationByUnbondingID {
s.Require().True(found)
s.Require().Equal(tc.expected, red)
require.NoError(err)
require.Equal(tc.expected, red)
} else {
s.Require().False(found)
require.ErrorIs(err, types.ErrNoRedelegation)
}
})
}
@ -206,6 +212,7 @@ func (s *KeeperTestSuite) TestRedelegationByUnbondingIDAccessors() {
func (s *KeeperTestSuite) TestValidatorByUnbondingIDAccessors() {
_, valAddrs := createValAddrs(3)
require := s.Require()
type exists struct {
setValidator bool
@ -237,19 +244,19 @@ func (s *KeeperTestSuite) TestValidatorByUnbondingIDAccessors() {
for i, tc := range cases {
s.Run(tc.name, func() {
if tc.exists.setValidator {
s.stakingKeeper.SetValidator(s.ctx, tc.validator)
require.NoError(s.stakingKeeper.SetValidator(s.ctx, tc.validator))
}
if tc.exists.setValidatorByUnbondingID {
s.stakingKeeper.SetValidatorByUnbondingID(s.ctx, tc.validator, uint64(i))
require.NoError(s.stakingKeeper.SetValidatorByUnbondingID(s.ctx, tc.validator, uint64(i)))
}
val, found := s.stakingKeeper.GetValidatorByUnbondingID(s.ctx, uint64(i))
val, err := s.stakingKeeper.GetValidatorByUnbondingID(s.ctx, uint64(i))
if tc.exists.setValidator && tc.exists.setValidatorByUnbondingID {
s.Require().True(found)
s.Require().Equal(tc.validator, val)
require.NoError(err)
require.Equal(tc.validator, val)
} else {
s.Require().False(found)
require.ErrorIs(err, types.ErrNoValidatorFound)
}
})
}
@ -257,17 +264,18 @@ func (s *KeeperTestSuite) TestValidatorByUnbondingIDAccessors() {
func (s *KeeperTestSuite) TestUnbondingCanComplete() {
delAddrs, valAddrs := createValAddrs(3)
require := s.Require()
unbondingID := uint64(1)
// no unbondingID set
err := s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID)
s.Require().ErrorIs(err, types.ErrUnbondingNotFound)
require.ErrorIs(err, types.ErrNoUnbondingType)
// unbonding delegation
s.stakingKeeper.SetUnbondingType(s.ctx, unbondingID, types.UnbondingType_UnbondingDelegation)
require.NoError(s.stakingKeeper.SetUnbondingType(s.ctx, unbondingID, types.UnbondingType_UnbondingDelegation))
err = s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID)
s.Require().ErrorIs(err, types.ErrUnbondingNotFound)
require.ErrorIs(err, types.ErrNoUnbondingDelegation)
ubd := types.NewUnbondingDelegation(
delAddrs[0],
@ -277,22 +285,22 @@ func (s *KeeperTestSuite) TestUnbondingCanComplete() {
sdk.NewInt(5),
unbondingID,
)
s.stakingKeeper.SetUnbondingDelegation(s.ctx, ubd)
s.stakingKeeper.SetUnbondingDelegationByUnbondingID(s.ctx, ubd, unbondingID)
require.NoError(s.stakingKeeper.SetUnbondingDelegation(s.ctx, ubd))
require.NoError(s.stakingKeeper.SetUnbondingDelegationByUnbondingID(s.ctx, ubd, unbondingID))
err = s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID)
s.Require().ErrorIs(err, types.ErrUnbondingOnHoldRefCountNegative)
require.ErrorIs(err, types.ErrUnbondingOnHoldRefCountNegative)
err = s.stakingKeeper.PutUnbondingOnHold(s.ctx, unbondingID)
s.Require().NoError(err)
require.NoError(err)
s.bankKeeper.EXPECT().UndelegateCoinsFromModuleToAccount(s.ctx, types.NotBondedPoolName, delAddrs[0], sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(5)))).Return(nil)
err = s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID)
s.Require().NoError(err)
require.NoError(err)
// redelegation
unbondingID++
s.stakingKeeper.SetUnbondingType(s.ctx, unbondingID, types.UnbondingType_Redelegation)
require.NoError(s.stakingKeeper.SetUnbondingType(s.ctx, unbondingID, types.UnbondingType_Redelegation))
err = s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID)
s.Require().ErrorIs(err, types.ErrUnbondingNotFound)
require.ErrorIs(err, types.ErrNoRedelegation)
red := types.NewRedelegation(
delAddrs[0],
@ -304,30 +312,26 @@ func (s *KeeperTestSuite) TestUnbondingCanComplete() {
math.LegacyNewDec(10),
unbondingID,
)
s.stakingKeeper.SetRedelegation(s.ctx, red)
s.stakingKeeper.SetRedelegationByUnbondingID(s.ctx, red, unbondingID)
require.NoError(s.stakingKeeper.SetRedelegation(s.ctx, red))
require.NoError(s.stakingKeeper.SetRedelegationByUnbondingID(s.ctx, red, unbondingID))
err = s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID)
s.Require().ErrorIs(err, types.ErrUnbondingOnHoldRefCountNegative)
require.ErrorIs(err, types.ErrUnbondingOnHoldRefCountNegative)
err = s.stakingKeeper.PutUnbondingOnHold(s.ctx, unbondingID)
s.Require().NoError(err)
err = s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID)
s.Require().NoError(err)
require.NoError(s.stakingKeeper.PutUnbondingOnHold(s.ctx, unbondingID))
require.NoError(s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID))
// validator unbonding
unbondingID++
s.stakingKeeper.SetUnbondingType(s.ctx, unbondingID, types.UnbondingType_ValidatorUnbonding)
require.NoError(s.stakingKeeper.SetUnbondingType(s.ctx, unbondingID, types.UnbondingType_ValidatorUnbonding))
err = s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID)
s.Require().ErrorIs(err, types.ErrUnbondingNotFound)
require.ErrorIs(err, types.ErrNoValidatorFound)
val := testutil.NewValidator(s.T(), valAddrs[0], PKs[0])
s.stakingKeeper.SetValidator(s.ctx, val)
s.stakingKeeper.SetValidatorByUnbondingID(s.ctx, val, unbondingID)
require.NoError(s.stakingKeeper.SetValidator(s.ctx, val))
require.NoError(s.stakingKeeper.SetValidatorByUnbondingID(s.ctx, val, unbondingID))
err = s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID)
s.Require().ErrorIs(err, types.ErrUnbondingOnHoldRefCountNegative)
require.ErrorIs(err, types.ErrUnbondingOnHoldRefCountNegative)
err = s.stakingKeeper.PutUnbondingOnHold(s.ctx, unbondingID)
s.Require().NoError(err)
err = s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID)
s.Require().NoError(err)
require.NoError(s.stakingKeeper.PutUnbondingOnHold(s.ctx, unbondingID))
require.NoError(s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID))
}

View File

@ -2,6 +2,7 @@ package keeper
import (
"bytes"
"context"
"fmt"
"sort"
@ -16,7 +17,7 @@ import (
// BlockValidatorUpdates calculates the ValidatorUpdates for the current block
// Called in each EndBlock
func (k Keeper) BlockValidatorUpdates(ctx sdk.Context) []abci.ValidatorUpdate {
func (k Keeper) BlockValidatorUpdates(ctx context.Context) ([]abci.ValidatorUpdate, error) {
// Calculate validator set changes.
//
// NOTE: ApplyAndReturnValidatorSetUpdates has to come before
@ -28,22 +29,30 @@ func (k Keeper) BlockValidatorUpdates(ctx sdk.Context) []abci.ValidatorUpdate {
// UnbondAllMatureValidatorQueue).
validatorUpdates, err := k.ApplyAndReturnValidatorSetUpdates(ctx)
if err != nil {
panic(err)
return nil, err
}
// unbond all mature validators from the unbonding queue
k.UnbondAllMatureValidators(ctx)
err = k.UnbondAllMatureValidators(ctx)
if err != nil {
return nil, err
}
sdkCtx := sdk.UnwrapSDKContext(ctx)
// Remove all mature unbonding delegations from the ubd queue.
matureUnbonds := k.DequeueAllMatureUBDQueue(ctx, ctx.BlockHeader().Time)
matureUnbonds, err := k.DequeueAllMatureUBDQueue(ctx, sdkCtx.BlockHeader().Time)
if err != nil {
return nil, err
}
for _, dvPair := range matureUnbonds {
addr, err := sdk.ValAddressFromBech32(dvPair.ValidatorAddress)
if err != nil {
panic(err)
return nil, err
}
delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(dvPair.DelegatorAddress)
if err != nil {
panic(err)
return nil, err
}
balances, err := k.CompleteUnbonding(ctx, delegatorAddress, addr)
@ -51,7 +60,7 @@ func (k Keeper) BlockValidatorUpdates(ctx sdk.Context) []abci.ValidatorUpdate {
continue
}
ctx.EventManager().EmitEvent(
sdkCtx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeCompleteUnbonding,
sdk.NewAttribute(sdk.AttributeKeyAmount, balances.String()),
@ -62,19 +71,23 @@ func (k Keeper) BlockValidatorUpdates(ctx sdk.Context) []abci.ValidatorUpdate {
}
// Remove all mature redelegations from the red queue.
matureRedelegations := k.DequeueAllMatureRedelegationQueue(ctx, ctx.BlockHeader().Time)
matureRedelegations, err := k.DequeueAllMatureRedelegationQueue(ctx, sdkCtx.BlockHeader().Time)
if err != nil {
return nil, err
}
for _, dvvTriplet := range matureRedelegations {
valSrcAddr, err := sdk.ValAddressFromBech32(dvvTriplet.ValidatorSrcAddress)
if err != nil {
panic(err)
return nil, err
}
valDstAddr, err := sdk.ValAddressFromBech32(dvvTriplet.ValidatorDstAddress)
if err != nil {
panic(err)
return nil, err
}
delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(dvvTriplet.DelegatorAddress)
if err != nil {
panic(err)
return nil, err
}
balances, err := k.CompleteRedelegation(
@ -87,7 +100,7 @@ func (k Keeper) BlockValidatorUpdates(ctx sdk.Context) []abci.ValidatorUpdate {
continue
}
ctx.EventManager().EmitEvent(
sdkCtx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeCompleteRedelegation,
sdk.NewAttribute(sdk.AttributeKeyAmount, balances.String()),
@ -98,7 +111,7 @@ func (k Keeper) BlockValidatorUpdates(ctx sdk.Context) []abci.ValidatorUpdate {
)
}
return validatorUpdates
return validatorUpdates, nil
}
// ApplyAndReturnValidatorSetUpdates applies and return accumulated updates to the bonded validator set. Also,
@ -113,8 +126,11 @@ func (k Keeper) BlockValidatorUpdates(ctx sdk.Context) []abci.ValidatorUpdate {
// CONTRACT: Only validators with non-zero power or zero-power that were bonded
// at the previous block height or were removed from the validator set entirely
// are returned to CometBFT.
func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx sdk.Context) (updates []abci.ValidatorUpdate, err error) {
params := k.GetParams(ctx)
func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx context.Context) (updates []abci.ValidatorUpdate, err error) {
params, err := k.GetParams(ctx)
if err != nil {
return nil, err
}
maxValidators := params.MaxValidators
powerReduction := k.PowerReduction(ctx)
totalPower := math.ZeroInt()
@ -129,7 +145,10 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx sdk.Context) (updates []ab
}
// Iterate over validators, highest power to lowest.
iterator := k.ValidatorsPowerStoreIterator(ctx)
iterator, err := k.ValidatorsPowerStoreIterator(ctx)
if err != nil {
return nil, err
}
defer iterator.Close()
for count := 0; iterator.Valid() && count < int(maxValidators); iterator.Next() {
@ -181,7 +200,9 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx sdk.Context) (updates []ab
if !found || !bytes.Equal(oldPowerBytes, newPowerBytes) {
updates = append(updates, validator.ABCIValidatorUpdate(powerReduction))
k.SetLastValidatorPower(ctx, valAddr, newPower)
if err = k.SetLastValidatorPower(ctx, valAddr, newPower); err != nil {
return nil, err
}
}
delete(last, valAddrStr)
@ -199,10 +220,13 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx sdk.Context) (updates []ab
validator := k.mustGetValidator(ctx, sdk.ValAddress(valAddrBytes))
validator, err = k.bondedToUnbonding(ctx, validator)
if err != nil {
return
return nil, err
}
amtFromBondedToNotBonded = amtFromBondedToNotBonded.Add(validator.GetTokens())
k.DeleteLastValidatorPower(ctx, validator.GetOperator())
if err = k.DeleteLastValidatorPower(ctx, validator.GetOperator()); err != nil {
return nil, err
}
updates = append(updates, validator.ABCIValidatorUpdateZero())
}
@ -215,26 +239,34 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx sdk.Context) (updates []ab
// Compare and subtract the respective amounts to only perform one transfer.
// This is done in order to avoid doing multiple updates inside each iterator/loop.
case amtFromNotBondedToBonded.GT(amtFromBondedToNotBonded):
k.notBondedTokensToBonded(ctx, amtFromNotBondedToBonded.Sub(amtFromBondedToNotBonded))
if err = k.notBondedTokensToBonded(ctx, amtFromNotBondedToBonded.Sub(amtFromBondedToNotBonded)); err != nil {
return nil, err
}
case amtFromNotBondedToBonded.LT(amtFromBondedToNotBonded):
k.bondedTokensToNotBonded(ctx, amtFromBondedToNotBonded.Sub(amtFromNotBondedToBonded))
if err = k.bondedTokensToNotBonded(ctx, amtFromBondedToNotBonded.Sub(amtFromNotBondedToBonded)); err != nil {
return nil, err
}
default: // equal amounts of tokens; no update required
}
// set total power on lookup index if there are any updates
if len(updates) > 0 {
k.SetLastTotalPower(ctx, totalPower)
if err = k.SetLastTotalPower(ctx, totalPower); err != nil {
return nil, err
}
}
// set the list of validator updates
k.SetValidatorUpdates(ctx, updates)
if err = k.SetValidatorUpdates(ctx, updates); err != nil {
return nil, err
}
return updates, err
}
// Validator state transitions
func (k Keeper) bondedToUnbonding(ctx sdk.Context, validator types.Validator) (types.Validator, error) {
func (k Keeper) bondedToUnbonding(ctx context.Context, validator types.Validator) (types.Validator, error) {
if !validator.IsBonded() {
panic(fmt.Sprintf("bad state transition bondedToUnbonding, validator: %v\n", validator))
}
@ -242,7 +274,7 @@ func (k Keeper) bondedToUnbonding(ctx sdk.Context, validator types.Validator) (t
return k.BeginUnbondingValidator(ctx, validator)
}
func (k Keeper) unbondingToBonded(ctx sdk.Context, validator types.Validator) (types.Validator, error) {
func (k Keeper) unbondingToBonded(ctx context.Context, validator types.Validator) (types.Validator, error) {
if !validator.IsUnbonding() {
panic(fmt.Sprintf("bad state transition unbondingToBonded, validator: %v\n", validator))
}
@ -250,7 +282,7 @@ func (k Keeper) unbondingToBonded(ctx sdk.Context, validator types.Validator) (t
return k.bondValidator(ctx, validator)
}
func (k Keeper) unbondedToBonded(ctx sdk.Context, validator types.Validator) (types.Validator, error) {
func (k Keeper) unbondedToBonded(ctx context.Context, validator types.Validator) (types.Validator, error) {
if !validator.IsUnbonded() {
panic(fmt.Sprintf("bad state transition unbondedToBonded, validator: %v\n", validator))
}
@ -259,49 +291,64 @@ func (k Keeper) unbondedToBonded(ctx sdk.Context, validator types.Validator) (ty
}
// UnbondingToUnbonded switches a validator from unbonding state to unbonded state
func (k Keeper) UnbondingToUnbonded(ctx sdk.Context, validator types.Validator) types.Validator {
func (k Keeper) UnbondingToUnbonded(ctx context.Context, validator types.Validator) (types.Validator, error) {
if !validator.IsUnbonding() {
panic(fmt.Sprintf("bad state transition unbondingToUnbonded, validator: %v\n", validator))
return types.Validator{}, fmt.Errorf("bad state transition unbondingToUnbonded, validator: %v", validator)
}
return k.completeUnbondingValidator(ctx, validator)
}
// send a validator to jail
func (k Keeper) jailValidator(ctx sdk.Context, validator types.Validator) {
func (k Keeper) jailValidator(ctx context.Context, validator types.Validator) error {
if validator.Jailed {
panic(fmt.Sprintf("cannot jail already jailed validator, validator: %v\n", validator))
return types.ErrValidatorJailed.Wrapf("cannot jail already jailed validator, validator: %v", validator)
}
validator.Jailed = true
k.SetValidator(ctx, validator)
k.DeleteValidatorByPowerIndex(ctx, validator)
if err := k.SetValidator(ctx, validator); err != nil {
return err
}
return k.DeleteValidatorByPowerIndex(ctx, validator)
}
// remove a validator from jail
func (k Keeper) unjailValidator(ctx sdk.Context, validator types.Validator) {
func (k Keeper) unjailValidator(ctx context.Context, validator types.Validator) error {
if !validator.Jailed {
panic(fmt.Sprintf("cannot unjail already unjailed validator, validator: %v\n", validator))
return fmt.Errorf("cannot unjail already unjailed validator, validator: %v", validator)
}
validator.Jailed = false
k.SetValidator(ctx, validator)
k.SetValidatorByPowerIndex(ctx, validator)
if err := k.SetValidator(ctx, validator); err != nil {
return err
}
return k.SetValidatorByPowerIndex(ctx, validator)
}
// perform all the store operations for when a validator status becomes bonded
func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) (types.Validator, error) {
func (k Keeper) bondValidator(ctx context.Context, validator types.Validator) (types.Validator, error) {
// delete the validator by power index, as the key will change
k.DeleteValidatorByPowerIndex(ctx, validator)
if err := k.DeleteValidatorByPowerIndex(ctx, validator); err != nil {
return validator, err
}
validator = validator.UpdateStatus(types.Bonded)
// save the now bonded validator record to the two referenced stores
k.SetValidator(ctx, validator)
k.SetValidatorByPowerIndex(ctx, validator)
if err := k.SetValidator(ctx, validator); err != nil {
return validator, err
}
if err := k.SetValidatorByPowerIndex(ctx, validator); err != nil {
return validator, err
}
// delete from queue if present
k.DeleteValidatorQueue(ctx, validator)
if err := k.DeleteValidatorQueue(ctx, validator); err != nil {
return validator, err
}
// trigger hook
consAddr, err := validator.GetConsAddr()
@ -317,33 +364,49 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) (types
}
// BeginUnbondingValidator performs all the store operations for when a validator begins unbonding
func (k Keeper) BeginUnbondingValidator(ctx sdk.Context, validator types.Validator) (types.Validator, error) {
params := k.GetParams(ctx)
func (k Keeper) BeginUnbondingValidator(ctx context.Context, validator types.Validator) (types.Validator, error) {
params, err := k.GetParams(ctx)
if err != nil {
return validator, err
}
// delete the validator by power index, as the key will change
k.DeleteValidatorByPowerIndex(ctx, validator)
if err = k.DeleteValidatorByPowerIndex(ctx, validator); err != nil {
return validator, err
}
// sanity check
if validator.Status != types.Bonded {
panic(fmt.Sprintf("should not already be unbonded or unbonding, validator: %v\n", validator))
}
id := k.IncrementUnbondingID(ctx)
id, err := k.IncrementUnbondingID(ctx)
if err != nil {
return validator, err
}
validator = validator.UpdateStatus(types.Unbonding)
sdkCtx := sdk.UnwrapSDKContext(ctx)
// set the unbonding completion time and completion height appropriately
validator.UnbondingTime = ctx.BlockHeader().Time.Add(params.UnbondingTime)
validator.UnbondingHeight = ctx.BlockHeader().Height
validator.UnbondingTime = sdkCtx.BlockHeader().Time.Add(params.UnbondingTime)
validator.UnbondingHeight = sdkCtx.BlockHeader().Height
validator.UnbondingIds = append(validator.UnbondingIds, id)
// save the now unbonded validator record and power index
k.SetValidator(ctx, validator)
k.SetValidatorByPowerIndex(ctx, validator)
if err = k.SetValidator(ctx, validator); err != nil {
return validator, err
}
if err = k.SetValidatorByPowerIndex(ctx, validator); err != nil {
return validator, err
}
// Adds to unbonding validator queue
k.InsertUnbondingValidatorQueue(ctx, validator)
if err = k.InsertUnbondingValidatorQueue(ctx, validator); err != nil {
return validator, err
}
// trigger hook
consAddr, err := validator.GetConsAddr()
@ -355,7 +418,9 @@ func (k Keeper) BeginUnbondingValidator(ctx sdk.Context, validator types.Validat
return validator, err
}
k.SetValidatorByUnbondingID(ctx, validator, id)
if err := k.SetValidatorByUnbondingID(ctx, validator, id); err != nil {
return validator, err
}
if err := k.Hooks().AfterUnbondingInitiated(ctx, id); err != nil {
return validator, err
@ -365,11 +430,13 @@ func (k Keeper) BeginUnbondingValidator(ctx sdk.Context, validator types.Validat
}
// perform all the store operations for when a validator status becomes unbonded
func (k Keeper) completeUnbondingValidator(ctx sdk.Context, validator types.Validator) types.Validator {
func (k Keeper) completeUnbondingValidator(ctx context.Context, validator types.Validator) (types.Validator, error) {
validator = validator.UpdateStatus(types.Unbonded)
k.SetValidator(ctx, validator)
if err := k.SetValidator(ctx, validator); err != nil {
return validator, err
}
return validator
return validator, nil
}
// map of operator bech32-addresses to serialized power
@ -377,10 +444,13 @@ func (k Keeper) completeUnbondingValidator(ctx sdk.Context, validator types.Vali
type validatorsByAddr map[string][]byte
// get the last validator set
func (k Keeper) getLastValidatorsByAddr(ctx sdk.Context) (validatorsByAddr, error) {
func (k Keeper) getLastValidatorsByAddr(ctx context.Context) (validatorsByAddr, error) {
last := make(validatorsByAddr)
iterator := k.LastValidatorsIterator(ctx)
iterator, err := k.LastValidatorsIterator(ctx)
if err != nil {
return nil, err
}
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {

View File

@ -1,11 +1,15 @@
package keeper
import (
"context"
"errors"
"fmt"
"time"
gogotypes "github.com/cosmos/gogoproto/types"
corestore "cosmossdk.io/core/store"
errorsmod "cosmossdk.io/errors"
"cosmossdk.io/math"
storetypes "cosmossdk.io/store/types"
@ -14,21 +18,23 @@ import (
)
// get a single validator
func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator types.Validator, found bool) {
store := ctx.KVStore(k.storeKey)
value := store.Get(types.GetValidatorKey(addr))
if value == nil {
return validator, false
func (k Keeper) GetValidator(ctx context.Context, addr sdk.ValAddress) (validator types.Validator, err error) {
store := k.storeService.OpenKVStore(ctx)
value, err := store.Get(types.GetValidatorKey(addr))
if err != nil {
return validator, err
}
validator = types.MustUnmarshalValidator(k.cdc, value)
return validator, true
if value == nil {
return validator, types.ErrNoValidatorFound
}
return types.UnmarshalValidator(k.cdc, value)
}
func (k Keeper) mustGetValidator(ctx sdk.Context, addr sdk.ValAddress) types.Validator {
validator, found := k.GetValidator(ctx, addr)
if !found {
func (k Keeper) mustGetValidator(ctx context.Context, addr sdk.ValAddress) types.Validator {
validator, err := k.GetValidator(ctx, addr)
if err != nil {
panic(fmt.Sprintf("validator record not found for address: %X\n", addr))
}
@ -36,20 +42,23 @@ func (k Keeper) mustGetValidator(ctx sdk.Context, addr sdk.ValAddress) types.Val
}
// get a single validator by consensus address
func (k Keeper) GetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) (validator types.Validator, found bool) {
store := ctx.KVStore(k.storeKey)
func (k Keeper) GetValidatorByConsAddr(ctx context.Context, consAddr sdk.ConsAddress) (validator types.Validator, err error) {
store := k.storeService.OpenKVStore(ctx)
opAddr, err := store.Get(types.GetValidatorByConsAddrKey(consAddr))
if err != nil {
return validator, err
}
opAddr := store.Get(types.GetValidatorByConsAddrKey(consAddr))
if opAddr == nil {
return validator, false
return validator, types.ErrNoValidatorFound
}
return k.GetValidator(ctx, opAddr)
}
func (k Keeper) mustGetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) types.Validator {
validator, found := k.GetValidatorByConsAddr(ctx, consAddr)
if !found {
func (k Keeper) mustGetValidatorByConsAddr(ctx context.Context, consAddr sdk.ConsAddress) types.Validator {
validator, err := k.GetValidatorByConsAddr(ctx, consAddr)
if err != nil {
panic(fmt.Errorf("validator with consensus-Address %s not found", consAddr))
}
@ -57,96 +66,122 @@ func (k Keeper) mustGetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAdd
}
// set the main record holding validator details
func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) {
store := ctx.KVStore(k.storeKey)
func (k Keeper) SetValidator(ctx context.Context, validator types.Validator) error {
store := k.storeService.OpenKVStore(ctx)
bz := types.MustMarshalValidator(k.cdc, &validator)
store.Set(types.GetValidatorKey(validator.GetOperator()), bz)
return store.Set(types.GetValidatorKey(validator.GetOperator()), bz)
}
// validator index
func (k Keeper) SetValidatorByConsAddr(ctx sdk.Context, validator types.Validator) error {
func (k Keeper) SetValidatorByConsAddr(ctx context.Context, validator types.Validator) error {
consPk, err := validator.GetConsAddr()
if err != nil {
return err
}
store := ctx.KVStore(k.storeKey)
store.Set(types.GetValidatorByConsAddrKey(consPk), validator.GetOperator())
return nil
store := k.storeService.OpenKVStore(ctx)
return store.Set(types.GetValidatorByConsAddrKey(consPk), validator.GetOperator())
}
// validator index
func (k Keeper) SetValidatorByPowerIndex(ctx sdk.Context, validator types.Validator) {
func (k Keeper) SetValidatorByPowerIndex(ctx context.Context, validator types.Validator) error {
// jailed validators are not kept in the power index
if validator.Jailed {
return
return nil
}
store := ctx.KVStore(k.storeKey)
store.Set(types.GetValidatorsByPowerIndexKey(validator, k.PowerReduction(ctx)), validator.GetOperator())
store := k.storeService.OpenKVStore(ctx)
return store.Set(types.GetValidatorsByPowerIndexKey(validator, k.PowerReduction(ctx)), validator.GetOperator())
}
// validator index
func (k Keeper) DeleteValidatorByPowerIndex(ctx sdk.Context, validator types.Validator) {
store := ctx.KVStore(k.storeKey)
store.Delete(types.GetValidatorsByPowerIndexKey(validator, k.PowerReduction(ctx)))
func (k Keeper) DeleteValidatorByPowerIndex(ctx context.Context, validator types.Validator) error {
store := k.storeService.OpenKVStore(ctx)
return store.Delete(types.GetValidatorsByPowerIndexKey(validator, k.PowerReduction(ctx)))
}
// validator index
func (k Keeper) SetNewValidatorByPowerIndex(ctx sdk.Context, validator types.Validator) {
store := ctx.KVStore(k.storeKey)
store.Set(types.GetValidatorsByPowerIndexKey(validator, k.PowerReduction(ctx)), validator.GetOperator())
func (k Keeper) SetNewValidatorByPowerIndex(ctx context.Context, validator types.Validator) error {
store := k.storeService.OpenKVStore(ctx)
return store.Set(types.GetValidatorsByPowerIndexKey(validator, k.PowerReduction(ctx)), validator.GetOperator())
}
// Update the tokens of an existing validator, update the validators power index key
func (k Keeper) AddValidatorTokensAndShares(ctx sdk.Context, validator types.Validator,
func (k Keeper) AddValidatorTokensAndShares(ctx context.Context, validator types.Validator,
tokensToAdd math.Int,
) (valOut types.Validator, addedShares math.LegacyDec) {
k.DeleteValidatorByPowerIndex(ctx, validator)
) (valOut types.Validator, addedShares math.LegacyDec, err error) {
err = k.DeleteValidatorByPowerIndex(ctx, validator)
if err != nil {
return valOut, addedShares, err
}
validator, addedShares = validator.AddTokensFromDel(tokensToAdd)
k.SetValidator(ctx, validator)
k.SetValidatorByPowerIndex(ctx, validator)
err = k.SetValidator(ctx, validator)
if err != nil {
return validator, addedShares, err
}
return validator, addedShares
err = k.SetValidatorByPowerIndex(ctx, validator)
return validator, addedShares, err
}
// Update the tokens of an existing validator, update the validators power index key
func (k Keeper) RemoveValidatorTokensAndShares(ctx sdk.Context, validator types.Validator,
func (k Keeper) RemoveValidatorTokensAndShares(ctx context.Context, validator types.Validator,
sharesToRemove math.LegacyDec,
) (valOut types.Validator, removedTokens math.Int) {
k.DeleteValidatorByPowerIndex(ctx, validator)
) (valOut types.Validator, removedTokens math.Int, err error) {
err = k.DeleteValidatorByPowerIndex(ctx, validator)
if err != nil {
return valOut, removedTokens, err
}
validator, removedTokens = validator.RemoveDelShares(sharesToRemove)
k.SetValidator(ctx, validator)
k.SetValidatorByPowerIndex(ctx, validator)
err = k.SetValidator(ctx, validator)
if err != nil {
return validator, removedTokens, err
}
return validator, removedTokens
err = k.SetValidatorByPowerIndex(ctx, validator)
return validator, removedTokens, err
}
// Update the tokens of an existing validator, update the validators power index key
func (k Keeper) RemoveValidatorTokens(ctx sdk.Context,
func (k Keeper) RemoveValidatorTokens(ctx context.Context,
validator types.Validator, tokensToRemove math.Int,
) types.Validator {
k.DeleteValidatorByPowerIndex(ctx, validator)
validator = validator.RemoveTokens(tokensToRemove)
k.SetValidator(ctx, validator)
k.SetValidatorByPowerIndex(ctx, validator)
) (types.Validator, error) {
if err := k.DeleteValidatorByPowerIndex(ctx, validator); err != nil {
return validator, err
}
return validator
validator = validator.RemoveTokens(tokensToRemove)
if err := k.SetValidator(ctx, validator); err != nil {
return validator, err
}
if err := k.SetValidatorByPowerIndex(ctx, validator); err != nil {
return validator, err
}
return validator, nil
}
// UpdateValidatorCommission attempts to update a validator's commission rate.
// An error is returned if the new commission rate is invalid.
func (k Keeper) UpdateValidatorCommission(ctx sdk.Context,
func (k Keeper) UpdateValidatorCommission(ctx context.Context,
validator types.Validator, newRate math.LegacyDec,
) (types.Commission, error) {
commission := validator.Commission
blockTime := ctx.BlockHeader().Time
sdkCtx := sdk.UnwrapSDKContext(ctx)
blockTime := sdkCtx.BlockHeader().Time
if err := commission.ValidateNewRate(newRate, blockTime); err != nil {
return commission, err
}
if newRate.LT(k.MinCommissionRate(ctx)) {
return commission, fmt.Errorf("cannot set validator commission to less than minimum rate of %s", k.MinCommissionRate(ctx))
minCommissionRate, err := k.MinCommissionRate(ctx)
if err != nil {
return commission, err
}
if newRate.LT(minCommissionRate) {
return commission, fmt.Errorf("cannot set validator commission to less than minimum rate of %s", minCommissionRate)
}
commission.Rate = newRate
@ -157,79 +192,105 @@ func (k Keeper) UpdateValidatorCommission(ctx sdk.Context,
// remove the validator record and associated indexes
// except for the bonded validator index which is only handled in ApplyAndReturnTendermintUpdates
// TODO, this function panics, and it's not good.
func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) {
func (k Keeper) RemoveValidator(ctx context.Context, address sdk.ValAddress) error {
// first retrieve the old validator record
validator, found := k.GetValidator(ctx, address)
if !found {
return
validator, err := k.GetValidator(ctx, address)
if errors.Is(err, types.ErrNoValidatorFound) {
return nil
}
if !validator.IsUnbonded() {
panic("cannot call RemoveValidator on bonded or unbonding validators")
return types.ErrBadRemoveValidator.Wrap("cannot call RemoveValidator on bonded or unbonding validators")
}
if validator.Tokens.IsPositive() {
panic("attempting to remove a validator which still contains tokens")
return types.ErrBadRemoveValidator.Wrap("attempting to remove a validator which still contains tokens")
}
valConsAddr, err := validator.GetConsAddr()
if err != nil {
panic(err)
return err
}
// delete the old validator record
store := ctx.KVStore(k.storeKey)
store.Delete(types.GetValidatorKey(address))
store.Delete(types.GetValidatorByConsAddrKey(valConsAddr))
store.Delete(types.GetValidatorsByPowerIndexKey(validator, k.PowerReduction(ctx)))
store := k.storeService.OpenKVStore(ctx)
if err = store.Delete(types.GetValidatorKey(address)); err != nil {
return err
}
if err = store.Delete(types.GetValidatorByConsAddrKey(valConsAddr)); err != nil {
return err
}
if err = store.Delete(types.GetValidatorsByPowerIndexKey(validator, k.PowerReduction(ctx))); err != nil {
return err
}
if err := k.Hooks().AfterValidatorRemoved(ctx, valConsAddr, validator.GetOperator()); err != nil {
k.Logger(ctx).Error("error in after validator removed hook", "error", err)
}
return nil
}
// get groups of validators
// get the set of all validators with no limits, used during genesis dump
func (k Keeper) GetAllValidators(ctx sdk.Context) (validators []types.Validator) {
store := ctx.KVStore(k.storeKey)
func (k Keeper) GetAllValidators(ctx context.Context) (validators []types.Validator, err error) {
store := k.storeService.OpenKVStore(ctx)
iterator := storetypes.KVStorePrefixIterator(store, types.ValidatorsKey)
iterator, err := store.Iterator(types.ValidatorsKey, storetypes.PrefixEndBytes(types.ValidatorsKey))
if err != nil {
return nil, err
}
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
validator := types.MustUnmarshalValidator(k.cdc, iterator.Value())
validator, err := types.UnmarshalValidator(k.cdc, iterator.Value())
if err != nil {
return nil, err
}
validators = append(validators, validator)
}
return validators
return validators, nil
}
// return a given amount of all the validators
func (k Keeper) GetValidators(ctx sdk.Context, maxRetrieve uint32) (validators []types.Validator) {
store := ctx.KVStore(k.storeKey)
func (k Keeper) GetValidators(ctx context.Context, maxRetrieve uint32) (validators []types.Validator, err error) {
store := k.storeService.OpenKVStore(ctx)
validators = make([]types.Validator, maxRetrieve)
iterator := storetypes.KVStorePrefixIterator(store, types.ValidatorsKey)
defer iterator.Close()
iterator, err := store.Iterator(types.ValidatorsKey, storetypes.PrefixEndBytes(types.ValidatorsKey))
if err != nil {
return nil, err
}
i := 0
for ; iterator.Valid() && i < int(maxRetrieve); iterator.Next() {
validator := types.MustUnmarshalValidator(k.cdc, iterator.Value())
validator, err := types.UnmarshalValidator(k.cdc, iterator.Value())
if err != nil {
return nil, err
}
validators[i] = validator
i++
}
return validators[:i] // trim if the array length < maxRetrieve
return validators[:i], nil // trim if the array length < maxRetrieve
}
// get the current group of bonded validators sorted by power-rank
func (k Keeper) GetBondedValidatorsByPower(ctx sdk.Context) []types.Validator {
maxValidators := k.MaxValidators(ctx)
func (k Keeper) GetBondedValidatorsByPower(ctx context.Context) ([]types.Validator, error) {
maxValidators, err := k.MaxValidators(ctx)
if err != nil {
return nil, err
}
validators := make([]types.Validator, maxValidators)
iterator := k.ValidatorsPowerStoreIterator(ctx)
iterator, err := k.ValidatorsPowerStoreIterator(ctx)
if err != nil {
return nil, err
}
defer iterator.Close()
i := 0
@ -243,82 +304,99 @@ func (k Keeper) GetBondedValidatorsByPower(ctx sdk.Context) []types.Validator {
}
}
return validators[:i] // trim
return validators[:i], nil // trim
}
// returns an iterator for the current validator power store
func (k Keeper) ValidatorsPowerStoreIterator(ctx sdk.Context) storetypes.Iterator {
store := ctx.KVStore(k.storeKey)
return storetypes.KVStoreReversePrefixIterator(store, types.ValidatorsByPowerIndexKey)
func (k Keeper) ValidatorsPowerStoreIterator(ctx context.Context) (corestore.Iterator, error) {
store := k.storeService.OpenKVStore(ctx)
return store.ReverseIterator(types.ValidatorsByPowerIndexKey, storetypes.PrefixEndBytes(types.ValidatorsByPowerIndexKey))
}
// Last Validator Index
// Load the last validator power.
// Returns zero if the operator was not a validator last block.
func (k Keeper) GetLastValidatorPower(ctx sdk.Context, operator sdk.ValAddress) (power int64) {
store := ctx.KVStore(k.storeKey)
func (k Keeper) GetLastValidatorPower(ctx context.Context, operator sdk.ValAddress) (power int64, err error) {
store := k.storeService.OpenKVStore(ctx)
bz, err := store.Get(types.GetLastValidatorPowerKey(operator))
if err != nil {
return 0, err
}
bz := store.Get(types.GetLastValidatorPowerKey(operator))
if bz == nil {
return 0
return 0, nil
}
intV := gogotypes.Int64Value{}
k.cdc.MustUnmarshal(bz, &intV)
err = k.cdc.Unmarshal(bz, &intV)
if err != nil {
return 0, err
}
return intV.GetValue()
return intV.GetValue(), nil
}
// Set the last validator power.
func (k Keeper) SetLastValidatorPower(ctx sdk.Context, operator sdk.ValAddress, power int64) {
store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshal(&gogotypes.Int64Value{Value: power})
store.Set(types.GetLastValidatorPowerKey(operator), bz)
func (k Keeper) SetLastValidatorPower(ctx context.Context, operator sdk.ValAddress, power int64) error {
store := k.storeService.OpenKVStore(ctx)
bz, err := k.cdc.Marshal(&gogotypes.Int64Value{Value: power})
if err != nil {
return err
}
return store.Set(types.GetLastValidatorPowerKey(operator), bz)
}
// Delete the last validator power.
func (k Keeper) DeleteLastValidatorPower(ctx sdk.Context, operator sdk.ValAddress) {
store := ctx.KVStore(k.storeKey)
store.Delete(types.GetLastValidatorPowerKey(operator))
func (k Keeper) DeleteLastValidatorPower(ctx context.Context, operator sdk.ValAddress) error {
store := k.storeService.OpenKVStore(ctx)
return store.Delete(types.GetLastValidatorPowerKey(operator))
}
// returns an iterator for the consensus validators in the last block
func (k Keeper) LastValidatorsIterator(ctx sdk.Context) (iterator storetypes.Iterator) {
store := ctx.KVStore(k.storeKey)
iterator = storetypes.KVStorePrefixIterator(store, types.LastValidatorPowerKey)
return iterator
func (k Keeper) LastValidatorsIterator(ctx context.Context) (corestore.Iterator, error) {
store := k.storeService.OpenKVStore(ctx)
return store.Iterator(types.LastValidatorPowerKey, storetypes.PrefixEndBytes(types.LastValidatorPowerKey))
}
// Iterate over last validator powers.
func (k Keeper) IterateLastValidatorPowers(ctx sdk.Context, handler func(operator sdk.ValAddress, power int64) (stop bool)) {
store := ctx.KVStore(k.storeKey)
iter := storetypes.KVStorePrefixIterator(store, types.LastValidatorPowerKey)
defer iter.Close()
func (k Keeper) IterateLastValidatorPowers(ctx context.Context, handler func(operator sdk.ValAddress, power int64) (stop bool)) error {
iter, err := k.LastValidatorsIterator(ctx)
if err != nil {
return err
}
for ; iter.Valid(); iter.Next() {
addr := sdk.ValAddress(types.AddressFromLastValidatorPowerKey(iter.Key()))
intV := &gogotypes.Int64Value{}
k.cdc.MustUnmarshal(iter.Value(), intV)
if err = k.cdc.Unmarshal(iter.Value(), intV); err != nil {
return err
}
if handler(addr, intV.GetValue()) {
break
}
}
return nil
}
// get the group of the bonded validators
func (k Keeper) GetLastValidators(ctx sdk.Context) (validators []types.Validator) {
store := ctx.KVStore(k.storeKey)
func (k Keeper) GetLastValidators(ctx context.Context) (validators []types.Validator, err error) {
store := k.storeService.OpenKVStore(ctx)
// add the actual validator power sorted store
maxValidators := k.MaxValidators(ctx)
maxValidators, err := k.MaxValidators(ctx)
if err != nil {
return nil, err
}
validators = make([]types.Validator, maxValidators)
iterator := storetypes.KVStorePrefixIterator(store, types.LastValidatorPowerKey)
iterator, err := store.Iterator(types.LastValidatorPowerKey, storetypes.PrefixEndBytes(types.LastValidatorPowerKey))
if err != nil {
return nil, err
}
defer iterator.Close()
i := 0
@ -329,72 +407,90 @@ func (k Keeper) GetLastValidators(ctx sdk.Context) (validators []types.Validator
}
address := types.AddressFromLastValidatorPowerKey(iterator.Key())
validator := k.mustGetValidator(ctx, address)
validator, err := k.GetValidator(ctx, address)
if err != nil {
return nil, err
}
validators[i] = validator
i++
}
return validators[:i] // trim
return validators[:i], nil // trim
}
// GetUnbondingValidators returns a slice of mature validator addresses that
// complete their unbonding at a given time and height.
func (k Keeper) GetUnbondingValidators(ctx sdk.Context, endTime time.Time, endHeight int64) []string {
store := ctx.KVStore(k.storeKey)
func (k Keeper) GetUnbondingValidators(ctx context.Context, endTime time.Time, endHeight int64) ([]string, error) {
store := k.storeService.OpenKVStore(ctx)
bz, err := store.Get(types.GetValidatorQueueKey(endTime, endHeight))
if err != nil {
return nil, err
}
bz := store.Get(types.GetValidatorQueueKey(endTime, endHeight))
if bz == nil {
return []string{}
return []string{}, nil
}
addrs := types.ValAddresses{}
k.cdc.MustUnmarshal(bz, &addrs)
if err = k.cdc.Unmarshal(bz, &addrs); err != nil {
return nil, err
}
return addrs.Addresses
return addrs.Addresses, nil
}
// SetUnbondingValidatorsQueue sets a given slice of validator addresses into
// the unbonding validator queue by a given height and time.
func (k Keeper) SetUnbondingValidatorsQueue(ctx sdk.Context, endTime time.Time, endHeight int64, addrs []string) {
store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshal(&types.ValAddresses{Addresses: addrs})
store.Set(types.GetValidatorQueueKey(endTime, endHeight), bz)
func (k Keeper) SetUnbondingValidatorsQueue(ctx context.Context, endTime time.Time, endHeight int64, addrs []string) error {
store := k.storeService.OpenKVStore(ctx)
bz, err := k.cdc.Marshal(&types.ValAddresses{Addresses: addrs})
if err != nil {
return err
}
return store.Set(types.GetValidatorQueueKey(endTime, endHeight), bz)
}
// InsertUnbondingValidatorQueue inserts a given unbonding validator address into
// the unbonding validator queue for a given height and time.
func (k Keeper) InsertUnbondingValidatorQueue(ctx sdk.Context, val types.Validator) {
addrs := k.GetUnbondingValidators(ctx, val.UnbondingTime, val.UnbondingHeight)
func (k Keeper) InsertUnbondingValidatorQueue(ctx context.Context, val types.Validator) error {
addrs, err := k.GetUnbondingValidators(ctx, val.UnbondingTime, val.UnbondingHeight)
if err != nil {
return err
}
addrs = append(addrs, val.OperatorAddress)
k.SetUnbondingValidatorsQueue(ctx, val.UnbondingTime, val.UnbondingHeight, addrs)
return k.SetUnbondingValidatorsQueue(ctx, val.UnbondingTime, val.UnbondingHeight, addrs)
}
// DeleteValidatorQueueTimeSlice deletes all entries in the queue indexed by a
// given height and time.
func (k Keeper) DeleteValidatorQueueTimeSlice(ctx sdk.Context, endTime time.Time, endHeight int64) {
store := ctx.KVStore(k.storeKey)
store.Delete(types.GetValidatorQueueKey(endTime, endHeight))
func (k Keeper) DeleteValidatorQueueTimeSlice(ctx context.Context, endTime time.Time, endHeight int64) error {
store := k.storeService.OpenKVStore(ctx)
return store.Delete(types.GetValidatorQueueKey(endTime, endHeight))
}
// DeleteValidatorQueue removes a validator by address from the unbonding queue
// indexed by a given height and time.
func (k Keeper) DeleteValidatorQueue(ctx sdk.Context, val types.Validator) {
addrs := k.GetUnbondingValidators(ctx, val.UnbondingTime, val.UnbondingHeight)
func (k Keeper) DeleteValidatorQueue(ctx context.Context, val types.Validator) error {
addrs, err := k.GetUnbondingValidators(ctx, val.UnbondingTime, val.UnbondingHeight)
if err != nil {
return err
}
newAddrs := []string{}
// since address string may change due to Bech32 prefix change, we parse the addresses into bytes
// format for normalization
deletingAddr, err := sdk.ValAddressFromBech32(val.OperatorAddress)
if err != nil {
panic(err)
return err
}
for _, addr := range addrs {
storedAddr, err := sdk.ValAddressFromBech32(addr)
if err != nil {
// even if we don't panic here, it will panic in UnbondAllMatureValidators at unbond time
panic(err)
// even if we don't error here, it will error in UnbondAllMatureValidators at unbond time
return err
}
if !storedAddr.Equals(deletingAddr) {
newAddrs = append(newAddrs, storedAddr.String())
@ -402,38 +498,42 @@ func (k Keeper) DeleteValidatorQueue(ctx sdk.Context, val types.Validator) {
}
if len(newAddrs) == 0 {
k.DeleteValidatorQueueTimeSlice(ctx, val.UnbondingTime, val.UnbondingHeight)
} else {
k.SetUnbondingValidatorsQueue(ctx, val.UnbondingTime, val.UnbondingHeight, newAddrs)
return k.DeleteValidatorQueueTimeSlice(ctx, val.UnbondingTime, val.UnbondingHeight)
}
return k.SetUnbondingValidatorsQueue(ctx, val.UnbondingTime, val.UnbondingHeight, newAddrs)
}
// ValidatorQueueIterator returns an interator ranging over validators that are
// unbonding whose unbonding completion occurs at the given height and time.
func (k Keeper) ValidatorQueueIterator(ctx sdk.Context, endTime time.Time, endHeight int64) storetypes.Iterator {
store := ctx.KVStore(k.storeKey)
func (k Keeper) ValidatorQueueIterator(ctx context.Context, endTime time.Time, endHeight int64) (corestore.Iterator, error) {
store := k.storeService.OpenKVStore(ctx)
return store.Iterator(types.ValidatorQueueKey, storetypes.InclusiveEndBytes(types.GetValidatorQueueKey(endTime, endHeight)))
}
// UnbondAllMatureValidators unbonds all the mature unbonding validators that
// have finished their unbonding period.
func (k Keeper) UnbondAllMatureValidators(ctx sdk.Context) {
blockTime := ctx.BlockTime()
blockHeight := ctx.BlockHeight()
func (k Keeper) UnbondAllMatureValidators(ctx context.Context) error {
sdkCtx := sdk.UnwrapSDKContext(ctx)
blockTime := sdkCtx.BlockTime()
blockHeight := sdkCtx.BlockHeight()
// unbondingValIterator will contains all validator addresses indexed under
// the ValidatorQueueKey prefix. Note, the entire index key is composed as
// ValidatorQueueKey | timeBzLen (8-byte big endian) | timeBz | heightBz (8-byte big endian),
// so it may be possible that certain validator addresses that are iterated
// over are not ready to unbond, so an explicit check is required.
unbondingValIterator := k.ValidatorQueueIterator(ctx, blockTime, blockHeight)
unbondingValIterator, err := k.ValidatorQueueIterator(ctx, blockTime, blockHeight)
if err != nil {
return err
}
defer unbondingValIterator.Close()
for ; unbondingValIterator.Valid(); unbondingValIterator.Next() {
key := unbondingValIterator.Key()
keyTime, keyHeight, err := types.ParseValidatorQueueKey(key)
if err != nil {
panic(fmt.Errorf("failed to parse unbonding key: %w", err))
return fmt.Errorf("failed to parse unbonding key: %w", err)
}
// All addresses for the given key have the same unbonding height and time.
@ -441,49 +541,61 @@ func (k Keeper) UnbondAllMatureValidators(ctx sdk.Context) {
// and time.
if keyHeight <= blockHeight && (keyTime.Before(blockTime) || keyTime.Equal(blockTime)) {
addrs := types.ValAddresses{}
k.cdc.MustUnmarshal(unbondingValIterator.Value(), &addrs)
if err = k.cdc.Unmarshal(unbondingValIterator.Value(), &addrs); err != nil {
return err
}
for _, valAddr := range addrs.Addresses {
addr, err := sdk.ValAddressFromBech32(valAddr)
if err != nil {
panic(err)
return err
}
val, found := k.GetValidator(ctx, addr)
if !found {
panic("validator in the unbonding queue was not found")
val, err := k.GetValidator(ctx, addr)
if err != nil {
return errorsmod.Wrap(err, "validator in the unbonding queue was not found")
}
if !val.IsUnbonding() {
panic("unexpected validator in unbonding queue; status was not unbonding")
return fmt.Errorf("unexpected validator in unbonding queue; status was not unbonding")
}
if val.UnbondingOnHoldRefCount == 0 {
for _, id := range val.UnbondingIds {
k.DeleteUnbondingIndex(ctx, id)
if err = k.DeleteUnbondingIndex(ctx, id); err != nil {
return err
}
}
val = k.UnbondingToUnbonded(ctx, val)
val, err = k.UnbondingToUnbonded(ctx, val)
if err != nil {
return err
}
if val.GetDelegatorShares().IsZero() {
k.RemoveValidator(ctx, val.GetOperator())
if err = k.RemoveValidator(ctx, val.GetOperator()); err != nil {
return err
}
} else {
// remove unbonding ids
val.UnbondingIds = []uint64{}
}
// remove validator from queue
k.DeleteValidatorQueue(ctx, val)
if err = k.DeleteValidatorQueue(ctx, val); err != nil {
return err
}
}
}
}
}
return nil
}
func (k Keeper) IsValidatorJailed(ctx sdk.Context, addr sdk.ConsAddress) bool {
v, ok := k.GetValidatorByConsAddr(ctx, addr)
if !ok {
return false
func (k Keeper) IsValidatorJailed(ctx context.Context, addr sdk.ConsAddress) (bool, error) {
v, err := k.GetValidatorByConsAddr(ctx, addr)
if err != nil {
return false, err
}
return v.Jailed
return v.Jailed, nil
}

View File

@ -6,9 +6,11 @@ import (
"github.com/golang/mock/gomock"
"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
abci "github.com/cometbft/cometbft/abci/types"
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
"github.com/cosmos/cosmos-sdk/x/staking/testutil"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
@ -37,15 +39,15 @@ func (s *KeeperTestSuite) TestValidator() {
require.Equal(stakingtypes.Unbonded, validator.Status)
require.Equal(valTokens, validator.Tokens)
require.Equal(valTokens, validator.DelegatorShares.RoundInt())
keeper.SetValidator(ctx, validator)
keeper.SetValidatorByPowerIndex(ctx, validator)
keeper.SetValidatorByConsAddr(ctx, validator)
require.NoError(keeper.SetValidator(ctx, validator))
require.NoError(keeper.SetValidatorByPowerIndex(ctx, validator))
require.NoError(keeper.SetValidatorByConsAddr(ctx, validator))
// ensure update
s.bankKeeper.EXPECT().SendCoinsFromModuleToModule(gomock.Any(), stakingtypes.NotBondedPoolName, stakingtypes.BondedPoolName, gomock.Any())
updates := s.applyValidatorSetUpdates(ctx, keeper, 1)
validator, found := keeper.GetValidator(ctx, valAddr)
require.True(found)
validator, err := keeper.GetValidator(ctx, valAddr)
require.NoError(err)
require.Equal(validator.ABCIValidatorUpdate(keeper.PowerReduction(ctx)), updates[0])
// after the save the validator should be bonded
@ -56,28 +58,33 @@ func (s *KeeperTestSuite) TestValidator() {
// check each store for being saved
consAddr, err := validator.GetConsAddr()
require.NoError(err)
resVal, found := keeper.GetValidatorByConsAddr(ctx, consAddr)
require.True(found)
resVal, err := keeper.GetValidatorByConsAddr(ctx, consAddr)
require.NoError(err)
require.True(validator.MinEqual(&resVal))
resVals := keeper.GetLastValidators(ctx)
resVals, err := keeper.GetLastValidators(ctx)
require.NoError(err)
require.Equal(1, len(resVals))
require.True(validator.MinEqual(&resVals[0]))
resVals = keeper.GetBondedValidatorsByPower(ctx)
resVals, err = keeper.GetBondedValidatorsByPower(ctx)
require.NoError(err)
require.Equal(1, len(resVals))
require.True(validator.MinEqual(&resVals[0]))
allVals := keeper.GetAllValidators(ctx)
allVals, err := keeper.GetAllValidators(ctx)
require.NoError(err)
require.Equal(1, len(allVals))
// check the last validator power
power := int64(100)
keeper.SetLastValidatorPower(ctx, valAddr, power)
resPower := keeper.GetLastValidatorPower(ctx, valAddr)
require.NoError(keeper.SetLastValidatorPower(ctx, valAddr, power))
resPower, err := keeper.GetLastValidatorPower(ctx, valAddr)
require.NoError(err)
require.Equal(power, resPower)
keeper.DeleteLastValidatorPower(ctx, valAddr)
resPower = keeper.GetLastValidatorPower(ctx, valAddr)
require.NoError(keeper.DeleteLastValidatorPower(ctx, valAddr))
resPower, err = keeper.GetLastValidatorPower(ctx, valAddr)
require.NoError(err)
require.Equal(int64(0), resPower)
}
@ -103,31 +110,34 @@ func (s *KeeperTestSuite) TestValidatorBasics() {
require.Equal(keeper.TokensFromConsensusPower(ctx, 7), validators[2].Tokens)
// check the empty keeper first
_, found := keeper.GetValidator(ctx, sdk.ValAddress(PKs[0].Address().Bytes()))
require.False(found)
resVals := keeper.GetLastValidators(ctx)
_, err := keeper.GetValidator(ctx, sdk.ValAddress(PKs[0].Address().Bytes()))
require.ErrorIs(err, stakingtypes.ErrNoValidatorFound)
resVals, err := keeper.GetLastValidators(ctx)
require.NoError(err)
require.Zero(len(resVals))
resVals = keeper.GetValidators(ctx, 2)
resVals, err = keeper.GetValidators(ctx, 2)
require.NoError(err)
require.Len(resVals, 0)
// set and retrieve a record
s.bankKeeper.EXPECT().SendCoinsFromModuleToModule(gomock.Any(), stakingtypes.NotBondedPoolName, stakingtypes.BondedPoolName, gomock.Any())
validators[0] = stakingkeeper.TestingUpdateValidator(keeper, ctx, validators[0], true)
keeper.SetValidatorByConsAddr(ctx, validators[0])
resVal, found := keeper.GetValidator(ctx, sdk.ValAddress(PKs[0].Address().Bytes()))
require.True(found)
require.NoError(keeper.SetValidatorByConsAddr(ctx, validators[0]))
resVal, err := keeper.GetValidator(ctx, sdk.ValAddress(PKs[0].Address().Bytes()))
require.NoError(err)
require.True(validators[0].MinEqual(&resVal))
// retrieve from consensus
resVal, found = keeper.GetValidatorByConsAddr(ctx, sdk.ConsAddress(PKs[0].Address()))
require.True(found)
resVal, err = keeper.GetValidatorByConsAddr(ctx, sdk.ConsAddress(PKs[0].Address()))
require.NoError(err)
require.True(validators[0].MinEqual(&resVal))
resVal, found = keeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(PKs[0]))
require.True(found)
resVal, err = keeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(PKs[0]))
require.NoError(err)
require.True(validators[0].MinEqual(&resVal))
resVals = keeper.GetLastValidators(ctx)
resVals, err = keeper.GetLastValidators(ctx)
require.NoError(err)
require.Equal(1, len(resVals))
require.True(validators[0].MinEqual(&resVals[0]))
require.Equal(stakingtypes.Bonded, validators[0].Status)
@ -138,11 +148,12 @@ func (s *KeeperTestSuite) TestValidatorBasics() {
validators[0].Tokens = keeper.TokensFromConsensusPower(ctx, 10)
validators[0].DelegatorShares = math.LegacyNewDecFromInt(validators[0].Tokens)
validators[0] = stakingkeeper.TestingUpdateValidator(keeper, ctx, validators[0], true)
resVal, found = keeper.GetValidator(ctx, sdk.ValAddress(PKs[0].Address().Bytes()))
require.True(found)
resVal, err = keeper.GetValidator(ctx, sdk.ValAddress(PKs[0].Address().Bytes()))
require.NoError(err)
require.True(validators[0].MinEqual(&resVal))
resVals = keeper.GetLastValidators(ctx)
resVals, err = keeper.GetLastValidators(ctx)
require.NoError(err)
require.Equal(1, len(resVals))
require.True(validators[0].MinEqual(&resVals[0]))
@ -151,33 +162,32 @@ func (s *KeeperTestSuite) TestValidatorBasics() {
validators[1] = stakingkeeper.TestingUpdateValidator(keeper, ctx, validators[1], true)
s.bankKeeper.EXPECT().SendCoinsFromModuleToModule(gomock.Any(), stakingtypes.NotBondedPoolName, stakingtypes.BondedPoolName, gomock.Any())
validators[2] = stakingkeeper.TestingUpdateValidator(keeper, ctx, validators[2], true)
resVal, found = keeper.GetValidator(ctx, sdk.ValAddress(PKs[1].Address().Bytes()))
require.True(found)
resVal, err = keeper.GetValidator(ctx, sdk.ValAddress(PKs[1].Address().Bytes()))
require.NoError(err)
require.True(validators[1].MinEqual(&resVal))
resVal, found = keeper.GetValidator(ctx, sdk.ValAddress(PKs[2].Address().Bytes()))
require.True(found)
resVal, err = keeper.GetValidator(ctx, sdk.ValAddress(PKs[2].Address().Bytes()))
require.NoError(err)
require.True(validators[2].MinEqual(&resVal))
resVals = keeper.GetLastValidators(ctx)
resVals, err = keeper.GetLastValidators(ctx)
require.NoError(err)
require.Equal(3, len(resVals))
// remove a record
// shouldn't be able to remove if status is not unbonded
require.PanicsWithValue("cannot call RemoveValidator on bonded or unbonding validators",
func() { keeper.RemoveValidator(ctx, validators[1].GetOperator()) })
require.EqualError(keeper.RemoveValidator(ctx, validators[1].GetOperator()), "cannot call RemoveValidator on bonded or unbonding validators: failed to remove validator")
// shouldn't be able to remove if there are still tokens left
validators[1].Status = stakingtypes.Unbonded
keeper.SetValidator(ctx, validators[1])
require.PanicsWithValue("attempting to remove a validator which still contains tokens",
func() { keeper.RemoveValidator(ctx, validators[1].GetOperator()) })
require.NoError(keeper.SetValidator(ctx, validators[1]))
require.EqualError(keeper.RemoveValidator(ctx, validators[1].GetOperator()), "attempting to remove a validator which still contains tokens: failed to remove validator")
validators[1].Tokens = math.ZeroInt() // ...remove all tokens
keeper.SetValidator(ctx, validators[1]) // ...set the validator
keeper.RemoveValidator(ctx, validators[1].GetOperator()) // Now it can be removed.
_, found = keeper.GetValidator(ctx, sdk.ValAddress(PKs[1].Address().Bytes()))
require.False(found)
validators[1].Tokens = math.ZeroInt() // ...remove all tokens
require.NoError(keeper.SetValidator(ctx, validators[1])) // ...set the validator
require.NoError(keeper.RemoveValidator(ctx, validators[1].GetOperator())) // Now it can be removed.
_, err = keeper.GetValidator(ctx, sdk.ValAddress(PKs[1].Address().Bytes()))
require.ErrorIs(err, stakingtypes.ErrNoValidatorFound)
}
func (s *KeeperTestSuite) TestUpdateValidatorByPowerIndex() {
@ -196,30 +206,30 @@ func (s *KeeperTestSuite) TestUpdateValidatorByPowerIndex() {
s.bankKeeper.EXPECT().SendCoinsFromModuleToModule(gomock.Any(), stakingtypes.NotBondedPoolName, stakingtypes.BondedPoolName, gomock.Any())
stakingkeeper.TestingUpdateValidator(keeper, ctx, validator, true)
validator, found := keeper.GetValidator(ctx, valAddr)
require.True(found)
validator, err := keeper.GetValidator(ctx, valAddr)
require.NoError(err)
require.Equal(valTokens, validator.Tokens)
power := stakingtypes.GetValidatorsByPowerIndexKey(validator, keeper.PowerReduction(ctx))
require.True(stakingkeeper.ValidatorByPowerIndexExists(ctx, keeper, power))
// burn half the delegator shares
keeper.DeleteValidatorByPowerIndex(ctx, validator)
require.NoError(keeper.DeleteValidatorByPowerIndex(ctx, validator))
validator, burned := validator.RemoveDelShares(delSharesCreated.Quo(math.LegacyNewDec(2)))
require.Equal(keeper.TokensFromConsensusPower(ctx, 50), burned)
stakingkeeper.TestingUpdateValidator(keeper, ctx, validator, true) // update the validator, possibly kicking it out
require.False(stakingkeeper.ValidatorByPowerIndexExists(ctx, keeper, power))
validator, found = keeper.GetValidator(ctx, valAddr)
require.True(found)
validator, err = keeper.GetValidator(ctx, valAddr)
require.NoError(err)
power = stakingtypes.GetValidatorsByPowerIndexKey(validator, keeper.PowerReduction(ctx))
require.True(stakingkeeper.ValidatorByPowerIndexExists(ctx, keeper, power))
// set new validator by power index
keeper.DeleteValidatorByPowerIndex(ctx, validator)
require.NoError(keeper.DeleteValidatorByPowerIndex(ctx, validator))
require.False(stakingkeeper.ValidatorByPowerIndexExists(ctx, keeper, power))
keeper.SetNewValidatorByPowerIndex(ctx, validator)
require.NoError(keeper.SetNewValidatorByPowerIndex(ctx, validator))
require.True(stakingkeeper.ValidatorByPowerIndexExists(ctx, keeper, power))
}
@ -272,9 +282,10 @@ func (s *KeeperTestSuite) TestUpdateValidatorCommission() {
require := s.Require()
// Set MinCommissionRate to 0.05
params := keeper.GetParams(ctx)
params, err := keeper.GetParams(ctx)
require.NoError(err)
params.MinCommissionRate = math.LegacyNewDecWithPrec(5, 2)
keeper.SetParams(ctx, params)
require.NoError(keeper.SetParams(ctx, params))
commission1 := stakingtypes.NewCommissionWithTime(
math.LegacyNewDecWithPrec(1, 1), math.LegacyNewDecWithPrec(3, 1),
@ -288,8 +299,8 @@ func (s *KeeperTestSuite) TestUpdateValidatorCommission() {
val1, _ = val1.SetInitialCommission(commission1)
val2, _ = val2.SetInitialCommission(commission2)
keeper.SetValidator(ctx, val1)
keeper.SetValidator(ctx, val2)
require.NoError(keeper.SetValidator(ctx, val1))
require.NoError(keeper.SetValidator(ctx, val2))
testCases := []struct {
validator stakingtypes.Validator
@ -310,16 +321,19 @@ func (s *KeeperTestSuite) TestUpdateValidatorCommission() {
if tc.expectedErr {
require.Error(err, "expected error for test case #%d with rate: %s", i, tc.newRate)
} else {
tc.validator.Commission = commission
keeper.SetValidator(ctx, tc.validator)
val, found := keeper.GetValidator(ctx, tc.validator.GetOperator())
require.True(found,
"expected to find validator for test case #%d with rate: %s", i, tc.newRate,
)
require.NoError(err,
"unexpected error for test case #%d with rate: %s", i, tc.newRate,
)
tc.validator.Commission = commission
err = keeper.SetValidator(ctx, tc.validator)
require.NoError(err)
val, err := keeper.GetValidator(ctx, tc.validator.GetOperator())
require.NoError(err,
"expected to find validator for test case #%d with rate: %s", i, tc.newRate,
)
require.Equal(tc.newRate, val.Commission.Rate,
"expected new validator commission rate for test case #%d with rate: %s", i, tc.newRate,
)
@ -340,17 +354,20 @@ func (s *KeeperTestSuite) TestValidatorToken() {
delTokens := keeper.TokensFromConsensusPower(ctx, 5)
validator := testutil.NewValidator(s.T(), valAddr, valPubKey)
validator, _ = keeper.AddValidatorTokensAndShares(ctx, validator, addTokens)
validator, _, err := keeper.AddValidatorTokensAndShares(ctx, validator, addTokens)
require.NoError(err)
require.Equal(addTokens, validator.Tokens)
validator, _ = keeper.GetValidator(ctx, valAddr)
require.Equal(math.LegacyNewDecFromInt(addTokens), validator.DelegatorShares)
keeper.RemoveValidatorTokensAndShares(ctx, validator, math.LegacyNewDecFromInt(delTokens))
_, _, err = keeper.RemoveValidatorTokensAndShares(ctx, validator, math.LegacyNewDecFromInt(delTokens))
require.NoError(err)
validator, _ = keeper.GetValidator(ctx, valAddr)
require.Equal(delTokens, validator.Tokens)
require.True(validator.DelegatorShares.Equal(math.LegacyNewDecFromInt(delTokens)))
keeper.RemoveValidatorTokens(ctx, validator, delTokens)
_, err = keeper.RemoveValidatorTokens(ctx, validator, delTokens)
require.NoError(err)
validator, _ = keeper.GetValidator(ctx, valAddr)
require.True(validator.Tokens.IsZero())
}
@ -367,9 +384,10 @@ func (s *KeeperTestSuite) TestUnbondingValidator() {
// set unbonding validator
endTime := time.Now()
endHeight := ctx.BlockHeight() + 10
keeper.SetUnbondingValidatorsQueue(ctx, endTime, endHeight, []string{valAddr.String()})
require.NoError(keeper.SetUnbondingValidatorsQueue(ctx, endTime, endHeight, []string{valAddr.String()}))
resVals := keeper.GetUnbondingValidators(ctx, endTime, endHeight)
resVals, err := keeper.GetUnbondingValidators(ctx, endTime, endHeight)
require.NoError(err)
require.Equal(1, len(resVals))
require.Equal(valAddr.String(), resVals[0])
@ -378,42 +396,43 @@ func (s *KeeperTestSuite) TestUnbondingValidator() {
validator1 := testutil.NewValidator(s.T(), valAddr1, PKs[1])
validator1.UnbondingHeight = endHeight
validator1.UnbondingTime = endTime
keeper.InsertUnbondingValidatorQueue(ctx, validator1)
require.NoError(keeper.InsertUnbondingValidatorQueue(ctx, validator1))
resVals = keeper.GetUnbondingValidators(ctx, endTime, endHeight)
resVals, err = keeper.GetUnbondingValidators(ctx, endTime, endHeight)
require.NoError(err)
require.Equal(2, len(resVals))
// delete unbonding validator from the queue
keeper.DeleteValidatorQueue(ctx, validator1)
resVals = keeper.GetUnbondingValidators(ctx, endTime, endHeight)
require.NoError(keeper.DeleteValidatorQueue(ctx, validator1))
resVals, err = keeper.GetUnbondingValidators(ctx, endTime, endHeight)
require.NoError(err)
require.Equal(1, len(resVals))
require.Equal(valAddr.String(), resVals[0])
// check unbonding mature validators
ctx = ctx.WithBlockHeight(endHeight).WithBlockTime(endTime)
require.PanicsWithValue("validator in the unbonding queue was not found", func() {
keeper.UnbondAllMatureValidators(ctx)
})
err = keeper.UnbondAllMatureValidators(ctx)
require.EqualError(err, "validator in the unbonding queue was not found: validator does not exist")
keeper.SetValidator(ctx, validator)
require.NoError(keeper.SetValidator(ctx, validator))
ctx = ctx.WithBlockHeight(endHeight).WithBlockTime(endTime)
require.PanicsWithValue("unexpected validator in unbonding queue; status was not unbonding", func() {
keeper.UnbondAllMatureValidators(ctx)
})
err = keeper.UnbondAllMatureValidators(ctx)
require.EqualError(err, "unexpected validator in unbonding queue; status was not unbonding")
validator.Status = stakingtypes.Unbonding
keeper.SetValidator(ctx, validator)
keeper.UnbondAllMatureValidators(ctx)
validator, found := keeper.GetValidator(ctx, valAddr)
require.False(found)
require.NoError(keeper.SetValidator(ctx, validator))
require.NoError(keeper.UnbondAllMatureValidators(ctx))
validator, err = keeper.GetValidator(ctx, valAddr)
require.ErrorIs(err, stakingtypes.ErrNoValidatorFound)
keeper.SetUnbondingValidatorsQueue(ctx, endTime, endHeight, []string{valAddr.String()})
require.NoError(keeper.SetUnbondingValidatorsQueue(ctx, endTime, endHeight, []string{valAddr.String()}))
validator = testutil.NewValidator(s.T(), valAddr, valPubKey)
validator, _ = validator.AddTokensFromDel(addTokens)
validator.Status = stakingtypes.Unbonding
keeper.SetValidator(ctx, validator)
keeper.UnbondAllMatureValidators(ctx)
validator, found = keeper.GetValidator(ctx, valAddr)
require.True(found)
require.NoError(keeper.SetValidator(ctx, validator))
require.NoError(keeper.UnbondAllMatureValidators(ctx))
validator, err = keeper.GetValidator(ctx, valAddr)
require.NoError(err)
require.Equal(stakingtypes.Unbonded, validator.Status)
}

View File

@ -59,9 +59,7 @@ func migrateValidatorsByPowerIndexKey(store storetypes.KVStore) {
// migration includes:
//
// - Setting the Power Reduction param in the paramstore
func MigrateStore(ctx sdk.Context, storeKey storetypes.StoreKey) error {
store := ctx.KVStore(storeKey)
func MigrateStore(ctx sdk.Context, store storetypes.KVStore) error {
MigratePrefixAddress(store, v1.LastValidatorPowerKey)
MigratePrefixAddress(store, v1.ValidatorsKey)

View File

@ -124,7 +124,7 @@ func TestStoreMigration(t *testing.T) {
}
// Run migrations.
err := v2.MigrateStore(ctx, stakingKey)
err := v2.MigrateStore(ctx, store)
require.NoError(t, err)
// Make sure the new keys are set and old keys are deleted.

View File

@ -23,7 +23,7 @@ type subspace interface {
// The migration includes:
//
// - Setting the MinCommissionRate param in the paramstore
func MigrateStore(ctx sdk.Context, storeKey storetypes.StoreKey, cdc codec.BinaryCodec, paramstore exported.Subspace) error {
func MigrateStore(ctx sdk.Context, store storetypes.KVStore, cdc codec.BinaryCodec, paramstore exported.Subspace) error {
migrateParamsStore(ctx, paramstore.(subspace))
return nil

View File

@ -20,12 +20,13 @@ func TestStoreMigration(t *testing.T) {
tStakingKey := storetypes.NewTransientStoreKey("transient_test")
ctx := testutil.DefaultContext(stakingKey, tStakingKey)
paramstore := paramtypes.NewSubspace(encCfg.Codec, encCfg.Amino, stakingKey, tStakingKey, "staking")
store := ctx.KVStore(stakingKey)
// Check no params
require.False(t, paramstore.Has(ctx, types.KeyMinCommissionRate))
// Run migrations.
err := v3.MigrateStore(ctx, stakingKey, encCfg.Codec, paramstore)
err := v3.MigrateStore(ctx, store, encCfg.Codec, paramstore)
require.NoError(t, err)
// Make sure the new params are set.

Some files were not shown because too many files have changed in this diff Show More