Merge branch 'develop' into cwgoes/slashing-period-spec
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
## Vesting
|
||||
|
||||
### Intro and Requirements
|
||||
|
||||
This paper specifies vesting account implementation for the Cosmos Hub.
|
||||
The requirements for this vesting account is that it should be initialized during genesis with
|
||||
a starting balance X coins and a vesting endtime T. The owner of this account should be able to delegate to validators
|
||||
and vote with locked coins, however they cannot send locked coins to other accounts until those coins have been unlocked.
|
||||
The vesting account should also be able to spend any coins it receives from other users.
|
||||
Thus, the bank module's `MsgSend` handler should error if a vesting account is trying to send an amount that exceeds their
|
||||
unlocked coin amount.
|
||||
|
||||
### Implementation
|
||||
|
||||
##### Vesting Account implementation
|
||||
|
||||
NOTE: `Now = ctx.BlockHeader().Time`
|
||||
|
||||
```go
|
||||
type VestingAccount interface {
|
||||
Account
|
||||
AssertIsVestingAccount() // existence implies that account is vesting.
|
||||
|
||||
// Calculates amount of coins that can be sent to other accounts given the current time
|
||||
SendableCoins(sdk.Context) sdk.Coins
|
||||
}
|
||||
|
||||
// Implements Vesting Account
|
||||
// Continuously vests by unlocking coins linearly with respect to time
|
||||
type ContinuousVestingAccount struct {
|
||||
BaseAccount
|
||||
OriginalVestingCoins sdk.Coins // Coins in account on Initialization
|
||||
ReceivedCoins sdk.Coins // Coins received from other accounts
|
||||
SentCoins sdk.Coins // Coins sent to other accounts
|
||||
|
||||
// StartTime and EndTime used to calculate how much of OriginalCoins is unlocked at any given point
|
||||
StartTime time.Time
|
||||
EndTime time.Time
|
||||
}
|
||||
|
||||
// Uses time in context to calculate total unlocked coins
|
||||
SendableCoins(vacc ContinuousVestingAccount, ctx sdk.Context) sdk.Coins:
|
||||
|
||||
// Coins unlocked by vesting schedule
|
||||
unlockedCoins := ReceivedCoins - SentCoins + OriginalVestingCoins * (Now - StartTime) / (EndTime - StartTime)
|
||||
|
||||
// Must still check for currentCoins constraint since some unlocked coins may have been delegated.
|
||||
currentCoins := vacc.BaseAccount.GetCoins()
|
||||
|
||||
// min will return sdk.Coins with each denom having the minimum amount from unlockedCoins and currentCoins
|
||||
return min(unlockedCoins, currentCoins)
|
||||
|
||||
```
|
||||
|
||||
The `VestingAccount` interface is used to assert that an account is a vesting account like so:
|
||||
|
||||
```go
|
||||
vacc, ok := acc.(VestingAccount); ok
|
||||
```
|
||||
|
||||
as well as to calculate the SendableCoins at any given moment.
|
||||
|
||||
The `ContinuousVestingAccount` struct implements the Vesting account interface. It uses `OriginalVestingCoins`, `ReceivedCoins`,
|
||||
`SentCoins`, `StartTime`, and `EndTime` to calculate how many coins are sendable at any given point.
|
||||
Since the vesting restrictions need to be implemented on a per-module basis, the `ContinuousVestingAccount` implements
|
||||
the `Account` interface exactly like `BaseAccount`. Thus, `ContinuousVestingAccount.GetCoins()` will return the total of
|
||||
both locked coins and unlocked coins currently in the account. Delegated coins are deducted from `Account.GetCoins()`, but do not count against unlocked coins because they are still at stake and will be reinstated (partially if slashed) after waiting the full unbonding period.
|
||||
|
||||
##### Changes to Keepers/Handler
|
||||
|
||||
Since a vesting account should be capable of doing everything but sending with its locked coins, the restriction should be
|
||||
handled at the `bank.Keeper` level. Specifically in methods that are explicitly used for sending like
|
||||
`sendCoins` and `inputOutputCoins`. These methods must check that an account is a vesting account using the check described above.
|
||||
|
||||
```go
|
||||
if acc is VestingAccount and Now < vestingAccount.EndTime:
|
||||
// Check if amount is less than currently allowed sendable coins
|
||||
if msg.Amount > vestingAccount.SendableCoins(ctx) then fail
|
||||
else:
|
||||
vestingAccount.SentCoins += msg.Amount
|
||||
|
||||
else:
|
||||
// Account has fully vested, treat like regular account
|
||||
if msg.Amount > account.GetCoins() then fail
|
||||
|
||||
// All checks passed, send the coins
|
||||
SendCoins(inputs, outputs)
|
||||
|
||||
```
|
||||
|
||||
Coins that are sent to a vesting account after initialization by users sending them coins should be spendable
|
||||
immediately after receiving them. Thus, handlers (like staking or bank) that send coins that a vesting account did not
|
||||
originally own should increment `ReceivedCoins` by the amount sent.
|
||||
Unlocked coins that are sent to other accounts will increment the vesting account's `SentCoins` attribute.
|
||||
|
||||
CONTRACT: Handlers SHOULD NOT update `ReceivedCoins` if they were originally sent from the vesting account. For example, if a vesting account unbonds from a validator, their tokens should be added back to account but staking handlers SHOULD NOT update `ReceivedCoins`.
|
||||
However when a user sends coins to vesting account, then `ReceivedCoins` SHOULD be incremented.
|
||||
|
||||
### Initializing at Genesis
|
||||
|
||||
To initialize both vesting accounts and base accounts, the `GenesisAccount` struct will include an EndTime. Accounts meant to be
|
||||
BaseAccounts will have `EndTime = 0`. The `initChainer` method will parse the GenesisAccount into BaseAccounts and VestingAccounts
|
||||
as appropriate.
|
||||
|
||||
```go
|
||||
type GenesisAccount struct {
|
||||
Address sdk.AccAddress `json:"address"`
|
||||
GenesisCoins sdk.Coins `json:"coins"`
|
||||
EndTime int64 `json:"lock"`
|
||||
}
|
||||
|
||||
initChainer:
|
||||
for gacc in GenesisAccounts:
|
||||
baseAccount := BaseAccount{
|
||||
Address: gacc.Address,
|
||||
Coins: gacc.GenesisCoins,
|
||||
}
|
||||
if gacc.EndTime != 0:
|
||||
vestingAccount := ContinuouslyVestingAccount{
|
||||
BaseAccount: baseAccount,
|
||||
OriginalVestingCoins: gacc.GenesisCoins,
|
||||
StartTime: RequestInitChain.Time,
|
||||
EndTime: gacc.EndTime,
|
||||
}
|
||||
AddAccountToState(vestingAccount)
|
||||
else:
|
||||
AddAccountToState(baseAccount)
|
||||
|
||||
```
|
||||
|
||||
### Formulas
|
||||
|
||||
`OriginalVestingCoins`: Amount of coins in account at Genesis
|
||||
|
||||
`CurrentCoins`: Coins currently in the baseaccount (both locked and unlocked: `vestingAccount.GetCoins`)
|
||||
|
||||
`ReceivedCoins`: Coins received from other accounts (always unlocked)
|
||||
|
||||
`LockedCoins`: Coins that are currently locked
|
||||
|
||||
`Delegated`: Coins that have been delegated (no longer in account; may be locked or unlocked)
|
||||
|
||||
`Sent`: Coins sent to other accounts (MUST be unlocked)
|
||||
|
||||
Maximum amount of coins vesting schedule allows to be sent:
|
||||
|
||||
`ReceivedCoins - SentCoins + OriginalVestingCoins * (Now - StartTime) / (EndTime - StartTime)`
|
||||
|
||||
`ReceivedCoins - SentCoins + OriginalVestingCoins - LockedCoins`
|
||||
|
||||
Coins currently in Account:
|
||||
|
||||
`CurrentCoins = OriginalVestingCoins + ReceivedCoins - Delegated - Sent`
|
||||
|
||||
`CurrentCoins = vestingAccount.GetCoins()`
|
||||
|
||||
**Maximum amount of coins spendable right now:**
|
||||
|
||||
`min( ReceivedCoins - SentCoins + OriginalVestingCoins - LockedCoins, CurrentCoins )`
|
||||
@@ -25,9 +25,9 @@ type VotingProcedure struct {
|
||||
|
||||
```go
|
||||
type TallyingProcedure struct {
|
||||
Threshold rational.Rational // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
|
||||
Veto rational.Rational // Minimum proportion of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
|
||||
GovernancePenalty sdk.Rat // Penalty if validator does not vote
|
||||
Threshold sdk.Dec // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
|
||||
Veto sdk.Dec // Minimum proportion of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
|
||||
GovernancePenalty sdk.Dec // Penalty if validator does not vote
|
||||
GracePeriod int64 // If validator entered validator set in this period of blocks before vote ended, governance penalty does not apply
|
||||
}
|
||||
```
|
||||
@@ -81,7 +81,7 @@ This type is used in a temp map when tallying
|
||||
|
||||
```go
|
||||
type ValidatorGovInfo struct {
|
||||
Minus sdk.Rat
|
||||
Minus sdk.Dec
|
||||
Vote Vote
|
||||
}
|
||||
```
|
||||
@@ -103,17 +103,17 @@ type Proposal struct {
|
||||
VotingStartBlock int64 // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached
|
||||
CurrentStatus ProposalStatus // Current status of the proposal
|
||||
|
||||
YesVotes sdk.Rat
|
||||
NoVotes sdk.Rat
|
||||
NoWithVetoVotes sdk.Rat
|
||||
AbstainVotes sdk.Rat
|
||||
YesVotes sdk.Dec
|
||||
NoVotes sdk.Dec
|
||||
NoWithVetoVotes sdk.Dec
|
||||
AbstainVotes sdk.Dec
|
||||
}
|
||||
```
|
||||
|
||||
We also mention a method to update the tally for a given proposal:
|
||||
|
||||
```go
|
||||
func (proposal Proposal) updateTally(vote byte, amount sdk.Rat)
|
||||
func (proposal Proposal) updateTally(vote byte, amount sdk.Dec)
|
||||
```
|
||||
|
||||
### Stores
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
The current annual inflation rate.
|
||||
|
||||
```golang
|
||||
type Inflation sdk.Rat
|
||||
type Inflation sdk.Dec
|
||||
```
|
||||
|
||||
### InflationLastTime
|
||||
|
||||
@@ -16,4 +16,3 @@ EndBlock() ValidatorSetChanges
|
||||
ClearTendermintUpdates()
|
||||
return vsc
|
||||
```
|
||||
|
||||
|
||||
+15
-15
@@ -13,7 +13,7 @@ type Pool struct {
|
||||
LooseTokens int64 // tokens not associated with any bonded validator
|
||||
BondedTokens int64 // reserve of bonded tokens
|
||||
InflationLastTime int64 // block which the last inflation was processed // TODO make time
|
||||
Inflation sdk.Rat // current annual inflation rate
|
||||
Inflation sdk.Dec // current annual inflation rate
|
||||
|
||||
DateLastCommissionReset int64 // unix timestamp for last commission accounting reset (daily)
|
||||
}
|
||||
@@ -28,10 +28,10 @@ overall functioning of the stake module.
|
||||
|
||||
```golang
|
||||
type Params struct {
|
||||
InflationRateChange sdk.Rat // maximum annual change in inflation rate
|
||||
InflationMax sdk.Rat // maximum inflation rate
|
||||
InflationMin sdk.Rat // minimum inflation rate
|
||||
GoalBonded sdk.Rat // Goal of percent bonded atoms
|
||||
InflationRateChange sdk.Dec // maximum annual change in inflation rate
|
||||
InflationMax sdk.Dec // maximum inflation rate
|
||||
InflationMin sdk.Dec // minimum inflation rate
|
||||
GoalBonded sdk.Dec // Goal of percent bonded atoms
|
||||
|
||||
MaxValidators uint16 // maximum number of validators
|
||||
BondDenom string // bondable coin denomination
|
||||
@@ -74,9 +74,9 @@ type Validator struct {
|
||||
Revoked bool // has the validator been revoked?
|
||||
|
||||
Status sdk.BondStatus // validator status (bonded/unbonding/unbonded)
|
||||
Tokens sdk.Rat // delegated tokens (incl. self-delegation)
|
||||
DelegatorShares sdk.Rat // total shares issued to a validator's delegators
|
||||
SlashRatio sdk.Rat // increases each time the validator is slashed
|
||||
Tokens sdk.Dec // delegated tokens (incl. self-delegation)
|
||||
DelegatorShares sdk.Dec // total shares issued to a validator's delegators
|
||||
SlashRatio sdk.Dec // increases each time the validator is slashed
|
||||
|
||||
Description Description // description terms for the validator
|
||||
|
||||
@@ -88,10 +88,10 @@ type Validator struct {
|
||||
}
|
||||
|
||||
type CommissionInfo struct {
|
||||
Rate sdk.Rat // the commission rate of fees charged to any delegators
|
||||
Max sdk.Rat // maximum commission rate which this validator can ever charge
|
||||
ChangeRate sdk.Rat // maximum daily increase of the validator commission
|
||||
ChangeToday sdk.Rat // commission rate change today, reset each day (UTC time)
|
||||
Rate sdk.Dec // the commission rate of fees charged to any delegators
|
||||
Max sdk.Dec // maximum commission rate which this validator can ever charge
|
||||
ChangeRate sdk.Dec // maximum daily increase of the validator commission
|
||||
ChangeToday sdk.Dec // commission rate change today, reset each day (UTC time)
|
||||
LastChange int64 // unix timestamp of last commission change
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ the transaction is the owner of the bond.
|
||||
|
||||
```golang
|
||||
type Delegation struct {
|
||||
Shares sdk.Rat // delegation shares recieved
|
||||
Shares sdk.Dec // delegation shares recieved
|
||||
Height int64 // last height bond updated
|
||||
}
|
||||
```
|
||||
@@ -178,8 +178,8 @@ the original redelegation has been completed.
|
||||
|
||||
```golang
|
||||
type Redelegation struct {
|
||||
SourceShares sdk.Rat // amount of source shares redelegating
|
||||
DestinationShares sdk.Rat // amount of destination shares created at redelegation
|
||||
SourceShares sdk.Dec // amount of source shares redelegating
|
||||
DestinationShares sdk.Dec // amount of destination shares created at redelegation
|
||||
CompleteTime int64 // unix time to complete redelegation
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
## Transaction Overview
|
||||
|
||||
In this section we describe the processing of the transactions and the
|
||||
corresponding updates to the state. Transactions:
|
||||
corresponding updates to the state. Transactions:
|
||||
- TxCreateValidator
|
||||
- TxEditValidator
|
||||
- TxDelegation
|
||||
@@ -18,8 +18,8 @@ Other notes:
|
||||
- `sender` denotes the address of the sender of the transaction
|
||||
- `getXxx`, `setXxx`, and `removeXxx` functions are used to retrieve and
|
||||
modify objects from the store
|
||||
- `sdk.Rat` refers to a rational numeric type specified by the SDK.
|
||||
|
||||
- `sdk.Dec` refers to a decimal type specified by the SDK.
|
||||
|
||||
### TxCreateValidator
|
||||
|
||||
- triggers: `distribution.CreateValidatorDistribution`
|
||||
@@ -28,74 +28,74 @@ A validator is created using the `TxCreateValidator` transaction.
|
||||
|
||||
```golang
|
||||
type TxCreateValidator struct {
|
||||
OwnerAddr sdk.Address
|
||||
Operator sdk.Address
|
||||
ConsensusPubKey crypto.PubKey
|
||||
GovernancePubKey crypto.PubKey
|
||||
SelfDelegation coin.Coin
|
||||
SelfDelegation coin.Coin
|
||||
|
||||
Description Description
|
||||
Commission sdk.Rat
|
||||
CommissionMax sdk.Rat
|
||||
CommissionMaxChange sdk.Rat
|
||||
Commission sdk.Dec
|
||||
CommissionMax sdk.Dec
|
||||
CommissionMaxChange sdk.Dec
|
||||
}
|
||||
|
||||
|
||||
|
||||
createValidator(tx TxCreateValidator):
|
||||
validator = getValidator(tx.OwnerAddr)
|
||||
validator = getValidator(tx.Operator)
|
||||
if validator != nil return // only one validator per address
|
||||
|
||||
validator = NewValidator(OwnerAddr, ConsensusPubKey, GovernancePubKey, Description)
|
||||
|
||||
validator = NewValidator(operatorAddr, ConsensusPubKey, GovernancePubKey, Description)
|
||||
init validator poolShares, delegatorShares set to 0
|
||||
init validator commision fields from tx
|
||||
validator.PoolShares = 0
|
||||
|
||||
|
||||
setValidator(validator)
|
||||
|
||||
txDelegate = TxDelegate(tx.OwnerAddr, tx.OwnerAddr, tx.SelfDelegation)
|
||||
|
||||
txDelegate = TxDelegate(tx.Operator, tx.Operator, tx.SelfDelegation)
|
||||
delegate(txDelegate, validator) // see delegate function in [TxDelegate](TxDelegate)
|
||||
return
|
||||
```
|
||||
```
|
||||
|
||||
### TxEditValidator
|
||||
|
||||
If either the `Description` (excluding `DateBonded` which is constant),
|
||||
`Commission`, or the `GovernancePubKey` need to be updated, the
|
||||
`TxEditCandidacy` transaction should be sent from the owner account:
|
||||
`TxEditCandidacy` transaction should be sent from the operator account:
|
||||
|
||||
```golang
|
||||
type TxEditCandidacy struct {
|
||||
GovernancePubKey crypto.PubKey
|
||||
Commission sdk.Rat
|
||||
Commission sdk.Dec
|
||||
Description Description
|
||||
}
|
||||
|
||||
|
||||
editCandidacy(tx TxEditCandidacy):
|
||||
validator = getValidator(tx.ValidatorAddr)
|
||||
|
||||
if tx.Commission > CommissionMax || tx.Commission < 0 then fail
|
||||
|
||||
if tx.Commission > CommissionMax || tx.Commission < 0 then fail
|
||||
if rateChange(tx.Commission) > CommissionMaxChange then fail
|
||||
validator.Commission = tx.Commission
|
||||
|
||||
if tx.GovernancePubKey != nil validator.GovernancePubKey = tx.GovernancePubKey
|
||||
if tx.Description != nil validator.Description = tx.Description
|
||||
|
||||
|
||||
setValidator(store, validator)
|
||||
return
|
||||
```
|
||||
|
||||
|
||||
### TxDelegate
|
||||
|
||||
|
||||
- triggers: `distribution.CreateOrModDelegationDistribution`
|
||||
|
||||
Within this transaction the delegator provides coins, and in return receives
|
||||
some amount of their validator's delegator-shares that are assigned to
|
||||
`Delegation.Shares`.
|
||||
`Delegation.Shares`.
|
||||
|
||||
```golang
|
||||
type TxDelegate struct {
|
||||
DelegatorAddr sdk.Address
|
||||
ValidatorAddr sdk.Address
|
||||
Amount sdk.Coin
|
||||
DelegatorAddr sdk.Address
|
||||
ValidatorAddr sdk.Address
|
||||
Amount sdk.Coin
|
||||
}
|
||||
|
||||
delegate(tx TxDelegate):
|
||||
@@ -104,14 +104,14 @@ delegate(tx TxDelegate):
|
||||
|
||||
delegation = getDelegatorBond(DelegatorAddr, ValidatorAddr)
|
||||
if delegation == nil then delegation = NewDelegation(DelegatorAddr, ValidatorAddr)
|
||||
|
||||
|
||||
validator, pool, issuedDelegatorShares = validator.addTokensFromDel(tx.Amount, pool)
|
||||
delegation.Shares += issuedDelegatorShares
|
||||
|
||||
|
||||
setDelegation(delegation)
|
||||
updateValidator(validator)
|
||||
setPool(pool)
|
||||
return
|
||||
return
|
||||
```
|
||||
|
||||
### TxStartUnbonding
|
||||
@@ -120,28 +120,28 @@ Delegator unbonding is defined with the following transaction:
|
||||
|
||||
```golang
|
||||
type TxStartUnbonding struct {
|
||||
DelegatorAddr sdk.Address
|
||||
ValidatorAddr sdk.Address
|
||||
Shares string
|
||||
DelegatorAddr sdk.Address
|
||||
ValidatorAddr sdk.Address
|
||||
Shares string
|
||||
}
|
||||
|
||||
startUnbonding(tx TxStartUnbonding):
|
||||
startUnbonding(tx TxStartUnbonding):
|
||||
delegation, found = getDelegatorBond(store, sender, tx.PubKey)
|
||||
if !found == nil return
|
||||
|
||||
if !found == nil return
|
||||
|
||||
if bond.Shares < tx.Shares
|
||||
return ErrNotEnoughBondShares
|
||||
|
||||
validator, found = GetValidator(tx.ValidatorAddr)
|
||||
if !found {
|
||||
return err
|
||||
return err
|
||||
|
||||
bond.Shares -= tx.Shares
|
||||
|
||||
revokeCandidacy = false
|
||||
if bond.Shares.IsZero() {
|
||||
|
||||
if bond.DelegatorAddr == validator.Owner && validator.Revoked == false
|
||||
if bond.DelegatorAddr == validator.Operator && validator.Revoked == false
|
||||
revokeCandidacy = true
|
||||
|
||||
removeDelegation( bond)
|
||||
@@ -162,7 +162,7 @@ startUnbonding(tx TxStartUnbonding):
|
||||
validator = updateValidator(validator)
|
||||
|
||||
if validator.DelegatorShares == 0 {
|
||||
removeValidator(validator.Owner)
|
||||
removeValidator(validator.Operator)
|
||||
|
||||
return
|
||||
```
|
||||
@@ -185,7 +185,7 @@ redelegationComplete(tx TxRedelegate):
|
||||
returnTokens = ExpectedTokens * tx.startSlashRatio/validator.SlashRatio
|
||||
AddCoins(unbonding.DelegatorAddr, returnTokens)
|
||||
removeUnbondingDelegation(unbonding)
|
||||
return
|
||||
return
|
||||
```
|
||||
|
||||
### TxRedelegation
|
||||
@@ -199,27 +199,27 @@ type TxRedelegate struct {
|
||||
DelegatorAddr Address
|
||||
ValidatorFrom Validator
|
||||
ValidatorTo Validator
|
||||
Shares sdk.Rat
|
||||
Shares sdk.Dec
|
||||
CompletedTime int64
|
||||
}
|
||||
|
||||
redelegate(tx TxRedelegate):
|
||||
|
||||
pool = getPool()
|
||||
delegation = getDelegatorBond(tx.DelegatorAddr, tx.ValidatorFrom.Owner)
|
||||
delegation = getDelegatorBond(tx.DelegatorAddr, tx.ValidatorFrom.Operator)
|
||||
if delegation == nil
|
||||
return
|
||||
|
||||
if delegation.Shares < tx.Shares
|
||||
return
|
||||
return
|
||||
|
||||
if delegation.Shares < tx.Shares
|
||||
return
|
||||
delegation.shares -= Tx.Shares
|
||||
validator, pool, createdCoins = validator.RemoveShares(pool, tx.Shares)
|
||||
setPool(pool)
|
||||
|
||||
redelegation = newRedelegation(tx.DelegatorAddr, tx.validatorFrom,
|
||||
|
||||
redelegation = newRedelegation(tx.DelegatorAddr, tx.validatorFrom,
|
||||
tx.validatorTo, tx.Shares, createdCoins, tx.CompletedTime)
|
||||
setRedelegation(redelegation)
|
||||
return
|
||||
return
|
||||
```
|
||||
|
||||
### TxCompleteRedelegation
|
||||
@@ -239,7 +239,7 @@ redelegationComplete(tx TxRedelegate):
|
||||
redelegation = getRedelegation(tx.DelegatorAddr, tx.validatorFrom, tx.validatorTo)
|
||||
if redelegation.CompleteTime >= CurrentBlockTime && redelegation.CompleteHeight >= CurrentBlockHeight
|
||||
removeRedelegation(redelegation)
|
||||
return
|
||||
return
|
||||
```
|
||||
|
||||
### Update Validators
|
||||
@@ -273,11 +273,11 @@ updateBondedValidators(newValidator Validator) (updatedVal Validator)
|
||||
// use the validator provided because it has not yet been updated
|
||||
// in the main validator store
|
||||
|
||||
ownerAddr = iterator.Value()
|
||||
if bytes.Equal(ownerAddr, newValidator.Owner) {
|
||||
operatorAddr = iterator.Value()
|
||||
if bytes.Equal(operatorAddr, newValidator.Operator) {
|
||||
validator = newValidator
|
||||
else
|
||||
validator = getValidator(ownerAddr)
|
||||
validator = getValidator(operatorAddr)
|
||||
|
||||
// if not previously a validator (and unrevoked),
|
||||
// kick the cliff validator / bond this new validator
|
||||
@@ -285,7 +285,7 @@ updateBondedValidators(newValidator Validator) (updatedVal Validator)
|
||||
kickCliffValidator = true
|
||||
|
||||
validator = bondValidator(ctx, store, validator)
|
||||
if bytes.Equal(ownerAddr, newValidator.Owner) {
|
||||
if bytes.Equal(operatorAddr, newValidator.Operator) {
|
||||
updatedVal = validator
|
||||
|
||||
bondedValidatorsCount++
|
||||
@@ -316,7 +316,7 @@ unbondValidator(ctx Context, store KVStore, validator Validator)
|
||||
}
|
||||
|
||||
// perform all the store operations for when a validator status becomes bonded
|
||||
bondValidator(ctx Context, store KVStore, validator Validator) Validator
|
||||
bondValidator(ctx Context, store KVStore, validator Validator) Validator
|
||||
pool = GetPool(ctx)
|
||||
|
||||
// set the status
|
||||
|
||||
Reference in New Issue
Block a user