# Messages

In this section we describe the processing of the staking messages and the corresponding updates to the state. All created/modified state objects specified by each message are defined within the state section.

### MsgCreateValidator <a href="#msgcreatevalidator" id="msgcreatevalidator"></a>

A validator is created using the `MsgCreateValidator` message. The validator must be created with an initial delegation from the operator.

```protobuf
// CreateValidator defines a method for creating a new validator.
rpc CreateValidator(MsgCreateValidator) returns (MsgCreateValidatorResponse);
```

```protobuf
// MsgCreateValidator defines a SDK message for creating a new validator.
message MsgCreateValidator {
  // NOTE(fdymylja): this is a particular case in which
  // if validator_address == delegator_address then only one
  // is expected to sign, otherwise both are.
  option (cosmos.msg.v1.signer) = "delegator_address";
  option (cosmos.msg.v1.signer) = "validator_address";

  option (gogoproto.equal)           = false;
  option (gogoproto.goproto_getters) = false;

  Description     description         = 1 [(gogoproto.nullable) = false];
  CommissionRates commission          = 2 [(gogoproto.nullable) = false];
  string          min_self_delegation = 3 [
    (cosmos_proto.scalar)  = "cosmos.Int",
    (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
    (gogoproto.nullable)   = false
  ];
  string                   delegator_address = 4 [(cosmos_proto.scalar) = "cosmos.AddressString"];
  string                   validator_address = 5 [(cosmos_proto.scalar) = "cosmos.AddressString"];
  google.protobuf.Any      pubkey            = 6 [(cosmos_proto.accepts_interface) = "cosmos.crypto.PubKey"];
  cosmos.base.v1beta1.Coin value             = 7 [(gogoproto.nullable) = false];
}
```

This message is expected to fail if:

* another validator with this operator address is already registered
* another validator with this pubkey is already registered
* the initial self-delegation tokens are of a denom not specified as the bonding denom
* the commission parameters are faulty, namely:
  * `MaxRate` is either > 1 or < 0
  * the initial `Rate` is either negative or > `MaxRate`
  * the initial `MaxChangeRate` is either negative or > `MaxRate`
* the description fields are too large

This message creates and stores the `Validator` object at appropriate indexes. Additionally a self-delegation is made with the initial tokens delegation tokens `Delegation`. The validator always starts as unbonded but may be bonded in the first end-block.

### MsgEditValidator <a href="#msgeditvalidator" id="msgeditvalidator"></a>

The `Description`, `CommissionRate` of a validator can be updated using the `MsgEditValidator` message.

```protobuf
// EditValidator defines a method for editing an existing validator.
rpc EditValidator(MsgEditValidator) returns (MsgEditValidatorResponse);
```

```protobuf
// MsgEditValidator defines a SDK message for editing an existing validator.
message MsgEditValidator {
  option (cosmos.msg.v1.signer) = "validator_address";

  option (gogoproto.equal)           = false;
  option (gogoproto.goproto_getters) = false;

  Description description       = 1 [(gogoproto.nullable) = false];
  string      validator_address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];

  // 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
  string commission_rate = 3
      [(cosmos_proto.scalar) = "cosmos.Dec", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec"];
  string min_self_delegation = 4
      [(cosmos_proto.scalar) = "cosmos.Int", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
}
```

This message is expected to fail if:

* the initial `CommissionRate` is either negative or > `MaxRate`
* the `CommissionRate` has already been updated within the previous 24 hours
* the `CommissionRate` is > `MaxChangeRate`
* the description fields are too large

This message stores the updated `Validator` object.

### MsgDelegate <a href="#msgdelegate" id="msgdelegate"></a>

Within this message the delegator provides coins, and in return receives some amount of their validator's (newly created) delegator-shares that are assigned to `Delegation.Shares`.

```protobuf
// Delegate defines a method for performing a delegation of coins
// from a delegator to a validator.
rpc Delegate(MsgDelegate) returns (MsgDelegateResponse);
```

```protobuf
// MsgDelegate defines a SDK message for performing a delegation of coins
// from a delegator to a validator.
message MsgDelegate {
  option (cosmos.msg.v1.signer) = "delegator_address";

  option (gogoproto.equal)           = false;
  option (gogoproto.goproto_getters) = false;

  string                   delegator_address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
  string                   validator_address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];
  cosmos.base.v1beta1.Coin amount            = 3 [(gogoproto.nullable) = false];
}
```

This message is expected to fail if:

