package types import ( "bytes" "encoding/json" "github.com/tendermint/tendermint/crypto" sdk "github.com/cosmos/cosmos-sdk/types" ) // ensure Msg interface compliance at compile time var ( _ sdk.Msg = &MsgCreateValidator{} _ sdk.Msg = &MsgEditValidator{} _ sdk.Msg = &MsgDelegate{} _ sdk.Msg = &MsgUndelegate{} _ sdk.Msg = &MsgBeginRedelegate{} ) //______________________________________________________________________ // MsgCreateValidator - struct for bonding transactions type MsgCreateValidator struct { Description Description `json:"description"` Commission CommissionMsg `json:"commission"` MinSelfDelegation sdk.Int `json:"min_self_delegation"` DelegatorAddress sdk.AccAddress `json:"delegator_address"` ValidatorAddress sdk.ValAddress `json:"validator_address"` PubKey crypto.PubKey `json:"pubkey"` Value sdk.Coin `json:"value"` } type msgCreateValidatorJSON struct { Description Description `json:"description"` Commission CommissionMsg `json:"commission"` MinSelfDelegation sdk.Int `json:"min_self_delegation"` DelegatorAddress sdk.AccAddress `json:"delegator_address"` ValidatorAddress sdk.ValAddress `json:"validator_address"` PubKey string `json:"pubkey"` Value sdk.Coin `json:"value"` } // Default way to create validator. Delegator address and validator address are the same func NewMsgCreateValidator( valAddr sdk.ValAddress, pubKey crypto.PubKey, selfDelegation sdk.Coin, description Description, commission CommissionMsg, minSelfDelegation sdk.Int, ) MsgCreateValidator { return MsgCreateValidator{ Description: description, DelegatorAddress: sdk.AccAddress(valAddr), ValidatorAddress: valAddr, PubKey: pubKey, Value: selfDelegation, Commission: commission, MinSelfDelegation: minSelfDelegation, } } //nolint func (msg MsgCreateValidator) Route() string { return RouterKey } func (msg MsgCreateValidator) Type() string { return "create_validator" } // Return address(es) that must sign over msg.GetSignBytes() func (msg MsgCreateValidator) GetSigners() []sdk.AccAddress { // delegator is first signer so delegator pays fees addrs := []sdk.AccAddress{msg.DelegatorAddress} if !bytes.Equal(msg.DelegatorAddress.Bytes(), msg.ValidatorAddress.Bytes()) { // if validator addr is not same as delegator addr, validator must sign // msg as well addrs = append(addrs, sdk.AccAddress(msg.ValidatorAddress)) } return addrs } // MarshalJSON implements the json.Marshaler interface to provide custom JSON // serialization of the MsgCreateValidator type. func (msg MsgCreateValidator) MarshalJSON() ([]byte, error) { return json.Marshal(msgCreateValidatorJSON{ Description: msg.Description, Commission: msg.Commission, DelegatorAddress: msg.DelegatorAddress, ValidatorAddress: msg.ValidatorAddress, PubKey: sdk.MustBech32ifyConsPub(msg.PubKey), Value: msg.Value, MinSelfDelegation: msg.MinSelfDelegation, }) } // UnmarshalJSON implements the json.Unmarshaler interface to provide custom // JSON deserialization of the MsgCreateValidator type. func (msg *MsgCreateValidator) UnmarshalJSON(bz []byte) error { var msgCreateValJSON msgCreateValidatorJSON if err := json.Unmarshal(bz, &msgCreateValJSON); err != nil { return err } msg.Description = msgCreateValJSON.Description msg.Commission = msgCreateValJSON.Commission msg.DelegatorAddress = msgCreateValJSON.DelegatorAddress msg.ValidatorAddress = msgCreateValJSON.ValidatorAddress var err error msg.PubKey, err = sdk.GetConsPubKeyBech32(msgCreateValJSON.PubKey) if err != nil { return err } msg.Value = msgCreateValJSON.Value msg.MinSelfDelegation = msgCreateValJSON.MinSelfDelegation return nil } // GetSignBytes returns the message bytes to sign over. func (msg MsgCreateValidator) GetSignBytes() []byte { bz := MsgCdc.MustMarshalJSON(msg) return sdk.MustSortJSON(bz) } // quick validity check func (msg MsgCreateValidator) ValidateBasic() sdk.Error { // note that unmarshaling from bech32 ensures either empty or valid if msg.DelegatorAddress.Empty() { return ErrNilDelegatorAddr(DefaultCodespace) } if msg.ValidatorAddress.Empty() { return ErrNilValidatorAddr(DefaultCodespace) } if !sdk.AccAddress(msg.ValidatorAddress).Equals(msg.DelegatorAddress) { return ErrBadValidatorAddr(DefaultCodespace) } if msg.Value.Amount.LTE(sdk.ZeroInt()) { return ErrBadDelegationAmount(DefaultCodespace) } if msg.Description == (Description{}) { return sdk.NewError(DefaultCodespace, CodeInvalidInput, "description must be included") } if msg.Commission == (CommissionMsg{}) { return sdk.NewError(DefaultCodespace, CodeInvalidInput, "commission must be included") } if !msg.MinSelfDelegation.GT(sdk.ZeroInt()) { return ErrMinSelfDelegationInvalid(DefaultCodespace) } if msg.Value.Amount.LT(msg.MinSelfDelegation) { return ErrSelfDelegationBelowMinimum(DefaultCodespace) } return nil } // MsgEditValidator - struct for editing a validator type MsgEditValidator struct { Description ValidatorAddress sdk.ValAddress `json:"address"` // We pass a reference to the new commission rate and min self delegation as it's not mandatory to // update. If not updated, the deserialized rate will be zero with no way to // distinguish if an update was intended. // // REF: #2373 CommissionRate *sdk.Dec `json:"commission_rate"` MinSelfDelegation *sdk.Int `json:"min_self_delegation"` } func NewMsgEditValidator(valAddr sdk.ValAddress, description Description, newRate *sdk.Dec, newMinSelfDelegation *sdk.Int) MsgEditValidator { return MsgEditValidator{ Description: description, CommissionRate: newRate, ValidatorAddress: valAddr, MinSelfDelegation: newMinSelfDelegation, } } //nolint func (msg MsgEditValidator) Route() string { return RouterKey } func (msg MsgEditValidator) Type() string { return "edit_validator" } func (msg MsgEditValidator) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{sdk.AccAddress(msg.ValidatorAddress)} } // get the bytes for the message signer to sign on func (msg MsgEditValidator) GetSignBytes() []byte { bz := MsgCdc.MustMarshalJSON(msg) return sdk.MustSortJSON(bz) } // quick validity check func (msg MsgEditValidator) ValidateBasic() sdk.Error { if msg.ValidatorAddress.Empty() { return sdk.NewError(DefaultCodespace, CodeInvalidInput, "nil validator address") } if msg.Description == (Description{}) { return sdk.NewError(DefaultCodespace, CodeInvalidInput, "transaction must include some information to modify") } if msg.MinSelfDelegation != nil && !(*msg.MinSelfDelegation).GT(sdk.ZeroInt()) { return ErrMinSelfDelegationInvalid(DefaultCodespace) } if msg.CommissionRate != nil { if msg.CommissionRate.GT(sdk.OneDec()) || msg.CommissionRate.LT(sdk.ZeroDec()) { return sdk.NewError(DefaultCodespace, CodeInvalidInput, "commission rate must be between 0 and 1, inclusive") } } return nil } // MsgDelegate - struct for bonding transactions type MsgDelegate struct { DelegatorAddress sdk.AccAddress `json:"delegator_address"` ValidatorAddress sdk.ValAddress `json:"validator_address"` Amount sdk.Coin `json:"amount"` } func NewMsgDelegate(delAddr sdk.AccAddress, valAddr sdk.ValAddress, amount sdk.Coin) MsgDelegate { return MsgDelegate{ DelegatorAddress: delAddr, ValidatorAddress: valAddr, Amount: amount, } } //nolint func (msg MsgDelegate) Route() string { return RouterKey } func (msg MsgDelegate) Type() string { return "delegate" } func (msg MsgDelegate) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{msg.DelegatorAddress} } // get the bytes for the message signer to sign on func (msg MsgDelegate) GetSignBytes() []byte { bz := MsgCdc.MustMarshalJSON(msg) return sdk.MustSortJSON(bz) } // quick validity check func (msg MsgDelegate) ValidateBasic() sdk.Error { if msg.DelegatorAddress.Empty() { return ErrNilDelegatorAddr(DefaultCodespace) } if msg.ValidatorAddress.Empty() { return ErrNilValidatorAddr(DefaultCodespace) } if msg.Amount.Amount.LTE(sdk.ZeroInt()) { return ErrBadDelegationAmount(DefaultCodespace) } return nil } //______________________________________________________________________ // MsgDelegate - struct for bonding transactions type MsgBeginRedelegate struct { DelegatorAddress sdk.AccAddress `json:"delegator_address"` ValidatorSrcAddress sdk.ValAddress `json:"validator_src_address"` ValidatorDstAddress sdk.ValAddress `json:"validator_dst_address"` Amount sdk.Coin `json:"amount"` } func NewMsgBeginRedelegate(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress, amount sdk.Coin) MsgBeginRedelegate { return MsgBeginRedelegate{ DelegatorAddress: delAddr, ValidatorSrcAddress: valSrcAddr, ValidatorDstAddress: valDstAddr, Amount: amount, } } //nolint func (msg MsgBeginRedelegate) Route() string { return RouterKey } func (msg MsgBeginRedelegate) Type() string { return "begin_redelegate" } func (msg MsgBeginRedelegate) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{msg.DelegatorAddress} } // get the bytes for the message signer to sign on func (msg MsgBeginRedelegate) GetSignBytes() []byte { bz := MsgCdc.MustMarshalJSON(msg) return sdk.MustSortJSON(bz) } // quick validity check func (msg MsgBeginRedelegate) ValidateBasic() sdk.Error { if msg.DelegatorAddress.Empty() { return ErrNilDelegatorAddr(DefaultCodespace) } if msg.ValidatorSrcAddress.Empty() { return ErrNilValidatorAddr(DefaultCodespace) } if msg.ValidatorDstAddress.Empty() { return ErrNilValidatorAddr(DefaultCodespace) } if msg.Amount.Amount.LTE(sdk.ZeroInt()) { return ErrBadSharesAmount(DefaultCodespace) } return nil } // MsgUndelegate - struct for unbonding transactions type MsgUndelegate struct { DelegatorAddress sdk.AccAddress `json:"delegator_address"` ValidatorAddress sdk.ValAddress `json:"validator_address"` Amount sdk.Coin `json:"amount"` } func NewMsgUndelegate(delAddr sdk.AccAddress, valAddr sdk.ValAddress, amount sdk.Coin) MsgUndelegate { return MsgUndelegate{ DelegatorAddress: delAddr, ValidatorAddress: valAddr, Amount: amount, } } //nolint func (msg MsgUndelegate) Route() string { return RouterKey } func (msg MsgUndelegate) Type() string { return "begin_unbonding" } func (msg MsgUndelegate) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{msg.DelegatorAddress} } // get the bytes for the message signer to sign on func (msg MsgUndelegate) GetSignBytes() []byte { bz := MsgCdc.MustMarshalJSON(msg) return sdk.MustSortJSON(bz) } // quick validity check func (msg MsgUndelegate) ValidateBasic() sdk.Error { if msg.DelegatorAddress.Empty() { return ErrNilDelegatorAddr(DefaultCodespace) } if msg.ValidatorAddress.Empty() { return ErrNilValidatorAddr(DefaultCodespace) } if msg.Amount.Amount.LTE(sdk.ZeroInt()) { return ErrBadSharesAmount(DefaultCodespace) } return nil }