feat!: add error handling to staking hooks (#9571)

<!--
The default pull request template is for types feat, fix, or refactor.
For other templates, add one of the following parameters to the url:
- template=docs.md
- template=other.md
-->

## Description

- Adds error handling for staking hooks

<!-- Add a description of the changes that this PR introduces and the files that
are the most critical to review. -->

---

### Author Checklist

*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*

I have...

- [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [x] added `!` to the type prefix if API or client breaking change
- [x] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [x] updated the relevant documentation or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed 
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
This commit is contained in:
Federico Kunze Küllmer 2021-06-30 06:13:07 -04:00 committed by GitHub
parent aef416f91e
commit f5b11bc328
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 203 additions and 106 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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