refactoring staking...
This commit is contained in:
parent
dc8636390c
commit
8e3f8319af
|
@ -2,6 +2,8 @@
|
|||
package stake
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
|
@ -43,6 +45,9 @@ func codeToDefaultMsg(code CodeType) string {
|
|||
//----------------------------------------
|
||||
// Error constructors
|
||||
|
||||
func ErrNotEnoughBondShares(shares string) sdk.Error {
|
||||
return newError(CodeInvalidBond, fmt.Sprintf("not enough shares only have %v", shares))
|
||||
}
|
||||
func ErrCandidateEmpty() sdk.Error {
|
||||
return newError(CodeInvalidValidator, "Cannot bond to an empty candidate")
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package stake
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
@ -214,7 +214,7 @@ func (tr transact) editCandidacy(tx MsgEditCandidacy) sdk.Error {
|
|||
|
||||
func (tr transact) delegate(tx MsgDelegate) sdk.Error {
|
||||
|
||||
if tr.mapper.loadCandidate(tx.Address) == nil { // does PubKey exist
|
||||
if tr.mapper.loadCandidate(tx.Address) == nil {
|
||||
return ErrBadCandidateAddr()
|
||||
}
|
||||
err := checkDenom(tr.mapper, tx.Bond)
|
||||
|
@ -239,24 +239,17 @@ func (tr transact) delegateWithCandidate(tx MsgDelegate, candidate *Candidate) s
|
|||
return ErrBondNotNominated()
|
||||
}
|
||||
|
||||
var poolAccount crypto.Address
|
||||
if candidate.Status == Bonded {
|
||||
poolAccount = tr.params.HoldBonded
|
||||
} else {
|
||||
poolAccount = tr.params.HoldUnbonded
|
||||
}
|
||||
|
||||
// Get or create the delegator bond
|
||||
bond := tr.mapper.loadDelegatorBond(tr.sender, tx.Address)
|
||||
if bond == nil {
|
||||
bond = &DelegatorBond{
|
||||
PubKey: tx.Address,
|
||||
Address: tx.Address,
|
||||
Shares: sdk.ZeroRat,
|
||||
}
|
||||
}
|
||||
|
||||
// Account new shares, save
|
||||
err := bond.BondTokens(candidate, tx.Bond, tr)
|
||||
err := bond.BondCoins(candidate, tx.Bond, tr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -269,38 +262,34 @@ func (tr transact) delegateWithCandidate(tx MsgDelegate, candidate *Candidate) s
|
|||
func (tr transact) unbond(tx MsgUnbond) sdk.Error {
|
||||
|
||||
// check if bond has any shares in it unbond
|
||||
existingBond := tr.mapper.loadDelegatorBond(tr.sender, tx.Address)
|
||||
sharesStr := viper.GetString(tx.Shares)
|
||||
if existingBond.Shares.LT(sdk.ZeroRat) { // bond shares < tx shares
|
||||
bond := tr.mapper.loadDelegatorBond(tr.sender, tx.Address)
|
||||
if bond == nil {
|
||||
return ErrNoDelegatorForAddress()
|
||||
}
|
||||
if !bond.Shares.GT(sdk.ZeroRat) { // bond shares < tx shares
|
||||
return ErrInsufficientFunds()
|
||||
}
|
||||
|
||||
// if shares set to special case Max then we're good
|
||||
if sharesStr != "MAX" {
|
||||
if tx.Shares != "MAX" {
|
||||
// test getting rational number from decimal provided
|
||||
shares, err := sdk.NewRatFromDecimal(sharesStr)
|
||||
shares, err := sdk.NewRatFromDecimal(tx.Shares)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// test that there are enough shares to unbond
|
||||
if bond.Shares.LT(shares) {
|
||||
return fmt.Errorf("not enough bond shares to unbond, have %v, trying to unbond %v",
|
||||
bond.Shares, tx.Shares)
|
||||
if !bond.Shares.GT(shares) {
|
||||
return ErrNotEnoughBondShares(tx.Shares)
|
||||
}
|
||||
}
|
||||
if tr.ctx.IsCheckTx() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// get delegator bond
|
||||
bond := tr.mapper.loadDelegatorBond(tr.sender, tx.Address)
|
||||
if bond == nil {
|
||||
return ErrNoDelegatorForAddress()
|
||||
}
|
||||
|
||||
// retrieve the amount of bonds to remove (TODO remove redundancy already serialized)
|
||||
var shares sdk.Rat
|
||||
var err sdk.Error
|
||||
if tx.Shares == "MAX" {
|
||||
shares = bond.Shares
|
||||
} else {
|
||||
|
@ -327,7 +316,7 @@ func (tr transact) unbond(tx MsgUnbond) sdk.Error {
|
|||
|
||||
// if the bond is the owner of the candidate then
|
||||
// trigger a revoke candidacy
|
||||
if tr.sender.Equals(candidate.Owner) &&
|
||||
if bytes.Equal(tr.sender, candidate.Address) &&
|
||||
candidate.Status != Revoked {
|
||||
revokeCandidacy = true
|
||||
}
|
||||
|
@ -338,20 +327,10 @@ func (tr transact) unbond(tx MsgUnbond) sdk.Error {
|
|||
tr.mapper.saveDelegatorBond(tr.sender, bond)
|
||||
}
|
||||
|
||||
// transfer coins back to account
|
||||
var poolAccount crypto.Address
|
||||
if candidate.Status == Bonded {
|
||||
poolAccount = tr.params.HoldBonded
|
||||
} else {
|
||||
poolAccount = tr.params.HoldUnbonded
|
||||
}
|
||||
|
||||
returnCoins := candidate.removeShares(shares, tr.gs)
|
||||
err := tr.transfer(poolAccount, tr.sender,
|
||||
sdk.Coins{{tr.params.BondDenom, returnCoins}})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Add the coins
|
||||
returnAmount := candidate.removeShares(shares, tr.gs)
|
||||
returnCoins := sdk.Coins{{tr.params.BondDenom, returnAmount}}
|
||||
tr.coinKeeper.AddCoins(tr.ctx, tr.sender, returnCoins)
|
||||
|
||||
// lastly if an revoke candidate if necessary
|
||||
if revokeCandidacy {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package stake
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/wire"
|
||||
)
|
||||
|
@ -26,7 +28,7 @@ func GetCandidateKey(address sdk.Address) []byte {
|
|||
}
|
||||
|
||||
// GetValidatorKey - get the key for the validator used in the power-store
|
||||
func GetValidatorKey(address sdk.Address, power sdk.Rational) []byte {
|
||||
func GetValidatorKey(address sdk.Address, power sdk.Rational, cdc *wire.Codec) []byte {
|
||||
b, _ := cdc.MarshalJSON(power) // TODO need to handle error here?
|
||||
return append(ValidatorKeyPrefix, append(b, address.Bytes()...)...) // TODO does this need prefix if its in its own store
|
||||
}
|
||||
|
@ -37,12 +39,12 @@ func GetValidatorUpdatesKey(address sdk.Address) []byte {
|
|||
}
|
||||
|
||||
// GetDelegatorBondKey - get the key for delegator bond with candidate
|
||||
func GetDelegatorBondKey(delegator, candidate sdk.Address) []byte {
|
||||
return append(GetDelegatorBondKeyPrefix(delegator), candidate.Bytes()...)
|
||||
func GetDelegatorBondKey(delegator, candidate sdk.Address, cdc *wire.Codec) []byte {
|
||||
return append(GetDelegatorBondKeyPrefix(delegator, cdc), candidate.Bytes()...)
|
||||
}
|
||||
|
||||
// GetDelegatorBondKeyPrefix - get the prefix for a delegator for all candidates
|
||||
func GetDelegatorBondKeyPrefix(delegator sdk.Address) []byte {
|
||||
func GetDelegatorBondKeyPrefix(delegator sdk.Address, cdc *wire.Codec) []byte {
|
||||
res, err := cdc.MarshalJSON(&delegator)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -51,7 +53,7 @@ func GetDelegatorBondKeyPrefix(delegator sdk.Address) []byte {
|
|||
}
|
||||
|
||||
// GetDelegatorBondsKey - get the key for list of all the delegator's bonds
|
||||
func GetDelegatorBondsKey(delegator sdk.Address) []byte {
|
||||
func GetDelegatorBondsKey(delegator sdk.Address, cdc *wire.Codec) []byte {
|
||||
res, err := cdc.MarshalJSON(&delegator)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -68,8 +70,8 @@ type Mapper struct {
|
|||
}
|
||||
|
||||
func NewMapper(ctx sdk.Context, cdc *wire.Codec, key sdk.StoreKey) Mapper {
|
||||
return StakeMapper{
|
||||
store: ctx.KVStore(m.key),
|
||||
return Mapper{
|
||||
store: ctx.KVStore(key),
|
||||
cdc: cdc,
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +82,7 @@ func (m Mapper) loadCandidate(address sdk.Address) *Candidate {
|
|||
return nil
|
||||
}
|
||||
candidate := new(Candidate)
|
||||
err := cdc.UnmarshalJSON(b, candidate)
|
||||
err := m.cdc.UnmarshalJSON(b, candidate)
|
||||
if err != nil {
|
||||
panic(err) // This error should never occur big problem if does
|
||||
}
|
||||
|
@ -90,11 +92,11 @@ func (m Mapper) loadCandidate(address sdk.Address) *Candidate {
|
|||
func (m Mapper) saveCandidate(candidate *Candidate) {
|
||||
|
||||
// XXX should only remove validator if we know candidate is a validator
|
||||
removeValidator(m.store, candidate.Address)
|
||||
m.removeValidator(candidate.Address)
|
||||
validator := &Validator{candidate.Address, candidate.VotingPower}
|
||||
updateValidator(m.store, validator)
|
||||
m.updateValidator(validator)
|
||||
|
||||
b, err := cdc.MarshalJSON(*candidate)
|
||||
b, err := m.cdc.MarshalJSON(*candidate)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -104,7 +106,7 @@ func (m Mapper) saveCandidate(candidate *Candidate) {
|
|||
func (m Mapper) removeCandidate(address sdk.Address) {
|
||||
|
||||
// XXX should only remove validator if we know candidate is a validator
|
||||
removeValidator(m.store, address)
|
||||
m.removeValidator(address)
|
||||
m.store.Delete(GetCandidateKey(address))
|
||||
}
|
||||
|
||||
|
@ -127,7 +129,7 @@ func (m Mapper) removeCandidate(address sdk.Address) {
|
|||
// in the changed validator substore
|
||||
func (m Mapper) updateValidator(validator *Validator) {
|
||||
|
||||
b, err := cdc.MarshalJSON(*validator)
|
||||
b, err := m.cdc.MarshalJSON(*validator)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -136,41 +138,41 @@ func (m Mapper) updateValidator(validator *Validator) {
|
|||
m.store.Set(GetValidatorUpdatesKey(validator.Address), b)
|
||||
|
||||
// update the list ordered by voting power
|
||||
m.store.Set(GetValidatorKey(validator.Address, validator.VotingPower), b)
|
||||
m.store.Set(GetValidatorKey(validator.Address, validator.VotingPower, m.cdc), b)
|
||||
}
|
||||
|
||||
func (m Mapper) removeValidator(address sdk.Address) {
|
||||
|
||||
//add validator with zero power to the validator updates
|
||||
b, err := cdc.MarshalJSON(Validator{address, sdk.ZeroRat})
|
||||
b, err := m.cdc.MarshalJSON(Validator{address, sdk.ZeroRat})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
m.store.Set(GetValidatorUpdatesKey(address), b)
|
||||
|
||||
// now actually delete from the validator set
|
||||
candidate := loadCandidate(m.store, address)
|
||||
candidate := m.loadCandidate(address)
|
||||
if candidate != nil {
|
||||
m.store.Delete(GetValidatorKey(address, candidate.VotingPower))
|
||||
m.store.Delete(GetValidatorKey(address, candidate.VotingPower, m.cdc))
|
||||
}
|
||||
}
|
||||
|
||||
// get the most recent updated validator set from the Candidates. These bonds
|
||||
// are already sorted by VotingPower from the UpdateVotingPower function which
|
||||
// is the only function which is to modify the VotingPower
|
||||
func (m Mapper) getValidators(maxVal int) (validators []Validator) {
|
||||
func (m Mapper) getValidators(maxVal uint16) (validators []Validator) {
|
||||
|
||||
iterator := m.store.Iterator(subspace(ValidatorKeyPrefix)) //smallest to largest
|
||||
|
||||
validators = make([]Validator, maxVal)
|
||||
for i := 0; ; i++ {
|
||||
if !iterator.Valid() || i > maxVal {
|
||||
if !iterator.Valid() || i > int(maxVal) {
|
||||
iterator.Close()
|
||||
break
|
||||
}
|
||||
valBytes := iterator.Value()
|
||||
var val Validator
|
||||
err := cdc.UnmarshalJSON(valBytes, &val)
|
||||
err := m.cdc.UnmarshalJSON(valBytes, &val)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -191,7 +193,7 @@ func (m Mapper) getValidatorUpdates() (updates []Validator) {
|
|||
for ; iterator.Valid(); iterator.Next() {
|
||||
valBytes := iterator.Value()
|
||||
var val Validator
|
||||
err := cdc.UnmarshalJSON(valBytes, &val)
|
||||
err := m.cdc.UnmarshalJSON(valBytes, &val)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -223,7 +225,7 @@ func (m Mapper) loadCandidates() (candidates Candidates) {
|
|||
for ; iterator.Valid(); iterator.Next() {
|
||||
candidateBytes := iterator.Value()
|
||||
var candidate Candidate
|
||||
err := cdc.UnmarshalJSON(candidateBytes, &candidate)
|
||||
err := m.cdc.UnmarshalJSON(candidateBytes, &candidate)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -238,12 +240,12 @@ func (m Mapper) loadCandidates() (candidates Candidates) {
|
|||
// load the pubkeys of all candidates a delegator is delegated too
|
||||
func (m Mapper) loadDelegatorCandidates(delegator sdk.Address) (candidateAddrs []sdk.Address) {
|
||||
|
||||
candidateBytes := m.store.Get(GetDelegatorBondsKey(delegator))
|
||||
candidateBytes := m.store.Get(GetDelegatorBondsKey(delegator, m.cdc))
|
||||
if candidateBytes == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := cdc.UnmarshalJSON(candidateBytes, &candidateAddrs)
|
||||
err := m.cdc.UnmarshalJSON(candidateBytes, &candidateAddrs)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -254,13 +256,13 @@ func (m Mapper) loadDelegatorCandidates(delegator sdk.Address) (candidateAddrs [
|
|||
|
||||
func (m Mapper) loadDelegatorBond(delegator, candidate sdk.Address) *DelegatorBond {
|
||||
|
||||
delegatorBytes := m.store.Get(GetDelegatorBondKey(delegator, candidate))
|
||||
delegatorBytes := m.store.Get(GetDelegatorBondKey(delegator, candidate, m.cdc))
|
||||
if delegatorBytes == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
bond := new(DelegatorBond)
|
||||
err := cdc.UnmarshalJSON(delegatorBytes, bond)
|
||||
err := m.cdc.UnmarshalJSON(delegatorBytes, bond)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -271,43 +273,43 @@ func (m Mapper) saveDelegatorBond(delegator sdk.Address,
|
|||
bond *DelegatorBond) {
|
||||
|
||||
// if a new bond add to the list of bonds
|
||||
if loadDelegatorBond(m.store, delegator, bond.Address) == nil {
|
||||
pks := loadDelegatorCandidates(m.store, delegator)
|
||||
if m.loadDelegatorBond(delegator, bond.Address) == nil {
|
||||
pks := m.loadDelegatorCandidates(delegator)
|
||||
pks = append(pks, (*bond).Address)
|
||||
b, err := cdc.MarshalJSON(pks)
|
||||
b, err := m.cdc.MarshalJSON(pks)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
m.store.Set(GetDelegatorBondsKey(delegator), b)
|
||||
m.store.Set(GetDelegatorBondsKey(delegator, m.cdc), b)
|
||||
}
|
||||
|
||||
// now actually save the bond
|
||||
b, err := cdc.MarshalJSON(*bond)
|
||||
b, err := m.cdc.MarshalJSON(*bond)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
m.store.Set(GetDelegatorBondKey(delegator, bond.Address), b)
|
||||
//updateDelegatorBonds(store, delegator)
|
||||
m.store.Set(GetDelegatorBondKey(delegator, bond.Address, m.cdc), b)
|
||||
//updateDelegatorBonds(store, delegator) //XXX remove?
|
||||
}
|
||||
|
||||
func (m Mapper) removeDelegatorBond(delegator sdk.Address, candidate sdk.Address) {
|
||||
func (m Mapper) removeDelegatorBond(delegator sdk.Address, candidateAddr sdk.Address) {
|
||||
// TODO use list queries on multistore to remove iterations here!
|
||||
// first remove from the list of bonds
|
||||
pks := loadDelegatorCandidates(m.store, delegator)
|
||||
for i, pk := range pks {
|
||||
if candidate.Equals(pk) {
|
||||
pks = append(pks[:i], pks[i+1:]...)
|
||||
addrs := m.loadDelegatorCandidates(delegator)
|
||||
for i, addr := range addrs {
|
||||
if bytes.Equal(candidateAddr, addr) {
|
||||
addrs = append(addrs[:i], addrs[i+1:]...)
|
||||
}
|
||||
}
|
||||
b, err := cdc.MarshalJSON(pks)
|
||||
b, err := m.cdc.MarshalJSON(pks)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
m.store.Set(GetDelegatorBondsKey(delegator), b)
|
||||
m.store.Set(GetDelegatorBondsKey(delegator, m.cdc), b)
|
||||
|
||||
// now remove the actual bond
|
||||
m.store.Delete(GetDelegatorBondKey(delegator, candidate))
|
||||
//updateDelegatorBonds(store, delegator)
|
||||
m.store.Delete(GetDelegatorBondKey(delegator, candidateAddr, m.cdc))
|
||||
//updateDelegatorBonds(store, delegator) //XXX remove?
|
||||
}
|
||||
|
||||
//_______________________________________________________________________
|
||||
|
@ -319,14 +321,14 @@ func (m Mapper) loadParams() (params Params) {
|
|||
return defaultParams()
|
||||
}
|
||||
|
||||
err := cdc.UnmarshalJSON(b, ¶ms)
|
||||
err := m.cdc.UnmarshalJSON(b, ¶ms)
|
||||
if err != nil {
|
||||
panic(err) // This error should never occur big problem if does
|
||||
}
|
||||
return
|
||||
}
|
||||
func (m Mapper) saveParams(params Params) {
|
||||
b, err := cdc.MarshalJSON(params)
|
||||
b, err := m.cdc.MarshalJSON(params)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -342,7 +344,7 @@ func (m Mapper) loadGlobalState() (gs *GlobalState) {
|
|||
return initialGlobalState()
|
||||
}
|
||||
gs = new(GlobalState)
|
||||
err := cdc.UnmarshalJSON(b, gs)
|
||||
err := m.cdc.UnmarshalJSON(b, gs)
|
||||
if err != nil {
|
||||
panic(err) // This error should never occur big problem if does
|
||||
}
|
||||
|
@ -350,7 +352,7 @@ func (m Mapper) loadGlobalState() (gs *GlobalState) {
|
|||
}
|
||||
|
||||
func (m Mapper) saveGlobalState(gs *GlobalState) {
|
||||
b, err := cdc.MarshalJSON(*gs)
|
||||
b, err := m.cdc.MarshalJSON(*gs)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
|
@ -6,27 +6,29 @@ import (
|
|||
)
|
||||
|
||||
// Tick - called at the end of every block
|
||||
func Tick(ctx sdk.Context, store sdk.KVStore) (change []*abci.Validator, err error) {
|
||||
func Tick(ctx sdk.Context, m Mapper) (change []*abci.Validator, err error) {
|
||||
|
||||
// retrieve params
|
||||
params := loadParams(store)
|
||||
gs := loadGlobalState(store)
|
||||
params := m.loadParams()
|
||||
gs := m.loadGlobalState()
|
||||
height := ctx.BlockHeight()
|
||||
|
||||
// Process Validator Provisions
|
||||
// XXX right now just process every 5 blocks, in new SDK make hourly
|
||||
if gs.InflationLastTime+5 <= height {
|
||||
gs.InflationLastTime = height
|
||||
processProvisions(store, gs, params)
|
||||
processProvisions(m, gs, params)
|
||||
}
|
||||
|
||||
return UpdateValidatorSet(store, gs, params)
|
||||
newVals := m.getValidators(params.MaxVals)
|
||||
// XXX determine change from old validators, set to change
|
||||
return change, nil
|
||||
}
|
||||
|
||||
var hrsPerYr = sdk.NewRat(8766) // as defined by a julian year of 365.25 days
|
||||
|
||||
// process provisions for an hour period
|
||||
func processProvisions(store sdk.KVStore, gs *GlobalState, params Params) {
|
||||
func processProvisions(m Mapper, gs *GlobalState, params Params) {
|
||||
|
||||
gs.Inflation = nextInflation(gs, params).Round(1000000000)
|
||||
|
||||
|
@ -34,7 +36,7 @@ func processProvisions(store sdk.KVStore, gs *GlobalState, params Params) {
|
|||
// more bonded tokens are added proportionally to all validators the only term
|
||||
// which needs to be updated is the `BondedPool`. So for each previsions cycle:
|
||||
|
||||
provisions := gs.Inflation.Mul(sdk.New(gs.TotalSupply)).Quo(hrsPerYr).Evaluate()
|
||||
provisions := gs.Inflation.Mul(sdk.NewRat(gs.TotalSupply)).Quo(hrsPerYr).Evaluate()
|
||||
gs.BondedPool += provisions
|
||||
gs.TotalSupply += provisions
|
||||
|
||||
|
@ -43,7 +45,7 @@ func processProvisions(store sdk.KVStore, gs *GlobalState, params Params) {
|
|||
// XXX XXX XXX XXX XXX XXX XXX XXX XXX
|
||||
|
||||
// save the params
|
||||
saveGlobalState(store, gs)
|
||||
m.saveGlobalState(gs)
|
||||
}
|
||||
|
||||
// get the next inflation rate for the hour
|
||||
|
@ -56,7 +58,7 @@ func nextInflation(gs *GlobalState, params Params) (inflation sdk.Rat) {
|
|||
// 7% and 20%.
|
||||
|
||||
// (1 - bondedRatio/GoalBonded) * InflationRateChange
|
||||
inflationRateChangePerYear := sdk.One.Sub(gs.bondedRatio().Quo(params.GoalBonded)).Mul(params.InflationRateChange)
|
||||
inflationRateChangePerYear := sdk.OneRat.Sub(gs.bondedRatio().Quo(params.GoalBonded)).Mul(params.InflationRateChange)
|
||||
inflationRateChange := inflationRateChangePerYear.Quo(hrsPerYr)
|
||||
|
||||
// increase the new annual inflation for this next cycle
|
||||
|
|
|
@ -34,9 +34,10 @@ func (msg MsgAddr) String() string {
|
|||
|
||||
// ValidateBasic - Check for non-empty candidate, and valid coins
|
||||
func (msg MsgAddr) ValidateBasic() sdk.Error {
|
||||
if msg.Address.Empty() {
|
||||
return errCandidateEmpty
|
||||
if msg.Address == nil {
|
||||
return ErrCandidateEmpty()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//______________________________________________________________________
|
||||
|
@ -54,7 +55,7 @@ func NewMsgDeclareCandidacy(bond sdk.Coin, address sdk.Address, pubkey crypto.Pu
|
|||
MsgAddr: NewMsgAddr(address),
|
||||
Description: description,
|
||||
Bond: bond,
|
||||
PubKey: PubKey,
|
||||
PubKey: pubkey,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,17 +70,17 @@ func (msg MsgDeclareCandidacy) GetSignBytes() []byte {
|
|||
|
||||
// quick validity check
|
||||
func (msg MsgDeclareCandidacy) ValidateBasic() sdk.Error {
|
||||
err := MsgAddr.ValidateBasic()
|
||||
err := msg.MsgAddr.ValidateBasic()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err := validateCoin(msg.Bond)
|
||||
err = validateCoin(msg.Bond)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
empty := Description{}
|
||||
if msg.Description == empty {
|
||||
return fmt.Errorf("description must be included")
|
||||
return newError(CodeInvalidInput, "description must be included")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -110,13 +111,13 @@ func (msg MsgEditCandidacy) GetSignBytes() []byte {
|
|||
|
||||
// quick validity check
|
||||
func (msg MsgEditCandidacy) ValidateBasic() sdk.Error {
|
||||
err := MsgAddr.ValidateBasic()
|
||||
err := msg.MsgAddr.ValidateBasic()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
empty := Description{}
|
||||
if msg.Description == empty {
|
||||
return fmt.Errorf("Transaction must include some information to modify")
|
||||
return newError(CodeInvalidInput, "Transaction must include some information to modify")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -147,11 +148,11 @@ func (msg MsgDelegate) GetSignBytes() []byte {
|
|||
|
||||
// quick validity check
|
||||
func (msg MsgDelegate) ValidateBasic() sdk.Error {
|
||||
err := MsgAddr.ValidateBasic()
|
||||
err := msg.MsgAddr.ValidateBasic()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err := validateCoin(msg.Bond)
|
||||
err = validateCoin(msg.Bond)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -167,7 +168,7 @@ type MsgUnbond struct {
|
|||
}
|
||||
|
||||
func NewMsgUnbond(shares string, address sdk.Address) MsgDelegate {
|
||||
return MsgUnbond{
|
||||
return MsgDelegate{
|
||||
MsgAddr: NewMsgAddr(address),
|
||||
Shares: shares,
|
||||
}
|
||||
|
@ -184,11 +185,12 @@ func (msg MsgUnbond) GetSignBytes() []byte {
|
|||
|
||||
// quick validity check
|
||||
func (msg MsgUnbond) ValidateBasic() sdk.Error {
|
||||
err := MsgAddr.ValidateBasic()
|
||||
err := msg.MsgAddr.ValidateBasic()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if msg.Shares {
|
||||
|
||||
if msg.Shares == "MAX" {
|
||||
return ErrCandidateEmpty()
|
||||
}
|
||||
return nil
|
||||
|
@ -197,9 +199,9 @@ func (msg MsgUnbond) ValidateBasic() sdk.Error {
|
|||
//______________________________________________________________________
|
||||
// helper
|
||||
|
||||
func validateCoin(coin coin.Coin) sdk.Error {
|
||||
coins := sdk.Coins{bond}
|
||||
if !sdk.IsValid() {
|
||||
func validateCoin(coin sdk.Coin) sdk.Error {
|
||||
coins := sdk.Coins{coin}
|
||||
if !coins.IsValid() {
|
||||
return sdk.ErrInvalidCoins()
|
||||
}
|
||||
if !coins.IsPositive() {
|
||||
|
|
|
@ -8,10 +8,10 @@ import (
|
|||
|
||||
// Params defines the high level settings for staking
|
||||
type Params struct {
|
||||
InflationRateChange sdk.Rational `json:"inflation_rate_change"` // maximum annual change in inflation rate
|
||||
InflationMax sdk.Rational `json:"inflation_max"` // maximum inflation rate
|
||||
InflationMin sdk.Rational `json:"inflation_min"` // minimum inflation rate
|
||||
GoalBonded sdk.Rational `json:"goal_bonded"` // Goal of percent bonded atoms
|
||||
InflationRateChange sdk.Rat `json:"inflation_rate_change"` // maximum annual change in inflation rate
|
||||
InflationMax sdk.Rat `json:"inflation_max"` // maximum inflation rate
|
||||
InflationMin sdk.Rat `json:"inflation_min"` // minimum inflation rate
|
||||
GoalBonded sdk.Rat `json:"goal_bonded"` // Goal of percent bonded atoms
|
||||
|
||||
MaxVals uint16 `json:"max_vals"` // maximum number of validators
|
||||
BondDenom string `json:"bond_denom"` // bondable coin denomination
|
||||
|
@ -43,12 +43,12 @@ func defaultParams() Params {
|
|||
// GlobalState - dynamic parameters of the current state
|
||||
type GlobalState struct {
|
||||
TotalSupply int64 `json:"total_supply"` // total supply of all tokens
|
||||
BondedShares sdk.Rational `json:"bonded_shares"` // sum of all shares distributed for the Bonded Pool
|
||||
UnbondedShares sdk.Rational `json:"unbonded_shares"` // sum of all shares distributed for the Unbonded Pool
|
||||
BondedShares sdk.Rat `json:"bonded_shares"` // sum of all shares distributed for the Bonded Pool
|
||||
UnbondedShares sdk.Rat `json:"unbonded_shares"` // sum of all shares distributed for the Unbonded Pool
|
||||
BondedPool int64 `json:"bonded_pool"` // reserve of bonded tokens
|
||||
UnbondedPool int64 `json:"unbonded_pool"` // reserve of unbonded tokens held with candidates
|
||||
InflationLastTime int64 `json:"inflation_last_time"` // block which the last inflation was processed // TODO make time
|
||||
Inflation sdk.Rational `json:"inflation"` // current annual inflation rate
|
||||
Inflation sdk.Rat `json:"inflation"` // current annual inflation rate
|
||||
}
|
||||
|
||||
// XXX define globalstate interface?
|
||||
|
@ -66,7 +66,7 @@ func initialGlobalState() *GlobalState {
|
|||
}
|
||||
|
||||
// get the bond ratio of the global state
|
||||
func (gs *GlobalState) bondedRatio() sdk.Rational {
|
||||
func (gs *GlobalState) bondedRatio() sdk.Rat {
|
||||
if gs.TotalSupply > 0 {
|
||||
return sdk.NewRat(gs.BondedPool, gs.TotalSupply)
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ func (gs *GlobalState) bondedRatio() sdk.Rational {
|
|||
}
|
||||
|
||||
// get the exchange rate of bonded token per issued share
|
||||
func (gs *GlobalState) bondedShareExRate() sdk.Rational {
|
||||
func (gs *GlobalState) bondedShareExRate() sdk.Rat {
|
||||
if gs.BondedShares.IsZero() {
|
||||
return sdk.OneRat
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ func (gs *GlobalState) bondedShareExRate() sdk.Rational {
|
|||
}
|
||||
|
||||
// get the exchange rate of unbonded tokens held in candidates per issued share
|
||||
func (gs *GlobalState) unbondedShareExRate() sdk.Rational {
|
||||
func (gs *GlobalState) unbondedShareExRate() sdk.Rat {
|
||||
if gs.UnbondedShares.IsZero() {
|
||||
return sdk.OneRat
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ func (gs *GlobalState) unbondedShareExRate() sdk.Rational {
|
|||
// expand to include the function of actually transfering the tokens
|
||||
|
||||
//XXX CONFIRM that use of the exRate is correct with Zarko Spec!
|
||||
func (gs *GlobalState) addTokensBonded(amount int64) (issuedShares sdk.Rational) {
|
||||
func (gs *GlobalState) addTokensBonded(amount int64) (issuedShares sdk.Rat) {
|
||||
issuedShares = gs.bondedShareExRate().Inv().Mul(sdk.NewRat(amount)) // (tokens/shares)^-1 * tokens
|
||||
gs.BondedPool += amount
|
||||
gs.BondedShares = gs.BondedShares.Add(issuedShares)
|
||||
|
@ -101,7 +101,7 @@ func (gs *GlobalState) addTokensBonded(amount int64) (issuedShares sdk.Rational)
|
|||
}
|
||||
|
||||
//XXX CONFIRM that use of the exRate is correct with Zarko Spec!
|
||||
func (gs *GlobalState) removeSharesBonded(shares sdk.Rational) (removedTokens int64) {
|
||||
func (gs *GlobalState) removeSharesBonded(shares sdk.Rat) (removedTokens int64) {
|
||||
removedTokens = gs.bondedShareExRate().Mul(shares).Evaluate() // (tokens/shares) * shares
|
||||
gs.BondedShares = gs.BondedShares.Sub(shares)
|
||||
gs.BondedPool -= removedTokens
|
||||
|
@ -109,7 +109,7 @@ func (gs *GlobalState) removeSharesBonded(shares sdk.Rational) (removedTokens in
|
|||
}
|
||||
|
||||
//XXX CONFIRM that use of the exRate is correct with Zarko Spec!
|
||||
func (gs *GlobalState) addTokensUnbonded(amount int64) (issuedShares sdk.Rational) {
|
||||
func (gs *GlobalState) addTokensUnbonded(amount int64) (issuedShares sdk.Rat) {
|
||||
issuedShares = gs.unbondedShareExRate().Inv().Mul(sdk.NewRat(amount)) // (tokens/shares)^-1 * tokens
|
||||
gs.UnbondedShares = gs.UnbondedShares.Add(issuedShares)
|
||||
gs.UnbondedPool += amount
|
||||
|
@ -117,7 +117,7 @@ func (gs *GlobalState) addTokensUnbonded(amount int64) (issuedShares sdk.Rationa
|
|||
}
|
||||
|
||||
//XXX CONFIRM that use of the exRate is correct with Zarko Spec!
|
||||
func (gs *GlobalState) removeSharesUnbonded(shares sdk.Rational) (removedTokens int64) {
|
||||
func (gs *GlobalState) removeSharesUnbonded(shares sdk.Rat) (removedTokens int64) {
|
||||
removedTokens = gs.unbondedShareExRate().Mul(shares).Evaluate() // (tokens/shares) * shares
|
||||
gs.UnbondedShares = gs.UnbondedShares.Sub(shares)
|
||||
gs.UnbondedPool -= removedTokens
|
||||
|
@ -149,9 +149,9 @@ type Candidate struct {
|
|||
Status CandidateStatus `json:"status"` // Bonded status
|
||||
PubKey crypto.PubKey `json:"pub_key"` // Pubkey of candidate
|
||||
Address sdk.Address `json:"owner"` // Sender of BondTx - UnbondTx returns here
|
||||
Assets sdk.Rational `json:"assets"` // total shares of a global hold pools TODO custom type PoolShares
|
||||
Liabilities sdk.Rational `json:"liabilities"` // total shares issued to a candidate's delegators TODO custom type DelegatorShares
|
||||
VotingPower sdk.Rational `json:"voting_power"` // Voting power if considered a validator
|
||||
Assets sdk.Rat `json:"assets"` // total shares of a global hold pools TODO custom type PoolShares
|
||||
Liabilities sdk.Rat `json:"liabilities"` // total shares issued to a candidate's delegators TODO custom type DelegatorShares
|
||||
VotingPower sdk.Rat `json:"voting_power"` // Voting power if considered a validator
|
||||
Description Description `json:"description"` // Description terms for the candidate
|
||||
}
|
||||
|
||||
|
@ -177,7 +177,7 @@ func NewCandidate(pubKey crypto.PubKey, address sdk.Address, description Descrip
|
|||
}
|
||||
|
||||
// get the exchange rate of global pool shares over delegator shares
|
||||
func (c *Candidate) delegatorShareExRate() sdk.Rational {
|
||||
func (c *Candidate) delegatorShareExRate() sdk.Rat {
|
||||
if c.Liabilities.IsZero() {
|
||||
return sdk.OneRat
|
||||
}
|
||||
|
@ -185,11 +185,11 @@ func (c *Candidate) delegatorShareExRate() sdk.Rational {
|
|||
}
|
||||
|
||||
// add tokens to a candidate
|
||||
func (c *Candidate) addTokens(amount int64, gs *GlobalState) (issuedDelegatorShares sdk.Rational) {
|
||||
func (c *Candidate) addTokens(amount int64, gs *GlobalState) (issuedDelegatorShares sdk.Rat) {
|
||||
|
||||
exRate := c.delegatorShareExRate()
|
||||
|
||||
var receivedGlobalShares sdk.Rational
|
||||
var receivedGlobalShares sdk.Rat
|
||||
if c.Status == Bonded {
|
||||
receivedGlobalShares = gs.addTokensBonded(amount)
|
||||
} else {
|
||||
|
@ -203,14 +203,14 @@ func (c *Candidate) addTokens(amount int64, gs *GlobalState) (issuedDelegatorSha
|
|||
}
|
||||
|
||||
// remove shares from a candidate
|
||||
func (c *Candidate) removeShares(shares sdk.Rational, gs *GlobalState) (removedTokens int64) {
|
||||
func (c *Candidate) removeShares(shares sdk.Rat, gs *GlobalState) (createdCoins int64) {
|
||||
|
||||
globalPoolSharesToRemove := c.delegatorShareExRate().Mul(shares)
|
||||
|
||||
if c.Status == Bonded {
|
||||
removedTokens = gs.removeSharesBonded(globalPoolSharesToRemove)
|
||||
createdCoins = gs.removeSharesBonded(globalPoolSharesToRemove)
|
||||
} else {
|
||||
removedTokens = gs.removeSharesUnbonded(globalPoolSharesToRemove)
|
||||
createdCoins = gs.removeSharesUnbonded(globalPoolSharesToRemove)
|
||||
}
|
||||
c.Assets = c.Assets.Sub(globalPoolSharesToRemove)
|
||||
|
||||
|
@ -229,8 +229,8 @@ func (c *Candidate) validator() Validator {
|
|||
|
||||
// Validator is one of the top Candidates
|
||||
type Validator struct {
|
||||
PubKey crypto.PubKey `json:"pub_key"` // Pubkey of candidate
|
||||
VotingPower sdk.Rational `json:"voting_power"` // Voting power if considered a validator
|
||||
Address sdk.Address `json:"address"` // Address of validator
|
||||
VotingPower sdk.Rat `json:"voting_power"` // Voting power if considered a validator
|
||||
}
|
||||
|
||||
// ABCIValidator - Get the validator from a bond value
|
||||
|
@ -257,7 +257,7 @@ type Candidates []*Candidate
|
|||
// pubKey.
|
||||
type DelegatorBond struct {
|
||||
Address sdk.Address `json:"pub_key"`
|
||||
Shares sdk.Rational `json:"shares"`
|
||||
Shares sdk.Rat `json:"shares"`
|
||||
}
|
||||
|
||||
// Perform all the actions required to bond tokens to a delegator bond from their account
|
||||
|
|
Loading…
Reference in New Issue