* the validator does not exist
* the `Amount` `Coin` has a denomination different than one defined by `params.BondDenom`
* the exchange rate is invalid, meaning the validator has no tokens (due to slashing) but there are outstanding shares
* the amount delegated is less than the minimum allowed delegation

If an existing `Delegation` object for provided addresses does not already exist then it is created as part of this message otherwise the existing `Delegation` is updated to include the newly received shares.

The delegator receives newly minted shares at the current exchange rate. The exchange rate is the number of existing shares in the validator divided by the number of currently delegated tokens.

The validator is updated in the `ValidatorByPower` index, and the delegation is tracked in validator object in the `Validators` index.

It is possible to delegate to a jailed validator, the only difference being it will not be added to the power index until it is unjailed.

### MsgUndelegate <a href="#msgundelegate" id="msgundelegate"></a>

The `MsgUndelegate` message allows delegators to undelegate their tokens from validator.

```protobuf
// Undelegate defines a method for performing an undelegation from a
// delegate and a validator.
rpc Undelegate(MsgUndelegate) returns (MsgUndelegateResponse);
```

```protobuf
// MsgUndelegate defines a SDK message for performing an undelegation from a
// delegate and a validator.
message MsgUndelegate {
  option (cosmos.msg.v1.signer) = "delegator_address";

  option (gogoproto.equal)           = false;
  option (gogoproto.goproto_getters) = false;

  string                   delegator_address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
  string                   validator_address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];
  cosmos.base.v1beta1.Coin amount            = 3 [(gogoproto.nullable) = false];
}
```

This message returns a response containing the completion time of the undelegation:

```protobuf
// MsgUndelegate defines a SDK message for performing an undelegation from a
// delegate and a validator.
message MsgUndelegate {
  option (cosmos.msg.v1.signer) = "delegator_address";

  option (gogoproto.equal)           = false;
  option (gogoproto.goproto_getters) = false;

  string                   delegator_address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
  string                   validator_address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];
  cosmos.base.v1beta1.Coin amount            = 3 [(gogoproto.nullable) = false];
}

// MsgUndelegateResponse defines the Msg/Undelegate response type.
message MsgUndelegateResponse {
  google.protobuf.Timestamp completion_time = 1 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
}
```

This message is expected to fail if:

* the delegation doesn't exist
* the validator doesn't exist
* the delegation has less shares than the ones worth of `Amount`
* existing `UnbondingDelegation` has maximum entries as defined by `params.MaxEntries`
* the `Amount` has a denomination different than one defined by `params.BondDenom`

When this message is processed the following actions occur:

