[RETRY] Distr-PR-3 More staking hooks (#2404)

* update commission hook for new commission work
* comment update
This commit is contained in:
Rigel 2018-09-26 02:11:57 -04:00 committed by Jae Kwon
parent 2fb3493ff5
commit b54801b4b3
11 changed files with 125 additions and 27 deletions

View File

@ -56,6 +56,7 @@ BREAKING CHANGES
* [types] \#2343 Make sdk.Msg have a names field, to facilitate automatic tagging.
* [baseapp] \#2366 Automatically add action tags to all messages
* [x/staking] \#2244 staking now holds a consensus-address-index instead of a consensus-pubkey-index
* [x/staking] \#2236 more distribution hooks for distribution
* Tendermint

View File

@ -91,7 +91,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams)
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.tkeyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace))
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace))
app.stakeKeeper = app.stakeKeeper.WithValidatorHooks(app.slashingKeeper.ValidatorHooks())
app.stakeKeeper = app.stakeKeeper.WithHooks(app.slashingKeeper.Hooks())
app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.paramsKeeper.Setter(), app.bankKeeper, app.stakeKeeper, app.RegisterCodespace(gov.DefaultCodespace))
app.feeCollectionKeeper = auth.NewFeeCollectionKeeper(app.cdc, app.keyFeeCollection)

View File

@ -0,0 +1,19 @@
## Receiver Hooks
The staking module allow for the following hooks to be registered with staking events:
``` golang
// event hooks for staking validator object
type StakingHooks interface {
OnValidatorCreated(ctx Context, address ValAddress) // called when a validator is created
OnValidatorCommissionChange(ctx Context, address ValAddress) // called when a validator's commission is modified
OnValidatorRemoved(ctx Context, address ValAddress) // called when a validator is deleted
OnValidatorBonded(ctx Context, address ConsAddress) // called when a validator is bonded
OnValidatorBeginUnbonding(ctx Context, address ConsAddress) // called when a validator begins unbonding
OnDelegationCreated(ctx Context, delAddr AccAddress, valAddr ValAddress) // called when a delegation is created
OnDelegationSharesModified(ctx Context, delAddr AccAddress, valAddr ValAddress) // called when a delegation's shares are modified
OnDelegationRemoved(ctx Context, delAddr AccAddress, valAddr ValAddress) // called when a delegation is removed
}
```

View File

