cosmos-sdk/x/staking/types/delegation.go

472 lines
16 KiB
Go

package types
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"time"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/staking/exported"
)
// DVPair is struct that just has a delegator-validator pair with no other data.
// It is intended to be used as a marshalable pointer. For example, a DVPair can be used to construct the
// key to getting an UnbondingDelegation from state.
type DVPair struct {
DelegatorAddress sdk.AccAddress
ValidatorAddress sdk.ValAddress
}
// DVVTriplet is struct that just has a delegator-validator-validator triplet with no other data.
// It is intended to be used as a marshalable pointer. For example, a DVVTriplet can be used to construct the
// key to getting a Redelegation from state.
type DVVTriplet struct {
DelegatorAddress sdk.AccAddress
ValidatorSrcAddress sdk.ValAddress
ValidatorDstAddress sdk.ValAddress
}
// Implements Delegation interface
var _ exported.DelegationI = Delegation{}
// Delegation represents the bond with tokens held by an account. It is
// owned by one delegator, and is associated with the voting power of one
// validator.
type Delegation struct {
DelegatorAddress sdk.AccAddress `json:"delegator_address" yaml:"delegator_address"`
ValidatorAddress sdk.ValAddress `json:"validator_address" yaml:"validator_address"`
Shares sdk.Dec `json:"shares" yaml:"shares"`
}
// NewDelegation creates a new delegation object
func NewDelegation(delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress,
shares sdk.Dec) Delegation {
return Delegation{
DelegatorAddress: delegatorAddr,
ValidatorAddress: validatorAddr,
Shares: shares,
}
}
// return the delegation
func MustMarshalDelegation(cdc *codec.Codec, delegation Delegation) []byte {
return cdc.MustMarshalBinaryLengthPrefixed(delegation)
}
// return the delegation
func MustUnmarshalDelegation(cdc *codec.Codec, value []byte) Delegation {
delegation, err := UnmarshalDelegation(cdc, value)
if err != nil {
panic(err)
}
return delegation
}
// return the delegation
func UnmarshalDelegation(cdc *codec.Codec, value []byte) (delegation Delegation, err error) {
err = cdc.UnmarshalBinaryLengthPrefixed(value, &delegation)
return delegation, err
}
// nolint
func (d Delegation) Equal(d2 Delegation) bool {
return bytes.Equal(d.DelegatorAddress, d2.DelegatorAddress) &&
bytes.Equal(d.ValidatorAddress, d2.ValidatorAddress) &&
d.Shares.Equal(d2.Shares)
}
// nolint - for Delegation
func (d Delegation) GetDelegatorAddr() sdk.AccAddress { return d.DelegatorAddress }
func (d Delegation) GetValidatorAddr() sdk.ValAddress { return d.ValidatorAddress }
func (d Delegation) GetShares() sdk.Dec { return d.Shares }
// String returns a human readable string representation of a Delegation.
func (d Delegation) String() string {
return fmt.Sprintf(`Delegation:
Delegator: %s
Validator: %s
Shares: %s`, d.DelegatorAddress,
d.ValidatorAddress, d.Shares)
}
// Delegations is a collection of delegations
type Delegations []Delegation
func (d Delegations) String() (out string) {
for _, del := range d {
out += del.String() + "\n"
}
return strings.TrimSpace(out)
}
// UnbondingDelegation stores all of a single delegator's unbonding bonds
// for a single validator in an time-ordered list
type UnbondingDelegation struct {
DelegatorAddress sdk.AccAddress `json:"delegator_address" yaml:"delegator_address"` // delegator
ValidatorAddress sdk.ValAddress `json:"validator_address" yaml:"validator_address"` // validator unbonding from operator addr
Entries []UnbondingDelegationEntry `json:"entries" yaml:"entries"` // unbonding delegation entries
}
// UnbondingDelegationEntry - entry to an UnbondingDelegation
type UnbondingDelegationEntry struct {
CreationHeight int64 `json:"creation_height" yaml:"creation_height"` // height which the unbonding took place
CompletionTime time.Time `json:"completion_time" yaml:"completion_time"` // time at which the unbonding delegation will complete
InitialBalance sdk.Int `json:"initial_balance" yaml:"initial_balance"` // atoms initially scheduled to receive at completion
Balance sdk.Int `json:"balance" yaml:"balance"` // atoms to receive at completion
}
// IsMature - is the current entry mature
func (e UnbondingDelegationEntry) IsMature(currentTime time.Time) bool {
return !e.CompletionTime.After(currentTime)
}
// NewUnbondingDelegation - create a new unbonding delegation object
func NewUnbondingDelegation(delegatorAddr sdk.AccAddress,
validatorAddr sdk.ValAddress, creationHeight int64, minTime time.Time,
balance sdk.Int) UnbondingDelegation {
entry := NewUnbondingDelegationEntry(creationHeight, minTime, balance)
return UnbondingDelegation{
DelegatorAddress: delegatorAddr,
ValidatorAddress: validatorAddr,
Entries: []UnbondingDelegationEntry{entry},
}
}
// NewUnbondingDelegation - create a new unbonding delegation object
func NewUnbondingDelegationEntry(creationHeight int64, completionTime time.Time,
balance sdk.Int) UnbondingDelegationEntry {
return UnbondingDelegationEntry{
CreationHeight: creationHeight,
CompletionTime: completionTime,
InitialBalance: balance,
Balance: balance,
}
}
// AddEntry - append entry to the unbonding delegation
func (d *UnbondingDelegation) AddEntry(creationHeight int64,
minTime time.Time, balance sdk.Int) {
entry := NewUnbondingDelegationEntry(creationHeight, minTime, balance)
d.Entries = append(d.Entries, entry)
}
// RemoveEntry - remove entry at index i to the unbonding delegation
func (d *UnbondingDelegation) RemoveEntry(i int64) {
d.Entries = append(d.Entries[:i], d.Entries[i+1:]...)
}
// return the unbonding delegation
func MustMarshalUBD(cdc *codec.Codec, ubd UnbondingDelegation) []byte {
return cdc.MustMarshalBinaryLengthPrefixed(ubd)
}
// unmarshal a unbonding delegation from a store value
func MustUnmarshalUBD(cdc *codec.Codec, value []byte) UnbondingDelegation {
ubd, err := UnmarshalUBD(cdc, value)
if err != nil {
panic(err)
}
return ubd
}
// unmarshal a unbonding delegation from a store value
func UnmarshalUBD(cdc *codec.Codec, value []byte) (ubd UnbondingDelegation, err error) {
err = cdc.UnmarshalBinaryLengthPrefixed(value, &ubd)
return ubd, err
}
// nolint
// inefficient but only used in testing
func (d UnbondingDelegation) Equal(d2 UnbondingDelegation) bool {
bz1 := ModuleCdc.MustMarshalBinaryLengthPrefixed(&d)
bz2 := ModuleCdc.MustMarshalBinaryLengthPrefixed(&d2)
return bytes.Equal(bz1, bz2)
}
// String returns a human readable string representation of an UnbondingDelegation.
func (d UnbondingDelegation) String() string {
out := fmt.Sprintf(`Unbonding Delegations between:
Delegator: %s
Validator: %s
Entries:`, d.DelegatorAddress, d.ValidatorAddress)
for i, entry := range d.Entries {
out += fmt.Sprintf(` Unbonding Delegation %d:
Creation Height: %v
Min time to unbond (unix): %v
Expected balance: %s`, i, entry.CreationHeight,
entry.CompletionTime, entry.Balance)
}
return out
}
// UnbondingDelegations is a collection of UnbondingDelegation
type UnbondingDelegations []UnbondingDelegation
func (ubds UnbondingDelegations) String() (out string) {
for _, u := range ubds {
out += u.String() + "\n"
}
return strings.TrimSpace(out)
}
// Redelegation contains the list of a particular delegator's
// redelegating bonds from a particular source validator to a
// particular destination validator
type Redelegation struct {
DelegatorAddress sdk.AccAddress `json:"delegator_address" yaml:"delegator_address"` // delegator
ValidatorSrcAddress sdk.ValAddress `json:"validator_src_address" yaml:"validator_src_address"` // validator redelegation source operator addr
ValidatorDstAddress sdk.ValAddress `json:"validator_dst_address" yaml:"validator_dst_address"` // validator redelegation destination operator addr
Entries []RedelegationEntry `json:"entries" yaml:"entries"` // redelegation entries
}
// RedelegationEntry - entry to a Redelegation
type RedelegationEntry struct {
CreationHeight int64 `json:"creation_height" yaml:"creation_height"` // height at which the redelegation took place
CompletionTime time.Time `json:"completion_time" yaml:"completion_time"` // time at which the redelegation will complete
InitialBalance sdk.Int `json:"initial_balance" yaml:"initial_balance"` // initial balance when redelegation started
SharesDst sdk.Dec `json:"shares_dst" yaml:"shares_dst"` // amount of destination-validator shares created by redelegation
}
// NewRedelegation - create a new redelegation object
func NewRedelegation(delegatorAddr sdk.AccAddress, validatorSrcAddr,
validatorDstAddr sdk.ValAddress, creationHeight int64,
minTime time.Time, balance sdk.Int,
sharesDst sdk.Dec) Redelegation {
entry := NewRedelegationEntry(creationHeight,
minTime, balance, sharesDst)
return Redelegation{
DelegatorAddress: delegatorAddr,
ValidatorSrcAddress: validatorSrcAddr,
ValidatorDstAddress: validatorDstAddr,
Entries: []RedelegationEntry{entry},
}
}
// NewRedelegation - create a new redelegation object
func NewRedelegationEntry(creationHeight int64,
completionTime time.Time, balance sdk.Int,
sharesDst sdk.Dec) RedelegationEntry {
return RedelegationEntry{
CreationHeight: creationHeight,
CompletionTime: completionTime,
InitialBalance: balance,
SharesDst: sharesDst,
}
}
// IsMature - is the current entry mature
func (e RedelegationEntry) IsMature(currentTime time.Time) bool {
return !e.CompletionTime.After(currentTime)
}
// AddEntry - append entry to the unbonding delegation
func (d *Redelegation) AddEntry(creationHeight int64,
minTime time.Time, balance sdk.Int,
sharesDst sdk.Dec) {
entry := NewRedelegationEntry(creationHeight, minTime, balance, sharesDst)
d.Entries = append(d.Entries, entry)
}
// RemoveEntry - remove entry at index i to the unbonding delegation
func (d *Redelegation) RemoveEntry(i int64) {
d.Entries = append(d.Entries[:i], d.Entries[i+1:]...)
}
// return the redelegation
func MustMarshalRED(cdc *codec.Codec, red Redelegation) []byte {
return cdc.MustMarshalBinaryLengthPrefixed(red)
}
// unmarshal a redelegation from a store value
func MustUnmarshalRED(cdc *codec.Codec, value []byte) Redelegation {
red, err := UnmarshalRED(cdc, value)
if err != nil {
panic(err)
}
return red
}
// unmarshal a redelegation from a store value
func UnmarshalRED(cdc *codec.Codec, value []byte) (red Redelegation, err error) {
err = cdc.UnmarshalBinaryLengthPrefixed(value, &red)
return red, err
}
// nolint
// inefficient but only used in tests
func (d Redelegation) Equal(d2 Redelegation) bool {
bz1 := ModuleCdc.MustMarshalBinaryLengthPrefixed(&d)
bz2 := ModuleCdc.MustMarshalBinaryLengthPrefixed(&d2)
return bytes.Equal(bz1, bz2)
}
// String returns a human readable string representation of a Redelegation.
func (d Redelegation) String() string {
out := fmt.Sprintf(`Redelegations between:
Delegator: %s
Source Validator: %s
Destination Validator: %s
Entries:
`,
d.DelegatorAddress, d.ValidatorSrcAddress, d.ValidatorDstAddress,
)
for i, entry := range d.Entries {
out += fmt.Sprintf(` Redelegation Entry #%d:
Creation height: %v
Min time to unbond (unix): %v
Dest Shares: %s
`,
i, entry.CreationHeight, entry.CompletionTime, entry.SharesDst,
)
}
return strings.TrimRight(out, "\n")
}
// Redelegations are a collection of Redelegation
type Redelegations []Redelegation
func (d Redelegations) String() (out string) {
for _, red := range d {
out += red.String() + "\n"
}
return strings.TrimSpace(out)
}
// ----------------------------------------------------------------------------
// Client Types
// DelegationResponse is equivalent to Delegation except that it contains a balance
// in addition to shares which is more suitable for client responses.
type DelegationResponse struct {
Delegation
Balance sdk.Coin `json:"balance" yaml:"balance"`
}
func NewDelegationResp(d sdk.AccAddress, v sdk.ValAddress, s sdk.Dec, b sdk.Coin) DelegationResponse {
return DelegationResponse{NewDelegation(d, v, s), b}
}
// String implements the Stringer interface for DelegationResponse.
func (d DelegationResponse) String() string {
return fmt.Sprintf("%s\n Balance: %s", d.Delegation.String(), d.Balance)
}
type delegationRespAlias DelegationResponse
// MarshalJSON implements the json.Marshaler interface. This is so we can
// achieve a flattened structure while embedding other types.
func (d DelegationResponse) MarshalJSON() ([]byte, error) {
return json.Marshal((delegationRespAlias)(d))
}
// UnmarshalJSON implements the json.Unmarshaler interface. This is so we can
// achieve a flattened structure while embedding other types.
func (d *DelegationResponse) UnmarshalJSON(bz []byte) error {
return json.Unmarshal(bz, (*delegationRespAlias)(d))
}
// DelegationResponses is a collection of DelegationResp
type DelegationResponses []DelegationResponse
// String implements the Stringer interface for DelegationResponses.
func (d DelegationResponses) String() (out string) {
for _, del := range d {
out += del.String() + "\n"
}
return strings.TrimSpace(out)
}
// RedelegationResponse is equivalent to a Redelegation except that its entries
// contain a balance in addition to shares which is more suitable for client
// responses.
type RedelegationResponse struct {
Redelegation
Entries []RedelegationEntryResponse `json:"entries" yaml:"entries"`
}
// RedelegationEntryResponse is equivalent to a RedelegationEntry except that it
// contains a balance in addition to shares which is more suitable for client
// responses.
type RedelegationEntryResponse struct {
RedelegationEntry
Balance sdk.Int `json:"balance"`
}
func NewRedelegationResponse(d sdk.AccAddress, vSrc, vDst sdk.ValAddress, entries []RedelegationEntryResponse) RedelegationResponse {
return RedelegationResponse{
Redelegation{
DelegatorAddress: d,
ValidatorSrcAddress: vSrc,
ValidatorDstAddress: vDst,
},
entries,
}
}
func NewRedelegationEntryResponse(ch int64, ct time.Time, s sdk.Dec, ib, b sdk.Int) RedelegationEntryResponse {
return RedelegationEntryResponse{NewRedelegationEntry(ch, ct, ib, s), b}
}
// String implements the Stringer interface for RedelegationResp.
func (r RedelegationResponse) String() string {
out := fmt.Sprintf(`Redelegations between:
Delegator: %s
Source Validator: %s
Destination Validator: %s
Entries:
`,
r.DelegatorAddress, r.ValidatorSrcAddress, r.ValidatorDstAddress,
)
for i, entry := range r.Entries {
out += fmt.Sprintf(` Redelegation Entry #%d:
Creation height: %v
Min time to unbond (unix): %v
Initial Balance: %s
Shares: %s
Balance: %s
`,
i, entry.CreationHeight, entry.CompletionTime, entry.InitialBalance, entry.SharesDst, entry.Balance,
)
}
return strings.TrimRight(out, "\n")
}
type redelegationRespAlias RedelegationResponse
// MarshalJSON implements the json.Marshaler interface. This is so we can
// achieve a flattened structure while embedding other types.
func (r RedelegationResponse) MarshalJSON() ([]byte, error) {
return json.Marshal((redelegationRespAlias)(r))
}
// UnmarshalJSON implements the json.Unmarshaler interface. This is so we can
// achieve a flattened structure while embedding other types.
func (r *RedelegationResponse) UnmarshalJSON(bz []byte) error {
return json.Unmarshal(bz, (*redelegationRespAlias)(r))
}
// RedelegationResponses are a collection of RedelegationResp
type RedelegationResponses []RedelegationResponse
func (r RedelegationResponses) String() (out string) {
for _, red := range r {
out += red.String() + "\n"
}
return strings.TrimSpace(out)
}