cosmos-sdk/x/stake/handler.go

210 lines
6.3 KiB
Go

package stake
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/stake/keeper"
"github.com/cosmos/cosmos-sdk/x/stake/tags"
"github.com/cosmos/cosmos-sdk/x/stake/types"
abci "github.com/tendermint/tendermint/abci/types"
)
func NewHandler(k keeper.Keeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
// NOTE msg already has validate basic run
switch msg := msg.(type) {
case types.MsgCreateValidator:
return handleMsgCreateValidator(ctx, msg, k)
case types.MsgEditValidator:
return handleMsgEditValidator(ctx, msg, k)
case types.MsgDelegate:
return handleMsgDelegate(ctx, msg, k)
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)
default:
return sdk.ErrTxDecode("invalid message parse in staking module").Result()
}
}
}
// Called every block, process inflation, update validator set
func EndBlocker(ctx sdk.Context, k keeper.Keeper) (ValidatorUpdates []abci.Validator) {
pool := k.GetPool(ctx)
// Process types.Validator Provisions
blockTime := ctx.BlockHeader().Time
if pool.InflationLastTime+blockTime >= 3600 {
pool.InflationLastTime = blockTime
pool = k.ProcessProvisions(ctx)
}
// save the params
k.SetPool(ctx, pool)
// reset the intra-transaction counter
k.SetIntraTxCounter(ctx, 0)
// calculate validator set changes
ValidatorUpdates = k.GetTendermintUpdates(ctx)
k.ClearTendermintUpdates(ctx)
return
}
//_____________________________________________________________________
// These functions assume everything has been authenticated,
// now we just perform action and save
func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k keeper.Keeper) sdk.Result {
// check to see if the pubkey or sender has been registered before
_, found := k.GetValidator(ctx, msg.ValidatorAddr)
if found {
return ErrValidatorAlreadyExists(k.Codespace()).Result()
}
if msg.SelfDelegation.Denom != k.GetParams(ctx).BondDenom {
return ErrBadDenom(k.Codespace()).Result()
}
validator := NewValidator(msg.ValidatorAddr, msg.PubKey, msg.Description)
k.SetValidator(ctx, validator)
k.SetValidatorByPubKeyIndex(ctx, validator)
// move coins from the msg.Address account to a (self-delegation) delegator account
// the validator account and global shares are updated within here
_, err := k.Delegate(ctx, msg.ValidatorAddr, msg.SelfDelegation, validator)
if err != nil {
return err.Result()
}
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),
)
return sdk.Result{
Tags: tags,
}
}
func handleMsgEditValidator(ctx sdk.Context, msg types.MsgEditValidator, k keeper.Keeper) sdk.Result {
// validator must already be registered
validator, found := k.GetValidator(ctx, msg.ValidatorAddr)
if !found {
return ErrNoValidatorFound(k.Codespace()).Result()
}
// replace all editable fields (clients should autofill existing values)
description, err := validator.Description.UpdateDescription(msg.Description)
if err != nil {
return err.Result()
}
validator.Description = description
k.UpdateValidator(ctx, validator)
tags := sdk.NewTags(
tags.Action, tags.ActionEditValidator,
tags.DstValidator, []byte(msg.ValidatorAddr.String()),
tags.Moniker, []byte(description.Moniker),
tags.Identity, []byte(description.Identity),
)
return sdk.Result{
Tags: tags,
}
}
func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper) sdk.Result {
validator, found := k.GetValidator(ctx, msg.ValidatorAddr)
if !found {
return ErrNoValidatorFound(k.Codespace()).Result()
}
if msg.Bond.Denom != k.GetParams(ctx).BondDenom {
return ErrBadDenom(k.Codespace()).Result()
}
if validator.Revoked == true {
return ErrValidatorRevoked(k.Codespace()).Result()
}
_, err := k.Delegate(ctx, msg.DelegatorAddr, msg.Bond, validator)
if err != nil {
return err.Result()
}
tags := sdk.NewTags(
tags.Action, tags.ActionDelegate,
tags.Delegator, []byte(msg.DelegatorAddr.String()),
tags.DstValidator, []byte(msg.ValidatorAddr.String()),
)
return sdk.Result{
Tags: tags,
}
}
func handleMsgBeginUnbonding(ctx sdk.Context, msg types.MsgBeginUnbonding, k keeper.Keeper) sdk.Result {
err := k.BeginUnbonding(ctx, msg.DelegatorAddr, msg.ValidatorAddr, msg.SharesAmount)
if err != nil {
return err.Result()
}
tags := sdk.NewTags(
tags.Action, tags.ActionBeginUnbonding,
tags.Delegator, []byte(msg.DelegatorAddr.String()),
tags.SrcValidator, []byte(msg.ValidatorAddr.String()),
)
return sdk.Result{Tags: tags}
}
func handleMsgCompleteUnbonding(ctx sdk.Context, msg types.MsgCompleteUnbonding, k keeper.Keeper) sdk.Result {
err := k.CompleteUnbonding(ctx, msg.DelegatorAddr, msg.ValidatorAddr)
if err != nil {
return err.Result()
}
tags := sdk.NewTags(
tags.Action, ActionCompleteUnbonding,
tags.Delegator, []byte(msg.DelegatorAddr.String()),
tags.SrcValidator, []byte(msg.ValidatorAddr.String()),
)
return sdk.Result{Tags: tags}
}
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()
}
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}
}
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()
}
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}
}