Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: add error handling to staking hooks #9571

Merged
merged 4 commits into from
Jun 30, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -43,6 +43,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

### API Breaking Changes

* [\#9571](https://github.com/cosmos/cosmos-sdk/pull/9571) Implemented error handling for staking hooks, which now return an error on failure.
* [\#9427](https://github.com/cosmos/cosmos-sdk/pull/9427) Move simapp `FundAccount` and `FundModuleAccount` to `x/bank/testutil`
* (client/tx) [\#9421](https://github.com/cosmos/cosmos-sdk/pull/9421/) `BuildUnsignedTx`, `BuildSimTx`, `PrintUnsignedStdTx` functions are moved to
the Tx Factory as methods.
4 changes: 3 additions & 1 deletion simapp/export.go
Original file line number Diff line number Diff line change
@@ -109,7 +109,9 @@ func (app *SimApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []
feePool.CommunityPool = feePool.CommunityPool.Add(scraps...)
app.DistrKeeper.SetFeePool(ctx, feePool)

app.DistrKeeper.Hooks().AfterValidatorCreated(ctx, val.GetOperator())
if err := app.DistrKeeper.Hooks().AfterValidatorCreated(ctx, val.GetOperator()); err != nil {
panic(err)
}
return false
})

40 changes: 27 additions & 13 deletions x/distribution/keeper/hooks.go
Original file line number Diff line number Diff line change
@@ -17,13 +17,14 @@ var _ stakingtypes.StakingHooks = Hooks{}
func (k Keeper) Hooks() Hooks { return Hooks{k} }

// initialize validator distribution record
func (h Hooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) {
func (h Hooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) error {
val := h.k.stakingKeeper.Validator(ctx, valAddr)
h.k.initializeValidator(ctx, val)
return nil
}

// AfterValidatorRemoved performs clean up after a validator is removed
func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, _ sdk.ConsAddress, valAddr sdk.ValAddress) {
func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, _ sdk.ConsAddress, valAddr sdk.ValAddress) error {
// fetch outstanding
outstanding := h.k.GetValidatorOutstandingRewardsCoins(ctx, valAddr)

@@ -47,7 +48,7 @@ func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, _ sdk.ConsAddress, valAddr
withdrawAddr := h.k.GetDelegatorWithdrawAddr(ctx, accAddr)

if err := h.k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, withdrawAddr, coins); err != nil {
panic(err)
return err
}
}
}
@@ -73,35 +74,48 @@ func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, _ sdk.ConsAddress, valAddr

// clear current rewards
h.k.DeleteValidatorCurrentRewards(ctx, valAddr)

return nil
}

// increment period
func (h Hooks) BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
func (h Hooks) BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error {
val := h.k.stakingKeeper.Validator(ctx, valAddr)
h.k.IncrementValidatorPeriod(ctx, val)
_ = h.k.IncrementValidatorPeriod(ctx, val)
return nil
}

// withdraw delegation rewards (which also increments period)
func (h Hooks) BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
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)

if _, err := h.k.withdrawDelegationRewards(ctx, val, del); err != nil {
panic(err)
return err
}

return nil
}

// create new delegation period record
func (h Hooks) AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
func (h Hooks) AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error {
h.k.initializeDelegation(ctx, valAddr, delAddr)
return nil
}

// record the slash event
func (h Hooks) BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, fraction sdk.Dec) {
func (h Hooks) BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, fraction sdk.Dec) error {
h.k.updateValidatorSlashFraction(ctx, valAddr, fraction)
return nil
}