* validator's `DelegatorShares` and the delegation's `Shares` are both reduced by the message `SharesAmount`
* calculate the token worth of the shares remove that amount tokens held within the validator
* with those removed tokens, if the validator is:
  * `Bonded` - add them to an entry in `UnbondingDelegation` (create `UnbondingDelegation` if it doesn't exist) with a completion time a full unbonding period from the current time. Update pool shares to reduce BondedTokens and increase NotBondedTokens by token worth of the shares.
  * `Unbonding` - add them to an entry in `UnbondingDelegation` (create `UnbondingDelegation` if it doesn't exist) with the same completion time as the validator (`UnbondingMinTime`).
  * `Unbonded` - then send the coins the message `DelegatorAddr`
* if there are no more `Shares` in the delegation, then the delegation object is removed from the store
  * under this situation if the delegation is the validator's self-delegation then also jail the validator.

### MsgCancelUnbondingDelegation <a href="#msgcancelunbondingdelegation" id="msgcancelunbondingdelegation"></a>

The `MsgCancelUnbondingDelegation` message allows delegators to cancel the `unbondingDelegation` entry and deleagate back to a previous validator.

```protobuf
// MsgCancelUnbondingDelegation defines the SDK message for performing a cancel unbonding delegation for delegator
//
// Since: cosmos-sdk 0.46
message MsgCancelUnbondingDelegation{
  option (cosmos.msg.v1.signer) = "delegator_address";
  option (gogoproto.equal)           = false;
  option (gogoproto.goproto_getters) = false;

  string                   delegator_address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
  string                   validator_address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];
  // amount is always less than or equal to unbonding delegation entry balance 
  cosmos.base.v1beta1.Coin amount            = 3 [(gogoproto.nullable) = false];
  // creation_height is the height which the unbonding took place.
  int64 creation_height = 4;
}

// MsgCancelUnbondingDelegationResponse
//
// Since: cosmos-sdk 0.46
message MsgCancelUnbondingDelegationResponse{}
```

This message is expected to fail if:

* the `unbondingDelegation` entry is already processed.
* the `cancel unbonding delegation` amount is greater than the `unbondingDelegation` entry balance.
* the `cancel unbonding delegation` height doesn't exists in the `unbondingDelegationQueue` of the delegator.

When this message is processed the following actions occur:

* if the `unbondingDelegation` Entry balance is zero
  * in this condition `unbondingDelegation` entry will be removed from `unbondingDelegationQueue`.
  * otherwise `unbondingDelegationQueue` will be updated with new `unbondingDelegation` entry balance and initial balance
* the validator's `DelegatorShares` and the delegation's `Shares` are both increased by the message `Amount`.

### MsgBeginRedelegate <a href="#msgbeginredelegate" id="msgbeginredelegate"></a>

The redelegation command allows delegators to instantly switch validators. Once the unbonding period has passed, the redelegation is automatically completed in the EndBlocker.

```protobuf
// BeginRedelegate defines a method for performing a redelegation
// of coins from a delegator and source validator to a destination validator.
rpc BeginRedelegate(MsgBeginRedelegate) returns (MsgBeginRedelegateResponse);
```

```protobuf
// MsgBeginRedelegate defines a SDK message for performing a redelegation
// of coins from a delegator and source validator to a destination validator.
message MsgBeginRedelegate {
  option (cosmos.msg.v1.signer) = "delegator_address";

  option (gogoproto.equal)           = false;
  option (gogoproto.goproto_getters) = false;

  string                   delegator_address     = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
  string                   validator_src_address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];
  string                   validator_dst_address = 3 [(cosmos_proto.scalar) = "cosmos.AddressString"];
  cosmos.base.v1beta1.Coin amount                = 4 [(gogoproto.nullable) = false];
}
```

This message returns a response containing the completion time of the redelegation:

```protobuf
// MsgBeginRedelegateResponse defines the Msg/BeginRedelegate response type.
message MsgBeginRedelegateResponse {
  google.protobuf.Timestamp completion_time = 1 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
}
```

This message is expected to fail if:

* the delegation doesn't exist
* the source or destination validators don't exist
* the delegation has less shares than the ones worth of `Amount`
* the source validator has a receiving redelegation which is not matured (aka. the redelegation may be transitive)
* existing `Redelegation` has maximum entries as defined by `params.MaxEntries`
* the `Amount` `Coin` has a denomination different than one defined by `params.BondDenom`

When this message is processed the following actions occur:

* the source validator's `DelegatorShares` and the delegations `Shares` are both reduced by the message `SharesAmount`
* calculate the token worth of the shares remove that amount tokens held within the source validator.
* if the source validator is:
  * `Bonded` - add an entry to the `Redelegation` (create `Redelegation` if it doesn't exist) with a completion time a full unbonding period from the current time. Update pool shares to reduce BondedTokens and increase NotBondedTokens by token worth of the shares (this may be effectively reversed in the next step however).
  * `Unbonding` - add an entry to the `Redelegation` (create `Redelegation` if it doesn't exist) with the same completion time as the validator (`UnbondingMinTime`).
  * `Unbonded` - no action required in this step
* Delegate the token worth to the destination validator, possibly moving tokens back to the bonded state.
* if there are no more `Shares` in the source delegation, then the source delegation object is removed from the store
  * under this situation if the delegation is the validator's self-delegation then also jail the validator.

### MsgUpdateParams <a href="#msgupdateparams" id="msgupdateparams"></a>

The `MsgUpdateParams` update the staking module parameters. The params are updated through a governance proposal where the signer is the gov module account address.

```protobuf
// MsgUpdateParams is the Msg/UpdateParams request type.
//
// Since: cosmos-sdk 0.47
message MsgUpdateParams {
  option (cosmos.msg.v1.signer) = "authority";

  // authority is the address of the governance account.
  string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
  // params defines the x/staking parameters to update.
  //
  // NOTE: All parameters must be supplied.
  Params params = 2 [(gogoproto.nullable) = false];
};

// MsgUpdateParamsResponse defines the response structure for executing a
// MsgUpdateParams message.
//
// Since: cosmos-sdk 0.47
message MsgUpdateParamsResponse {};
```

The message handling can fail if:

* signer is not the authority defined in the staking keeper (usually the gov module account).
