Skip to content

Commit

Permalink
added msg types for unbonding, redelegation
Browse files Browse the repository at this point in the history
  • Loading branch information
rigelrozanski committed Jun 2, 2018
1 parent 9619765 commit d8d7525
Show file tree
Hide file tree
Showing 7 changed files with 189 additions and 54 deletions.
6 changes: 3 additions & 3 deletions x/stake/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ func GetCmdCompleteRedelegate(cdc *wire.Codec) *cobra.Command {
return err
}

msg := stake.NewMsgCompleteRedelegation(delegatorAddr, validatorSrcAddr, validatorDstAddr)
msg := stake.NewMsgCompleteRedelegate(delegatorAddr, validatorSrcAddr, validatorDstAddr)

// build and sign the transaction, then broadcast to Tendermint
ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc))
Expand Down Expand Up @@ -305,7 +305,7 @@ func GetCmdBeginUnbonding(cdc *wire.Codec) *cobra.Command {
return err
}

msg := stake.NewMsgBeginUnbond(delegatorAddr, validatorAddr, sharesAmount, sharesPercent)
msg := stake.NewMsgBeginUnbonding(delegatorAddr, validatorAddr, sharesAmount, sharesPercent)

// build and sign the transaction, then broadcast to Tendermint
ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc))
Expand Down Expand Up @@ -339,7 +339,7 @@ func GetCmdCompleteUnbonding(cdc *wire.Codec) *cobra.Command {
return err
}

msg := stake.NewMsgCompleteUnbond(delegatorAddr, validatorAddr)
msg := stake.NewMsgCompleteUnbonding(delegatorAddr, validatorAddr)

// build and sign the transaction, then broadcast to Tendermint
ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc))
Expand Down
12 changes: 6 additions & 6 deletions x/stake/client/rest/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ func registerTxRoutes(ctx context.CoreContext, r *mux.Router, cdc *wire.Codec, k
}

type editDelegationsBody struct {
LocalAccountName string `json:"name"`
Password string `json:"password"`
ChainID string `json:"chain_id"`
Sequence int64 `json:"sequence"`
Delegate []stake.MsgDelegate `json:"delegate"`
Unbond []stake.MsgUnbond `json:"unbond"`
LocalAccountName string `json:"name"`
Password string `json:"password"`
ChainID string `json:"chain_id"`
Sequence int64 `json:"sequence"`
Delegate []stake.MsgDelegate `json:"delegate"`
Unbond []stake.MsgBeginUnbonding `json:"unbond"` // XXXXXXXXXXXXXXXXXXXXXXXXXX XXX
}

func editDelegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx context.CoreContext) http.HandlerFunc {
Expand Down
15 changes: 12 additions & 3 deletions x/stake/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ func ErrBadBondingDenom(codespace sdk.CodespaceType) sdk.Error {
func ErrBadBondingAmount(codespace sdk.CodespaceType) sdk.Error {
return newError(codespace, CodeInvalidBond, "Amount must be > 0")
}
func ErrBadSharesAmount(codespace sdk.CodespaceType) sdk.Error {
return newError(codespace, CodeInvalidBond, "Shares must be > 0")
}
func ErrBadSharesPercent(codespace sdk.CodespaceType) sdk.Error {
return newError(codespace, CodeInvalidBond, "Shares percent must be >0 and <=1")
}
func ErrNoBondingAcct(codespace sdk.CodespaceType) sdk.Error {
return newError(codespace, CodeInvalidValidator, "No bond account for this (address, validator) pair")
}
Expand All @@ -69,6 +75,12 @@ func ErrCommissionHuge(codespace sdk.CodespaceType) sdk.Error {
func ErrBadValidatorAddr(codespace sdk.CodespaceType) sdk.Error {
return newError(codespace, CodeInvalidValidator, "Validator does not exist for that address")
}
func ErrBothShareMsgsGiven(codespace sdk.CodespaceType) sdk.Error {
return newError(codespace, CodeInvalidInput, "Both shares amount and shares percent provided")
}
func ErrNeitherShareMsgsGiven(codespace sdk.CodespaceType) sdk.Error {
return newError(codespace, CodeInvalidInput, "Neither shares amount nor shares percent provided")
}
func ErrBadDelegatorAddr(codespace sdk.CodespaceType) sdk.Error {
return newError(codespace, CodeInvalidValidator, "Delegator does not exist for that address")
}
Expand All @@ -93,9 +105,6 @@ func ErrNoDelegatorForAddress(codespace sdk.CodespaceType) sdk.Error {
func ErrInsufficientFunds(codespace sdk.CodespaceType) sdk.Error {
return newError(codespace, CodeInvalidInput, "Insufficient bond shares")
}
func ErrBadShares(codespace sdk.CodespaceType) sdk.Error {
return newError(codespace, CodeInvalidInput, "bad shares provided as input, must be MAX or decimal")
}
func ErrBadRemoveValidator(codespace sdk.CodespaceType) sdk.Error {
return newError(codespace, CodeInvalidValidator, "Error removing validator")
}
Expand Down
46 changes: 31 additions & 15 deletions x/stake/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,14 @@ func NewHandler(k Keeper) sdk.Handler {
return handleMsgEditValidator(ctx, msg, k)
case MsgDelegate:
return handleMsgDelegate(ctx, msg, k)
case MsgUnbond:
return handleMsgUnbond(ctx, msg, k)
case MsgBeginRedelegate:
return handleMsgBeginRedelegate(ctx, msg, k)
case MsgCompleteRedelegate:
return handleMsgCompleteRedelegate(ctx, msg, k)
case MsgBeginUnbonding:
return handleMsgBeginUnbonding(ctx, msg, k)
case MsgCompleteUnbonding:
return handleMsgCompleteUnbonding(ctx, msg, k)
default:
return sdk.ErrTxDecode("invalid message parse in staking module").Result()
}
Expand Down Expand Up @@ -176,7 +182,7 @@ func delegate(ctx sdk.Context, k Keeper, delegatorAddr sdk.Address,
return tags, nil
}

func handleMsgUnbond(ctx sdk.Context, msg MsgUnbond, k Keeper) sdk.Result {
func handleMsgBeginUnbonding(ctx sdk.Context, msg MsgBeginUnbonding, k Keeper) sdk.Result {

// check if bond has any shares in it unbond
bond, found := k.GetDelegation(ctx, msg.DelegatorAddr, msg.ValidatorAddr)
Expand All @@ -187,18 +193,13 @@ func handleMsgUnbond(ctx sdk.Context, msg MsgUnbond, k Keeper) sdk.Result {
var delShares sdk.Rat

// test that there are enough shares to unbond
if msg.Shares == "MAX" {
if !msg.SharesPercent.Equal(sdk.ZeroRat()) {
if !bond.Shares.GT(sdk.ZeroRat()) {
return ErrNotEnoughBondShares(k.codespace, msg.Shares).Result()
return ErrNotEnoughBondShares(k.codespace, bond.Shares.String()).Result()
}
} else {
var err sdk.Error
delShares, err = sdk.NewRatFromDecimal(msg.Shares)
if err != nil {
return err.Result()
}
if bond.Shares.LT(delShares) {
return ErrNotEnoughBondShares(k.codespace, msg.Shares).Result()
if bond.Shares.LT(msg.SharesAmount) {
return ErrNotEnoughBondShares(k.codespace, bond.Shares.String()).Result()
}
}

Expand All @@ -212,9 +213,9 @@ func handleMsgUnbond(ctx sdk.Context, msg MsgUnbond, k Keeper) sdk.Result {
return sdk.Result{}
}

// retrieve the amount of bonds to remove (TODO remove redundancy already serialized)
if msg.Shares == "MAX" {
delShares = bond.Shares
// retrieve the amount of bonds to remove
if !msg.SharesPercent.Equal(sdk.ZeroRat()) {
delShares = bond.Shares.Mul(msg.SharesPercent)
}

// subtract bond tokens from delegator bond
Expand Down Expand Up @@ -262,3 +263,18 @@ func handleMsgUnbond(ctx sdk.Context, msg MsgUnbond, k Keeper) sdk.Result {
Tags: tags,
}
}

func handleMsgCompleteUnbonding(ctx sdk.Context, msg MsgCompleteUnbonding, k Keeper) sdk.Result {
// XXX
return sdk.Result{}
}

func handleMsgBeginRedelegate(ctx sdk.Context, msg MsgBeginRedelegate, k Keeper) sdk.Result {
// XXX
return sdk.Result{}
}

func handleMsgCompleteRedelegate(ctx sdk.Context, msg MsgCompleteRedelegate, k Keeper) sdk.Result {
// XXX
return sdk.Result{}
}
154 changes: 129 additions & 25 deletions x/stake/msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ const MsgType = "stake"
const StakingToken = "steak"

//Verify interface at compile time
var _, _, _, _ sdk.Msg = &MsgCreateValidator{}, &MsgEditValidator{}, &MsgDelegate{}, &MsgUnbond{}
var _, _, _ sdk.Msg = &MsgCreateValidator{}, &MsgEditValidator{}, &MsgDelegate{}
var _, _ sdk.Msg = &MsgBeginUnbonding{}, &MsgCompleteUnbonding{}
var _, _ sdk.Msg = &MsgBeginRedelegate{}, &MsgCompleteRedelegate{}

//______________________________________________________________________

Expand Down Expand Up @@ -164,15 +166,19 @@ type MsgBeginRedelegate struct {
DelegatorAddr sdk.Address `json:"delegator_addr"`
ValidatorSrcAddr sdk.Address `json:"validator_source_addr"`
ValidatorDstAddr sdk.Address `json:"validator_destination_addr"`
Shares sdk.Rat `json:"shares"`
SharesAmount sdk.Rat `json:"shares_amount"`
SharesPercent sdk.Rat `json:"shares_percent"`
}

func NewMsgBeginRedelegate(delegatorAddr, validatorSrcAddr, validatorDstAddr sdk.Address, shares sdk.Rational) MsgDelegate {
return MsgDelegate{
func NewMsgBeginRedelegate(delegatorAddr, validatorSrcAddr,
validatorDstAddr sdk.Address, sharesAmount, sharesPercent sdk.Rat) MsgBeginRedelegate {

return MsgBeginRedelegate{
DelegatorAddr: delegatorAddr,
ValidatorSrcAddr: validatorSrcAddr,
ValidatorDstAddr: validatorDstAddr,
Shares: shares,
SharesAmount: sharesAmount,
SharesPercent: sharesPercent,
}
}

Expand Down Expand Up @@ -202,35 +208,101 @@ func (msg MsgBeginRedelegate) ValidateBasic() sdk.Error {
if msg.ValidatorDstAddr == nil {
return ErrBadValidatorAddr(DefaultCodespace)
}
if msg.Bond.Amount <= 0 {
return ErrBadBondingAmount(DefaultCodespace)
err := testShares(msg.SharesAmount, msg.SharesPercent)
if err != nil {
return err
}
return nil
}

func testShares(sharesAmount, sharesPercent sdk.Rat) sdk.Error {
if !sharesAmount.Equal(sdk.ZeroRat()) && !sharesPercent.Equal(sdk.ZeroRat()) {
return ErrBothShareMsgsGiven(DefaultCodespace)
}
if sharesAmount.Equal(sdk.ZeroRat()) && sharesPercent.Equal(sdk.ZeroRat()) {
return ErrNeitherShareMsgsGiven(DefaultCodespace)
}
if !sharesAmount.Equal(sdk.ZeroRat()) && sharesAmount.LTE(sdk.ZeroRat()) {
return ErrBadSharesAmount(DefaultCodespace)
}
if !sharesPercent.Equal(sdk.ZeroRat()) &&
(sharesPercent.LTE(sdk.ZeroRat()) || sharesPercent.LTE(sdk.OneRat())) {
return ErrBadSharesPercent(DefaultCodespace)
}
return nil
}

// MsgDelegate - struct for bonding transactions
type MsgCompleteRedelegate struct {
DelegatorAddr sdk.Address `json:"delegator_addr"`
ValidatorSrcAddr sdk.Address `json:"validator_source_addr"`
ValidatorDstAddr sdk.Address `json:"validator_destination_addr"`
}

func NewMsgCompleteRedelegate(delegatorAddr, validatorSrcAddr,
validatorDstAddr sdk.Address) MsgCompleteRedelegate {

return MsgCompleteRedelegate{
DelegatorAddr: delegatorAddr,
ValidatorSrcAddr: validatorSrcAddr,
ValidatorDstAddr: validatorDstAddr,
}
}

//nolint
func (msg MsgCompleteRedelegate) Type() string { return MsgType }
func (msg MsgCompleteRedelegate) GetSigners() []sdk.Address {
return []sdk.Address{msg.DelegatorAddr}
}

// get the bytes for the message signer to sign on
func (msg MsgCompleteRedelegate) GetSignBytes() []byte {
b, err := msgCdc.MarshalJSON(msg)
if err != nil {
panic(err)
}
return b
}

// quick validity check
func (msg MsgCompleteRedelegate) ValidateBasic() sdk.Error {
if msg.DelegatorAddr == nil {
return ErrBadDelegatorAddr(DefaultCodespace)
}
if msg.ValidatorSrcAddr == nil {
return ErrBadValidatorAddr(DefaultCodespace)
}
if msg.ValidatorDstAddr == nil {
return ErrBadValidatorAddr(DefaultCodespace)
}
return nil
}

//______________________________________________________________________

// MsgUnbond - struct for unbonding transactions
type MsgUnbond struct {
// MsgBeginUnbonding - struct for unbonding transactions
type MsgBeginUnbonding struct {
DelegatorAddr sdk.Address `json:"delegator_addr"`
ValidatorAddr sdk.Address `json:"validator_addr"`
Shares string `json:"shares"`
SharesAmount sdk.Rat `json:"shares_amount"`
SharesPercent sdk.Rat `json:"shares_percent"`
}

func NewMsgUnbond(delegatorAddr, validatorAddr sdk.Address, shares string) MsgUnbond {
return MsgUnbond{
func NewMsgBeginUnbonding(delegatorAddr, validatorAddr sdk.Address, sharesAmount, sharesPercent sdk.Rat) MsgBeginUnbonding {
return MsgBeginUnbonding{
DelegatorAddr: delegatorAddr,
ValidatorAddr: validatorAddr,
Shares: shares,
SharesAmount: sharesAmount,
SharesPercent: sharesPercent,
}
}

//nolint
func (msg MsgUnbond) Type() string { return MsgType }
func (msg MsgUnbond) GetSigners() []sdk.Address { return []sdk.Address{msg.DelegatorAddr} }
func (msg MsgBeginUnbonding) Type() string { return MsgType }
func (msg MsgBeginUnbonding) GetSigners() []sdk.Address { return []sdk.Address{msg.DelegatorAddr} }

// get the bytes for the message signer to sign on
func (msg MsgUnbond) GetSignBytes() []byte {
func (msg MsgBeginUnbonding) GetSignBytes() []byte {
b, err := msgCdc.MarshalJSON(msg)
if err != nil {
panic(err)
Expand All @@ -239,21 +311,53 @@ func (msg MsgUnbond) GetSignBytes() []byte {
}

// quick validity check
func (msg MsgUnbond) ValidateBasic() sdk.Error {
func (msg MsgBeginUnbonding) ValidateBasic() sdk.Error {
if msg.DelegatorAddr == nil {
return ErrBadDelegatorAddr(DefaultCodespace)
}
if msg.ValidatorAddr == nil {
return ErrBadValidatorAddr(DefaultCodespace)
}
if msg.Shares != "MAX" {
rat, err := sdk.NewRatFromDecimal(msg.Shares)
if err != nil {
return ErrBadShares(DefaultCodespace)
}
if rat.IsZero() || rat.LT(sdk.ZeroRat()) {
return ErrBadShares(DefaultCodespace)
}
err := testShares(msg.SharesAmount, msg.SharesPercent)
if err != nil {
return err
}
return nil
}

// MsgCompleteUnbonding - struct for unbonding transactions
type MsgCompleteUnbonding struct {
DelegatorAddr sdk.Address `json:"delegator_addr"`
ValidatorAddr sdk.Address `json:"validator_addr"`
}

func NewMsgCompleteUnbonding(delegatorAddr, validatorAddr sdk.Address) MsgCompleteUnbonding {
return MsgCompleteUnbonding{
DelegatorAddr: delegatorAddr,
ValidatorAddr: validatorAddr,
}
}

//nolint
func (msg MsgCompleteUnbonding) Type() string { return MsgType }
func (msg MsgCompleteUnbonding) GetSigners() []sdk.Address { return []sdk.Address{msg.DelegatorAddr} }

// get the bytes for the message signer to sign on
func (msg MsgCompleteUnbonding) GetSignBytes() []byte {
b, err := msgCdc.MarshalJSON(msg)
if err != nil {
panic(err)
}
return b
}

// quick validity check
func (msg MsgCompleteUnbonding) ValidateBasic() sdk.Error {
if msg.DelegatorAddr == nil {
return ErrBadDelegatorAddr(DefaultCodespace)
}
if msg.ValidatorAddr == nil {
return ErrBadValidatorAddr(DefaultCodespace)
}
return nil
}
5 changes: 4 additions & 1 deletion x/stake/test_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,10 @@ func makeTestCodec() *wire.Codec {
cdc.RegisterConcrete(bank.MsgIssue{}, "test/stake/Issue", nil)
cdc.RegisterConcrete(MsgCreateValidator{}, "test/stake/CreateValidator", nil)
cdc.RegisterConcrete(MsgEditValidator{}, "test/stake/EditValidator", nil)
cdc.RegisterConcrete(MsgUnbond{}, "test/stake/Unbond", nil)
cdc.RegisterConcrete(MsgBeginUnbonding{}, "test/stake/BeginUnbonding", nil)
cdc.RegisterConcrete(MsgCompleteUnbonding{}, "test/stake/CompleteUnbonding", nil)
cdc.RegisterConcrete(MsgBeginRedelegate{}, "test/stake/BeginRedelegate", nil)
cdc.RegisterConcrete(MsgCompleteRedelegate{}, "test/stake/CompleteRedelegate", nil)

// Register AppAccount
cdc.RegisterInterface((*auth.Account)(nil), nil)
Expand Down
5 changes: 4 additions & 1 deletion x/stake/wire.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ func RegisterWire(cdc *wire.Codec) {
cdc.RegisterConcrete(MsgCreateValidator{}, "cosmos-sdk/MsgCreateValidator", nil)
cdc.RegisterConcrete(MsgEditValidator{}, "cosmos-sdk/MsgEditValidator", nil)
cdc.RegisterConcrete(MsgDelegate{}, "cosmos-sdk/MsgDelegate", nil)
cdc.RegisterConcrete(MsgUnbond{}, "cosmos-sdk/MsgUnbond", nil)
cdc.RegisterConcrete(MsgBeginUnbonding{}, "cosmos-sdk/BeginUnbonding", nil)
cdc.RegisterConcrete(MsgCompleteUnbonding{}, "cosmos-sdk/CompleteUnbonding", nil)
cdc.RegisterConcrete(MsgBeginRedelegate{}, "cosmos-sdk/BeginRedelegate", nil)
cdc.RegisterConcrete(MsgCompleteRedelegate{}, "cosmos-sdk/CompleteRedelegate", nil)
}

var msgCdc = wire.NewCodec()
Expand Down

0 comments on commit d8d7525

Please sign in to comment.