func (h Hooks) BeforeValidatorModified(_ sdk.Context, _ sdk.ValAddress) {}
func (h Hooks) AfterValidatorBonded(_ sdk.Context, _ sdk.ConsAddress, _ sdk.ValAddress) {}
func (h Hooks) AfterValidatorBeginUnbonding(_ sdk.Context, _ sdk.ConsAddress, _ sdk.ValAddress) {}
func (h Hooks) BeforeDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {}
func (h Hooks) BeforeValidatorModified(_ sdk.Context, _ sdk.ValAddress) error { return nil }
func (h Hooks) AfterValidatorBonded(_ sdk.Context, _ sdk.ConsAddress, _ sdk.ValAddress) error {
return nil
}
func (h Hooks) AfterValidatorBeginUnbonding(_ sdk.Context, _ sdk.ConsAddress, _ sdk.ValAddress) error {
return nil
}
func (h Hooks) BeforeDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) error {
return nil
}
46 changes: 29 additions & 17 deletions x/slashing/keeper/hooks.go
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/slashing/types"
)

func (k Keeper) AfterValidatorBonded(ctx sdk.Context, address sdk.ConsAddress, _ sdk.ValAddress) {
func (k Keeper) AfterValidatorBonded(ctx sdk.Context, address sdk.ConsAddress, _ sdk.ValAddress) error {
// Update the signing info start height or create a new signing info
_, found := k.GetValidatorSigningInfo(ctx, address)
if !found {
@@ -23,6 +23,8 @@ func (k Keeper) AfterValidatorBonded(ctx sdk.Context, address sdk.ConsAddress, _
)
k.SetValidatorSigningInfo(ctx, address, signingInfo)
}

return nil
}

// AfterValidatorCreated adds the address-pubkey relation when a validator is created.
@@ -32,14 +34,14 @@ func (k Keeper) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) e
if err != nil {
return err
}
k.AddPubkey(ctx, consPk)

return nil
return k.AddPubkey(ctx, consPk)
}

// AfterValidatorRemoved deletes the address-pubkey relation when a validator is removed,
func (k Keeper) AfterValidatorRemoved(ctx sdk.Context, address sdk.ConsAddress) {
func (k Keeper) AfterValidatorRemoved(ctx sdk.Context, address sdk.ConsAddress) error {
k.deleteAddrPubkeyRelation(ctx, crypto.Address(address))
return nil
}

// Hooks wrapper struct for slashing keeper
@@ -55,24 +57,34 @@ func (k Keeper) Hooks() Hooks {
}

// Implements sdk.ValidatorHooks
func (h Hooks) AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
h.k.AfterValidatorBonded(ctx, consAddr, valAddr)
func (h Hooks) AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error {
return h.k.AfterValidatorBonded(ctx, consAddr, valAddr)
}

// Implements sdk.ValidatorHooks
func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, _ sdk.ValAddress) {
h.k.AfterValidatorRemoved(ctx, consAddr)
func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, _ sdk.ValAddress) error {
return h.k.AfterValidatorRemoved(ctx, consAddr)
}

// Implements sdk.ValidatorHooks
func (h Hooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) {
h.k.AfterValidatorCreated(ctx, valAddr)
func (h Hooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) error {
return h.k.AfterValidatorCreated(ctx, valAddr)
}

func (h Hooks) AfterValidatorBeginUnbonding(_ sdk.Context, _ sdk.ConsAddress, _ sdk.ValAddress) {}
func (h Hooks) BeforeValidatorModified(_ sdk.Context, _ sdk.ValAddress) {}
func (h Hooks) BeforeDelegationCreated(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {}
func (h Hooks) BeforeDelegationSharesModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {}
func (h Hooks) BeforeDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {}
func (h Hooks) AfterDelegationModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {}
func (h Hooks) BeforeValidatorSlashed(_ sdk.Context, _ sdk.ValAddress, _ sdk.Dec) {}
func (h Hooks) AfterValidatorBeginUnbonding(_ sdk.Context, _ sdk.ConsAddress, _ sdk.ValAddress) error {
return nil
}
func (h Hooks) BeforeValidatorModified(_ sdk.Context, _ sdk.ValAddress) error { return nil }
func (h Hooks) BeforeDelegationCreated(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) error {
return nil
}
func (h Hooks) BeforeDelegationSharesModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) error {
return nil
}
func (h Hooks) BeforeDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) error {
return nil
}
func (h Hooks) AfterDelegationModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) error {
return nil
}
func (h Hooks) BeforeValidatorSlashed(_ sdk.Context, _ sdk.ValAddress, _ sdk.Dec) error { return nil }
6 changes: 3 additions & 3 deletions x/slashing/types/expected_keepers.go
Original file line number Diff line number Diff line change
@@ -56,8 +56,8 @@ type StakingKeeper interface {

// 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
AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) // Must be called when a validator is deleted
AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) error // Must be called when a validator is created
AfterValidatorRemoved(ctx sdk.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) // Must be called when a validator is bonded
AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error // Must be called when a validator is bonded
}
15 changes: 10 additions & 5 deletions x/staking/genesis.go
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@ package staking

