parent
59b10d33c1
commit
292e156872
55
glide.yaml
55
glide.yaml
|
@ -1,55 +0,0 @@
|
||||||
package: github.com/cosmos/cosmos-sdk
|
|
||||||
import:
|
|
||||||
- package: github.com/golang/protobuf
|
|
||||||
version: ^1.0.0
|
|
||||||
subpackages:
|
|
||||||
- proto
|
|
||||||
- package: github.com/bgentry/speakeasy
|
|
||||||
version: ^0.1.0
|
|
||||||
- package: github.com/mattn/go-isatty
|
|
||||||
version: ~0.0.3
|
|
||||||
- package: github.com/pkg/errors
|
|
||||||
version: ^0.8.0
|
|
||||||
- package: github.com/rigelrozanski/common
|
|
||||||
- package: github.com/tendermint/abci
|
|
||||||
version: develop
|
|
||||||
subpackages:
|
|
||||||
- server
|
|
||||||
- types
|
|
||||||
- package: github.com/tendermint/go-crypto
|
|
||||||
version: develop
|
|
||||||
- package: github.com/tendermint/go-wire
|
|
||||||
version: develop
|
|
||||||
- package: github.com/tendermint/iavl
|
|
||||||
version: develop
|
|
||||||
- package: github.com/tendermint/tmlibs
|
|
||||||
version: develop
|
|
||||||
subpackages:
|
|
||||||
- common
|
|
||||||
- db
|
|
||||||
- log
|
|
||||||
- logger
|
|
||||||
- merkle
|
|
||||||
- package: github.com/tendermint/tendermint
|
|
||||||
version: breaking/wire-sdk2
|
|
||||||
subpackages:
|
|
||||||
- cmd/tendermint/commands
|
|
||||||
- config
|
|
||||||
- lite
|
|
||||||
- rpc/client
|
|
||||||
- types
|
|
||||||
- package: golang.org/x/crypto
|
|
||||||
subpackages:
|
|
||||||
- ripemd160
|
|
||||||
- package: github.com/spf13/pflag
|
|
||||||
version: v1.0.0
|
|
||||||
- package: github.com/spf13/cobra
|
|
||||||
version: v0.0.1
|
|
||||||
- package: github.com/spf13/viper
|
|
||||||
version: ^1.0.0
|
|
||||||
testImport:
|
|
||||||
- package: github.com/stretchr/testify
|
|
||||||
version: ^1.2.1
|
|
||||||
subpackages:
|
|
||||||
- assert
|
|
||||||
- require
|
|
|
@ -2,23 +2,11 @@ package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
wire "github.com/tendermint/go-wire"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var ratCdc = RegisterWire(wire.NewCodec())
|
|
||||||
|
|
||||||
// add rational codec elements to provided codec
|
|
||||||
func RegisterWire(cdc *wire.Codec) *wire.Codec {
|
|
||||||
cdc.RegisterInterface((*Rational)(nil), nil)
|
|
||||||
cdc.RegisterConcrete(Rat{}, "rat", nil)
|
|
||||||
return cdc
|
|
||||||
}
|
|
||||||
|
|
||||||
// "that's one big rat!"
|
// "that's one big rat!"
|
||||||
// ______
|
// ______
|
||||||
// / / /\ \____oo
|
// / / /\ \____oo
|
||||||
|
@ -175,32 +163,44 @@ func (r Rat) Round(precisionFactor int64) Rational {
|
||||||
|
|
||||||
//___________________________________________________________________________________
|
//___________________________________________________________________________________
|
||||||
|
|
||||||
|
//var ratCdc = RegisterWire(wire.NewCodec())
|
||||||
|
//// add rational codec elements to provided codec
|
||||||
|
//func RegisterWire(cdc *wire.Codec) *wire.Codec {
|
||||||
|
//cdc.RegisterInterface((*Rational)(nil), nil)
|
||||||
|
//cdc.RegisterConcrete(Rat{}, "rat", nil)
|
||||||
|
//return cdc
|
||||||
|
//}
|
||||||
|
|
||||||
//TODO there has got to be a better way using native MarshalText and UnmarshalText
|
//TODO there has got to be a better way using native MarshalText and UnmarshalText
|
||||||
|
|
||||||
// RatMarshal - Marshable Rat Struct
|
// RatMarshal - Marshable Rat Struct
|
||||||
type RatMarshal struct {
|
//type RatMarshal struct {
|
||||||
Numerator int64 `json:"numerator"`
|
//Numerator int64 `json:"numerator"`
|
||||||
Denominator int64 `json:"denominator"`
|
//Denominator int64 `json:"denominator"`
|
||||||
}
|
//}
|
||||||
|
|
||||||
// MarshalJSON - custom implementation of JSON Marshal
|
//// MarshalJSON - custom implementation of JSON Marshal
|
||||||
func (r Rat) MarshalJSON() ([]byte, error) {
|
//func (r Rat) MarshalJSON() ([]byte, error) {
|
||||||
return ratCdc.MarshalJSON(RatMarshal{r.Num(), r.Denom()})
|
//return ratCdc.MarshalJSON(RatMarshal{r.Num(), r.Denom()})
|
||||||
}
|
//}
|
||||||
|
|
||||||
// UnmarshalJSON - custom implementation of JSON Unmarshal
|
//// UnmarshalJSON - custom implementation of JSON Unmarshal
|
||||||
func (r *Rat) UnmarshalJSON(data []byte) (err error) {
|
//func (r *Rat) UnmarshalJSON(data []byte) (err error) {
|
||||||
defer func() {
|
//defer func() {
|
||||||
if rcv := recover(); rcv != nil {
|
//if rcv := recover(); rcv != nil {
|
||||||
err = fmt.Errorf("Panic during UnmarshalJSON: %v", rcv)
|
//err = fmt.Errorf("Panic during UnmarshalJSON: %v", rcv)
|
||||||
}
|
//}
|
||||||
}()
|
//}()
|
||||||
|
|
||||||
ratMar := new(RatMarshal)
|
//ratMar := new(RatMarshal)
|
||||||
if err := ratCdc.UnmarshalJSON(data, ratMar); err != nil {
|
//if err := ratCdc.UnmarshalJSON(data, ratMar); err != nil {
|
||||||
return err
|
//return err
|
||||||
}
|
//}
|
||||||
r.Rat = big.NewRat(ratMar.Numerator, ratMar.Denominator)
|
//r.Rat = big.NewRat(ratMar.Numerator, ratMar.Denominator)
|
||||||
|
|
||||||
return nil
|
//return nil
|
||||||
}
|
//}
|
||||||
|
|
||||||
|
//nolint
|
||||||
|
func (r Rat) MarshalJSON() ([]byte, error) { return r.MarshalText() }
|
||||||
|
func (r *Rat) UnmarshalJSON(data []byte) (err error) { return r.UnmarshalText(data) }
|
||||||
|
|
|
@ -14,9 +14,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// separated for testing
|
// separated for testing
|
||||||
func InitState(ctx sdk.Context, key, value string) error {
|
func InitState(ctx sdk.Context, mapper Mapper, key, value string) error {
|
||||||
|
|
||||||
params := loadParams(store)
|
params := mapper.loadParams()
|
||||||
switch key {
|
switch key {
|
||||||
case "allowed_bond_denom":
|
case "allowed_bond_denom":
|
||||||
params.AllowedBondDenom = value
|
params.AllowedBondDenom = value
|
||||||
|
@ -39,74 +39,57 @@ func InitState(ctx sdk.Context, key, value string) error {
|
||||||
params.GasUnbond = int64(i)
|
params.GasUnbond = int64(i)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return sdk.ErrUnknownKey(key)
|
return sdk.ErrUnknownRequest(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
saveParams(store, params)
|
mapper.saveParams(params)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//_______________________________________________________________________
|
//_______________________________________________________________________
|
||||||
|
|
||||||
func NewHandler(stakeKey sdk.StoreKey, ck bank.CoinKeeper) sdk.Handler {
|
func NewHandler(mapper Mapper, ck bank.CoinKeeper) sdk.Handler {
|
||||||
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
|
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
|
||||||
|
|
||||||
res := sdk.Result{}
|
params := mapper.loadParams()
|
||||||
|
|
||||||
err := msg.ValidateBasic()
|
res := msg.ValidateBasic().Result()
|
||||||
if err != nil {
|
if res.Code != sdk.CodeOK {
|
||||||
return res, err
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the fee for each tx type
|
|
||||||
if ctx.IsCheckTx() {
|
|
||||||
// XXX: add some tags so we can search it!
|
|
||||||
switch txInner := tx.Unwrap().(type) {
|
|
||||||
case TxDeclareCandidacy:
|
|
||||||
return sdk.NewCheck(params.GasDeclareCandidacy, "")
|
|
||||||
case TxEditCandidacy:
|
|
||||||
return sdk.NewCheck(params.GasEditCandidacy, "")
|
|
||||||
case TxDelegate:
|
|
||||||
return sdk.NewCheck(params.GasDelegate, "")
|
|
||||||
case TxUnbond:
|
|
||||||
return sdk.NewCheck(params.GasUnbond, "")
|
|
||||||
default:
|
|
||||||
return sdk.ErrUnknownTxType(tx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: remove redundancy
|
|
||||||
// also we don't need to check the res - gas is already deducted in sdk
|
|
||||||
_, err = h.CheckTx(ctx, store, tx, nil)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
sender, err := getTxSender(ctx)
|
sender, err := getTxSender(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
keeper := NewKeeper(ctx, stakeKey)
|
|
||||||
transact := NewTransact(ctx, ck)
|
transact := NewTransact(ctx, ck)
|
||||||
|
|
||||||
// Run the transaction
|
// Run the transaction
|
||||||
switch _tx := tx.Unwrap().(type) {
|
switch _tx := tx.Unwrap().(type) {
|
||||||
case TxDeclareCandidacy:
|
case TxDeclareCandidacy:
|
||||||
res.GasUsed = params.GasDeclareCandidacy
|
if !ctx.IsCheckTx() {
|
||||||
|
res.GasUsed = params.GasDeclareCandidacy
|
||||||
|
}
|
||||||
return res, transact.declareCandidacy(_tx)
|
return res, transact.declareCandidacy(_tx)
|
||||||
case TxEditCandidacy:
|
case TxEditCandidacy:
|
||||||
res.GasUsed = params.GasEditCandidacy
|
if !ctx.IsCheckTx() {
|
||||||
|
res.GasUsed = params.GasEditCandidacy
|
||||||
|
}
|
||||||
return res, transact.editCandidacy(_tx)
|
return res, transact.editCandidacy(_tx)
|
||||||
case TxDelegate:
|
case TxDelegate:
|
||||||
res.GasUsed = params.GasDelegate
|
if !ctx.IsCheckTx() {
|
||||||
|
res.GasUsed = params.GasDelegate
|
||||||
|
}
|
||||||
return res, transact.delegate(_tx)
|
return res, transact.delegate(_tx)
|
||||||
case TxUnbond:
|
case TxUnbond:
|
||||||
//context with hold account permissions
|
//context with hold account permissions
|
||||||
params := loadParams(store)
|
if !ctx.IsCheckTx() {
|
||||||
res.GasUsed = params.GasUnbond
|
params := loadParams(store)
|
||||||
//ctx2 := ctx.WithPermissions(params.HoldBonded) //TODO remove this line if non-permissioned ctx works
|
res.GasUsed = params.GasUnbond
|
||||||
|
}
|
||||||
return res, transact.unbond(_tx)
|
return res, transact.unbond(_tx)
|
||||||
|
default:
|
||||||
|
return sdk.ErrUnknownTxType(msgType)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -126,20 +109,21 @@ func getTxSender(ctx sdk.Context) (sender crypto.Address, err error) {
|
||||||
// common fields to all transactions
|
// common fields to all transactions
|
||||||
type transact struct {
|
type transact struct {
|
||||||
sender crypto.Address
|
sender crypto.Address
|
||||||
keeper Keeper
|
mapper Mapper
|
||||||
coinKeeper bank.CoinKeeper
|
coinKeeper bank.CoinKeeper
|
||||||
params Params
|
params Params
|
||||||
gs *GlobalState
|
gs *GlobalState
|
||||||
|
isCheckTx sdk.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX move keeper creation to application?
|
func newTransact(ctx sdk.Context, sender sdk.Address, mapper Mapper, ck bank.CoinKeeper) transact {
|
||||||
func newTransact(ctx sdk.Context, keeper Keeper, ck bank.CoinKeeper) transact {
|
|
||||||
return transact{
|
return transact{
|
||||||
sender: sender,
|
sender: sender,
|
||||||
keeper: keeper,
|
mapper: mapper,
|
||||||
coinKeeper: ck,
|
coinKeeper: ck,
|
||||||
params: keeper.loadParams(),
|
params: mapper.loadParams(),
|
||||||
gs: keeper.loadGlobalState(),
|
gs: mapper.loadGlobalState(),
|
||||||
|
isCheckTx: ctx.IsCheckTx(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,8 +156,8 @@ func (tr transact) unbondedToBondedPool(candidate *Candidate) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// return an error if the bonds coins are incorrect
|
// return an error if the bonds coins are incorrect
|
||||||
func checkDenom(keeper Keeper, tx BondUpdate) error {
|
func checkDenom(mapper Mapper, tx BondUpdate) error {
|
||||||
if tx.Bond.Denom != keeper.loadParams().AllowedBondDenom {
|
if tx.Bond.Denom != mapper.loadParams().AllowedBondDenom {
|
||||||
return fmt.Errorf("Invalid coin denomination")
|
return fmt.Errorf("Invalid coin denomination")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -186,25 +170,26 @@ func checkDenom(keeper Keeper, tx BondUpdate) error {
|
||||||
func (tr transact) declareCandidacy(tx TxDeclareCandidacy) error {
|
func (tr transact) declareCandidacy(tx TxDeclareCandidacy) error {
|
||||||
|
|
||||||
// check to see if the pubkey or sender has been registered before
|
// check to see if the pubkey or sender has been registered before
|
||||||
candidate := tr.keeper.loadCandidate(tx.PubKey)
|
if tr.mapper.loadCandidate(tx.PubKey) != nil {
|
||||||
if candidate != nil {
|
|
||||||
return fmt.Errorf("cannot bond to pubkey which is already declared candidacy"+
|
return fmt.Errorf("cannot bond to pubkey which is already declared candidacy"+
|
||||||
" PubKey %v already registered with %v candidate address",
|
" PubKey %v already registered with %v candidate address",
|
||||||
candidate.PubKey, candidate.Owner)
|
candidate.PubKey, candidate.Owner)
|
||||||
}
|
}
|
||||||
err := checkDenom(tx.BondUpdate, tr.keeper)
|
err := checkDenom(tx.BondUpdate, tr.mapper)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// XXX end of old check tx
|
if tr.IsCheckTx {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// create and save the empty candidate
|
// create and save the empty candidate
|
||||||
bond := tr.keeper.loadCandidate(tx.PubKey)
|
bond := tr.mapper.loadCandidate(tx.PubKey)
|
||||||
if bond != nil {
|
if bond != nil {
|
||||||
return ErrCandidateExistsAddr()
|
return ErrCandidateExistsAddr()
|
||||||
}
|
}
|
||||||
candidate := NewCandidate(tx.PubKey, tr.sender, tx.Description)
|
candidate := NewCandidate(tx.PubKey, tr.sender, tx.Description)
|
||||||
tr.keeper.saveCandidate(candidate)
|
tr.mapper.saveCandidate(candidate)
|
||||||
|
|
||||||
// move coins from the tr.sender account to a (self-bond) delegator account
|
// move coins from the tr.sender account to a (self-bond) delegator account
|
||||||
// the candidate account and global shares are updated within here
|
// the candidate account and global shares are updated within here
|
||||||
|
@ -215,14 +200,15 @@ func (tr transact) declareCandidacy(tx TxDeclareCandidacy) error {
|
||||||
func (tr transact) editCandidacy(tx TxEditCandidacy) error {
|
func (tr transact) editCandidacy(tx TxEditCandidacy) error {
|
||||||
|
|
||||||
// candidate must already be registered
|
// candidate must already be registered
|
||||||
candidate := tr.keeper.loadCandidate(tx.PubKey)
|
if tr.mapper.loadCandidate(tx.PubKey) == nil { // does PubKey exist
|
||||||
if candidate == nil { // does PubKey exist
|
|
||||||
return fmt.Errorf("cannot delegate to non-existant PubKey %v", tx.PubKey)
|
return fmt.Errorf("cannot delegate to non-existant PubKey %v", tx.PubKey)
|
||||||
}
|
}
|
||||||
// XXX end of old check tx
|
if tr.IsCheckTx {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Get the pubKey bond account
|
// Get the pubKey bond account
|
||||||
candidate := tr.keeper.loadCandidate(tx.PubKey)
|
candidate := tr.mapper.loadCandidate(tx.PubKey)
|
||||||
if candidate == nil {
|
if candidate == nil {
|
||||||
return ErrBondNotNominated()
|
return ErrBondNotNominated()
|
||||||
}
|
}
|
||||||
|
@ -244,24 +230,25 @@ func (tr transact) editCandidacy(tx TxEditCandidacy) error {
|
||||||
candidate.Description.Details = tx.Description.Details
|
candidate.Description.Details = tx.Description.Details
|
||||||
}
|
}
|
||||||
|
|
||||||
tr.keeper.saveCandidate(candidate)
|
tr.mapper.saveCandidate(candidate)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr transact) delegate(tx TxDelegate) error {
|
func (tr transact) delegate(tx TxDelegate) error {
|
||||||
|
|
||||||
candidate := tr.keeper.loadCandidate(tx.PubKey)
|
if tr.mapper.loadCandidate(tx.PubKey) == nil { // does PubKey exist
|
||||||
if candidate == nil { // does PubKey exist
|
|
||||||
return fmt.Errorf("cannot delegate to non-existant PubKey %v", tx.PubKey)
|
return fmt.Errorf("cannot delegate to non-existant PubKey %v", tx.PubKey)
|
||||||
}
|
}
|
||||||
err := checkDenom(tx.BondUpdate, tr.keeper)
|
err := checkDenom(tx.BondUpdate, tr.mapper)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// end of old check tx
|
if tr.IsCheckTx {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Get the pubKey bond account
|
// Get the pubKey bond account
|
||||||
candidate := tr.keeper.loadCandidate(tx.PubKey)
|
candidate := tr.mapper.loadCandidate(tx.PubKey)
|
||||||
if candidate == nil {
|
if candidate == nil {
|
||||||
return ErrBondNotNominated()
|
return ErrBondNotNominated()
|
||||||
}
|
}
|
||||||
|
@ -289,7 +276,7 @@ func (tr transact) delegateWithCandidate(tx TxDelegate, candidate *Candidate) er
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get or create the delegator bond
|
// Get or create the delegator bond
|
||||||
bond := tr.keeper.loadDelegatorBond(tr.sender, tx.PubKey)
|
bond := tr.mapper.loadDelegatorBond(tr.sender, tx.PubKey)
|
||||||
if bond == nil {
|
if bond == nil {
|
||||||
bond = &DelegatorBond{
|
bond = &DelegatorBond{
|
||||||
PubKey: tx.PubKey,
|
PubKey: tx.PubKey,
|
||||||
|
@ -299,19 +286,19 @@ func (tr transact) delegateWithCandidate(tx TxDelegate, candidate *Candidate) er
|
||||||
|
|
||||||
// Account new shares, save
|
// Account new shares, save
|
||||||
bond.Shares = bond.Shares.Add(candidate.addTokens(tx.Bond.Amount, tr.gs))
|
bond.Shares = bond.Shares.Add(candidate.addTokens(tx.Bond.Amount, tr.gs))
|
||||||
tr.keeper.saveCandidate(candidate)
|
tr.mapper.saveCandidate(candidate)
|
||||||
tr.keeper.saveDelegatorBond(tr.sender, bond)
|
tr.mapper.saveDelegatorBond(tr.sender, bond)
|
||||||
tr.keeper.saveGlobalState(tr.gs)
|
tr.mapper.saveGlobalState(tr.gs)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr transact) unbond(tx TxUnbond) error {
|
func (tr transact) unbond(tx TxUnbond) error {
|
||||||
|
|
||||||
// check if bond has any shares in it unbond
|
// check if bond has any shares in it unbond
|
||||||
bond := tr.keeper.loadDelegatorBond(tr.sender, tx.PubKey)
|
existingBond := tr.mapper.loadDelegatorBond(tr.sender, tx.PubKey)
|
||||||
sharesStr := viper.GetString(tx.Shares)
|
sharesStr := viper.GetString(tx.Shares)
|
||||||
if bond.Shares.LT(sdk.ZeroRat) { // bond shares < tx shares
|
if existingBond.Shares.LT(sdk.ZeroRat) { // bond shares < tx shares
|
||||||
return fmt.Errorf("no shares in account to unbond")
|
return errors.New("no shares in account to unbond")
|
||||||
}
|
}
|
||||||
|
|
||||||
// if shares set to special case Max then we're good
|
// if shares set to special case Max then we're good
|
||||||
|
@ -331,7 +318,7 @@ func (tr transact) unbond(tx TxUnbond) error {
|
||||||
// XXX end of old checkTx
|
// XXX end of old checkTx
|
||||||
|
|
||||||
// get delegator bond
|
// get delegator bond
|
||||||
bond := tr.keeper.loadDelegatorBond(tr.sender, tx.PubKey)
|
bond := tr.mapper.loadDelegatorBond(tr.sender, tx.PubKey)
|
||||||
if bond == nil {
|
if bond == nil {
|
||||||
return ErrNoDelegatorForAddress()
|
return ErrNoDelegatorForAddress()
|
||||||
}
|
}
|
||||||
|
@ -355,7 +342,7 @@ func (tr transact) unbond(tx TxUnbond) error {
|
||||||
bond.Shares = bond.Shares.Sub(shares)
|
bond.Shares = bond.Shares.Sub(shares)
|
||||||
|
|
||||||
// get pubKey candidate
|
// get pubKey candidate
|
||||||
candidate := tr.keeper.loadCandidate(tx.PubKey)
|
candidate := tr.mapper.loadCandidate(tx.PubKey)
|
||||||
if candidate == nil {
|
if candidate == nil {
|
||||||
return ErrNoCandidateForAddress()
|
return ErrNoCandidateForAddress()
|
||||||
}
|
}
|
||||||
|
@ -371,9 +358,9 @@ func (tr transact) unbond(tx TxUnbond) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove the bond
|
// remove the bond
|
||||||
tr.keeper.removeDelegatorBond(tr.sender, tx.PubKey)
|
tr.mapper.removeDelegatorBond(tr.sender, tx.PubKey)
|
||||||
} else {
|
} else {
|
||||||
tr.keeper.saveDelegatorBond(tr.sender, bond)
|
tr.mapper.saveDelegatorBond(tr.sender, bond)
|
||||||
}
|
}
|
||||||
|
|
||||||
// transfer coins back to account
|
// transfer coins back to account
|
||||||
|
@ -408,11 +395,11 @@ func (tr transact) unbond(tx TxUnbond) error {
|
||||||
|
|
||||||
// deduct shares from the candidate and save
|
// deduct shares from the candidate and save
|
||||||
if candidate.Liabilities.IsZero() {
|
if candidate.Liabilities.IsZero() {
|
||||||
tr.keeper.removeCandidate(tx.PubKey)
|
tr.mapper.removeCandidate(tx.PubKey)
|
||||||
} else {
|
} else {
|
||||||
tr.keeper.saveCandidate(candidate)
|
tr.mapper.saveCandidate(candidate)
|
||||||
}
|
}
|
||||||
|
|
||||||
tr.keeper.saveGlobalState(tr.gs)
|
tr.mapper.saveGlobalState(tr.gs)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
crypto "github.com/tendermint/go-crypto"
|
crypto "github.com/tendermint/go-crypto"
|
||||||
"github.com/tendermint/tmlibs/rational"
|
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
coin "github.com/cosmos/cosmos-sdk/x/bank" // XXX fix
|
coin "github.com/cosmos/cosmos-sdk/x/bank" // XXX fix
|
||||||
|
@ -16,23 +15,7 @@ import (
|
||||||
|
|
||||||
//______________________________________________________________________
|
//______________________________________________________________________
|
||||||
|
|
||||||
// dummy transfer functions, represents store operations on account balances
|
func initAccounts(n int, amount int64) ([]sdk.Address, map[string]int64) {
|
||||||
|
|
||||||
type testCoinSender struct {
|
|
||||||
store map[string]int64
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ coinSend = testCoinSender{} // enforce interface at compile time
|
|
||||||
|
|
||||||
func (c testCoinSender) transferFn(sender, receiver sdk.Actor, coins coin.Coins) error {
|
|
||||||
c.store[string(sender.Address)] -= coins[0].Amount
|
|
||||||
c.store[string(receiver.Address)] += coins[0].Amount
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//______________________________________________________________________
|
|
||||||
|
|
||||||
func initAccounts(n int, amount int64) ([]sdk.Actor, map[string]int64) {
|
|
||||||
accStore := map[string]int64{}
|
accStore := map[string]int64{}
|
||||||
senders := newActors(n)
|
senders := newActors(n)
|
||||||
for _, sender := range senders {
|
for _, sender := range senders {
|
||||||
|
@ -69,10 +52,10 @@ func paramsNoInflation() Params {
|
||||||
return Params{
|
return Params{
|
||||||
HoldBonded: sdk.NewActor(stakingModuleName, []byte("77777777777777777777777777777777")),
|
HoldBonded: sdk.NewActor(stakingModuleName, []byte("77777777777777777777777777777777")),
|
||||||
HoldUnbonded: sdk.NewActor(stakingModuleName, []byte("88888888888888888888888888888888")),
|
HoldUnbonded: sdk.NewActor(stakingModuleName, []byte("88888888888888888888888888888888")),
|
||||||
InflationRateChange: rational.Zero,
|
InflationRateChange: sdk.Zero,
|
||||||
InflationMax: rational.Zero,
|
InflationMax: sdk.Zero,
|
||||||
InflationMin: rational.Zero,
|
InflationMin: sdk.Zero,
|
||||||
GoalBonded: rational.New(67, 100),
|
GoalBonded: sdk.New(67, 100),
|
||||||
MaxVals: 100,
|
MaxVals: 100,
|
||||||
AllowedBondDenom: "fermion",
|
AllowedBondDenom: "fermion",
|
||||||
GasDeclareCandidacy: 20,
|
GasDeclareCandidacy: 20,
|
||||||
|
@ -82,17 +65,11 @@ func paramsNoInflation() Params {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDeliver(t, sender sdk.Actor, accStore map[string]int64) deliver {
|
func newTestTransact(t, sender sdk.Address, isCheckTx bool) transact {
|
||||||
store := initTestStore()
|
store, mapper, coinKeeper := createTestInput(t, isCheckTx)
|
||||||
params := paramsNoInflation()
|
params := paramsNoInflation()
|
||||||
saveParams(store, params)
|
mapper.saveParams(params)
|
||||||
return deliver{
|
newTransact(ctx, sender, mapper, coinKeeper)
|
||||||
store: store,
|
|
||||||
sender: sender,
|
|
||||||
params: params,
|
|
||||||
gs: loadGlobalState(store),
|
|
||||||
transfer: testCoinSender{accStore}.transferFn,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDuplicatesTxDeclareCandidacy(t *testing.T) {
|
func TestDuplicatesTxDeclareCandidacy(t *testing.T) {
|
||||||
|
|
|
@ -2,9 +2,9 @@ package stake
|
||||||
|
|
||||||
import (
|
import (
|
||||||
crypto "github.com/tendermint/go-crypto"
|
crypto "github.com/tendermint/go-crypto"
|
||||||
wire "github.com/tendermint/go-wire"
|
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
//nolint
|
//nolint
|
||||||
|
@ -28,7 +28,7 @@ func GetCandidateKey(pubKey crypto.PubKey) []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetValidatorKey - get the key for the validator used in the power-store
|
// GetValidatorKey - get the key for the validator used in the power-store
|
||||||
func GetValidatorKey(pubKey crypto.PubKey, power types.Rational) []byte {
|
func GetValidatorKey(pubKey crypto.PubKey, power sdk.Rational) []byte {
|
||||||
b, _ := cdc.MarshalJSON(power) // TODO need to handle error here?
|
b, _ := cdc.MarshalJSON(power) // TODO need to handle error here?
|
||||||
return append(ValidatorKeyPrefix, append(b, pubKey.Bytes()...)...) // TODO does this need prefix if its in its own store
|
return append(ValidatorKeyPrefix, append(b, pubKey.Bytes()...)...) // TODO does this need prefix if its in its own store
|
||||||
}
|
}
|
||||||
|
@ -63,26 +63,26 @@ func GetDelegatorBondsKey(delegator crypto.Address) []byte {
|
||||||
|
|
||||||
//___________________________________________________________________________
|
//___________________________________________________________________________
|
||||||
|
|
||||||
// keeper of the staking store
|
// mapper of the staking store
|
||||||
type Keeper struct {
|
type Mapper struct {
|
||||||
store types.KVStore
|
store sdk.KVStore
|
||||||
cdc *wire.Codec
|
cdc *wire.Codec
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewKeeper(ctx sdk.Context, key sdk.StoreKey) Keeper {
|
func NewMapper(ctx sdk.Context, key sdk.StoreKey) Mapper {
|
||||||
cdc := wire.NewCodec()
|
cdc := wire.NewCodec()
|
||||||
cdc.RegisterInterface((*types.Rational)(nil), nil) // XXX make like crypto.RegisterWire()
|
cdc.RegisterInterface((*sdk.Rational)(nil), nil) // XXX make like crypto.RegisterWire()
|
||||||
cdc.RegisterConcrete(types.Rat{}, "rat", nil)
|
cdc.RegisterConcrete(sdk.Rat{}, "rat", nil)
|
||||||
crypto.RegisterWire(cdc)
|
crypto.RegisterWire(cdc)
|
||||||
|
|
||||||
return StakeKeeper{
|
return StakeMapper{
|
||||||
store: ctx.KVStore(k.key),
|
store: ctx.KVStore(m.key),
|
||||||
cdc: cdc,
|
cdc: cdc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Keeper) loadCandidate(pubKey crypto.PubKey) *Candidate {
|
func (m Mapper) loadCandidate(pubKey crypto.PubKey) *Candidate {
|
||||||
b := k.store.Get(GetCandidateKey(pubKey))
|
b := m.store.Get(GetCandidateKey(pubKey))
|
||||||
if b == nil {
|
if b == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -94,31 +94,31 @@ func (k Keeper) loadCandidate(pubKey crypto.PubKey) *Candidate {
|
||||||
return candidate
|
return candidate
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Keeper) saveCandidate(candidate *Candidate) {
|
func (m Mapper) saveCandidate(candidate *Candidate) {
|
||||||
|
|
||||||
// XXX should only remove validator if we know candidate is a validator
|
// XXX should only remove validator if we know candidate is a validator
|
||||||
removeValidator(k.store, candidate.PubKey)
|
removeValidator(m.store, candidate.PubKey)
|
||||||
validator := &Validator{candidate.PubKey, candidate.VotingPower}
|
validator := &Validator{candidate.PubKey, candidate.VotingPower}
|
||||||
updateValidator(k.store, validator)
|
updateValidator(m.store, validator)
|
||||||
|
|
||||||
b, err := cdc.MarshalJSON(*candidate)
|
b, err := cdc.MarshalJSON(*candidate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
k.store.Set(GetCandidateKey(candidate.PubKey), b)
|
m.store.Set(GetCandidateKey(candidate.PubKey), b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Keeper) removeCandidate(pubKey crypto.PubKey) {
|
func (m Mapper) removeCandidate(pubKey crypto.PubKey) {
|
||||||
|
|
||||||
// XXX should only remove validator if we know candidate is a validator
|
// XXX should only remove validator if we know candidate is a validator
|
||||||
removeValidator(k.store, pubKey)
|
removeValidator(m.store, pubKey)
|
||||||
k.store.Delete(GetCandidateKey(pubKey))
|
m.store.Delete(GetCandidateKey(pubKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
//___________________________________________________________________________
|
//___________________________________________________________________________
|
||||||
|
|
||||||
//func loadValidator(k.store types.KVStore, pubKey crypto.PubKey, votingPower types.Rational) *Validator {
|
//func loadValidator(m.store sdk.KVStore, pubKey crypto.PubKey, votingPower sdk.Rational) *Validator {
|
||||||
//b := k.store.Get(GetValidatorKey(pubKey, votingPower))
|
//b := m.store.Get(GetValidatorKey(pubKey, votingPower))
|
||||||
//if b == nil {
|
//if b == nil {
|
||||||
//return nil
|
//return nil
|
||||||
//}
|
//}
|
||||||
|
@ -132,7 +132,7 @@ func (k Keeper) removeCandidate(pubKey crypto.PubKey) {
|
||||||
|
|
||||||
// updateValidator - update a validator and create accumulate any changes
|
// updateValidator - update a validator and create accumulate any changes
|
||||||
// in the changed validator substore
|
// in the changed validator substore
|
||||||
func (k Keeper) updateValidator(validator *Validator) {
|
func (m Mapper) updateValidator(validator *Validator) {
|
||||||
|
|
||||||
b, err := cdc.MarshalJSON(*validator)
|
b, err := cdc.MarshalJSON(*validator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -140,34 +140,34 @@ func (k Keeper) updateValidator(validator *Validator) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// add to the validators to update list if necessary
|
// add to the validators to update list if necessary
|
||||||
k.store.Set(GetValidatorUpdatesKey(validator.PubKey), b)
|
m.store.Set(GetValidatorUpdatesKey(validator.PubKey), b)
|
||||||
|
|
||||||
// update the list ordered by voting power
|
// update the list ordered by voting power
|
||||||
k.store.Set(GetValidatorKey(validator.PubKey, validator.VotingPower), b)
|
m.store.Set(GetValidatorKey(validator.PubKey, validator.VotingPower), b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Keeper) removeValidator(pubKey crypto.PubKey) {
|
func (m Mapper) removeValidator(pubKey crypto.PubKey) {
|
||||||
|
|
||||||
//add validator with zero power to the validator updates
|
//add validator with zero power to the validator updates
|
||||||
b, err := cdc.MarshalJSON(Validator{pubKey, types.ZeroRat})
|
b, err := cdc.MarshalJSON(Validator{pubKey, sdk.ZeroRat})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
k.store.Set(GetValidatorUpdatesKey(pubKey), b)
|
m.store.Set(GetValidatorUpdatesKey(pubKey), b)
|
||||||
|
|
||||||
// now actually delete from the validator set
|
// now actually delete from the validator set
|
||||||
candidate := loadCandidate(k.store, pubKey)
|
candidate := loadCandidate(m.store, pubKey)
|
||||||
if candidate != nil {
|
if candidate != nil {
|
||||||
k.store.Delete(GetValidatorKey(pubKey, candidate.VotingPower))
|
m.store.Delete(GetValidatorKey(pubKey, candidate.VotingPower))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the most recent updated validator set from the Candidates. These bonds
|
// get the most recent updated validator set from the Candidates. These bonds
|
||||||
// are already sorted by VotingPower from the UpdateVotingPower function which
|
// are already sorted by VotingPower from the UpdateVotingPower function which
|
||||||
// is the only function which is to modify the VotingPower
|
// is the only function which is to modify the VotingPower
|
||||||
func (k Keeper) getValidators(maxVal int) (validators []Validator) {
|
func (m Mapper) getValidators(maxVal int) (validators []Validator) {
|
||||||
|
|
||||||
iterator := k.store.Iterator(subspace(ValidatorKeyPrefix)) //smallest to largest
|
iterator := m.store.Iterator(subspace(ValidatorKeyPrefix)) //smallest to largest
|
||||||
|
|
||||||
validators = make([]Validator, maxVal)
|
validators = make([]Validator, maxVal)
|
||||||
for i := 0; ; i++ {
|
for i := 0; ; i++ {
|
||||||
|
@ -191,9 +191,9 @@ func (k Keeper) getValidators(maxVal int) (validators []Validator) {
|
||||||
//_________________________________________________________________________
|
//_________________________________________________________________________
|
||||||
|
|
||||||
// get the most updated validators
|
// get the most updated validators
|
||||||
func (k Keeper) getValidatorUpdates() (updates []Validator) {
|
func (m Mapper) getValidatorUpdates() (updates []Validator) {
|
||||||
|
|
||||||
iterator := k.store.Iterator(subspace(ValidatorUpdatesKeyPrefix)) //smallest to largest
|
iterator := m.store.Iterator(subspace(ValidatorUpdatesKeyPrefix)) //smallest to largest
|
||||||
|
|
||||||
for ; iterator.Valid(); iterator.Next() {
|
for ; iterator.Valid(); iterator.Next() {
|
||||||
valBytes := iterator.Value()
|
valBytes := iterator.Value()
|
||||||
|
@ -210,10 +210,10 @@ func (k Keeper) getValidatorUpdates() (updates []Validator) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove all validator update entries
|
// remove all validator update entries
|
||||||
func (k Keeper) clearValidatorUpdates(maxVal int) {
|
func (m Mapper) clearValidatorUpdates(maxVal int) {
|
||||||
iterator := k.store.Iterator(subspace(ValidatorUpdatesKeyPrefix))
|
iterator := m.store.Iterator(subspace(ValidatorUpdatesKeyPrefix))
|
||||||
for ; iterator.Valid(); iterator.Next() {
|
for ; iterator.Valid(); iterator.Next() {
|
||||||
k.store.Delete(iterator.Key()) // XXX write test for this, may need to be in a second loop
|
m.store.Delete(iterator.Key()) // XXX write test for this, may need to be in a second loop
|
||||||
}
|
}
|
||||||
iterator.Close()
|
iterator.Close()
|
||||||
}
|
}
|
||||||
|
@ -221,11 +221,11 @@ func (k Keeper) clearValidatorUpdates(maxVal int) {
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
// loadCandidates - get the active list of all candidates TODO replace with multistore
|
// loadCandidates - get the active list of all candidates TODO replace with multistore
|
||||||
func (k Keeper) loadCandidates() (candidates Candidates) {
|
func (m Mapper) loadCandidates() (candidates Candidates) {
|
||||||
|
|
||||||
iterator := k.store.Iterator(subspace(CandidateKeyPrefix))
|
iterator := m.store.Iterator(subspace(CandidateKeyPrefix))
|
||||||
//iterator := k.store.Iterator(CandidateKeyPrefix, []byte(nil))
|
//iterator := m.store.Iterator(CandidateKeyPrefix, []byte(nil))
|
||||||
//iterator := k.store.Iterator([]byte{}, []byte(nil))
|
//iterator := m.store.Iterator([]byte{}, []byte(nil))
|
||||||
|
|
||||||
for ; iterator.Valid(); iterator.Next() {
|
for ; iterator.Valid(); iterator.Next() {
|
||||||
candidateBytes := iterator.Value()
|
candidateBytes := iterator.Value()
|
||||||
|
@ -243,9 +243,9 @@ func (k Keeper) loadCandidates() (candidates Candidates) {
|
||||||
//_____________________________________________________________________
|
//_____________________________________________________________________
|
||||||
|
|
||||||
// load the pubkeys of all candidates a delegator is delegated too
|
// load the pubkeys of all candidates a delegator is delegated too
|
||||||
func (k Keeper) loadDelegatorCandidates(delegator crypto.Address) (candidates []crypto.PubKey) {
|
func (m Mapper) loadDelegatorCandidates(delegator crypto.Address) (candidates []crypto.PubKey) {
|
||||||
|
|
||||||
candidateBytes := k.store.Get(GetDelegatorBondsKey(delegator))
|
candidateBytes := m.store.Get(GetDelegatorBondsKey(delegator))
|
||||||
if candidateBytes == nil {
|
if candidateBytes == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -259,10 +259,10 @@ func (k Keeper) loadDelegatorCandidates(delegator crypto.Address) (candidates []
|
||||||
|
|
||||||
//_____________________________________________________________________
|
//_____________________________________________________________________
|
||||||
|
|
||||||
func (k Keeper) loadDelegatorBond(delegator crypto.Address,
|
func (m Mapper) loadDelegatorBond(delegator crypto.Address,
|
||||||
candidate crypto.PubKey) *DelegatorBond {
|
candidate crypto.PubKey) *DelegatorBond {
|
||||||
|
|
||||||
delegatorBytes := k.store.Get(GetDelegatorBondKey(delegator, candidate))
|
delegatorBytes := m.store.Get(GetDelegatorBondKey(delegator, candidate))
|
||||||
if delegatorBytes == nil {
|
if delegatorBytes == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -275,18 +275,18 @@ func (k Keeper) loadDelegatorBond(delegator crypto.Address,
|
||||||
return bond
|
return bond
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Keeper) saveDelegatorBond(delegator crypto.Address,
|
func (m Mapper) saveDelegatorBond(delegator crypto.Address,
|
||||||
bond *DelegatorBond) {
|
bond *DelegatorBond) {
|
||||||
|
|
||||||
// if a new bond add to the list of bonds
|
// if a new bond add to the list of bonds
|
||||||
if loadDelegatorBond(k.store, delegator, bond.PubKey) == nil {
|
if loadDelegatorBond(m.store, delegator, bond.PubKey) == nil {
|
||||||
pks := loadDelegatorCandidates(k.store, delegator)
|
pks := loadDelegatorCandidates(m.store, delegator)
|
||||||
pks = append(pks, (*bond).PubKey)
|
pks = append(pks, (*bond).PubKey)
|
||||||
b, err := cdc.MarshalJSON(pks)
|
b, err := cdc.MarshalJSON(pks)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
k.store.Set(GetDelegatorBondsKey(delegator), b)
|
m.store.Set(GetDelegatorBondsKey(delegator), b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// now actually save the bond
|
// now actually save the bond
|
||||||
|
@ -294,14 +294,14 @@ func (k Keeper) saveDelegatorBond(delegator crypto.Address,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
k.store.Set(GetDelegatorBondKey(delegator, bond.PubKey), b)
|
m.store.Set(GetDelegatorBondKey(delegator, bond.PubKey), b)
|
||||||
//updateDelegatorBonds(store, delegator)
|
//updateDelegatorBonds(store, delegator)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Keeper) removeDelegatorBond(delegator crypto.Address, candidate crypto.PubKey) {
|
func (m Mapper) removeDelegatorBond(delegator crypto.Address, candidate crypto.PubKey) {
|
||||||
// TODO use list queries on multistore to remove iterations here!
|
// TODO use list queries on multistore to remove iterations here!
|
||||||
// first remove from the list of bonds
|
// first remove from the list of bonds
|
||||||
pks := loadDelegatorCandidates(k.store, delegator)
|
pks := loadDelegatorCandidates(m.store, delegator)
|
||||||
for i, pk := range pks {
|
for i, pk := range pks {
|
||||||
if candidate.Equals(pk) {
|
if candidate.Equals(pk) {
|
||||||
pks = append(pks[:i], pks[i+1:]...)
|
pks = append(pks[:i], pks[i+1:]...)
|
||||||
|
@ -311,18 +311,18 @@ func (k Keeper) removeDelegatorBond(delegator crypto.Address, candidate crypto.P
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
k.store.Set(GetDelegatorBondsKey(delegator), b)
|
m.store.Set(GetDelegatorBondsKey(delegator), b)
|
||||||
|
|
||||||
// now remove the actual bond
|
// now remove the actual bond
|
||||||
k.store.Delete(GetDelegatorBondKey(delegator, candidate))
|
m.store.Delete(GetDelegatorBondKey(delegator, candidate))
|
||||||
//updateDelegatorBonds(store, delegator)
|
//updateDelegatorBonds(store, delegator)
|
||||||
}
|
}
|
||||||
|
|
||||||
//_______________________________________________________________________
|
//_______________________________________________________________________
|
||||||
|
|
||||||
// load/save the global staking params
|
// load/save the global staking params
|
||||||
func (k Keeper) loadParams() (params Params) {
|
func (m Mapper) loadParams() (params Params) {
|
||||||
b := k.store.Get(ParamKey)
|
b := m.store.Get(ParamKey)
|
||||||
if b == nil {
|
if b == nil {
|
||||||
return defaultParams()
|
return defaultParams()
|
||||||
}
|
}
|
||||||
|
@ -333,19 +333,19 @@ func (k Keeper) loadParams() (params Params) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
func (k Keeper) saveParams(params Params) {
|
func (m Mapper) saveParams(params Params) {
|
||||||
b, err := cdc.MarshalJSON(params)
|
b, err := cdc.MarshalJSON(params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
k.store.Set(ParamKey, b)
|
m.store.Set(ParamKey, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
//_______________________________________________________________________
|
//_______________________________________________________________________
|
||||||
|
|
||||||
// load/save the global staking state
|
// load/save the global staking state
|
||||||
func (k Keeper) loadGlobalState() (gs *GlobalState) {
|
func (m Mapper) loadGlobalState() (gs *GlobalState) {
|
||||||
b := k.store.Get(GlobalStateKey)
|
b := m.store.Get(GlobalStateKey)
|
||||||
if b == nil {
|
if b == nil {
|
||||||
return initialGlobalState()
|
return initialGlobalState()
|
||||||
}
|
}
|
||||||
|
@ -357,10 +357,10 @@ func (k Keeper) loadGlobalState() (gs *GlobalState) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Keeper) saveGlobalState(gs *GlobalState) {
|
func (m Mapper) saveGlobalState(gs *GlobalState) {
|
||||||
b, err := cdc.MarshalJSON(*gs)
|
b, err := cdc.MarshalJSON(*gs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
k.store.Set(GlobalStateKey, b)
|
m.store.Set(GlobalStateKey, b)
|
||||||
}
|
}
|
|
@ -161,7 +161,7 @@ import (
|
||||||
//}
|
//}
|
||||||
|
|
||||||
func TestState(t *testing.T) {
|
func TestState(t *testing.T) {
|
||||||
store := initTestStore(t)
|
store := createTestInput(t)
|
||||||
|
|
||||||
//delegator := crypto.Address{[]byte("addressdelegator")}
|
//delegator := crypto.Address{[]byte("addressdelegator")}
|
||||||
//validator := crypto.Address{[]byte("addressvalidator")}
|
//validator := crypto.Address{[]byte("addressvalidator")}
|
||||||
|
@ -260,7 +260,7 @@ func TestState(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetValidators(t *testing.T) {
|
func TestGetValidators(t *testing.T) {
|
||||||
store := initTestStore(t)
|
store, ctx, key := createTestInput(t, false)
|
||||||
N := 5
|
N := 5
|
||||||
addrs := newAddrs(N)
|
addrs := newAddrs(N)
|
||||||
candidatesFromActors(store, addrs, []int64{400, 200, 0, 0, 0})
|
candidatesFromActors(store, addrs, []int64{400, 200, 0, 0, 0})
|
|
@ -7,10 +7,10 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
abci "github.com/tendermint/abci/types"
|
||||||
crypto "github.com/tendermint/go-crypto"
|
crypto "github.com/tendermint/go-crypto"
|
||||||
dbm "github.com/tendermint/tmlibs/db"
|
dbm "github.com/tendermint/tmlibs/db"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/store"
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -21,16 +21,18 @@ func subspace(prefix []byte) (start, end []byte) {
|
||||||
return prefix, end
|
return prefix, end
|
||||||
}
|
}
|
||||||
|
|
||||||
func initTestStore(t *testing.T) sdk.KVStore {
|
func createTestInput(t *testing.T, isCheckTx bool) (store sdk.KVStore, ctx sdk.Context, key sdk.StoreKey) {
|
||||||
// Capabilities key to access the main KVStore.
|
|
||||||
//db, err := dbm.NewGoLevelDB("stake", "data")
|
|
||||||
db := dbm.NewMemDB()
|
db := dbm.NewMemDB()
|
||||||
stakeStoreKey := sdk.NewKVStoreKey("stake")
|
key = sdk.NewKVStoreKey("stake")
|
||||||
|
|
||||||
ms := store.NewCommitMultiStore(db)
|
ms := store.NewCommitMultiStore(db)
|
||||||
ms.MountStoreWithDB(stakeStoreKey, sdk.StoreTypeIAVL, db)
|
ms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db)
|
||||||
err := ms.LoadLatestVersion()
|
err := ms.LoadLatestVersion()
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
return ms.GetKVStore(stakeStoreKey)
|
|
||||||
|
ctx = sdk.NewContext(ms, abci.Header{ChainID: "foochainid"}, isCheckTx, nil)
|
||||||
|
store = ms.GetKVStore(key)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAddrs(n int) (addrs []crypto.Address) {
|
func newAddrs(n int) (addrs []crypto.Address) {
|
||||||
|
|
|
@ -2,13 +2,11 @@ package stake
|
||||||
|
|
||||||
import (
|
import (
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
|
||||||
abci "github.com/tendermint/abci/types"
|
abci "github.com/tendermint/abci/types"
|
||||||
"github.com/tendermint/tmlibs/rational"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Tick - called at the end of every block
|
// Tick - called at the end of every block
|
||||||
func Tick(ctx sdk.Context, store types.KVStore) (change []*abci.Validator, err error) {
|
func Tick(ctx sdk.Context, store sdk.KVStore) (change []*abci.Validator, err error) {
|
||||||
|
|
||||||
// retrieve params
|
// retrieve params
|
||||||
params := loadParams(store)
|
params := loadParams(store)
|
||||||
|
@ -25,10 +23,10 @@ func Tick(ctx sdk.Context, store types.KVStore) (change []*abci.Validator, err e
|
||||||
return UpdateValidatorSet(store, gs, params)
|
return UpdateValidatorSet(store, gs, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
var hrsPerYr = rational.New(8766) // as defined by a julian year of 365.25 days
|
var hrsPerYr = sdk.NewRat(8766) // as defined by a julian year of 365.25 days
|
||||||
|
|
||||||
// process provisions for an hour period
|
// process provisions for an hour period
|
||||||
func processProvisions(store types.KVStore, gs *GlobalState, params Params) {
|
func processProvisions(store sdk.KVStore, gs *GlobalState, params Params) {
|
||||||
|
|
||||||
gs.Inflation = nextInflation(gs, params).Round(1000000000)
|
gs.Inflation = nextInflation(gs, params).Round(1000000000)
|
||||||
|
|
||||||
|
@ -36,7 +34,7 @@ func processProvisions(store types.KVStore, gs *GlobalState, params Params) {
|
||||||
// more bonded tokens are added proportionally to all validators the only term
|
// 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:
|
// which needs to be updated is the `BondedPool`. So for each previsions cycle:
|
||||||
|
|
||||||
provisions := gs.Inflation.Mul(rational.New(gs.TotalSupply)).Quo(hrsPerYr).Evaluate()
|
provisions := gs.Inflation.Mul(sdk.New(gs.TotalSupply)).Quo(hrsPerYr).Evaluate()
|
||||||
gs.BondedPool += provisions
|
gs.BondedPool += provisions
|
||||||
gs.TotalSupply += provisions
|
gs.TotalSupply += provisions
|
||||||
|
|
||||||
|
@ -49,7 +47,7 @@ func processProvisions(store types.KVStore, gs *GlobalState, params Params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the next inflation rate for the hour
|
// get the next inflation rate for the hour
|
||||||
func nextInflation(gs *GlobalState, params Params) (inflation rational.Rat) {
|
func nextInflation(gs *GlobalState, params Params) (inflation sdk.Rat) {
|
||||||
|
|
||||||
// The target annual inflation rate is recalculated for each previsions cycle. The
|
// The target annual inflation rate is recalculated for each previsions cycle. The
|
||||||
// inflation is also subject to a rate change (positive of negative) depending or
|
// inflation is also subject to a rate change (positive of negative) depending or
|
||||||
|
@ -58,7 +56,7 @@ func nextInflation(gs *GlobalState, params Params) (inflation rational.Rat) {
|
||||||
// 7% and 20%.
|
// 7% and 20%.
|
||||||
|
|
||||||
// (1 - bondedRatio/GoalBonded) * InflationRateChange
|
// (1 - bondedRatio/GoalBonded) * InflationRateChange
|
||||||
inflationRateChangePerYear := rational.One.Sub(gs.bondedRatio().Quo(params.GoalBonded)).Mul(params.InflationRateChange)
|
inflationRateChangePerYear := sdk.One.Sub(gs.bondedRatio().Quo(params.GoalBonded)).Mul(params.InflationRateChange)
|
||||||
inflationRateChange := inflationRateChangePerYear.Quo(hrsPerYr)
|
inflationRateChange := inflationRateChangePerYear.Quo(hrsPerYr)
|
||||||
|
|
||||||
// increase the new annual inflation for this next cycle
|
// increase the new annual inflation for this next cycle
|
||||||
|
|
|
@ -3,12 +3,12 @@ package stake
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/tendermint/tmlibs/rational"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetInflation(t *testing.T) {
|
func TestGetInflation(t *testing.T) {
|
||||||
store := initTestStore(t)
|
store, ctx, key := createTestInput(t, false)
|
||||||
params := loadParams(store)
|
params := loadParams(store)
|
||||||
gs := loadGlobalState(store)
|
gs := loadGlobalState(store)
|
||||||
|
|
||||||
|
@ -18,27 +18,27 @@ func TestGetInflation(t *testing.T) {
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
setBondedPool, setTotalSupply int64
|
setBondedPool, setTotalSupply int64
|
||||||
setInflation, expectedChange rational.Rat
|
setInflation, expectedChange sdk.Rat
|
||||||
}{
|
}{
|
||||||
// with 0% bonded atom supply the inflation should increase by InflationRateChange
|
// with 0% bonded atom supply the inflation should increase by InflationRateChange
|
||||||
{0, 0, rational.New(7, 100), params.InflationRateChange.Quo(hrsPerYr)},
|
{0, 0, sdk.New(7, 100), params.InflationRateChange.Quo(hrsPerYr)},
|
||||||
|
|
||||||
// 100% bonded, starting at 20% inflation and being reduced
|
// 100% bonded, starting at 20% inflation and being reduced
|
||||||
{1, 1, rational.New(20, 100), rational.One.Sub(rational.One.Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYr)},
|
{1, 1, sdk.New(20, 100), sdk.One.Sub(sdk.One.Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYr)},
|
||||||
|
|
||||||
// 50% bonded, starting at 10% inflation and being increased
|
// 50% bonded, starting at 10% inflation and being increased
|
||||||
{1, 2, rational.New(10, 100), rational.One.Sub(rational.New(1, 2).Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYr)},
|
{1, 2, sdk.New(10, 100), sdk.One.Sub(sdk.New(1, 2).Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYr)},
|
||||||
|
|
||||||
// test 7% minimum stop (testing with 100% bonded)
|
// test 7% minimum stop (testing with 100% bonded)
|
||||||
{1, 1, rational.New(7, 100), rational.Zero},
|
{1, 1, sdk.New(7, 100), sdk.Zero},
|
||||||
{1, 1, rational.New(70001, 1000000), rational.New(-1, 1000000)},
|
{1, 1, sdk.New(70001, 1000000), sdk.New(-1, 1000000)},
|
||||||
|
|
||||||
// test 20% maximum stop (testing with 0% bonded)
|
// test 20% maximum stop (testing with 0% bonded)
|
||||||
{0, 0, rational.New(20, 100), rational.Zero},
|
{0, 0, sdk.New(20, 100), sdk.Zero},
|
||||||
{0, 0, rational.New(199999, 1000000), rational.New(1, 1000000)},
|
{0, 0, sdk.New(199999, 1000000), sdk.New(1, 1000000)},
|
||||||
|
|
||||||
// perfect balance shouldn't change inflation
|
// perfect balance shouldn't change inflation
|
||||||
{67, 100, rational.New(15, 100), rational.Zero},
|
{67, 100, sdk.New(15, 100), sdk.Zero},
|
||||||
}
|
}
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
gs.BondedPool, gs.TotalSupply = tc.setBondedPool, tc.setTotalSupply
|
gs.BondedPool, gs.TotalSupply = tc.setBondedPool, tc.setTotalSupply
|
||||||
|
@ -53,7 +53,7 @@ func TestGetInflation(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestProcessProvisions(t *testing.T) {
|
func TestProcessProvisions(t *testing.T) {
|
||||||
store := initTestStore(t)
|
store, ctx, key := createTestInput(t, false)
|
||||||
params := loadParams(store)
|
params := loadParams(store)
|
||||||
gs := loadGlobalState(store)
|
gs := loadGlobalState(store)
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ func TestProcessProvisions(t *testing.T) {
|
||||||
var unbondedShares int64 = 400000000
|
var unbondedShares int64 = 400000000
|
||||||
|
|
||||||
// initial bonded ratio ~ 27%
|
// initial bonded ratio ~ 27%
|
||||||
assert.True(t, gs.bondedRatio().Equal(rational.New(bondedShares, totalSupply)), "%v", gs.bondedRatio())
|
assert.True(t, gs.bondedRatio().Equal(sdk.New(bondedShares, totalSupply)), "%v", gs.bondedRatio())
|
||||||
|
|
||||||
// Supplies
|
// Supplies
|
||||||
assert.Equal(t, totalSupply, gs.TotalSupply)
|
assert.Equal(t, totalSupply, gs.TotalSupply)
|
||||||
|
@ -83,7 +83,7 @@ func TestProcessProvisions(t *testing.T) {
|
||||||
assert.Equal(t, unbondedShares, gs.UnbondedPool)
|
assert.Equal(t, unbondedShares, gs.UnbondedPool)
|
||||||
|
|
||||||
// test the value of candidate shares
|
// test the value of candidate shares
|
||||||
assert.True(t, gs.bondedShareExRate().Equal(rational.One), "%v", gs.bondedShareExRate())
|
assert.True(t, gs.bondedShareExRate().Equal(sdk.One), "%v", gs.bondedShareExRate())
|
||||||
|
|
||||||
initialSupply := gs.TotalSupply
|
initialSupply := gs.TotalSupply
|
||||||
initialUnbonded := gs.TotalSupply - gs.BondedPool
|
initialUnbonded := gs.TotalSupply - gs.BondedPool
|
||||||
|
@ -91,7 +91,7 @@ func TestProcessProvisions(t *testing.T) {
|
||||||
// process the provisions a year
|
// process the provisions a year
|
||||||
for hr := 0; hr < 8766; hr++ {
|
for hr := 0; hr < 8766; hr++ {
|
||||||
expInflation := nextInflation(gs, params).Round(1000000000)
|
expInflation := nextInflation(gs, params).Round(1000000000)
|
||||||
expProvisions := (expInflation.Mul(rational.New(gs.TotalSupply)).Quo(hrsPerYr)).Evaluate()
|
expProvisions := (expInflation.Mul(sdk.New(gs.TotalSupply)).Quo(hrsPerYr)).Evaluate()
|
||||||
startBondedPool := gs.BondedPool
|
startBondedPool := gs.BondedPool
|
||||||
startTotalSupply := gs.TotalSupply
|
startTotalSupply := gs.TotalSupply
|
||||||
processProvisions(store, gs, params)
|
processProvisions(store, gs, params)
|
||||||
|
@ -103,7 +103,7 @@ func TestProcessProvisions(t *testing.T) {
|
||||||
//panic(fmt.Sprintf("debug total %v, bonded %v, diff %v\n", gs.TotalSupply, gs.BondedPool, gs.TotalSupply-gs.BondedPool))
|
//panic(fmt.Sprintf("debug total %v, bonded %v, diff %v\n", gs.TotalSupply, gs.BondedPool, gs.TotalSupply-gs.BondedPool))
|
||||||
|
|
||||||
// initial bonded ratio ~ 35% ~ 30% increase for bonded holders
|
// initial bonded ratio ~ 35% ~ 30% increase for bonded holders
|
||||||
assert.True(t, gs.bondedRatio().Equal(rational.New(105906511, 305906511)), "%v", gs.bondedRatio())
|
assert.True(t, gs.bondedRatio().Equal(sdk.New(105906511, 305906511)), "%v", gs.bondedRatio())
|
||||||
|
|
||||||
// global supply
|
// global supply
|
||||||
assert.Equal(t, int64(611813022), gs.TotalSupply)
|
assert.Equal(t, int64(611813022), gs.TotalSupply)
|
||||||
|
@ -111,6 +111,6 @@ func TestProcessProvisions(t *testing.T) {
|
||||||
assert.Equal(t, unbondedShares, gs.UnbondedPool)
|
assert.Equal(t, unbondedShares, gs.UnbondedPool)
|
||||||
|
|
||||||
// test the value of candidate shares
|
// test the value of candidate shares
|
||||||
assert.True(t, gs.bondedShareExRate().Mul(rational.New(bondedShares)).Equal(rational.New(211813022)), "%v", gs.bondedShareExRate())
|
assert.True(t, gs.bondedShareExRate().Mul(sdk.New(bondedShares)).Equal(sdk.New(211813022)), "%v", gs.bondedShareExRate())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,10 +18,11 @@ const (
|
||||||
ByteTxEditCandidacy = 0x56
|
ByteTxEditCandidacy = 0x56
|
||||||
ByteTxDelegate = 0x57
|
ByteTxDelegate = 0x57
|
||||||
ByteTxUnbond = 0x58
|
ByteTxUnbond = 0x58
|
||||||
TypeTxDeclareCandidacy = stakingModuleName + "/declareCandidacy"
|
|
||||||
TypeTxEditCandidacy = stakingModuleName + "/editCandidacy"
|
TypeTxDeclareCandidacy = "staking/declareCandidacy"
|
||||||
TypeTxDelegate = stakingModuleName + "/delegate"
|
TypeTxEditCandidacy = "staking/editCandidacy"
|
||||||
TypeTxUnbond = stakingModuleName + "/unbond"
|
TypeTxDelegate = "staking/delegate"
|
||||||
|
TypeTxUnbond = "staking/unbond"
|
||||||
)
|
)
|
||||||
|
|
||||||
//func init() {
|
//func init() {
|
||||||
|
|
|
@ -13,8 +13,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
validator = sdk.Actor{"testChain", "testapp", []byte("addressvalidator1")}
|
validator = []byte("addressvalidator1")
|
||||||
empty sdk.Actor
|
empty sdk.Address
|
||||||
|
|
||||||
coinPos = sdk.Coin{"fermion", 1000}
|
coinPos = sdk.Coin{"fermion", 1000}
|
||||||
coinZero = sdk.Coin{"fermion", 0}
|
coinZero = sdk.Coin{"fermion", 0}
|
||||||
|
|
|
@ -139,6 +139,8 @@ const (
|
||||||
// bond shares is based on the amount of coins delegated divided by the current
|
// bond shares is based on the amount of coins delegated divided by the current
|
||||||
// exchange rate. Voting power can be calculated as total bonds multiplied by
|
// exchange rate. Voting power can be calculated as total bonds multiplied by
|
||||||
// exchange rate.
|
// exchange rate.
|
||||||
|
|
||||||
|
// XXX update to use Address as the main key NOT the pubkey
|
||||||
type Candidate struct {
|
type Candidate struct {
|
||||||
Status CandidateStatus `json:"status"` // Bonded status
|
Status CandidateStatus `json:"status"` // Bonded status
|
||||||
PubKey crypto.PubKey `json:"pub_key"` // Pubkey of candidate
|
PubKey crypto.PubKey `json:"pub_key"` // Pubkey of candidate
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package stake
|
package stake
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/tendermint/go-wire"
|
"github.com/cosmos/cosmos-sdk/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
// XXX complete
|
// XXX complete
|
||||||
|
|
Loading…
Reference in New Issue