2018-02-23 15:57:31 -08:00
|
|
|
package stake
|
|
|
|
|
|
|
|
import (
|
2018-08-12 00:33:48 -07:00
|
|
|
"time"
|
|
|
|
|
2018-02-23 15:57:31 -08:00
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
2018-06-26 19:00:12 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/x/stake/keeper"
|
|
|
|
"github.com/cosmos/cosmos-sdk/x/stake/tags"
|
|
|
|
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
2018-06-28 17:54:47 -07:00
|
|
|
abci "github.com/tendermint/tendermint/abci/types"
|
2018-02-23 15:57:31 -08:00
|
|
|
)
|
|
|
|
|
2018-06-26 19:00:12 -07:00
|
|
|
func NewHandler(k keeper.Keeper) sdk.Handler {
|
2018-02-27 18:07:20 -08:00
|
|
|
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
|
2018-03-20 06:56:07 -07:00
|
|
|
// NOTE msg already has validate basic run
|
2018-03-14 11:42:50 -07:00
|
|
|
switch msg := msg.(type) {
|
2018-06-26 19:00:12 -07:00
|
|
|
case types.MsgCreateValidator:
|
2018-05-31 12:22:46 -07:00
|
|
|
return handleMsgCreateValidator(ctx, msg, k)
|
2018-06-26 19:00:12 -07:00
|
|
|
case types.MsgEditValidator:
|
2018-05-31 12:22:46 -07:00
|
|
|
return handleMsgEditValidator(ctx, msg, k)
|
2018-06-26 19:00:12 -07:00
|
|
|
case types.MsgDelegate:
|
2018-03-27 17:26:52 -07:00
|
|
|
return handleMsgDelegate(ctx, msg, k)
|
2018-06-26 19:00:12 -07:00
|
|
|
case types.MsgBeginRedelegate:
|
|
|
|
return handleMsgBeginRedelegate(ctx, msg, k)
|
|
|
|
case types.MsgCompleteRedelegate:
|
|
|
|
return handleMsgCompleteRedelegate(ctx, msg, k)
|
|
|
|
case types.MsgBeginUnbonding:
|
|
|
|
return handleMsgBeginUnbonding(ctx, msg, k)
|
|
|
|
case types.MsgCompleteUnbonding:
|
|
|
|
return handleMsgCompleteUnbonding(ctx, msg, k)
|
2018-03-13 11:27:52 -07:00
|
|
|
default:
|
2018-03-23 09:15:41 -07:00
|
|
|
return sdk.ErrTxDecode("invalid message parse in staking module").Result()
|
2018-02-27 18:07:20 -08:00
|
|
|
}
|
2018-02-23 15:57:31 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-01 14:24:48 -07:00
|
|
|
// Called every block, process inflation, update validator set
|
2018-06-26 19:00:12 -07:00
|
|
|
func EndBlocker(ctx sdk.Context, k keeper.Keeper) (ValidatorUpdates []abci.Validator) {
|
2018-07-20 08:39:29 -07:00
|
|
|
pool := k.GetPool(ctx)
|
2018-06-01 14:24:48 -07:00
|
|
|
|
2018-07-20 08:35:13 -07:00
|
|
|
// Process provision inflation
|
2018-06-26 19:00:12 -07:00
|
|
|
blockTime := ctx.BlockHeader().Time
|
2018-08-12 00:33:48 -07:00
|
|
|
if blockTime.Sub(pool.InflationLastTime) >= time.Hour {
|
2018-07-20 08:35:13 -07:00
|
|
|
params := k.GetParams(ctx)
|
2018-06-01 14:24:48 -07:00
|
|
|
pool.InflationLastTime = blockTime
|
2018-07-13 13:46:14 -07:00
|
|
|
pool = pool.ProcessProvisions(params)
|
2018-07-20 08:35:13 -07:00
|
|
|
k.SetPool(ctx, pool)
|
2018-04-04 20:22:13 -07:00
|
|
|
}
|
2018-06-01 14:24:48 -07:00
|
|
|
|
|
|
|
// reset the intra-transaction counter
|
2018-06-26 19:00:12 -07:00
|
|
|
k.SetIntraTxCounter(ctx, 0)
|
2018-06-01 14:24:48 -07:00
|
|
|
|
|
|
|
// calculate validator set changes
|
2018-06-26 19:00:12 -07:00
|
|
|
ValidatorUpdates = k.GetTendermintUpdates(ctx)
|
|
|
|
k.ClearTendermintUpdates(ctx)
|
2018-06-01 14:24:48 -07:00
|
|
|
return
|
2018-04-04 20:22:13 -07:00
|
|
|
}
|
|
|
|
|
2018-02-23 15:57:31 -08:00
|
|
|
//_____________________________________________________________________
|
|
|
|
|
|
|
|
// These functions assume everything has been authenticated,
|
|
|
|
// now we just perform action and save
|
2018-03-14 11:42:50 -07:00
|
|
|
|
2018-06-26 19:00:12 -07:00
|
|
|
func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k keeper.Keeper) sdk.Result {
|
2018-02-23 15:57:31 -08:00
|
|
|
|
2018-02-27 18:07:20 -08:00
|
|
|
// check to see if the pubkey or sender has been registered before
|
2018-05-09 21:01:58 -07:00
|
|
|
_, found := k.GetValidator(ctx, msg.ValidatorAddr)
|
2018-03-20 14:21:18 -07:00
|
|
|
if found {
|
2018-07-09 17:42:57 -07:00
|
|
|
return ErrValidatorOwnerExists(k.Codespace()).Result()
|
|
|
|
}
|
|
|
|
_, found = k.GetValidatorByPubKey(ctx, msg.PubKey)
|
|
|
|
if found {
|
|
|
|
return ErrValidatorPubKeyExists(k.Codespace()).Result()
|
2018-02-27 18:07:20 -08:00
|
|
|
}
|
2018-07-10 17:16:37 -07:00
|
|
|
if msg.Delegation.Denom != k.GetParams(ctx).BondDenom {
|
2018-06-26 19:00:12 -07:00
|
|
|
return ErrBadDenom(k.Codespace()).Result()
|
2018-03-13 11:27:52 -07:00
|
|
|
}
|
2018-02-27 18:07:20 -08:00
|
|
|
|
2018-05-09 21:01:58 -07:00
|
|
|
validator := NewValidator(msg.ValidatorAddr, msg.PubKey, msg.Description)
|
2018-06-26 19:00:12 -07:00
|
|
|
k.SetValidator(ctx, validator)
|
|
|
|
k.SetValidatorByPubKeyIndex(ctx, validator)
|
2018-02-23 15:57:31 -08:00
|
|
|
|
2018-06-26 19:00:12 -07:00
|
|
|
// move coins from the msg.Address account to a (self-delegation) delegator account
|
2018-05-09 21:01:58 -07:00
|
|
|
// the validator account and global shares are updated within here
|
2018-07-12 16:38:35 -07:00
|
|
|
_, err := k.Delegate(ctx, msg.DelegatorAddr, msg.Delegation, validator, true)
|
2018-04-03 10:03:49 -07:00
|
|
|
if err != nil {
|
|
|
|
return err.Result()
|
|
|
|
}
|
2018-06-26 19:00:12 -07:00
|
|
|
|
|
|
|
tags := sdk.NewTags(
|
|
|
|
tags.Action, tags.ActionCreateValidator,
|
|
|
|
tags.DstValidator, []byte(msg.ValidatorAddr.String()),
|
|
|
|
tags.Moniker, []byte(msg.Description.Moniker),
|
|
|
|
tags.Identity, []byte(msg.Description.Identity),
|
|
|
|
)
|
2018-05-10 08:19:06 -07:00
|
|
|
return sdk.Result{
|
|
|
|
Tags: tags,
|
|
|
|
}
|
2018-02-23 15:57:31 -08:00
|
|
|
}
|
|
|
|
|
2018-06-26 19:00:12 -07:00
|
|
|
func handleMsgEditValidator(ctx sdk.Context, msg types.MsgEditValidator, k keeper.Keeper) sdk.Result {
|
2018-02-23 15:57:31 -08:00
|
|
|
|
2018-05-09 21:01:58 -07:00
|
|
|
// validator must already be registered
|
|
|
|
validator, found := k.GetValidator(ctx, msg.ValidatorAddr)
|
2018-03-20 14:21:18 -07:00
|
|
|
if !found {
|
2018-06-26 19:00:12 -07:00
|
|
|
return ErrNoValidatorFound(k.Codespace()).Result()
|
2018-03-13 11:27:52 -07:00
|
|
|
}
|
2018-02-23 15:57:31 -08:00
|
|
|
|
2018-03-28 08:08:22 -07:00
|
|
|
// replace all editable fields (clients should autofill existing values)
|
2018-06-26 19:00:12 -07:00
|
|
|
description, err := validator.Description.UpdateDescription(msg.Description)
|
|
|
|
if err != nil {
|
|
|
|
return err.Result()
|
|
|
|
}
|
|
|
|
validator.Description = description
|
2018-05-09 21:01:58 -07:00
|
|
|
|
2018-07-27 21:42:07 -07:00
|
|
|
// We don't need to run through all the power update logic within k.UpdateValidator
|
|
|
|
// We just need to override the entry in state, since only the description has changed.
|
|
|
|
k.SetValidator(ctx, validator)
|
2018-05-09 21:01:58 -07:00
|
|
|
tags := sdk.NewTags(
|
2018-06-26 19:00:12 -07:00
|
|
|
tags.Action, tags.ActionEditValidator,
|
|
|
|
tags.DstValidator, []byte(msg.ValidatorAddr.String()),
|
|
|
|
tags.Moniker, []byte(description.Moniker),
|
|
|
|
tags.Identity, []byte(description.Identity),
|
2018-05-09 21:01:58 -07:00
|
|
|
)
|
2018-05-10 12:55:51 -07:00
|
|
|
return sdk.Result{
|
|
|
|
Tags: tags,
|
|
|
|
}
|
2018-02-23 15:57:31 -08:00
|
|
|
}
|
|
|
|
|
2018-06-26 19:00:12 -07:00
|
|
|
func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper) sdk.Result {
|
2018-02-27 18:07:20 -08:00
|
|
|
|
2018-05-09 21:01:58 -07:00
|
|
|
validator, found := k.GetValidator(ctx, msg.ValidatorAddr)
|
2018-03-20 14:21:18 -07:00
|
|
|
if !found {
|
2018-06-26 19:00:12 -07:00
|
|
|
return ErrNoValidatorFound(k.Codespace()).Result()
|
2018-02-27 18:07:20 -08:00
|
|
|
}
|
2018-07-10 17:16:37 -07:00
|
|
|
if msg.Delegation.Denom != k.GetParams(ctx).BondDenom {
|
2018-06-26 19:00:12 -07:00
|
|
|
return ErrBadDenom(k.Codespace()).Result()
|
2018-02-27 18:07:20 -08:00
|
|
|
}
|
2018-08-22 08:56:13 -07:00
|
|
|
if validator.Jailed {
|
|
|
|
return ErrValidatorJailed(k.Codespace()).Result()
|
2018-03-13 11:27:52 -07:00
|
|
|
}
|
2018-07-12 16:38:35 -07:00
|
|
|
_, err := k.Delegate(ctx, msg.DelegatorAddr, msg.Delegation, validator, true)
|
2018-04-03 10:03:49 -07:00
|
|
|
if err != nil {
|
|
|
|
return err.Result()
|
|
|
|
}
|
2018-06-26 19:00:12 -07:00
|
|
|
|
|
|
|
tags := sdk.NewTags(
|
|
|
|
tags.Action, tags.ActionDelegate,
|
|
|
|
tags.Delegator, []byte(msg.DelegatorAddr.String()),
|
|
|
|
tags.DstValidator, []byte(msg.ValidatorAddr.String()),
|
|
|
|
)
|
2018-05-10 08:19:06 -07:00
|
|
|
return sdk.Result{
|
|
|
|
Tags: tags,
|
|
|
|
}
|
2018-02-23 15:57:31 -08:00
|
|
|
}
|
|
|
|
|
2018-06-26 19:00:12 -07:00
|
|
|
func handleMsgBeginUnbonding(ctx sdk.Context, msg types.MsgBeginUnbonding, k keeper.Keeper) sdk.Result {
|
|
|
|
err := k.BeginUnbonding(ctx, msg.DelegatorAddr, msg.ValidatorAddr, msg.SharesAmount)
|
2018-03-16 13:36:16 -07:00
|
|
|
if err != nil {
|
2018-06-26 19:00:12 -07:00
|
|
|
return err.Result()
|
2018-03-16 13:36:16 -07:00
|
|
|
}
|
2018-04-03 19:26:39 -07:00
|
|
|
|
2018-06-26 19:00:12 -07:00
|
|
|
tags := sdk.NewTags(
|
|
|
|
tags.Action, tags.ActionBeginUnbonding,
|
|
|
|
tags.Delegator, []byte(msg.DelegatorAddr.String()),
|
|
|
|
tags.SrcValidator, []byte(msg.ValidatorAddr.String()),
|
|
|
|
)
|
|
|
|
return sdk.Result{Tags: tags}
|
2018-03-16 13:36:16 -07:00
|
|
|
}
|
|
|
|
|
2018-06-26 19:00:12 -07:00
|
|
|
func handleMsgCompleteUnbonding(ctx sdk.Context, msg types.MsgCompleteUnbonding, k keeper.Keeper) sdk.Result {
|
2018-03-27 17:54:54 -07:00
|
|
|
|
2018-06-26 19:00:12 -07:00
|
|
|
err := k.CompleteUnbonding(ctx, msg.DelegatorAddr, msg.ValidatorAddr)
|
|
|
|
if err != nil {
|
|
|
|
return err.Result()
|
2018-02-23 15:57:31 -08:00
|
|
|
}
|
|
|
|
|
2018-06-26 19:00:12 -07:00
|
|
|
tags := sdk.NewTags(
|
|
|
|
tags.Action, ActionCompleteUnbonding,
|
|
|
|
tags.Delegator, []byte(msg.DelegatorAddr.String()),
|
|
|
|
tags.SrcValidator, []byte(msg.ValidatorAddr.String()),
|
|
|
|
)
|
2018-02-23 15:57:31 -08:00
|
|
|
|
2018-06-26 19:00:12 -07:00
|
|
|
return sdk.Result{Tags: tags}
|
|
|
|
}
|
2018-02-23 15:57:31 -08:00
|
|
|
|
2018-06-26 19:00:12 -07:00
|
|
|
func handleMsgBeginRedelegate(ctx sdk.Context, msg types.MsgBeginRedelegate, k keeper.Keeper) sdk.Result {
|
|
|
|
err := k.BeginRedelegation(ctx, msg.DelegatorAddr, msg.ValidatorSrcAddr,
|
|
|
|
msg.ValidatorDstAddr, msg.SharesAmount)
|
|
|
|
if err != nil {
|
|
|
|
return err.Result()
|
2018-02-23 15:57:31 -08:00
|
|
|
}
|
|
|
|
|
2018-06-26 19:00:12 -07:00
|
|
|
tags := sdk.NewTags(
|
|
|
|
tags.Action, tags.ActionBeginRedelegation,
|
|
|
|
tags.Delegator, []byte(msg.DelegatorAddr.String()),
|
|
|
|
tags.SrcValidator, []byte(msg.ValidatorSrcAddr.String()),
|
|
|
|
tags.DstValidator, []byte(msg.ValidatorDstAddr.String()),
|
|
|
|
)
|
|
|
|
return sdk.Result{Tags: tags}
|
|
|
|
}
|
2018-05-23 14:06:54 -07:00
|
|
|
|
2018-06-26 19:00:12 -07:00
|
|
|
func handleMsgCompleteRedelegate(ctx sdk.Context, msg types.MsgCompleteRedelegate, k keeper.Keeper) sdk.Result {
|
|
|
|
err := k.CompleteRedelegation(ctx, msg.DelegatorAddr, msg.ValidatorSrcAddr, msg.ValidatorDstAddr)
|
|
|
|
if err != nil {
|
|
|
|
return err.Result()
|
2018-02-23 15:57:31 -08:00
|
|
|
}
|
2018-05-23 14:06:54 -07:00
|
|
|
|
2018-06-26 19:00:12 -07:00
|
|
|
tags := sdk.NewTags(
|
|
|
|
tags.Action, tags.ActionCompleteRedelegation,
|
|
|
|
tags.Delegator, []byte(msg.DelegatorAddr.String()),
|
|
|
|
tags.SrcValidator, []byte(msg.ValidatorSrcAddr.String()),
|
|
|
|
tags.DstValidator, []byte(msg.ValidatorDstAddr.String()),
|
|
|
|
)
|
|
|
|
return sdk.Result{Tags: tags}
|
2018-02-23 15:57:31 -08:00
|
|
|
}
|