import (
"fmt"
"log"

abci "github.com/tendermint/tendermint/abci/types"
tmtypes "github.com/tendermint/tendermint/types"
@@ -44,7 +43,9 @@ func InitGenesis(

// Call the creation hook if not exported
if !data.Exported {
keeper.AfterValidatorCreated(ctx, validator.GetOperator())
if err := keeper.AfterValidatorCreated(ctx, validator.GetOperator()); err != nil {
panic(err)
}
}

// update timeslice if necessary
@@ -70,13 +71,17 @@ func InitGenesis(

// Call the before-creation hook if not exported
if !data.Exported {
keeper.BeforeDelegationCreated(ctx, delegatorAddress, delegation.GetValidatorAddr())
if err := keeper.BeforeDelegationCreated(ctx, delegatorAddress, delegation.GetValidatorAddr()); err != nil {
panic(err)
}
}

keeper.SetDelegation(ctx, delegation)
// Call the after-modification hook if not exported
if !data.Exported {
keeper.AfterDelegationModified(ctx, delegatorAddress, delegation.GetValidatorAddr())
if err := keeper.AfterDelegationModified(ctx, delegatorAddress, delegation.GetValidatorAddr()); err != nil {
panic(err)
}
}
}

@@ -149,7 +154,7 @@ func InitGenesis(
var err error
res, err = keeper.ApplyAndReturnValidatorSetUpdates(ctx)
if err != nil {
log.Fatal(err)
panic(err)
}
}

32 changes: 24 additions & 8 deletions x/staking/keeper/delegation.go
Original file line number Diff line number Diff line change
@@ -101,15 +101,19 @@ func (k Keeper) SetDelegation(ctx sdk.Context, delegation types.Delegation) {
}

// remove a delegation
func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) {
func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) error {
delegatorAddress, err := sdk.AccAddressFromBech32(delegation.DelegatorAddress)
if err != nil {
panic(err)
}
// TODO: Consider calling hooks outside of the store wrapper functions, it's unobvious.
k.BeforeDelegationRemoved(ctx, delegatorAddress, delegation.GetValidatorAddr())
if err := k.BeforeDelegationRemoved(ctx, delegatorAddress, delegation.GetValidatorAddr()); err != nil {
return err
}

store := ctx.KVStore(k.storeKey)
store.Delete(types.GetDelegationKey(delegatorAddress, delegation.GetValidatorAddr()))
return nil
}

// return a given amount of all the delegator unbonding-delegations
@@ -563,9 +567,13 @@ func (k Keeper) Delegate(

// call the appropriate hook if present
if found {
k.BeforeDelegationSharesModified(ctx, delAddr, validator.GetOperator())
err = k.BeforeDelegationSharesModified(ctx, delAddr, validator.GetOperator())
} else {
k.BeforeDelegationCreated(ctx, delAddr, validator.GetOperator())
err = k.BeforeDelegationCreated(ctx, delAddr, validator.GetOperator())
}

if err != nil {
return sdk.ZeroDec(), err
}

delegatorAddress, err := sdk.AccAddressFromBech32(delegation.DelegatorAddress)
@@ -621,7 +629,9 @@ func (k Keeper) Delegate(
k.SetDelegation(ctx, delegation)

// Call the after-modification hook
k.AfterDelegationModified(ctx, delegatorAddress, delegation.GetValidatorAddr())
if err := k.AfterDelegationModified(ctx, delegatorAddress, delegation.GetValidatorAddr()); err != nil {
return newShares, err
}

return newShares, nil
}
@@ -637,7 +647,9 @@ func (k Keeper) Unbond(
}

// call the before-delegation-modified hook
k.BeforeDelegationSharesModified(ctx, delAddr, valAddr)
if err := k.BeforeDelegationSharesModified(ctx, delAddr, valAddr); err != nil {
return amount, err
}

// ensure that we have enough shares to remove
if delegation.Shares.LT(shares) {
@@ -670,11 +682,15 @@ func (k Keeper) Unbond(

// remove the delegation
if delegation.Shares.IsZero() {
k.RemoveDelegation(ctx, delegation)
err = k.RemoveDelegation(ctx, delegation)
} else {
k.SetDelegation(ctx, delegation)
// call the after delegation modification hook
k.AfterDelegationModified(ctx, delegatorAddress, delegation.GetValidatorAddr())
err = k.AfterDelegationModified(ctx, delegatorAddress, delegation.GetValidatorAddr())
}

if err != nil {
return amount, err
}

// remove the shares and coins from the validator
48 changes: 29 additions & 19 deletions x/staking/keeper/hooks.go
Original file line number Diff line number Diff line change
@@ -9,71 +9,81 @@ import (
var _ types.StakingHooks = Keeper{}

// AfterValidatorCreated - call hook if registered
func (k Keeper) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) {
func (k Keeper) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) error {
if k.hooks != nil {
k.hooks.AfterValidatorCreated(ctx, valAddr)
return k.hooks.AfterValidatorCreated(ctx, valAddr)
}
return nil
}

// BeforeValidatorModified - call hook if registered
func (k Keeper) BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) {
func (k Keeper) BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) error {
if k.hooks != nil {
k.hooks.BeforeValidatorModified(ctx, valAddr)
return k.hooks.BeforeValidatorModified(ctx, valAddr)
}
return nil
}

// AfterValidatorRemoved - call hook if registered
func (k Keeper) AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
func (k Keeper) AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error {
if k.hooks != nil {
k.hooks.AfterValidatorRemoved(ctx, consAddr, valAddr)
return k.hooks.AfterValidatorRemoved(ctx, consAddr, valAddr)
}
return nil
}

// AfterValidatorBonded - call hook if registered
func (k Keeper) AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
func (k Keeper) AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error {
if k.hooks != nil {
k.hooks.AfterValidatorBonded(ctx, consAddr, valAddr)
return k.hooks.AfterValidatorBonded(ctx, consAddr, valAddr)
}
return nil
}

// AfterValidatorBeginUnbonding - call hook if registered
func (k Keeper) AfterValidatorBeginUnbonding(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
func (k Keeper) AfterValidatorBeginUnbonding(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error {
if k.hooks != nil {
k.hooks.AfterValidatorBeginUnbonding(ctx, consAddr, valAddr)
return k.hooks.AfterValidatorBeginUnbonding(ctx, consAddr, valAddr)
}
return nil
}

// BeforeDelegationCreated - call hook if registered
func (k Keeper) BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
func (k Keeper) BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error {
if k.hooks != nil {
k.hooks.BeforeDelegationCreated(ctx, delAddr, valAddr)
return k.hooks.BeforeDelegationCreated(ctx, delAddr, valAddr)
}
return nil
}

// BeforeDelegationSharesModified - call hook if registered
func (k Keeper) BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
func (k Keeper) BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error {
if k.hooks != nil {
k.hooks.BeforeDelegationSharesModified(ctx, delAddr, valAddr)
return k.hooks.BeforeDelegationSharesModified(ctx, delAddr, valAddr)
}
return nil
}

// BeforeDelegationRemoved - call hook if registered
func (k Keeper) BeforeDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
func (k Keeper) BeforeDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error {
if k.hooks != nil {
k.hooks.BeforeDelegationRemoved(ctx, delAddr, valAddr)
}
return nil
}

// AfterDelegationModified - call hook if registered
func (k Keeper) AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
func (k Keeper) AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error {
if k.hooks != nil {
k.hooks.AfterDelegationModified(ctx, delAddr, valAddr)
return k.hooks.AfterDelegationModified(ctx, delAddr, valAddr)
}
return nil
}

// BeforeValidatorSlashed - call hook if registered
func (k Keeper) BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, fraction sdk.Dec) {
func (k Keeper) BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, fraction sdk.Dec) error {
if k.hooks != nil {
k.hooks.BeforeValidatorSlashed(ctx, valAddr, fraction)
return k.hooks.BeforeValidatorSlashed(ctx, valAddr, fraction)
}
return nil
}
8 changes: 6 additions & 2 deletions x/staking/keeper/msg_server.go
Original file line number Diff line number Diff line change
@@ -96,7 +96,9 @@ func (k msgServer) CreateValidator(goCtx context.Context, msg *types.MsgCreateVa
k.SetNewValidatorByPowerIndex(ctx, validator)

// call the after-creation hook
k.AfterValidatorCreated(ctx, validator.GetOperator())
if err := k.AfterValidatorCreated(ctx, validator.GetOperator()); err != nil {
return nil, err
}

// move coins from the msg.Address account to a (self-delegation) delegator account
// the validator account and global shares are updated within here
@@ -150,7 +152,9 @@ func (k msgServer) EditValidator(goCtx context.Context, msg *types.MsgEditValida
}

// call the before-modification hook since we're about to update the commission
k.BeforeValidatorModified(ctx, valAddr)
if err := k.BeforeValidatorModified(ctx, valAddr); err != nil {
return nil, err
}

validator.Commission = commission
}
16 changes: 8 additions & 8 deletions x/staking/spec/06_hooks.md
Original file line number Diff line number Diff line change
@@ -9,19 +9,19 @@ occurred within staking. These events can be registered to execute either
right `Before` or `After` the staking event (as per the hook name). The
following hooks can registered with staking:

- `AfterValidatorCreated(Context, ValAddress)`
- `AfterValidatorCreated(Context, ValAddress) error`
- called when a validator is created
- `BeforeValidatorModified(Context, ValAddress)`
- `BeforeValidatorModified(Context, ValAddress) error`
- called when a validator's state is changed
- `AfterValidatorRemoved(Context, ConsAddress, ValAddress)`
- `AfterValidatorRemoved(Context, ConsAddress, ValAddress) error`
- called when a validator is deleted
- `AfterValidatorBonded(Context, ConsAddress, ValAddress)`
- `AfterValidatorBonded(Context, ConsAddress, ValAddress) error`
- called when a validator is bonded
- `AfterValidatorBeginUnbonding(Context, ConsAddress, ValAddress)`
- `AfterValidatorBeginUnbonding(Context, ConsAddress, ValAddress) error`
- called when a validator begins unbonding
- `BeforeDelegationCreated(Context, AccAddress, ValAddress)`
- `BeforeDelegationCreated(Context, AccAddress, ValAddress) error`
- called when a delegation is created
- `BeforeDelegationSharesModified(Context, AccAddress, ValAddress)`
- `BeforeDelegationSharesModified(Context, AccAddress, ValAddress) error`
- called when a delegation's shares are modified
- `BeforeDelegationRemoved(Context, AccAddress, ValAddress)`
- `BeforeDelegationRemoved(Context, AccAddress, ValAddress) error`
- called when a delegation is removed
24 changes: 12 additions & 12 deletions x/staking/types/expected_keepers.go
Original file line number Diff line number Diff line change
@@ -89,16 +89,16 @@ type DelegationSet interface {

// 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
BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) // Must be called when a validator's state changes
AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) // Must be called when a validator is deleted

AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) // Must be called when a validator is bonded
AfterValidatorBeginUnbonding(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) // Must be called when a validator begins unbonding

BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) // Must be called when a delegation is created
BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) // Must be called when a delegation's shares are modified
BeforeDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) // Must be called when a delegation is removed
AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress)
BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, fraction sdk.Dec)
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

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

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 sdk.Dec) error
}
73 changes: 53 additions & 20 deletions x/staking/types/hooks.go
Original file line number Diff line number Diff line change
@@ -5,59 +5,92 @@ import (
)

