diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 39cb596946..3213029e04 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -96,7 +96,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio auth.ProtoBaseAccount, // prototype ) - // add handlers + // add handlers and hooks app.bankKeeper = bank.NewBaseKeeper(app.accountMapper) app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace)) app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams) @@ -208,6 +208,7 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.StakeData) gov.InitGenesis(ctx, app.govKeeper, genesisState.GovData) + distr.InitGenesis(ctx, app.distrKeeper, genesisState.DistrData) err = GaiaValidateGenesisState(genesisState) if err != nil { // TODO find a way to do this w/o panics @@ -235,6 +236,7 @@ func (app *GaiaApp) ExportAppStateAndValidators() (appState json.RawMessage, val genState := GenesisState{ Accounts: accounts, StakeData: stake.WriteGenesis(ctx, app.stakeKeeper), + DistrData: distr.WriteGenesis(ctx, app.distrKeeper), GovData: gov.WriteGenesis(ctx, app.govKeeper), } appState, err = codec.MarshalJSONIndent(app.cdc, genState) @@ -244,3 +246,39 @@ func (app *GaiaApp) ExportAppStateAndValidators() (appState json.RawMessage, val validators = stake.WriteValidators(ctx, app.stakeKeeper) return appState, validators, nil } + +//______________________________________________________________________________________________ + +// Combine Staking Hooks +type Hooks struct { + dh distr.Hooks + sh slashing.Hooks +} + +var _ sdk.StakingHooks = Hooks{} + +// nolint +func (h Hooks) OnValidatorCreated(ctx sdk.Context, addr sdk.ValAddress) { + h.dh.OnValidatorCreated(ctx, addr) +} +func (h Hooks) OnValidatorCommissionChange(ctx sdk.Context, addr sdk.ValAddress) { + h.dh.OnValidatorCommissionChange(ctx, addr) +} +func (h Hooks) OnValidatorRemoved(ctx sdk.Context, addr sdk.ValAddress) { + h.dh.OnValidatorRemoved(ctx, addr) +} +func (h Hooks) OnValidatorBonded(ctx sdk.Context, addr sdk.ConsAddress) { + h.sh.OnValidatorBonded(ctx, addr) +} +func (h Hooks) OnValidatorBeginBonded(ctx sdk.Context, addr sdk.ConsAddress) { + h.sh.OnValidatorBeginBonding(ctx, addr) +} +func (h Hooks) OnDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + h.dh.OnDelegationCreated(ctx, delAddr, valAddr) +} +func (h Hooks) OnDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + h.dh.OnDelegationSharesModified(ctx, delAddr, valAddr) +} +func (h Hooks) OnDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + h.dh.OnDelegationRemoved(ctx, delAddr, valAddr) +} diff --git a/cmd/gaia/app/genesis.go b/cmd/gaia/app/genesis.go index 84f0ea7fa7..d2a567fa4b 100644 --- a/cmd/gaia/app/genesis.go +++ b/cmd/gaia/app/genesis.go @@ -13,6 +13,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/gov" "github.com/cosmos/cosmos-sdk/x/stake" + distr "github.com/cosmos/cosmos-sdk/x/stake" stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types" "github.com/spf13/pflag" @@ -34,6 +35,7 @@ var ( type GenesisState struct { Accounts []GenesisAccount `json:"accounts"` StakeData stake.GenesisState `json:"stake"` + DistrData distr.GenesisState `json:"distr_data"` GovData gov.GenesisState `json:"gov"` } @@ -194,6 +196,7 @@ func GaiaAppGenState(cdc *codec.Codec, appGenTxs []json.RawMessage) (genesisStat genesisState = GenesisState{ Accounts: genaccs, StakeData: stakeData, + DistrData: distr.DefaultGenesisState(), GovData: gov.DefaultGenesisState(), } return diff --git a/types/stake.go b/types/stake.go index 54fd564afd..68257689d2 100644 --- a/types/stake.go +++ b/types/stake.go @@ -107,18 +107,17 @@ type DelegationSet interface { // 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 ValidatorHooks interface { - OnValidatorCreated(ctx Context, address ValAddress) // Must be called when a validator is created - OnValidatorBondModified(ctx Context, address ValAddress) // Must be called when a validator's bond amount is modified - OnValidatorRemoved(ctx Context, address ValAddress) // Must be called when a validator is deleted +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 -} -// event hooks for staking delegator object -type DelegatorHooks interface { 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 diff --git a/x/distribution/genesis.go b/x/distribution/genesis.go index 1ff4a06d6f..f377750f8e 100644 --- a/x/distribution/genesis.go +++ b/x/distribution/genesis.go @@ -1,8 +1,6 @@ package distribution import ( - abci "github.com/tendermint/tendermint/abci/types" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake/types" ) @@ -13,7 +11,7 @@ import ( // 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 InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) (res []abci.Validator, err error) { +func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) { keeper.SetFeePool(ctx, data.FeePool) for _, vdi := range data.ValidatorDistInfos { @@ -25,8 +23,6 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) (res [ for _, dw := range data.DelegatorWithdrawAddrs { keeper.SetDelegatorWithdrawAddr(ctx, dw.DelegatorAddr, dw.WithdrawAddr) } - - return } // WriteGenesis returns a GenesisState for a given context and keeper. The diff --git a/x/distribution/hooks.go b/x/distribution/hooks.go index 9a6f7cfbf9..3a4d8fbd2d 100644 --- a/x/distribution/hooks.go +++ b/x/distribution/hooks.go @@ -1,6 +1,9 @@ package distribution -import "github.com/cosmos/cosmos-sdk/x/distribution/types" +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/distribution/types" +) /* ## Create or modify delegation distribution @@ -43,15 +46,9 @@ func (k Keeper) onValidatorCreated(ctx sdk.Context, addr sdk.ValAddress) { k.SetValidatorDistInfo(ctx, vdi) } -// Withdrawal all distubution rewards // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXX -func (k Keeper) onValidatorBondModified(ctx sdk.Context, addr sdk.ValAddress) { - slashingPeriod := ValidatorSlashingPeriod{ - ValidatorAddr: address, - StartHeight: ctx.BlockHeight(), - EndHeight: 0, - SlashedSoFar: sdk.ZeroDec(), - } - k.addOrUpdateValidatorSlashingPeriod(ctx, slashingPeriod) +// Withdrawal all validator rewards +func (k Keeper) onValidatorCommissionChange(ctx sdk.Context, addr sdk.ValAddress) { + k.WithdrawValidatorRewardsAll(ctx, addr) } // Withdrawal all validator distribution rewards and cleanup the distribution record @@ -61,60 +58,56 @@ func (k Keeper) onValidatorRemoved(ctx sdk.Context, addr sdk.ValAddress) { //_________________________________________________________________________________________ -// Create a new validator distribution record -func (k Keeper) onDelegationCreated(ctx sdk.Context, address sdk.ConsAddress) { - slashingPeriod := ValidatorSlashingPeriod{ - ValidatorAddr: address, - StartHeight: ctx.BlockHeight(), - EndHeight: 0, - SlashedSoFar: sdk.ZeroDec(), +// Create a new delegator distribution record +func (k Keeper) onDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, + valAddr sdk.ValAddress) { + + ddi := types.DelegatorDistInfo{ + DelegatorAddr: delAddr, + ValOperatorAddr: valAddr, + WithdrawalHeight: ctx.BlockHeight(), } - k.addOrUpdateValidatorSlashingPeriod(ctx, slashingPeriod) + k.SetDelegatorDistInfo(ctx, ddi) +} + +// Withdrawal all validator rewards +func (k Keeper) onDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, + valAddr sdk.ValAddress) { + + k.WithdrawDelegationReward(ctx, delAddr, valAddr) +} + +// Withdrawal all validator distribution rewards and cleanup the distribution record +func (k Keeper) onDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, + valAddr sdk.ValAddress) { + + k.RemoveDelegatorDistInfo(ctx, delAddr, valAddr) } //_________________________________________________________________________________________ -// Wrapper struct for sdk.ValidatorHooks -type ValidatorHooks struct { +// Wrapper struct +type Hooks struct { k Keeper } -var _ sdk.ValidatorHooks = ValidatorHooks{} - // nolint func (k Keeper) ValidatorHooks() sdk.ValidatorHooks { return ValidatorHooks{k} } -func (v ValidatorHooks) OnValidatorCreated(ctx sdk.Context, addr sdk.VlAddress) { - v.k.OnValidatorCreated(ctx, address) +func (h Hooks) OnValidatorCreated(ctx sdk.Context, addr sdk.VlAddress) { + v.k.onValidatorCreated(ctx, address) } -func (v ValidatorHooks) OnValidatorBondModified(ctx sdk.Context, addr sdk.ValAddress) { - v.k.OnValidatorBondModified(ctx, address) +func (h Hooks) OnValidatorCommissionChange(ctx sdk.Context, addr sdk.ValAddress) { + v.k.onValidatorCommissionChange(ctx, address) } -func (v ValidatorHooks) OnValidatorRemoved(ctx sdk.Context, addr sdk.ValAddress) { - v.k.OnValidatorRemoved(ctx, address) +func (h Hooks) OnValidatorRemoved(ctx sdk.Context, addr sdk.ValAddress) { + v.k.onValidatorRemoved(ctx, address) } -func (v ValidatorHooks) OnValidatorBonded(_ sdk.Context, _ sdk.ConsAddress) {} -func (v ValidatorHooks) OnValidatorBeginBonded(_ sdk.Context, _ sdk.ConsAddress) {} - -//_________________________________________________________________________________________ - -// Wrapper struct for sdk.DelegationHooks -type DelegationHooks struct { - k Keeper +func (h Hooks) OnDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + h.k.onDelegationCreated(ctx, delAddr, valAddr) } - -var _ sdk.DelegationHooks = DelegationHooks{} - -// nolint -func (k Keeper) DelegationHooks() sdk.DelegationHooks { return DelegationHooks{k} } -func (d DelegationHooks) OnDelegatoinCreated(ctx sdk.Context, - delAddr sdk.AccAddress, valAddr sdk.ValAddress) { - d.k.OnDelegatoinCreated(ctx, address) +func (h Hooks) OnDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + d.k.onDelegationSharesModified(ctx, delAddr, valAddr) } -func (d DelegationHooks) OnDelegationSharesModified(ctx sdk.Context, - delAddr sdk.AccAddress, valAddr sdk.ValAddress) { - d.k.OnDelegationSharesModified(ctx, address) -} -func (d DelegationHooks) OnDelegationRemoved(ctx sdk.Context, - delAddr sdk.AccAddress, valAddr sdk.ValAddress) { - d.k.OnDelegationRemoved(ctx, address) +func (h Hooks) OnDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + h.k.onDelegationRemoved(ctx, delAddr, valAddr) } diff --git a/x/distribution/keeper/validator.go b/x/distribution/keeper/validator.go index 7de71300cd..ce73b22719 100644 --- a/x/distribution/keeper/validator.go +++ b/x/distribution/keeper/validator.go @@ -35,12 +35,13 @@ func (k Keeper) RemoveValidatorDistInfo(ctx sdk.Context, valAddr sdk.ValAddress) // withdrawal all the validator rewards including the commission func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context, - operatorAddr sdk.ValAddress, withdrawAddr sdk.AccAddress) { + operatorAddr sdk.ValAddress) { // withdraw self-delegation height := ctx.BlockHeight() validator := k.GetValidator(ctx, operatorAddr) - withdraw := k.GetDelegatorRewardsAll(ctx, validator.OperatorAddr, height) + accAddr := sdk.AccAddress{operatorAddr.Bytes()} + withdraw := k.GetDelegatorRewardsAll(ctx, accAddr, height) // withdrawal validator commission rewards pool := k.stakeKeeper.GetPool(ctx) @@ -51,5 +52,6 @@ func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context, withdraw = withdraw.Add(commission) k.SetFeePool(feePool) + withdrawAddr := k.GetDelegatorWithdrawAddr(accAddr) k.coinKeeper.AddCoins(withdrawAddr, withdraw.TruncateDecimal()) } diff --git a/x/stake/keeper/keeper.go b/x/stake/keeper/keeper.go index a3754f7504..b9db3cbfb1 100644 --- a/x/stake/keeper/keeper.go +++ b/x/stake/keeper/keeper.go @@ -10,11 +10,11 @@ import ( // keeper of the stake store type Keeper struct { - storeKey sdk.StoreKey - storeTKey sdk.StoreKey - cdc *codec.Codec - bankKeeper bank.Keeper - validatorHooks sdk.ValidatorHooks + storeKey sdk.StoreKey + storeTKey sdk.StoreKey + cdc *codec.Codec + bankKeeper bank.Keeper + hooks sdk.StakingHooks // codespace codespace sdk.CodespaceType @@ -33,11 +33,11 @@ func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ck bank.Keeper, codespa } // Set the validator hooks -func (k Keeper) WithValidatorHooks(v sdk.ValidatorHooks) Keeper { - if k.validatorHooks != nil { +func (k Keeper) WithHooks(sh sdk.StakingHooks) Keeper { + if k.stakingHooks != nil { panic("cannot set validator hooks twice") } - k.validatorHooks = v + k.validatorHooks = sh return k }