cwgoes comments, improved pseudocode
This commit is contained in:
parent
14c1ff27f3
commit
ab028a7805
@ -3,15 +3,5 @@
|
||||
Here we cover many aspects of handling keys within the Cosmos SDK
|
||||
framework.
|
||||
|
||||
## Pseudo Code
|
||||
|
||||
Generating an address for an ed25519 public key (in pseudo code):
|
||||
|
||||
```
|
||||
const TypeDistinguisher = HexToBytes("1624de6220")
|
||||
|
||||
// prepend the TypeDistinguisher as Bytes
|
||||
SerializedBytes = TypeDistinguisher ++ PubKey.asBytes()
|
||||
|
||||
Address = ripemd160(SerializedBytes)
|
||||
```
|
||||
// TODO add relevant key discussion
|
||||
(related https://github.com/tendermint/tendermint/blob/master/docs/spec/blockchain/encoding.md#public-key-cryptography)
|
||||
|
||||
@ -8,23 +8,24 @@ The Cosmos Hub is a Tendermint-based Delegated Proof of Stake (DPos) blockchain
|
||||
system that serves as a backbone of the Cosmos ecosystem. It is operated and
|
||||
secured by an open and globally decentralized set of validators. Tendermint is
|
||||
a Byzantine fault-tolerant distributed protocol for consensus among distrusting
|
||||
parties, in this case the group of validators which produce the blocks for
|
||||
cosmos. To avoid the nothing-at-stake problem, a validator in Tendermint needs
|
||||
to lock up coins in a bond deposit. Each bond's atoms are illiquid, they cannot
|
||||
be transferred however they can be unbonded to become liquid, this process
|
||||
takes the unbonding-period which will be 3 weeks by default at Cosmos-Hub
|
||||
launch. Tendermint protocol messages are signed by the validator's private key,
|
||||
and this is a basis for Tendermint strict accountability that allows punishing
|
||||
misbehaving validators by slashing (burning) their bonded Atoms. On the other
|
||||
hand, validators are rewarded for their service of securing blockchain network
|
||||
by the inflationary provisions and transactions fees. This incentivizes correct
|
||||
behavior of the validators and provides the economic security of the network.
|
||||
parties, in this case the group of validators which produce the blocks for the
|
||||
Cosmos Hub. To avoid the nothing-at-stake problem, a validator in Tendermint
|
||||
needs to lock up coins in a bond deposit. Each bond's atoms are illiquid, they
|
||||
cannot be transferred - in order to become liquid, they must be unbonded, a
|
||||
process which will take 3 weeks by default at Cosmos Hub launch. Tendermint
|
||||
protocol messages are signed by the validator's private key and are therefor
|
||||
attributable. Validators acting outside protocol specifications can be made
|
||||
accountable through punishing by slashing (burning) their bonded Atoms. On the
|
||||
other hand, validators are rewarded for their service of securing blockchain
|
||||
network by the inflationary provisions and transactions fees. This incentivizes
|
||||
correct behavior of the validators and provides the economic security of the
|
||||
network.
|
||||
|
||||
The native token of the Cosmos Hub is called the Atom; becoming a validator of the
|
||||
Cosmos Hub requires holding Atoms. However, not all Atom holders are validators
|
||||
of the Cosmos Hub. More precisely, there is a selection process that determines
|
||||
the validator set as a subset of all validators (Atom holders that
|
||||
wants to become a validator). The other option for Atom holder is to delegate
|
||||
want to become a validator). The other option for Atom holders is to delegate
|
||||
their atoms to validators, i.e., being a delegator. A delegator is an Atom
|
||||
holder that has put its Atoms at stake by delegating it to a validator. By bonding
|
||||
Atoms to secure the network (and taking a risk of being slashed in case of
|
||||
@ -59,20 +60,22 @@ transaction fees.
|
||||
bonded the shares must first remain in an inbetween unbonding state for the
|
||||
duration of the unbonding period
|
||||
* Redelegating Shares - Process of redelegating atoms from one validator to
|
||||
another. This process is instantanious, the redelegated delegation is
|
||||
slashible to the old validator for all blocks before the redelegation and to
|
||||
the new validator for all new blocks.
|
||||
another. This process is instantaneous, but the redelegated atoms are
|
||||
retrospecively slashable if the old validator is found to misbehave for any
|
||||
blocks before the redelegation. These atoms are simultaniously slashable
|
||||
for any new blocks which the new validator misbehavess
|
||||
* Validator - entity with atoms which is either actively validating the Tendermint
|
||||
protocol (bonded validator) or vying to validate .
|
||||
* Bonded Validator - a validator whose atoms are currently bonded and liable to
|
||||
be slashed. These validators are to be able to sign protocol messages in the
|
||||
Tendermint consensus protocol. There are limited number of bonded validators
|
||||
at Cosmos Hub genesis there is a maximum of 100 bonded validators. Only Bonded
|
||||
Validators receive atom provisions and fee rewards.
|
||||
be slashed. These validators are to be able to sign protocol messages for
|
||||
Tendermint consensus. At Cosmos Hub genesis there is a maximum of 100
|
||||
bonded validator positions. Only Bonded Validators receive atom provisions
|
||||
and fee rewards.
|
||||
* Delegator - an Atom holder that has bonded Atoms to a validator
|
||||
* Unbonding period - time required in the unbonding state when unbonding
|
||||
shares. Time slashable to old validator after a redelegation. Time for which
|
||||
validators can be slashed after an infraction
|
||||
validators can be slashed after an infraction. To provide the requisite
|
||||
cryptoeconomic security guarantees, all of these must be equal.
|
||||
* Atom provisions - The process of increasing the Atom supply. Atoms are
|
||||
periodically created on the Cosmos Hub and issued to bonded Atom holders.
|
||||
The goal of inflation is to incentize most of the Atoms in existence to be
|
||||
@ -90,7 +93,7 @@ At the core of the Staking module is the concept of a pool which denotes a
|
||||
collection of Atoms contributed by different Atom holders. There are three
|
||||
pools in the Staking module: the bonded, unbonding, and unbonded pool. Bonded
|
||||
Atoms are part of the global bonded pool. If a validator or delegator wants to
|
||||
unbond its Shares, these Shares are moved to the the unbonding pool for the
|
||||
unbond its shares, these Shares are moved to the the unbonding pool for the
|
||||
duration of the unbonding period. From here normally Atoms will be moved
|
||||
directly into the delegators wallet, however under the situation thatn an
|
||||
entire validator gets unbonded, the Atoms of the delegations will remain with
|
||||
@ -169,17 +172,17 @@ delegators (we will explain this in section X).
|
||||
|
||||
#### Delegator shares
|
||||
|
||||
A validator is, depending on its status, contributing Atoms to either the bond,
|
||||
A validator is, depending on its status, contributing Atoms to either the
|
||||
unbonding or unbonded pool - the validator in turn holds some amount of pool
|
||||
shares. Not all of a validators Atoms (and respective shares) are owned by the
|
||||
validator, some may be owned by delegators to that validator. The mechanism for
|
||||
distribution of Atoms (and shares) between a validator and its delegators is
|
||||
based on a notion of delegator shares. More precisely, every validator is
|
||||
issuing (local) delegator shares (`Validator.IssuedDelegatorShares`) that
|
||||
represents some portion of global shares managed by the validator
|
||||
(`Validator.GlobalStakeShares`). The principle behind managing delegator shares
|
||||
is the same as described in [Section](#The pool and the share). We now
|
||||
illustrate it with an example.
|
||||
shares. Not all of a validator's Atoms (and respective shares) are necessarily
|
||||
owned by the validator, some may be owned by delegators to that validator. The
|
||||
mechanism for distribution of Atoms (and shares) between a validator and its
|
||||
delegators is based on a notion of delegator shares. More precisely, every
|
||||
validator is issuing (local) delegator shares
|
||||
(`Validator.IssuedDelegatorShares`) that represents some portion of global
|
||||
shares managed by the validator (`Validator.GlobalStakeShares`). The principle
|
||||
behind managing delegator shares is the same as described in [Section](#The
|
||||
pool and the share). We now illustrate it with an example.
|
||||
|
||||
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
XXX TODO make way less verbose lets use bullet points to describe the example
|
||||
|
||||
@ -10,7 +10,7 @@ NOTE: the specifications are not yet complete and very much a work in progress.
|
||||
- [Governance](governance) - Governance related specifications including
|
||||
proposals and voting.
|
||||
- [IBC](ibc) - Specification of the Cosmos inter-blockchain communication (IBC) protocol.
|
||||
- [Staking](staking) - Proof of Stake related specifications including bonding
|
||||
- [Staking](staking) - Proof-of-stake related specifications including bonding
|
||||
and delegation transactions, inflation, etc.
|
||||
- [Slashing](slashing) - Specifications of validator punishment mechanisms
|
||||
- [Provisioning](provisioning) - Fee distribution, and atom provision distribution specification
|
||||
|
||||
@ -8,6 +8,8 @@ information about the total amounts of Atoms in all states, representative
|
||||
validator shares for stake in the global pools, moving Atom inflation
|
||||
information, etc.
|
||||
|
||||
- stored object:
|
||||
|
||||
```golang
|
||||
type Pool struct {
|
||||
LooseUnbondedTokens int64 // tokens not associated with any validator
|
||||
@ -35,6 +37,8 @@ type PoolShares struct {
|
||||
Params is global data structure that stores system parameters and defines
|
||||
overall functioning of the stake module.
|
||||
|
||||
- stored object:
|
||||
|
||||
```golang
|
||||
type Params struct {
|
||||
InflationRateChange sdk.Rat // maximum annual change in inflation rate
|
||||
@ -59,6 +63,8 @@ Related Store which holds Validator.ABCIValidator()
|
||||
The `Validator` holds the current state and some historical actions of the
|
||||
validator.
|
||||
|
||||
- stored object:
|
||||
|
||||
```golang
|
||||
type Validator struct {
|
||||
Owner sdk.Address // sender of BondTx - UnbondTx returns here
|
||||
@ -98,6 +104,8 @@ funds are held in a `Delegation` data structure. It is owned by one
|
||||
delegator, and is associated with the shares for one validator. The sender of
|
||||
the transaction is the owner of the bond.
|
||||
|
||||
- stored object:
|
||||
|
||||
```golang
|
||||
type Delegation struct {
|
||||
DelegatorAddr sdk.Address // delegation owner address
|
||||
@ -114,6 +122,8 @@ A UnbondingDelegation object is created every time an unbonding is initiated.
|
||||
The unbond must be completed with a second transaction provided by the
|
||||
delegation owner after the unbonding period has passed.
|
||||
|
||||
- stored object:
|
||||
|
||||
```golang
|
||||
type UnbondingDelegation struct {
|
||||
DelegationKey sdk.Address // key of the delegation
|
||||
@ -135,6 +145,8 @@ delegation owner after the unbonding period has passed. The destination
|
||||
delegation of a redelegation may not itself undergo a new redelegation until
|
||||
the original redelegation has been completed.
|
||||
|
||||
- stored object:
|
||||
|
||||
```golang
|
||||
type Redelegation struct {
|
||||
SourceDelegation sdk.Address // source delegation key
|
||||
|
||||
@ -44,7 +44,7 @@ createValidator(tx TxCreateValidator):
|
||||
if validator != nil return // only one validator per address
|
||||
|
||||
validator = NewValidator(OwnerAddr, ConsensusPubKey, GovernancePubKey, Description)
|
||||
init validator poolShares, delegatorShares set to 0 //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
init validator poolShares, delegatorShares set to 0
|
||||
init validator commision fields from tx
|
||||
validator.PoolShares = 0
|
||||
|
||||
@ -71,8 +71,8 @@ type TxEditCandidacy struct {
|
||||
editCandidacy(tx TxEditCandidacy):
|
||||
validator = getValidator(tx.ValidatorAddr)
|
||||
|
||||
if tx.Commission > CommissionMax || tx.Commission < 0 return halt tx
|
||||
if rateChange(tx.Commission) > CommissionMaxChange return halt tx
|
||||
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
|
||||
@ -126,28 +126,16 @@ startUnbonding(tx TxStartUnbonding):
|
||||
delegation, found = getDelegatorBond(store, sender, tx.PubKey)
|
||||
if !found == nil return
|
||||
|
||||
if tx.Shares == "MAX" {
|
||||
if !bond.Shares.GT(sdk.ZeroRat()) {
|
||||
return ErrNotEnoughBondShares
|
||||
else
|
||||
var err sdk.Error
|
||||
delShares, err = sdk.NewRatFromDecimal(tx.Shares)
|
||||
if err != nil
|
||||
return err
|
||||
if bond.Shares.LT(delShares)
|
||||
if bond.Shares < tx.Shares
|
||||
return ErrNotEnoughBondShares
|
||||
|
||||
validator, found := GetValidator(tx.ValidatorAddr)
|
||||
validator, found = GetValidator(tx.ValidatorAddr)
|
||||
if !found {
|
||||
return err
|
||||
|
||||
if tx.Shares == "MAX"
|
||||
delShares = bond.Shares
|
||||
bond.Shares -= tx.Shares
|
||||
|
||||
bond.Shares -= delShares
|
||||
|
||||
|
||||
revokeCandidacy := false
|
||||
revokeCandidacy = false
|
||||
if bond.Shares.IsZero() {
|
||||
|
||||
if bond.DelegatorAddr == validator.Owner && validator.Revoked == false
|
||||
@ -158,8 +146,8 @@ startUnbonding(tx TxStartUnbonding):
|
||||
bond.Height = currentBlockHeight
|
||||
setDelegation(bond)
|
||||
|
||||
pool := GetPool()
|
||||
validator, pool, returnAmount := validator.removeDelShares(pool, delShares)
|
||||
pool = GetPool()
|
||||
validator, pool, returnAmount = validator.removeDelShares(pool, tx.Shares)
|
||||
setPool( pool)
|
||||
|
||||
unbondingDelegation = NewUnbondingDelegation(sender, returnAmount, currentHeight/Time, startSlashRatio)
|
||||
@ -261,13 +249,13 @@ Tendermint.
|
||||
```golang
|
||||
updateBondedValidators(newValidator Validator) (updatedVal Validator)
|
||||
|
||||
kickCliffValidator := false
|
||||
oldCliffValidatorAddr := getCliffValidator(ctx)
|
||||
kickCliffValidator = false
|
||||
oldCliffValidatorAddr = getCliffValidator(ctx)
|
||||
|
||||
// add the actual validator power sorted store
|
||||
maxValidators := GetParams(ctx).MaxValidators
|
||||
iterator := ReverseSubspaceIterator(ValidatorsByPowerKey) // largest to smallest
|
||||
bondedValidatorsCount := 0
|
||||
maxValidators = GetParams(ctx).MaxValidators
|
||||
iterator = ReverseSubspaceIterator(ValidatorsByPowerKey) // largest to smallest
|
||||
bondedValidatorsCount = 0
|
||||
var validator Validator
|
||||
for {
|
||||
if !iterator.Valid() || bondedValidatorsCount > int(maxValidators-1) {
|
||||
@ -282,7 +270,7 @@ updateBondedValidators(newValidator Validator) (updatedVal Validator)
|
||||
// use the validator provided because it has not yet been updated
|
||||
// in the main validator store
|
||||
|
||||
ownerAddr := iterator.Value()
|
||||
ownerAddr = iterator.Value()
|
||||
if bytes.Equal(ownerAddr, newValidator.Owner) {
|
||||
validator = newValidator
|
||||
else
|
||||
@ -290,7 +278,7 @@ updateBondedValidators(newValidator Validator) (updatedVal Validator)
|
||||
|
||||
// if not previously a validator (and unrevoked),
|
||||
// kick the cliff validator / bond this new validator
|
||||
if validator.Status() != sdk.Bonded && !validator.Revoked {
|
||||
if validator.Status() != Bonded && !validator.Revoked {
|
||||
kickCliffValidator = true
|
||||
|
||||
validator = bondValidator(ctx, store, validator)
|
||||
@ -302,16 +290,16 @@ updateBondedValidators(newValidator Validator) (updatedVal Validator)
|
||||
|
||||
// perform the actual kicks
|
||||
if oldCliffValidatorAddr != nil && kickCliffValidator {
|
||||
validator := getValidator(store, oldCliffValidatorAddr)
|
||||
validator = getValidator(store, oldCliffValidatorAddr)
|
||||
unbondValidator(ctx, store, validator)
|
||||
return
|
||||
|
||||
// perform all the store operations for when a validator status becomes unbonded
|
||||
unbondValidator(ctx sdk.Context, store sdk.KVStore, validator Validator)
|
||||
pool := GetPool(ctx)
|
||||
unbondValidator(ctx Context, store KVStore, validator Validator)
|
||||
pool = GetPool(ctx)
|
||||
|
||||
// set the status
|
||||
validator, pool = validator.UpdateStatus(pool, sdk.Unbonded)
|
||||
validator, pool = validator.UpdateStatus(pool, Unbonded)
|
||||
setPool(ctx, pool)
|
||||
|
||||
// save the now unbonded validator record
|
||||
@ -325,11 +313,11 @@ unbondValidator(ctx sdk.Context, store sdk.KVStore, validator Validator)
|
||||
}
|
||||
|
||||
// perform all the store operations for when a validator status becomes bonded
|
||||
bondValidator(ctx sdk.Context, store sdk.KVStore, validator Validator) Validator
|
||||
pool := GetPool(ctx)
|
||||
bondValidator(ctx Context, store KVStore, validator Validator) Validator
|
||||
pool = GetPool(ctx)
|
||||
|
||||
// set the status
|
||||
validator, pool = validator.UpdateStatus(pool, sdk.Bonded)
|
||||
validator, pool = validator.UpdateStatus(pool, Bonded)
|
||||
setPool(ctx, pool)
|
||||
|
||||
// save the now bonded validator record to the three referenced stores
|
||||
|
||||
Loading…
Reference in New Issue
Block a user