2018-06-26 19:00:12 -07:00
|
|
|
package types
|
2018-01-25 19:31:07 -08:00
|
|
|
|
|
|
|
import (
|
2018-04-30 23:07:06 -07:00
|
|
|
"bytes"
|
2018-05-26 14:21:29 -07:00
|
|
|
"fmt"
|
2019-12-18 05:20:02 -08:00
|
|
|
"sort"
|
2019-01-22 09:28:39 -08:00
|
|
|
"strings"
|
2018-08-24 18:47:31 -07:00
|
|
|
"time"
|
2018-04-30 23:07:06 -07:00
|
|
|
|
2018-06-28 17:54:47 -07:00
|
|
|
abci "github.com/tendermint/tendermint/abci/types"
|
2020-11-09 08:01:43 -08:00
|
|
|
tmprotocrypto "github.com/tendermint/tendermint/proto/tendermint/crypto"
|
2020-08-28 09:02:38 -07:00
|
|
|
"gopkg.in/yaml.v2"
|
2018-06-26 19:00:12 -07:00
|
|
|
|
2018-09-13 11:17:32 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/codec"
|
2020-10-23 05:07:52 -07:00
|
|
|
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
2020-11-09 08:01:43 -08:00
|
|
|
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
|
2020-09-25 01:41:16 -07:00
|
|
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
2018-06-26 19:00:12 -07:00
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
2019-12-27 09:57:54 -08:00
|
|
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
2018-01-25 19:31:07 -08:00
|
|
|
)
|
|
|
|
|
2019-02-07 17:41:23 -08:00
|
|
|
const (
|
|
|
|
// TODO: Why can't we just have one string description which can be JSON by convention
|
2019-08-12 06:10:16 -07:00
|
|
|
MaxMonikerLength = 70
|
|
|
|
MaxIdentityLength = 3000
|
|
|
|
MaxWebsiteLength = 140
|
|
|
|
MaxSecurityContactLength = 140
|
|
|
|
MaxDetailsLength = 280
|
2019-02-07 17:41:23 -08:00
|
|
|
)
|
|
|
|
|
2020-10-12 06:56:02 -07:00
|
|
|
var (
|
|
|
|
BondStatusUnspecified = BondStatus_name[int32(Unspecified)]
|
|
|
|
BondStatusUnbonded = BondStatus_name[int32(Unbonded)]
|
|
|
|
BondStatusUnbonding = BondStatus_name[int32(Unbonding)]
|
|
|
|
BondStatusBonded = BondStatus_name[int32(Bonded)]
|
|
|
|
)
|
|
|
|
|
|
|
|
var _ ValidatorI = Validator{}
|
2019-06-04 15:06:58 -07:00
|
|
|
|
2020-09-25 03:25:37 -07:00
|
|
|
// NewValidator constructs a new Validator
|
|
|
|
//nolint:interfacer
|
2020-11-09 08:01:43 -08:00
|
|
|
func NewValidator(operator sdk.ValAddress, pubKey cryptotypes.PubKey, description Description) (Validator, error) {
|
2020-12-18 06:55:25 -08:00
|
|
|
pkAny, err := codectypes.NewAnyWithValue(pubKey)
|
2020-10-23 05:07:52 -07:00
|
|
|
if err != nil {
|
|
|
|
return Validator{}, err
|
2020-02-06 11:21:02 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return Validator{
|
2020-09-25 03:25:37 -07:00
|
|
|
OperatorAddress: operator.String(),
|
2020-10-23 05:07:52 -07:00
|
|
|
ConsensusPubkey: pkAny,
|
2020-02-06 11:21:02 -08:00
|
|
|
Jailed: false,
|
2020-10-12 06:56:02 -07:00
|
|
|
Status: Unbonded,
|
2020-02-06 11:21:02 -08:00
|
|
|
Tokens: sdk.ZeroInt(),
|
|
|
|
DelegatorShares: sdk.ZeroDec(),
|
|
|
|
Description: description,
|
|
|
|
UnbondingHeight: int64(0),
|
|
|
|
UnbondingTime: time.Unix(0, 0).UTC(),
|
|
|
|
Commission: NewCommission(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()),
|
|
|
|
MinSelfDelegation: sdk.OneInt(),
|
2020-10-23 05:07:52 -07:00
|
|
|
}, nil
|
2020-02-06 11:21:02 -08:00
|
|
|
}
|
2019-06-08 11:00:36 -07:00
|
|
|
|
2020-02-06 11:21:02 -08:00
|
|
|
// String implements the Stringer interface for a Validator object.
|
|
|
|
func (v Validator) String() string {
|
|
|
|
out, _ := yaml.Marshal(v)
|
|
|
|
return string(out)
|
2019-06-08 11:00:36 -07:00
|
|
|
}
|
|
|
|
|
2019-01-22 09:28:39 -08:00
|
|
|
// Validators is a collection of Validator
|
|
|
|
type Validators []Validator
|
|
|
|
|
|
|
|
func (v Validators) String() (out string) {
|
|
|
|
for _, val := range v {
|
|
|
|
out += val.String() + "\n"
|
|
|
|
}
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2019-01-22 09:28:39 -08:00
|
|
|
return strings.TrimSpace(out)
|
|
|
|
}
|
|
|
|
|
2020-11-09 08:01:43 -08:00
|
|
|
// ToSDKValidators - convenience function convert []Validator to []sdk.ValidatorI
|
2020-10-12 06:56:02 -07:00
|
|
|
func (v Validators) ToSDKValidators() (validators []ValidatorI) {
|
2019-02-13 15:01:50 -08:00
|
|
|
for _, val := range v {
|
|
|
|
validators = append(validators, val)
|
|
|
|
}
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2019-02-13 15:01:50 -08:00
|
|
|
return validators
|
|
|
|
}
|
|
|
|
|
2019-12-18 05:20:02 -08:00
|
|
|
// Sort Validators sorts validator array in ascending operator address order
|
|
|
|
func (v Validators) Sort() {
|
|
|
|
sort.Sort(v)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Implements sort interface
|
|
|
|
func (v Validators) Len() int {
|
|
|
|
return len(v)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Implements sort interface
|
|
|
|
func (v Validators) Less(i, j int) bool {
|
2020-09-25 03:25:37 -07:00
|
|
|
return bytes.Compare(v[i].GetOperator().Bytes(), v[j].GetOperator().Bytes()) == -1
|
2019-12-18 05:20:02 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Implements sort interface
|
|
|
|
func (v Validators) Swap(i, j int) {
|
|
|
|
it := v[i]
|
|
|
|
v[i] = v[j]
|
|
|
|
v[j] = it
|
|
|
|
}
|
|
|
|
|
2020-10-29 05:17:37 -07:00
|
|
|
// ValidatorsByVotingPower implements sort.Interface for []Validator based on
|
|
|
|
// the VotingPower and Address fields.
|
|
|
|
// The validators are sorted first by their voting power (descending). Secondary index - Address (ascending).
|
|
|
|
// Copied from tendermint/types/validator_set.go
|
|
|
|
type ValidatorsByVotingPower []Validator
|
|
|
|
|
|
|
|
func (valz ValidatorsByVotingPower) Len() int { return len(valz) }
|
|
|
|
|
|
|
|
func (valz ValidatorsByVotingPower) Less(i, j int) bool {
|
|
|
|
if valz[i].ConsensusPower() == valz[j].ConsensusPower() {
|
|
|
|
addrI, errI := valz[i].GetConsAddr()
|
|
|
|
addrJ, errJ := valz[j].GetConsAddr()
|
|
|
|
// If either returns error, then return false
|
|
|
|
if errI != nil || errJ != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return bytes.Compare(addrI, addrJ) == -1
|
|
|
|
}
|
|
|
|
return valz[i].ConsensusPower() > valz[j].ConsensusPower()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (valz ValidatorsByVotingPower) Swap(i, j int) {
|
|
|
|
valz[i], valz[j] = valz[j], valz[i]
|
|
|
|
}
|
|
|
|
|
2020-10-23 05:07:52 -07:00
|
|
|
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
|
|
|
|
func (v Validators) UnpackInterfaces(c codectypes.AnyUnpacker) error {
|
|
|
|
for i := range v {
|
|
|
|
if err := v[i].UnpackInterfaces(c); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-01-07 12:42:52 -08:00
|
|
|
// return the redelegation
|
2020-10-23 05:07:52 -07:00
|
|
|
func MustMarshalValidator(cdc codec.BinaryMarshaler, validator *Validator) []byte {
|
|
|
|
return cdc.MustMarshalBinaryBare(validator)
|
2018-07-03 22:32:49 -07:00
|
|
|
}
|
|
|
|
|
2019-01-07 12:42:52 -08:00
|
|
|
// unmarshal a redelegation from a store value
|
2020-07-25 01:03:58 -07:00
|
|
|
func MustUnmarshalValidator(cdc codec.BinaryMarshaler, value []byte) Validator {
|
2019-01-07 12:42:52 -08:00
|
|
|
validator, err := UnmarshalValidator(cdc, value)
|
2018-07-04 14:07:06 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2018-07-04 14:07:06 -07:00
|
|
|
return validator
|
|
|
|
}
|
|
|
|
|
2019-01-07 12:42:52 -08:00
|
|
|
// unmarshal a redelegation from a store value
|
2020-07-25 01:03:58 -07:00
|
|
|
func UnmarshalValidator(cdc codec.BinaryMarshaler, value []byte) (v Validator, err error) {
|
2020-03-13 12:58:43 -07:00
|
|
|
err = cdc.UnmarshalBinaryBare(value, &v)
|
2020-02-06 11:21:02 -08:00
|
|
|
return v, err
|
2018-08-31 17:01:23 -07:00
|
|
|
}
|
|
|
|
|
2019-06-04 15:06:58 -07:00
|
|
|
// IsBonded checks if the validator status equals Bonded
|
|
|
|
func (v Validator) IsBonded() bool {
|
2020-10-12 06:56:02 -07:00
|
|
|
return v.GetStatus() == Bonded
|
2019-06-04 15:06:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// IsUnbonded checks if the validator status equals Unbonded
|
|
|
|
func (v Validator) IsUnbonded() bool {
|
2020-10-12 06:56:02 -07:00
|
|
|
return v.GetStatus() == Unbonded
|
2019-06-04 15:06:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// IsUnbonding checks if the validator status equals Unbonding
|
|
|
|
func (v Validator) IsUnbonding() bool {
|
2020-10-12 06:56:02 -07:00
|
|
|
return v.GetStatus() == Unbonding
|
2019-06-04 15:06:58 -07:00
|
|
|
}
|
|
|
|
|
2018-07-26 10:41:34 -07:00
|
|
|
// constant used in flags to indicate that description field should not be updated
|
|
|
|
const DoNotModifyDesc = "[do-not-modify]"
|
|
|
|
|
2019-08-12 06:10:16 -07:00
|
|
|
func NewDescription(moniker, identity, website, securityContact, details string) Description {
|
2018-03-26 07:48:15 -07:00
|
|
|
return Description{
|
2019-08-12 06:10:16 -07:00
|
|
|
Moniker: moniker,
|
|
|
|
Identity: identity,
|
|
|
|
Website: website,
|
|
|
|
SecurityContact: securityContact,
|
|
|
|
Details: details,
|
2018-03-26 07:48:15 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-06 11:21:02 -08:00
|
|
|
// String implements the Stringer interface for a Description object.
|
|
|
|
func (d Description) String() string {
|
|
|
|
out, _ := yaml.Marshal(d)
|
|
|
|
return string(out)
|
|
|
|
}
|
|
|
|
|
2018-07-03 21:21:36 -07:00
|
|
|
// UpdateDescription updates the fields of a given description. An error is
|
|
|
|
// returned if the resulting description contains an invalid length.
|
2019-12-27 09:57:54 -08:00
|
|
|
func (d Description) UpdateDescription(d2 Description) (Description, error) {
|
2018-07-26 10:41:34 -07:00
|
|
|
if d2.Moniker == DoNotModifyDesc {
|
2018-06-26 19:00:12 -07:00
|
|
|
d2.Moniker = d.Moniker
|
|
|
|
}
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2018-07-26 10:41:34 -07:00
|
|
|
if d2.Identity == DoNotModifyDesc {
|
2018-06-26 19:00:12 -07:00
|
|
|
d2.Identity = d.Identity
|
|
|
|
}
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2018-07-26 10:41:34 -07:00
|
|
|
if d2.Website == DoNotModifyDesc {
|
2018-06-26 19:00:12 -07:00
|
|
|
d2.Website = d.Website
|
|
|
|
}
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2019-08-12 06:10:16 -07:00
|
|
|
if d2.SecurityContact == DoNotModifyDesc {
|
|
|
|
d2.SecurityContact = d.SecurityContact
|
|
|
|
}
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2018-07-26 10:41:34 -07:00
|
|
|
if d2.Details == DoNotModifyDesc {
|
2018-06-26 19:00:12 -07:00
|
|
|
d2.Details = d.Details
|
|
|
|
}
|
2018-07-03 21:21:36 -07:00
|
|
|
|
2019-08-12 06:10:16 -07:00
|
|
|
return NewDescription(
|
|
|
|
d2.Moniker,
|
|
|
|
d2.Identity,
|
|
|
|
d2.Website,
|
|
|
|
d2.SecurityContact,
|
|
|
|
d2.Details,
|
|
|
|
).EnsureLength()
|
2018-06-26 19:00:12 -07:00
|
|
|
}
|
|
|
|
|
2018-07-03 21:21:36 -07:00
|
|
|
// EnsureLength ensures the length of a validator's description.
|
2019-12-27 09:57:54 -08:00
|
|
|
func (d Description) EnsureLength() (Description, error) {
|
2019-02-07 17:41:23 -08:00
|
|
|
if len(d.Moniker) > MaxMonikerLength {
|
2019-12-27 09:57:54 -08:00
|
|
|
return d, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid moniker length; got: %d, max: %d", len(d.Moniker), MaxMonikerLength)
|
2018-06-26 19:00:12 -07:00
|
|
|
}
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2019-02-07 17:41:23 -08:00
|
|
|
if len(d.Identity) > MaxIdentityLength {
|
2019-12-27 09:57:54 -08:00
|
|
|
return d, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid identity length; got: %d, max: %d", len(d.Identity), MaxIdentityLength)
|
2018-06-26 19:00:12 -07:00
|
|
|
}
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2019-02-07 17:41:23 -08:00
|
|
|
if len(d.Website) > MaxWebsiteLength {
|
2019-12-27 09:57:54 -08:00
|
|
|
return d, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid website length; got: %d, max: %d", len(d.Website), MaxWebsiteLength)
|
2018-06-26 19:00:12 -07:00
|
|
|
}
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2019-08-12 06:10:16 -07:00
|
|
|
if len(d.SecurityContact) > MaxSecurityContactLength {
|
2019-12-27 09:57:54 -08:00
|
|
|
return d, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid security contact length; got: %d, max: %d", len(d.SecurityContact), MaxSecurityContactLength)
|
2019-08-12 06:10:16 -07:00
|
|
|
}
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2019-02-07 17:41:23 -08:00
|
|
|
if len(d.Details) > MaxDetailsLength {
|
2019-12-27 09:57:54 -08:00
|
|
|
return d, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid details length; got: %d, max: %d", len(d.Details), MaxDetailsLength)
|
2018-06-26 19:00:12 -07:00
|
|
|
}
|
2018-07-03 21:21:36 -07:00
|
|
|
|
2018-06-26 19:00:12 -07:00
|
|
|
return d, nil
|
|
|
|
}
|
2018-05-12 15:54:50 -07:00
|
|
|
|
2019-02-07 17:41:23 -08:00
|
|
|
// ABCIValidatorUpdate returns an abci.ValidatorUpdate from a staking validator type
|
2018-10-03 08:48:23 -07:00
|
|
|
// with the full validator power
|
|
|
|
func (v Validator) ABCIValidatorUpdate() abci.ValidatorUpdate {
|
2020-11-09 08:01:43 -08:00
|
|
|
tmProtoPk, err := v.TmConsPublicKey()
|
2020-08-14 10:58:53 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2018-10-03 08:48:23 -07:00
|
|
|
return abci.ValidatorUpdate{
|
2020-11-09 08:01:43 -08:00
|
|
|
PubKey: tmProtoPk,
|
2019-06-12 08:57:47 -07:00
|
|
|
Power: v.ConsensusPower(),
|
2018-04-04 20:22:13 -07:00
|
|
|
}
|
2018-01-31 18:56:46 -08:00
|
|
|
}
|
|
|
|
|
2019-02-07 17:41:23 -08:00
|
|
|
// ABCIValidatorUpdateZero returns an abci.ValidatorUpdate from a staking validator type
|
2018-10-03 08:48:23 -07:00
|
|
|
// with zero power used for validator updates.
|
|
|
|
func (v Validator) ABCIValidatorUpdateZero() abci.ValidatorUpdate {
|
2020-11-09 08:01:43 -08:00
|
|
|
tmProtoPk, err := v.TmConsPublicKey()
|
2020-08-14 10:58:53 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2018-10-03 08:48:23 -07:00
|
|
|
return abci.ValidatorUpdate{
|
2020-11-09 08:01:43 -08:00
|
|
|
PubKey: tmProtoPk,
|
2018-10-03 08:48:23 -07:00
|
|
|
Power: 0,
|
2018-04-05 09:31:36 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-24 15:23:58 -07:00
|
|
|
// SetInitialCommission attempts to set a validator's initial commission. An
|
|
|
|
// error is returned if the commission is invalid.
|
2019-12-27 09:57:54 -08:00
|
|
|
func (v Validator) SetInitialCommission(commission Commission) (Validator, error) {
|
2018-09-24 15:23:58 -07:00
|
|
|
if err := commission.Validate(); err != nil {
|
|
|
|
return v, err
|
|
|
|
}
|
|
|
|
|
|
|
|
v.Commission = commission
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2018-09-24 15:23:58 -07:00
|
|
|
return v, nil
|
|
|
|
}
|
|
|
|
|
2019-03-06 10:54:12 -08:00
|
|
|
// In some situations, the exchange rate becomes invalid, e.g. if
|
|
|
|
// Validator loses all tokens due to slashing. In this case,
|
|
|
|
// make all future delegations invalid.
|
|
|
|
func (v Validator) InvalidExRate() bool {
|
|
|
|
return v.Tokens.IsZero() && v.DelegatorShares.IsPositive()
|
|
|
|
}
|
|
|
|
|
|
|
|
// calculate the token worth of provided shares
|
2019-03-25 14:13:02 -07:00
|
|
|
func (v Validator) TokensFromShares(shares sdk.Dec) sdk.Dec {
|
2019-03-06 10:54:12 -08:00
|
|
|
return (shares.MulInt(v.Tokens)).Quo(v.DelegatorShares)
|
|
|
|
}
|
|
|
|
|
|
|
|
// calculate the token worth of provided shares, truncated
|
2019-03-25 14:13:02 -07:00
|
|
|
func (v Validator) TokensFromSharesTruncated(shares sdk.Dec) sdk.Dec {
|
2019-03-06 10:54:12 -08:00
|
|
|
return (shares.MulInt(v.Tokens)).QuoTruncate(v.DelegatorShares)
|
2018-07-13 13:46:14 -07:00
|
|
|
}
|
2018-07-03 21:21:36 -07:00
|
|
|
|
2019-04-10 15:53:42 -07:00
|
|
|
// TokensFromSharesRoundUp returns the token worth of provided shares, rounded
|
|
|
|
// up.
|
|
|
|
func (v Validator) TokensFromSharesRoundUp(shares sdk.Dec) sdk.Dec {
|
|
|
|
return (shares.MulInt(v.Tokens)).QuoRoundUp(v.DelegatorShares)
|
|
|
|
}
|
|
|
|
|
2019-03-25 14:13:02 -07:00
|
|
|
// SharesFromTokens returns the shares of a delegation given a bond amount. It
|
|
|
|
// returns an error if the validator has no tokens.
|
2019-12-27 09:57:54 -08:00
|
|
|
func (v Validator) SharesFromTokens(amt sdk.Int) (sdk.Dec, error) {
|
2019-03-25 14:13:02 -07:00
|
|
|
if v.Tokens.IsZero() {
|
2019-12-27 09:57:54 -08:00
|
|
|
return sdk.ZeroDec(), ErrInsufficientShares
|
2019-03-25 14:13:02 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return v.GetDelegatorShares().MulInt(amt).QuoInt(v.GetTokens()), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// SharesFromTokensTruncated returns the truncated shares of a delegation given
|
|
|
|
// a bond amount. It returns an error if the validator has no tokens.
|
2019-12-27 09:57:54 -08:00
|
|
|
func (v Validator) SharesFromTokensTruncated(amt sdk.Int) (sdk.Dec, error) {
|
2019-03-25 14:13:02 -07:00
|
|
|
if v.Tokens.IsZero() {
|
2019-12-27 09:57:54 -08:00
|
|
|
return sdk.ZeroDec(), ErrInsufficientShares
|
2019-03-25 14:13:02 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return v.GetDelegatorShares().MulInt(amt).QuoTruncate(v.GetTokens().ToDec()), nil
|
|
|
|
}
|
|
|
|
|
2019-02-05 21:30:48 -08:00
|
|
|
// get the bonded tokens which the validator holds
|
2019-01-02 12:29:47 -08:00
|
|
|
func (v Validator) BondedTokens() sdk.Int {
|
2019-06-04 15:06:58 -07:00
|
|
|
if v.IsBonded() {
|
2018-07-13 13:46:14 -07:00
|
|
|
return v.Tokens
|
|
|
|
}
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2019-01-02 12:29:47 -08:00
|
|
|
return sdk.ZeroInt()
|
2018-05-15 21:41:21 -07:00
|
|
|
}
|
|
|
|
|
2020-11-09 08:01:43 -08:00
|
|
|
// ConsensusPower gets the consensus-engine power. Aa reduction of 10^6 from
|
|
|
|
// validator tokens is applied
|
2019-06-12 08:57:47 -07:00
|
|
|
func (v Validator) ConsensusPower() int64 {
|
2019-06-04 15:06:58 -07:00
|
|
|
if v.IsBonded() {
|
2019-06-12 08:57:47 -07:00
|
|
|
return v.PotentialConsensusPower()
|
2019-02-05 21:30:48 -08:00
|
|
|
}
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2019-02-05 21:30:48 -08:00
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
2020-11-09 08:01:43 -08:00
|
|
|
// PotentialConsensusPower returns the potential consensus-engine power.
|
2019-06-12 08:57:47 -07:00
|
|
|
func (v Validator) PotentialConsensusPower() int64 {
|
|
|
|
return sdk.TokensToConsensusPower(v.Tokens)
|
2019-02-05 21:30:48 -08:00
|
|
|
}
|
|
|
|
|
2019-06-28 13:11:27 -07:00
|
|
|
// UpdateStatus updates the location of the shares within a validator
|
|
|
|
// to reflect the new status
|
2020-10-12 06:56:02 -07:00
|
|
|
func (v Validator) UpdateStatus(newStatus BondStatus) Validator {
|
2019-06-28 13:11:27 -07:00
|
|
|
v.Status = newStatus
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddTokensFromDel adds tokens to a validator
|
|
|
|
func (v Validator) AddTokensFromDel(amount sdk.Int) (Validator, sdk.Dec) {
|
|
|
|
// calculate the shares to issue
|
|
|
|
var issuedShares sdk.Dec
|
|
|
|
if v.DelegatorShares.IsZero() {
|
|
|
|
// the first delegation to a validator sets the exchange rate to one
|
|
|
|
issuedShares = amount.ToDec()
|
|
|
|
} else {
|
|
|
|
shares, err := v.SharesFromTokens(amount)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
issuedShares = shares
|
|
|
|
}
|
|
|
|
|
|
|
|
v.Tokens = v.Tokens.Add(amount)
|
|
|
|
v.DelegatorShares = v.DelegatorShares.Add(issuedShares)
|
|
|
|
|
|
|
|
return v, issuedShares
|
|
|
|
}
|
|
|
|
|
|
|
|
// RemoveTokens removes tokens from a validator
|
|
|
|
func (v Validator) RemoveTokens(tokens sdk.Int) Validator {
|
|
|
|
if tokens.IsNegative() {
|
|
|
|
panic(fmt.Sprintf("should not happen: trying to remove negative tokens %v", tokens))
|
|
|
|
}
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2019-06-28 13:11:27 -07:00
|
|
|
if v.Tokens.LT(tokens) {
|
|
|
|
panic(fmt.Sprintf("should not happen: only have %v tokens, trying to remove %v", v.Tokens, tokens))
|
|
|
|
}
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2019-06-28 13:11:27 -07:00
|
|
|
v.Tokens = v.Tokens.Sub(tokens)
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2019-06-28 13:11:27 -07:00
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
// RemoveDelShares removes delegator shares from a validator.
|
|
|
|
// NOTE: because token fractions are left in the valiadator,
|
|
|
|
// the exchange rate of future shares of this validator can increase.
|
|
|
|
func (v Validator) RemoveDelShares(delShares sdk.Dec) (Validator, sdk.Int) {
|
|
|
|
remainingShares := v.DelegatorShares.Sub(delShares)
|
2020-02-06 11:21:02 -08:00
|
|
|
|
2019-06-28 13:11:27 -07:00
|
|
|
var issuedTokens sdk.Int
|
|
|
|
if remainingShares.IsZero() {
|
|
|
|
// last delegation share gets any trimmings
|
|
|
|
issuedTokens = v.Tokens
|
|
|
|
v.Tokens = sdk.ZeroInt()
|
|
|
|
} else {
|
|
|
|
// leave excess tokens in the validator
|
|
|
|
// however fully use all the delegator shares
|
|
|
|
issuedTokens = v.TokensFromShares(delShares).TruncateInt()
|
|
|
|
v.Tokens = v.Tokens.Sub(issuedTokens)
|
2020-02-06 11:21:02 -08:00
|
|
|
|
2019-06-28 13:11:27 -07:00
|
|
|
if v.Tokens.IsNegative() {
|
|
|
|
panic("attempting to remove more tokens than available in validator")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
v.DelegatorShares = remainingShares
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2019-06-28 13:11:27 -07:00
|
|
|
return v, issuedTokens
|
|
|
|
}
|
|
|
|
|
2020-02-06 11:21:02 -08:00
|
|
|
// MinEqual defines a more minimum set of equality conditions when comparing two
|
|
|
|
// validators.
|
2020-10-23 05:07:52 -07:00
|
|
|
func (v *Validator) MinEqual(other *Validator) bool {
|
|
|
|
return v.OperatorAddress == other.OperatorAddress &&
|
2020-10-12 06:56:02 -07:00
|
|
|
v.Status == other.Status &&
|
2020-02-06 11:21:02 -08:00
|
|
|
v.Tokens.Equal(other.Tokens) &&
|
|
|
|
v.DelegatorShares.Equal(other.DelegatorShares) &&
|
2020-10-23 05:07:52 -07:00
|
|
|
v.Description.Equal(other.Description) &&
|
|
|
|
v.Commission.Equal(other.Commission) &&
|
|
|
|
v.Jailed == other.Jailed &&
|
|
|
|
v.MinSelfDelegation.Equal(other.MinSelfDelegation) &&
|
|
|
|
v.ConsensusPubkey.Equal(other.ConsensusPubkey)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Equal checks if the receiver equals the parameter
|
|
|
|
func (v *Validator) Equal(v2 *Validator) bool {
|
|
|
|
return v.MinEqual(v2) &&
|
|
|
|
v.UnbondingHeight == v2.UnbondingHeight &&
|
|
|
|
v.UnbondingTime.Equal(v2.UnbondingTime)
|
2020-02-06 11:21:02 -08:00
|
|
|
}
|
|
|
|
|
2020-10-12 06:56:02 -07:00
|
|
|
func (v Validator) IsJailed() bool { return v.Jailed }
|
|
|
|
func (v Validator) GetMoniker() string { return v.Description.Moniker }
|
|
|
|
func (v Validator) GetStatus() BondStatus { return v.Status }
|
2020-09-25 03:25:37 -07:00
|
|
|
func (v Validator) GetOperator() sdk.ValAddress {
|
|
|
|
if v.OperatorAddress == "" {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
addr, err := sdk.ValAddressFromBech32(v.OperatorAddress)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return addr
|
|
|
|
}
|
2020-10-23 05:07:52 -07:00
|
|
|
|
2020-11-09 08:01:43 -08:00
|
|
|
// ConsPubKey returns the validator PubKey as a cryptotypes.PubKey.
|
|
|
|
func (v Validator) ConsPubKey() (cryptotypes.PubKey, error) {
|
2020-10-23 05:07:52 -07:00
|
|
|
pk, ok := v.ConsensusPubkey.GetCachedValue().(cryptotypes.PubKey)
|
|
|
|
if !ok {
|
2020-11-09 08:01:43 -08:00
|
|
|
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "expecting cryptotypes.PubKey, got %T", pk)
|
|
|
|
}
|
|
|
|
|
|
|
|
return pk, nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// TmConsPublicKey casts Validator.ConsensusPubkey to tmprotocrypto.PubKey.
|
|
|
|
func (v Validator) TmConsPublicKey() (tmprotocrypto.PublicKey, error) {
|
|
|
|
pk, err := v.ConsPubKey()
|
|
|
|
if err != nil {
|
|
|
|
return tmprotocrypto.PublicKey{}, err
|
2020-10-23 05:07:52 -07:00
|
|
|
}
|
|
|
|
|
2020-11-09 08:01:43 -08:00
|
|
|
tmPk, err := cryptocodec.ToTmProtoPublicKey(pk)
|
|
|
|
if err != nil {
|
|
|
|
return tmprotocrypto.PublicKey{}, err
|
2020-09-25 01:41:16 -07:00
|
|
|
}
|
2020-11-09 08:01:43 -08:00
|
|
|
|
|
|
|
return tmPk, nil
|
2020-10-23 05:07:52 -07:00
|
|
|
}
|
2020-09-25 01:41:16 -07:00
|
|
|
|
2020-10-23 05:07:52 -07:00
|
|
|
// GetConsAddr extracts Consensus key address
|
|
|
|
func (v Validator) GetConsAddr() (sdk.ConsAddress, error) {
|
2020-11-09 08:01:43 -08:00
|
|
|
pk, ok := v.ConsensusPubkey.GetCachedValue().(cryptotypes.PubKey)
|
|
|
|
if !ok {
|
|
|
|
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "expecting cryptotypes.PubKey, got %T", pk)
|
2020-10-23 05:07:52 -07:00
|
|
|
}
|
2020-11-09 08:01:43 -08:00
|
|
|
|
2020-10-23 05:07:52 -07:00
|
|
|
return sdk.ConsAddress(pk.Address()), nil
|
2020-02-06 11:21:02 -08:00
|
|
|
}
|
2020-10-23 05:07:52 -07:00
|
|
|
|
2019-03-06 10:54:12 -08:00
|
|
|
func (v Validator) GetTokens() sdk.Int { return v.Tokens }
|
|
|
|
func (v Validator) GetBondedTokens() sdk.Int { return v.BondedTokens() }
|
2019-06-12 08:57:47 -07:00
|
|
|
func (v Validator) GetConsensusPower() int64 { return v.ConsensusPower() }
|
2019-03-06 10:54:12 -08:00
|
|
|
func (v Validator) GetCommission() sdk.Dec { return v.Commission.Rate }
|
|
|
|
func (v Validator) GetMinSelfDelegation() sdk.Int { return v.MinSelfDelegation }
|
|
|
|
func (v Validator) GetDelegatorShares() sdk.Dec { return v.DelegatorShares }
|
2020-10-23 05:07:52 -07:00
|
|
|
|
|
|
|
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
|
|
|
|
func (v Validator) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
|
2020-11-09 08:01:43 -08:00
|
|
|
var pk cryptotypes.PubKey
|
2020-10-23 05:07:52 -07:00
|
|
|
return unpacker.UnpackAny(v.ConsensusPubkey, &pk)
|
|
|
|
}
|