@ -101,12 +101,25 @@ type DelegationSet interface {
fn func(index int64, delegation Delegation) (stop bool))
}
// validator event hooks
// These can be utilized to communicate between a staking keeper
// and another keeper which must take particular actions when
// validators are bonded and unbonded. The second keeper must implement
// this interface, which then the staking keeper can call.
type ValidatorHooks interface {
//_______________________________________________________________________________
// Event Hooks
// These can be utilized to communicate between a staking keeper and another
// keeper which must take particular actions when validators/delegators change
// state. The second keeper must implement this interface, which then the
// staking keeper can call.
// TODO refactor event hooks out to the receiver modules
// event hooks for staking validator object
type StakingHooks interface {
OnValidatorCreated(ctx Context, address ValAddress) // Must be called when a validator is created
OnValidatorCommissionChange(ctx Context, address ValAddress) // Must be called when a validator's commission is modified
OnValidatorRemoved(ctx Context, address ValAddress) // Must be called when a validator is deleted
OnValidatorBonded(ctx Context, address ConsAddress) // Must be called when a validator is bonded
OnValidatorBeginUnbonding(ctx Context, address ConsAddress) // Must be called when a validator begins unbonding
OnDelegationCreated(ctx Context, delAddr AccAddress, valAddr ValAddress) // Must be called when a delegation is created
OnDelegationSharesModified(ctx Context, delAddr AccAddress, valAddr ValAddress) // Must be called when a delegation's shares are modified
OnDelegationRemoved(ctx Context, delAddr AccAddress, valAddr ValAddress) // Must be called when a delegation is removed
}

View File

@ -29,10 +29,10 @@ type Hooks struct {
k Keeper
}
var _ sdk.ValidatorHooks = Hooks{}
var _ sdk.StakingHooks = Hooks{}
// Return the wrapper struct
func (k Keeper) ValidatorHooks() Hooks {
func (k Keeper) Hooks() Hooks {
return Hooks{k}
}
@ -45,3 +45,11 @@ func (h Hooks) OnValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) {
func (h Hooks) OnValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddress) {
h.k.onValidatorBeginUnbonding(ctx, address)
}
// nolint - unused hooks
func (h Hooks) OnValidatorCreated(_ sdk.Context, _ sdk.ValAddress) {}
func (h Hooks) OnValidatorCommissionChange(_ sdk.Context, _ sdk.ValAddress) {}
func (h Hooks) OnValidatorRemoved(_ sdk.Context, _ sdk.ValAddress) {}
func (h Hooks) OnDelegationCreated(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {}
func (h Hooks) OnDelegationSharesModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {}
func (h Hooks) OnDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {}

View File

@ -27,7 +27,7 @@ func TestHandleDoubleSign(t *testing.T) {
// initial setup
ctx, ck, sk, _, keeper := createTestInput(t)
sk = sk.WithValidatorHooks(keeper.ValidatorHooks())
sk = sk.WithHooks(keeper.Hooks())
amtInt := int64(100)
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt))
@ -69,7 +69,7 @@ func TestSlashingPeriodCap(t *testing.T) {
// initial setup
ctx, ck, sk, _, keeper := createTestInput(t)
sk = sk.WithValidatorHooks(keeper.ValidatorHooks())
sk = sk.WithHooks(keeper.Hooks())
amtInt := int64(100)
addr, amt := addrs[0], sdk.NewInt(amtInt)
valConsPubKey, valConsAddr := pks[0], sdk.ConsAddress(pks[0].Address())
@ -125,7 +125,7 @@ func TestHandleAbsentValidator(t *testing.T) {
// initial setup
ctx, ck, sk, _, keeper := createTestInput(t)
sk = sk.WithValidatorHooks(keeper.ValidatorHooks())
sk = sk.WithHooks(keeper.Hooks())
amtInt := int64(100)
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
sh := stake.NewHandler(sk)

View File

@ -98,6 +98,10 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k
return err.Result()
}
k.OnValidatorCreated(ctx, validator.OperatorAddr)
accAddr := sdk.AccAddress(validator.OperatorAddr)
k.OnDelegationCreated(ctx, accAddr, validator.OperatorAddr)
tags := sdk.NewTags(
tags.Action, tags.ActionCreateValidator,
tags.DstValidator, []byte(msg.ValidatorAddr.String()),
@ -166,6 +170,9 @@ func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper)
return err.Result()
}
// call the hook if present
k.OnDelegationCreated(ctx, msg.DelegatorAddr, validator.OperatorAddr)
tags := sdk.NewTags(
tags.Action, tags.ActionDelegate,
tags.Delegator, []byte(msg.DelegatorAddr.String()),

View File

@ -66,7 +66,7 @@ func (k Keeper) SetDelegation(ctx sdk.Context, delegation types.Delegation) {
// remove a delegation from store
func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) {
k.OnDelegationRemoved(ctx, delegation.DelegatorAddr, delegation.ValidatorAddr)
store := ctx.KVStore(k.storeKey)
store.Delete(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr))
}
@ -283,6 +283,8 @@ func (k Keeper) Delegate(ctx sdk.Context, delAddr sdk.AccAddress, bondAmt sdk.Co
func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress,
shares sdk.Dec) (amount sdk.Dec, err sdk.Error) {
k.OnDelegationSharesModified(ctx, delAddr, valAddr)
// check if delegation has any shares in it unbond
delegation, found := k.GetDelegation(ctx, delAddr, valAddr)
if !found {
@ -334,6 +336,7 @@ func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValA
k.RemoveValidator(ctx, validator.OperatorAddr)
}
k.OnDelegationSharesModified(ctx, delegation.DelegatorAddr, validator.OperatorAddr)
return amount, nil
}

54
x/stake/keeper/hooks.go Normal file
View File

@ -0,0 +1,54 @@
//nolint
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
// Expose the hooks if present
func (k Keeper) OnValidatorCreated(ctx sdk.Context, address sdk.ValAddress) {
if k.hooks != nil {
k.hooks.OnValidatorCreated(ctx, address)
}
}
func (k Keeper) OnValidatorCommissionChange(ctx sdk.Context, address sdk.ValAddress) {
if k.hooks != nil {
k.hooks.OnValidatorCommissionChange(ctx, address)
}
}
func (k Keeper) OnValidatorRemoved(ctx sdk.Context, address sdk.ValAddress) {
if k.hooks != nil {
k.hooks.OnValidatorRemoved(ctx, address)
}
}
func (k Keeper) OnValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) {
if k.hooks != nil {
k.hooks.OnValidatorBonded(ctx, address)
}
}
func (k Keeper) OnValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddress) {
if k.hooks != nil {
k.hooks.OnValidatorBeginUnbonding(ctx, address)
}
}
func (k Keeper) OnDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
if k.hooks != nil {
k.hooks.OnDelegationCreated(ctx, delAddr, valAddr)
}
}
func (k Keeper) OnDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
if k.hooks != nil {
k.hooks.OnDelegationSharesModified(ctx, delAddr, valAddr)
}
}
func (k Keeper) OnDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
if k.hooks != nil {
k.hooks.OnDelegationRemoved(ctx, delAddr, valAddr)
}
}