// combine multiple staking hooks, all hook functions are run in array sequence
var _ StakingHooks = &MultiStakingHooks{}

type MultiStakingHooks []StakingHooks

func NewMultiStakingHooks(hooks ...StakingHooks) MultiStakingHooks {
return hooks
}

func (h MultiStakingHooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) {
func (h MultiStakingHooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) error {
for i := range h {
h[i].AfterValidatorCreated(ctx, valAddr)
if err := h[i].AfterValidatorCreated(ctx, valAddr); err != nil {
return err
}
}

return nil
}
func (h MultiStakingHooks) BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) {
func (h MultiStakingHooks) BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) error {
for i := range h {
h[i].BeforeValidatorModified(ctx, valAddr)
if err := h[i].BeforeValidatorModified(ctx, valAddr); err != nil {
return err
}
}
return nil
}
func (h MultiStakingHooks) AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
func (h MultiStakingHooks) AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error {
for i := range h {
h[i].AfterValidatorRemoved(ctx, consAddr, valAddr)
if err := h[i].AfterValidatorRemoved(ctx, consAddr, valAddr); err != nil {
return err
}
}
return nil
}
func (h MultiStakingHooks) AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
func (h MultiStakingHooks) AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error {
for i := range h {
h[i].AfterValidatorBonded(ctx, consAddr, valAddr)
if err := h[i].AfterValidatorBonded(ctx, consAddr, valAddr); err != nil {
return err
}
}
return nil
}
func (h MultiStakingHooks) AfterValidatorBeginUnbonding(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
func (h MultiStakingHooks) AfterValidatorBeginUnbonding(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error {
for i := range h {
h[i].AfterValidatorBeginUnbonding(ctx, consAddr, valAddr)
if err := h[i].AfterValidatorBeginUnbonding(ctx, consAddr, valAddr); err != nil {
return err
}
}
return nil
}
func (h MultiStakingHooks) BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
func (h MultiStakingHooks) BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error {
for i := range h {
h[i].BeforeDelegationCreated(ctx, delAddr, valAddr)
if err := h[i].BeforeDelegationCreated(ctx, delAddr, valAddr); err != nil {
return err
}
}
return nil
}
func (h MultiStakingHooks) BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
func (h MultiStakingHooks) BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error {
for i := range h {
h[i].BeforeDelegationSharesModified(ctx, delAddr, valAddr)
if err := h[i].BeforeDelegationSharesModified(ctx, delAddr, valAddr); err != nil {
return err
}
}
return nil
}
func (h MultiStakingHooks) BeforeDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
func (h MultiStakingHooks) BeforeDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error {
for i := range h {
h[i].BeforeDelegationRemoved(ctx, delAddr, valAddr)
if err := h[i].BeforeDelegationRemoved(ctx, delAddr, valAddr); err != nil {
return err
}
}
return nil
}
func (h MultiStakingHooks) AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
func (h MultiStakingHooks) AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error {
for i := range h {
h[i].AfterDelegationModified(ctx, delAddr, valAddr)
if err := h[i].AfterDelegationModified(ctx, delAddr, valAddr); err != nil {
return err
}
}
return nil
}
func (h MultiStakingHooks) BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, fraction sdk.Dec) {
func (h MultiStakingHooks) BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, fraction sdk.Dec) error {
for i := range h {
h[i].BeforeValidatorSlashed(ctx, valAddr, fraction)
if err := h[i].BeforeValidatorSlashed(ctx, valAddr, fraction); err != nil {
return err
}
}
return nil
}