View File

@ -14,7 +14,7 @@ type Keeper struct {
storeTKey sdk.StoreKey
cdc *codec.Codec
bankKeeper bank.Keeper
hooks sdk.ValidatorHooks
hooks sdk.StakingHooks
// codespace
codespace sdk.CodespaceType
@ -33,7 +33,7 @@ func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ck bank.Keeper, codespa
}
// Set the validator hooks
func (k Keeper) WithValidatorHooks(sh sdk.ValidatorHooks) Keeper {
func (k Keeper) WithHooks(sh sdk.StakingHooks) Keeper {
if k.hooks != nil {
panic("cannot set validator hooks twice")
}

View File

@ -617,12 +617,7 @@ func (k Keeper) beginUnbondingValidator(ctx sdk.Context, validator types.Validat
// also remove from the Bonded types.Validators Store
store.Delete(GetValidatorsBondedIndexKey(validator.OperatorAddr))
// call the unbond hook if present
if k.hooks != nil {
k.hooks.OnValidatorBeginUnbonding(ctx, validator.ConsAddress())
}
// return updated validator
k.OnValidatorBeginUnbonding(ctx, validator.ConsAddress())
return validator
}
@ -652,18 +647,15 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types.
tstore := ctx.TransientStore(k.storeTKey)
tstore.Set(GetTendermintUpdatesTKey(validator.OperatorAddr), bzABCI)
// call the bond hook if present
if k.hooks != nil {
k.hooks.OnValidatorBonded(ctx, validator.ConsAddress())
}
// return updated validator
k.OnValidatorBonded(ctx, validator.ConsAddress())
return validator
}
// remove the validator record and associated indexes
func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) {
k.OnValidatorRemoved(ctx, address)
// first retrieve the old validator record
validator, found := k.GetValidator(ctx, address)
if !found {
@ -703,6 +695,7 @@ func (k Keeper) UpdateValidatorCommission(ctx sdk.Context, validator types.Valid
validator.Commission.UpdateTime = blockTime
k.SetValidator(ctx, validator)
k.OnValidatorCommissionChange(ctx, validator.OperatorAddr)
return nil
}