Integrate in types and rational staking
This commit is contained in:
parent
73eb98ca7f
commit
a1c7722a80
|
@ -0,0 +1,55 @@
|
||||||
|
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
|
221
x/stake/store.go
221
x/stake/store.go
|
@ -1,39 +1,54 @@
|
||||||
package stake
|
package stake
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
|
||||||
|
|
||||||
crypto "github.com/tendermint/go-crypto"
|
crypto "github.com/tendermint/go-crypto"
|
||||||
|
wire "github.com/tendermint/go-wire"
|
||||||
|
"github.com/tendermint/tmlibs/rational"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/types"
|
"github.com/cosmos/cosmos-sdk/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// nolint
|
// nolint
|
||||||
var (
|
var (
|
||||||
|
|
||||||
|
// internal wire codec
|
||||||
|
cdc *wire.Codec
|
||||||
|
|
||||||
// Keys for store prefixes
|
// Keys for store prefixes
|
||||||
CandidatesPubKeysKey = []byte{0x01} // key for all candidates' pubkeys
|
CandidatesPubKeysKey = []byte{0x01} // key for all candidates' pubkeys
|
||||||
ParamKey = []byte{0x02} // key for global parameters relating to staking
|
ParamKey = []byte{0x02} // key for global parameters relating to staking
|
||||||
GlobalStateKey = []byte{0x03} // key for global parameters relating to staking
|
GlobalStateKey = []byte{0x03} // key for global parameters relating to staking
|
||||||
|
|
||||||
// Key prefixes
|
// Key prefixes
|
||||||
CandidateKeyPrefix = []byte{0x04} // prefix for each key to a candidate
|
CandidateKeyPrefix = []byte{0x04} // prefix for each key to a candidate
|
||||||
ValidatorKeyPrefix = []byte{0x05} // prefix for each key to a candidate
|
ValidatorKeyPrefix = []byte{0x05} // prefix for each key to a candidate
|
||||||
DelegatorBondKeyPrefix = []byte{0x06} // prefix for each key to a delegator's bond
|
ValidatorUpdatesKeyPrefix = []byte{0x06} // prefix for each key to a candidate
|
||||||
DelegatorBondsKeyPrefix = []byte{0x07} // prefix for each key to a delegator's bond
|
DelegatorBondKeyPrefix = []byte{0x07} // prefix for each key to a delegator's bond
|
||||||
|
DelegatorBondsKeyPrefix = []byte{0x08} // prefix for each key to a delegator's bond
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cdc = wire.NewCodec()
|
||||||
|
cdc.RegisterInterface((*rational.Rational)(nil), nil)
|
||||||
|
cdc.RegisterConcrete(rational.Rat{}, "rat", nil)
|
||||||
|
}
|
||||||
|
|
||||||
// GetCandidateKey - get the key for the candidate with pubKey
|
// GetCandidateKey - get the key for the candidate with pubKey
|
||||||
func GetCandidateKey(pubKey crypto.PubKey) []byte {
|
func GetCandidateKey(pubKey crypto.PubKey) []byte {
|
||||||
return append(CandidateKeyPrefix, pubKey.Bytes()...)
|
return append(CandidateKeyPrefix, pubKey.Bytes()...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 int64) []byte {
|
func GetValidatorKey(pubKey crypto.PubKey, power rational.Rational) []byte {
|
||||||
b := make([]byte, 8)
|
b, _ := cdc.MarshalJSON(power) // TODO need to handle error here?
|
||||||
binary.LittleEndian.PutUint64(b, uint64(power))
|
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetValidatorUpdatesKey - get the key for the validator used in the power-store
|
||||||
|
func GetValidatorUpdatesKey(pubKey crypto.PubKey) []byte {
|
||||||
|
return append(ValidatorUpdatesKeyPrefix, pubKey.Bytes()...) // TODO does this need prefix if its in its own store
|
||||||
|
}
|
||||||
|
|
||||||
// GetDelegatorBondKey - get the key for delegator bond with candidate
|
// GetDelegatorBondKey - get the key for delegator bond with candidate
|
||||||
func GetDelegatorBondKey(delegator crypto.Address, candidate crypto.PubKey) []byte {
|
func GetDelegatorBondKey(delegator crypto.Address, candidate crypto.PubKey) []byte {
|
||||||
return append(GetDelegatorBondKeyPrefix(delegator), candidate.Bytes()...)
|
return append(GetDelegatorBondKeyPrefix(delegator), candidate.Bytes()...)
|
||||||
|
@ -41,7 +56,7 @@ func GetDelegatorBondKey(delegator crypto.Address, candidate crypto.PubKey) []by
|
||||||
|
|
||||||
// GetDelegatorBondKeyPrefix - get the prefix for a delegator for all candidates
|
// GetDelegatorBondKeyPrefix - get the prefix for a delegator for all candidates
|
||||||
func GetDelegatorBondKeyPrefix(delegator crypto.Address) []byte {
|
func GetDelegatorBondKeyPrefix(delegator crypto.Address) []byte {
|
||||||
res, err := cdc.MarshalBinary(&delegator)
|
res, err := cdc.MarshalJSON(&delegator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -50,7 +65,7 @@ func GetDelegatorBondKeyPrefix(delegator crypto.Address) []byte {
|
||||||
|
|
||||||
// GetDelegatorBondsKey - get the key for list of all the delegator's bonds
|
// GetDelegatorBondsKey - get the key for list of all the delegator's bonds
|
||||||
func GetDelegatorBondsKey(delegator crypto.Address) []byte {
|
func GetDelegatorBondsKey(delegator crypto.Address) []byte {
|
||||||
res, err := cdc.MarshalBinary(&delegator)
|
res, err := cdc.MarshalJSON(&delegator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -60,15 +75,12 @@ func GetDelegatorBondsKey(delegator crypto.Address) []byte {
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
func loadCandidate(store types.KVStore, pubKey crypto.PubKey) *Candidate {
|
func loadCandidate(store types.KVStore, pubKey crypto.PubKey) *Candidate {
|
||||||
//if pubKey.Empty() {
|
|
||||||
//return nil
|
|
||||||
//}
|
|
||||||
b := store.Get(GetCandidateKey(pubKey))
|
b := store.Get(GetCandidateKey(pubKey))
|
||||||
if b == nil {
|
if b == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
candidate := new(Candidate)
|
candidate := new(Candidate)
|
||||||
err := cdc.UnmarshalBinary(b, candidate)
|
err := cdc.UnmarshalJSON(b, candidate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err) // This error should never occur big problem if does
|
panic(err) // This error should never occur big problem if does
|
||||||
}
|
}
|
||||||
|
@ -77,11 +89,12 @@ func loadCandidate(store types.KVStore, pubKey crypto.PubKey) *Candidate {
|
||||||
|
|
||||||
func saveCandidate(store types.KVStore, candidate *Candidate) {
|
func saveCandidate(store types.KVStore, candidate *Candidate) {
|
||||||
|
|
||||||
removeValidatorFromKey(store, candidate.PubKey)
|
// XXX should only remove validator if we know candidate is a validator
|
||||||
|
removeValidator(store, candidate.PubKey)
|
||||||
validator := &Validator{candidate.PubKey, candidate.VotingPower}
|
validator := &Validator{candidate.PubKey, candidate.VotingPower}
|
||||||
saveValidator(store, validator)
|
updateValidator(store, validator)
|
||||||
|
|
||||||
b, err := cdc.MarshalBinary(*candidate)
|
b, err := cdc.MarshalJSON(*candidate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -89,54 +102,67 @@ func saveCandidate(store types.KVStore, candidate *Candidate) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeCandidate(store types.KVStore, pubKey crypto.PubKey) {
|
func removeCandidate(store types.KVStore, pubKey crypto.PubKey) {
|
||||||
removeValidatorFromKey(store, pubKey)
|
|
||||||
|
// XXX should only remove validator if we know candidate is a validator
|
||||||
|
removeValidator(store, pubKey)
|
||||||
store.Delete(GetCandidateKey(pubKey))
|
store.Delete(GetCandidateKey(pubKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
func loadValidator(store types.KVStore, pubKey crypto.PubKey, votingPower int64) *Validator {
|
//func loadValidator(store types.KVStore, pubKey crypto.PubKey, votingPower rational.Rational) *Validator {
|
||||||
b := store.Get(GetValidatorKey(pubKey, votingPower))
|
//b := store.Get(GetValidatorKey(pubKey, votingPower))
|
||||||
if b == nil {
|
//if b == nil {
|
||||||
return nil
|
//return nil
|
||||||
}
|
//}
|
||||||
validator := new(Validator)
|
//validator := new(Validator)
|
||||||
err := cdc.UnmarshalBinary(b, validator)
|
//err := cdc.UnmarshalJSON(b, validator)
|
||||||
if err != nil {
|
//if err != nil {
|
||||||
panic(err) // This error should never occur big problem if does
|
//panic(err) // This error should never occur big problem if does
|
||||||
}
|
//}
|
||||||
return validator
|
//return validator
|
||||||
}
|
//}
|
||||||
|
|
||||||
func saveValidator(store types.KVStore, validator *Validator) {
|
// updateValidator - update a validator and create accumulate any changes
|
||||||
b, err := cdc.MarshalBinary(*validator)
|
// in the changed validator substore
|
||||||
|
func updateValidator(store types.KVStore, validator *Validator) {
|
||||||
|
|
||||||
|
b, err := cdc.MarshalJSON(*validator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add to the validators to update list if necessary
|
||||||
|
store.Set(GetValidatorUpdatesKey(validator.PubKey), b)
|
||||||
|
|
||||||
|
// update the list ordered by voting power
|
||||||
store.Set(GetValidatorKey(validator.PubKey, validator.VotingPower), b)
|
store.Set(GetValidatorKey(validator.PubKey, validator.VotingPower), b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeValidator(store types.KVStore, pubKey crypto.PubKey, votingPower int64) {
|
func removeValidator(store types.KVStore, pubKey crypto.PubKey) {
|
||||||
store.Delete(GetValidatorKey(pubKey, votingPower))
|
|
||||||
}
|
|
||||||
|
|
||||||
func removeValidatorFromKey(store types.KVStore, pubKey crypto.PubKey) {
|
//add validator with zero power to the validator updates
|
||||||
// remove validator if already there, then add new validator
|
b, err := cdc.MarshalJSON(Validator{pubKey, rational.Zero})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
store.Set(GetValidatorUpdatesKey(pubKey), b)
|
||||||
|
|
||||||
|
// now actually delete from the validator set
|
||||||
candidate := loadCandidate(store, pubKey)
|
candidate := loadCandidate(store, pubKey)
|
||||||
if candidate != nil {
|
if candidate != nil {
|
||||||
removeValidator(store, pubKey, candidate.VotingPower)
|
store.Delete(GetValidatorKey(pubKey, candidate.VotingPower))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validators - get the most recent updated validator set from the
|
// get the most recent updated validator set from the Candidates. These bonds
|
||||||
// Candidates. These bonds are already sorted by VotingPower from
|
// are already sorted by VotingPower from the UpdateVotingPower function which
|
||||||
// the UpdateVotingPower function which is the only function which
|
// is the only function which is to modify the VotingPower
|
||||||
// is to modify the VotingPower
|
func getValidators(store types.KVStore, maxVal int) (validators []Validator) {
|
||||||
func getValidators(store types.KVStore, maxVal int) Validators {
|
|
||||||
|
|
||||||
iterator := store.Iterator(subspace(ValidatorKeyPrefix)) //smallest to largest
|
iterator := store.Iterator(subspace(ValidatorKeyPrefix)) //smallest to largest
|
||||||
|
|
||||||
validators := make(Validators, maxVal)
|
validators = make([]Validator, maxVal)
|
||||||
for i := 0; ; i++ {
|
for i := 0; ; i++ {
|
||||||
if !iterator.Valid() || i > maxVal {
|
if !iterator.Valid() || i > maxVal {
|
||||||
iterator.Close()
|
iterator.Close()
|
||||||
|
@ -144,7 +170,7 @@ func getValidators(store types.KVStore, maxVal int) Validators {
|
||||||
}
|
}
|
||||||
valBytes := iterator.Value()
|
valBytes := iterator.Value()
|
||||||
var val Validator
|
var val Validator
|
||||||
err := cdc.UnmarshalBinary(valBytes, &val)
|
err := cdc.UnmarshalJSON(valBytes, &val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -152,7 +178,37 @@ func getValidators(store types.KVStore, maxVal int) Validators {
|
||||||
iterator.Next()
|
iterator.Next()
|
||||||
}
|
}
|
||||||
|
|
||||||
return validators
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
// get the most updated validators
|
||||||
|
func getValidatorUpdates(store types.KVStore) (updates []Validator) {
|
||||||
|
|
||||||
|
iterator := store.Iterator(subspace(ValidatorUpdatesKeyPrefix)) //smallest to largest
|
||||||
|
|
||||||
|
for ; iterator.Valid(); iterator.Next() {
|
||||||
|
valBytes := iterator.Value()
|
||||||
|
var val Validator
|
||||||
|
err := cdc.UnmarshalJSON(valBytes, &val)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
updates = append(updates, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove all validator update entries
|
||||||
|
func clearValidatorUpdates(store types.KVStore, maxVal int) {
|
||||||
|
iterator := store.Iterator(subspace(ValidatorUpdatesKeyPrefix))
|
||||||
|
for ; iterator.Valid(); iterator.Next() {
|
||||||
|
store.Delete(iterator.Key()) // XXX write test for this, may need to be in a second loop
|
||||||
|
}
|
||||||
|
iterator.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
|
@ -160,26 +216,20 @@ func getValidators(store types.KVStore, maxVal int) Validators {
|
||||||
// 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 loadCandidates(store types.KVStore) (candidates Candidates) {
|
func loadCandidates(store types.KVStore) (candidates Candidates) {
|
||||||
|
|
||||||
//iterator := store.Iterator(subspace(CandidateKeyPrefix)) //smallest to largest
|
iterator := store.Iterator(subspace(CandidateKeyPrefix))
|
||||||
//iterator := store.Iterator(CandidateKeyPrefix, []byte(nil)) //smallest to largest
|
//iterator := store.Iterator(CandidateKeyPrefix, []byte(nil))
|
||||||
iterator := store.Iterator([]byte{}, []byte(nil)) //smallest to largest
|
//iterator := store.Iterator([]byte{}, []byte(nil))
|
||||||
|
|
||||||
for i := 0; ; i++ {
|
for ; iterator.Valid(); iterator.Next() {
|
||||||
if !iterator.Valid() {
|
|
||||||
//panic(fmt.Sprintf("debug i: %v\n", i))
|
|
||||||
iterator.Close()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
candidateBytes := iterator.Value()
|
candidateBytes := iterator.Value()
|
||||||
var candidate Candidate
|
var candidate Candidate
|
||||||
err := cdc.UnmarshalBinary(candidateBytes, &candidate)
|
err := cdc.UnmarshalJSON(candidateBytes, &candidate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
candidates[i] = &candidate
|
candidates = append(candidates, &candidate)
|
||||||
iterator.Next()
|
|
||||||
}
|
}
|
||||||
|
iterator.Close()
|
||||||
return candidates
|
return candidates
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +244,7 @@ func loadDelegatorCandidates(store types.KVStore,
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
err := cdc.UnmarshalBinary(candidateBytes, &candidates)
|
err := cdc.UnmarshalJSON(candidateBytes, &candidates)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -212,7 +262,7 @@ func loadDelegatorBond(store types.KVStore,
|
||||||
}
|
}
|
||||||
|
|
||||||
bond := new(DelegatorBond)
|
bond := new(DelegatorBond)
|
||||||
err := cdc.UnmarshalBinary(delegatorBytes, bond)
|
err := cdc.UnmarshalJSON(delegatorBytes, bond)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -225,7 +275,7 @@ func saveDelegatorBond(store types.KVStore, delegator crypto.Address, bond *Dele
|
||||||
if loadDelegatorBond(store, delegator, bond.PubKey) == nil {
|
if loadDelegatorBond(store, delegator, bond.PubKey) == nil {
|
||||||
pks := loadDelegatorCandidates(store, delegator)
|
pks := loadDelegatorCandidates(store, delegator)
|
||||||
pks = append(pks, (*bond).PubKey)
|
pks = append(pks, (*bond).PubKey)
|
||||||
b, err := cdc.MarshalBinary(pks)
|
b, err := cdc.MarshalJSON(pks)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -233,7 +283,7 @@ func saveDelegatorBond(store types.KVStore, delegator crypto.Address, bond *Dele
|
||||||
}
|
}
|
||||||
|
|
||||||
// now actually save the bond
|
// now actually save the bond
|
||||||
b, err := cdc.MarshalBinary(*bond)
|
b, err := cdc.MarshalJSON(*bond)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -250,7 +300,7 @@ func removeDelegatorBond(store types.KVStore, delegator crypto.Address, candidat
|
||||||
pks = append(pks[:i], pks[i+1:]...)
|
pks = append(pks[:i], pks[i+1:]...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b, err := cdc.MarshalBinary(pks)
|
b, err := cdc.MarshalJSON(pks)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -261,39 +311,6 @@ func removeDelegatorBond(store types.KVStore, delegator crypto.Address, candidat
|
||||||
//updateDelegatorBonds(store, delegator)
|
//updateDelegatorBonds(store, delegator)
|
||||||
}
|
}
|
||||||
|
|
||||||
//func updateDelegatorBonds(store types.KVStore,
|
|
||||||
//delegator crypto.Address) {
|
|
||||||
|
|
||||||
//var bonds []*DelegatorBond
|
|
||||||
|
|
||||||
//prefix := GetDelegatorBondKeyPrefix(delegator)
|
|
||||||
//l := len(prefix)
|
|
||||||
//delegatorsBytes := store.List(prefix,
|
|
||||||
//append(prefix[:l-1], (prefix[l-1]+1)), loadParams(store).MaxVals)
|
|
||||||
|
|
||||||
//for _, delegatorBytesModel := range delegatorsBytes {
|
|
||||||
//delegatorBytes := delegatorBytesModel.Value
|
|
||||||
//if delegatorBytes == nil {
|
|
||||||
//continue
|
|
||||||
//}
|
|
||||||
|
|
||||||
//bond := new(DelegatorBond)
|
|
||||||
//err := wire.UnmarshalBinary(delegatorBytes, bond)
|
|
||||||
//if err != nil {
|
|
||||||
//panic(err)
|
|
||||||
//}
|
|
||||||
//bonds = append(bonds, bond)
|
|
||||||
//}
|
|
||||||
|
|
||||||
//if len(bonds) == 0 {
|
|
||||||
//store.Remove(GetDelegatorBondsKey(delegator))
|
|
||||||
//return
|
|
||||||
//}
|
|
||||||
|
|
||||||
//b := wire.MarshalBinary(bonds)
|
|
||||||
//store.Set(GetDelegatorBondsKey(delegator), b)
|
|
||||||
//}
|
|
||||||
|
|
||||||
//_______________________________________________________________________
|
//_______________________________________________________________________
|
||||||
|
|
||||||
// load/save the global staking params
|
// load/save the global staking params
|
||||||
|
@ -303,7 +320,7 @@ func loadParams(store types.KVStore) (params Params) {
|
||||||
return defaultParams()
|
return defaultParams()
|
||||||
}
|
}
|
||||||
|
|
||||||
err := cdc.UnmarshalBinary(b, ¶ms)
|
err := cdc.UnmarshalJSON(b, ¶ms)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err) // This error should never occur big problem if does
|
panic(err) // This error should never occur big problem if does
|
||||||
}
|
}
|
||||||
|
@ -311,7 +328,7 @@ func loadParams(store types.KVStore) (params Params) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
func saveParams(store types.KVStore, params Params) {
|
func saveParams(store types.KVStore, params Params) {
|
||||||
b, err := cdc.MarshalBinary(params)
|
b, err := cdc.MarshalJSON(params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -327,14 +344,14 @@ func loadGlobalState(store types.KVStore) (gs *GlobalState) {
|
||||||
return initialGlobalState()
|
return initialGlobalState()
|
||||||
}
|
}
|
||||||
gs = new(GlobalState)
|
gs = new(GlobalState)
|
||||||
err := cdc.UnmarshalBinary(b, gs)
|
err := cdc.UnmarshalJSON(b, gs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err) // This error should never occur big problem if does
|
panic(err) // This error should never occur big problem if does
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
func saveGlobalState(store types.KVStore, gs *GlobalState) {
|
func saveGlobalState(store types.KVStore, gs *GlobalState) {
|
||||||
b, err := cdc.MarshalBinary(*gs)
|
b, err := cdc.MarshalJSON(*gs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,25 +4,201 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/store"
|
"github.com/tendermint/tmlibs/rational"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
||||||
dbm "github.com/tendermint/tmlibs/db"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
crypto "github.com/tendermint/go-crypto"
|
crypto "github.com/tendermint/go-crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
func initTestStore(t *testing.T) sdk.KVStore {
|
// XXX XXX XXX
|
||||||
// Capabilities key to access the main KVStore.
|
// XXX revive these tests but for the store update proceedure
|
||||||
db, err := dbm.NewGoLevelDB("stake", "data")
|
// XXX XXX XXX
|
||||||
require.Nil(t, err)
|
|
||||||
stakeStoreKey := sdk.NewKVStoreKey("stake")
|
//func TestUpdateVotingPower(t *testing.T) {
|
||||||
ms := store.NewCommitMultiStore(db)
|
//assert := assert.New(t)
|
||||||
ms.MountStoreWithDB(stakeStoreKey, sdk.StoreTypeIAVL, db)
|
//store := initTestStore(t)
|
||||||
ms.LoadLatestVersion()
|
//params := loadParams(store)
|
||||||
return ms.GetKVStore(stakeStoreKey)
|
//gs := loadGlobalState(store)
|
||||||
}
|
|
||||||
|
//N := 5
|
||||||
|
//actors := newAddrs(N)
|
||||||
|
//candidates := candidatesFromActors(actors, []int64{400, 200, 100, 10, 1})
|
||||||
|
|
||||||
|
//// test a basic change in voting power
|
||||||
|
//candidates[0].Assets = rational.New(500)
|
||||||
|
//candidates.updateVotingPower(store, gs, params)
|
||||||
|
//assert.Equal(int64(500), candidates[0].VotingPower.Evaluate(), "%v", candidates[0])
|
||||||
|
|
||||||
|
//// test a swap in voting power
|
||||||
|
//candidates[1].Assets = rational.New(600)
|
||||||
|
//candidates.updateVotingPower(store, gs, params)
|
||||||
|
//assert.Equal(int64(600), candidates[0].VotingPower.Evaluate(), "%v", candidates[0])
|
||||||
|
//assert.Equal(int64(500), candidates[1].VotingPower.Evaluate(), "%v", candidates[1])
|
||||||
|
|
||||||
|
//// test the max validators term
|
||||||
|
//params.MaxVals = 4
|
||||||
|
//saveParams(store, params)
|
||||||
|
//candidates.updateVotingPower(store, gs, params)
|
||||||
|
//assert.Equal(int64(0), candidates[4].VotingPower.Evaluate(), "%v", candidates[4])
|
||||||
|
//}
|
||||||
|
|
||||||
|
//func TestValidatorsChanged(t *testing.T) {
|
||||||
|
//require := require.New(t)
|
||||||
|
|
||||||
|
//v1 := (&Candidate{PubKey: pks[0], VotingPower: rational.New(10)}).validator()
|
||||||
|
//v2 := (&Candidate{PubKey: pks[1], VotingPower: rational.New(10)}).validator()
|
||||||
|
//v3 := (&Candidate{PubKey: pks[2], VotingPower: rational.New(10)}).validator()
|
||||||
|
//v4 := (&Candidate{PubKey: pks[3], VotingPower: rational.New(10)}).validator()
|
||||||
|
//v5 := (&Candidate{PubKey: pks[4], VotingPower: rational.New(10)}).validator()
|
||||||
|
|
||||||
|
//// test from nothing to something
|
||||||
|
//vs1 := []Validator{}
|
||||||
|
//vs2 := []Validator{v1, v2}
|
||||||
|
//changed := vs1.validatorsUpdated(vs2)
|
||||||
|
//require.Equal(2, len(changed))
|
||||||
|
//testChange(t, vs2[0], changed[0])
|
||||||
|
//testChange(t, vs2[1], changed[1])
|
||||||
|
|
||||||
|
//// test from something to nothing
|
||||||
|
//vs1 = []Validator{v1, v2}
|
||||||
|
//vs2 = []Validator{}
|
||||||
|
//changed = vs1.validatorsUpdated(vs2)
|
||||||
|
//require.Equal(2, len(changed))
|
||||||
|
//testRemove(t, vs1[0], changed[0])
|
||||||
|
//testRemove(t, vs1[1], changed[1])
|
||||||
|
|
||||||
|
//// test identical
|
||||||
|
//vs1 = []Validator{v1, v2, v4}
|
||||||
|
//vs2 = []Validator{v1, v2, v4}
|
||||||
|
//changed = vs1.validatorsUpdated(vs2)
|
||||||
|
//require.Zero(len(changed))
|
||||||
|
|
||||||
|
//// test single value change
|
||||||
|
//vs2[2].VotingPower = rational.One
|
||||||
|
//changed = vs1.validatorsUpdated(vs2)
|
||||||
|
//require.Equal(1, len(changed))
|
||||||
|
//testChange(t, vs2[2], changed[0])
|
||||||
|
|
||||||
|
//// test multiple value change
|
||||||
|
//vs2[0].VotingPower = rational.New(11)
|
||||||
|
//vs2[2].VotingPower = rational.New(5)
|
||||||
|
//changed = vs1.validatorsUpdated(vs2)
|
||||||
|
//require.Equal(2, len(changed))
|
||||||
|
//testChange(t, vs2[0], changed[0])
|
||||||
|
//testChange(t, vs2[2], changed[1])
|
||||||
|
|
||||||
|
//// test validator added at the beginning
|
||||||
|
//vs1 = []Validator{v2, v4}
|
||||||
|
//vs2 = []Validator{v2, v4, v1}
|
||||||
|
//changed = vs1.validatorsUpdated(vs2)
|
||||||
|
//require.Equal(1, len(changed))
|
||||||
|
//testChange(t, vs2[0], changed[0])
|
||||||
|
|
||||||
|
//// test validator added in the middle
|
||||||
|
//vs1 = []Validator{v1, v2, v4}
|
||||||
|
//vs2 = []Validator{v3, v1, v4, v2}
|
||||||
|
//changed = vs1.validatorsUpdated(vs2)
|
||||||
|
//require.Equal(1, len(changed))
|
||||||
|
//testChange(t, vs2[2], changed[0])
|
||||||
|
|
||||||
|
//// test validator added at the end
|
||||||
|
//vs2 = []Validator{v1, v2, v4, v5}
|
||||||
|
//changed = vs1.validatorsUpdated(vs2)
|
||||||
|
//require.Equal(1, len(changed))
|
||||||
|
//testChange(t, vs2[3], changed[0])
|
||||||
|
|
||||||
|
//// test multiple validators added
|
||||||
|
//vs2 = []Validator{v1, v2, v3, v4, v5}
|
||||||
|
//changed = vs1.validatorsUpdated(vs2)
|
||||||
|
//require.Equal(2, len(changed))
|
||||||
|
//testChange(t, vs2[2], changed[0])
|
||||||
|
//testChange(t, vs2[4], changed[1])
|
||||||
|
|
||||||
|
//// test validator removed at the beginning
|
||||||
|
//vs2 = []Validator{v2, v4}
|
||||||
|
//changed = vs1.validatorsUpdated(vs2)
|
||||||
|
//require.Equal(1, len(changed))
|
||||||
|
//testRemove(t, vs1[0], changed[0])
|
||||||
|
|
||||||
|
//// test validator removed in the middle
|
||||||
|
//vs2 = []Validator{v1, v4}
|
||||||
|
//changed = vs1.validatorsUpdated(vs2)
|
||||||
|
//require.Equal(1, len(changed))
|
||||||
|
//testRemove(t, vs1[1], changed[0])
|
||||||
|
|
||||||
|
//// test validator removed at the end
|
||||||
|
//vs2 = []Validator{v1, v2}
|
||||||
|
//changed = vs1.validatorsUpdated(vs2)
|
||||||
|
//require.Equal(1, len(changed))
|
||||||
|
//testRemove(t, vs1[2], changed[0])
|
||||||
|
|
||||||
|
//// test multiple validators removed
|
||||||
|
//vs2 = []Validator{v1}
|
||||||
|
//changed = vs1.validatorsUpdated(vs2)
|
||||||
|
//require.Equal(2, len(changed))
|
||||||
|
//testRemove(t, vs1[1], changed[0])
|
||||||
|
//testRemove(t, vs1[2], changed[1])
|
||||||
|
|
||||||
|
//// test many types of changes
|
||||||
|
//vs2 = []Validator{v1, v3, v4, v5}
|
||||||
|
//vs2[2].VotingPower = rational.New(11)
|
||||||
|
//changed = vs1.validatorsUpdated(vs2)
|
||||||
|
//require.Equal(4, len(changed), "%v", changed) // change 1, remove 1, add 2
|
||||||
|
//testRemove(t, vs1[1], changed[0])
|
||||||
|
//testChange(t, vs2[1], changed[1])
|
||||||
|
//testChange(t, vs2[2], changed[2])
|
||||||
|
//testChange(t, vs2[3], changed[3])
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
//func TestUpdateValidatorSet(t *testing.T) {
|
||||||
|
//assert, require := assert.New(t), require.New(t)
|
||||||
|
//store := initTestStore(t)
|
||||||
|
//params := loadParams(store)
|
||||||
|
//gs := loadGlobalState(store)
|
||||||
|
|
||||||
|
//N := 5
|
||||||
|
//actors := newAddrs(N)
|
||||||
|
//candidates := candidatesFromActors(actors, []int64{400, 200, 100, 10, 1})
|
||||||
|
//for _, c := range candidates {
|
||||||
|
//saveCandidate(store, c)
|
||||||
|
//}
|
||||||
|
|
||||||
|
//// they should all already be validators
|
||||||
|
//change, err := UpdateValidatorSet(store, gs, params)
|
||||||
|
//require.Nil(err)
|
||||||
|
//require.Equal(0, len(change), "%v", change) // change 1, remove 1, add 2
|
||||||
|
|
||||||
|
//// test the max value and test again
|
||||||
|
//params.MaxVals = 4
|
||||||
|
//saveParams(store, params)
|
||||||
|
//change, err = UpdateValidatorSet(store, gs, params)
|
||||||
|
//require.Nil(err)
|
||||||
|
//require.Equal(1, len(change), "%v", change)
|
||||||
|
//testRemove(t, candidates[4].validator(), change[0])
|
||||||
|
//candidates = loadCandidates(store)
|
||||||
|
//assert.Equal(int64(0), candidates[4].VotingPower.Evaluate())
|
||||||
|
|
||||||
|
//// mess with the power's of the candidates and test
|
||||||
|
//candidates[0].Assets = rational.New(10)
|
||||||
|
//candidates[1].Assets = rational.New(600)
|
||||||
|
//candidates[2].Assets = rational.New(1000)
|
||||||
|
//candidates[3].Assets = rational.One
|
||||||
|
//candidates[4].Assets = rational.New(10)
|
||||||
|
//for _, c := range candidates {
|
||||||
|
//saveCandidate(store, c)
|
||||||
|
//}
|
||||||
|
//change, err = UpdateValidatorSet(store, gs, params)
|
||||||
|
//require.Nil(err)
|
||||||
|
//require.Equal(5, len(change), "%v", change) // 3 changed, 1 added, 1 removed
|
||||||
|
//candidates = loadCandidates(store)
|
||||||
|
//testChange(t, candidates[0].validator(), change[0])
|
||||||
|
//testChange(t, candidates[1].validator(), change[1])
|
||||||
|
//testChange(t, candidates[2].validator(), change[2])
|
||||||
|
//testRemove(t, candidates[3].validator(), change[3])
|
||||||
|
//testChange(t, candidates[4].validator(), change[4])
|
||||||
|
//}
|
||||||
|
|
||||||
func TestState(t *testing.T) {
|
func TestState(t *testing.T) {
|
||||||
assert, require := assert.New(t), require.New(t)
|
assert, require := assert.New(t), require.New(t)
|
||||||
|
@ -45,9 +221,9 @@ func TestState(t *testing.T) {
|
||||||
candidate := &Candidate{
|
candidate := &Candidate{
|
||||||
Owner: validator,
|
Owner: validator,
|
||||||
PubKey: pk,
|
PubKey: pk,
|
||||||
Assets: 9, //rational.New(9),
|
Assets: rational.New(9),
|
||||||
Liabilities: 9, // rational.New(9),
|
Liabilities: rational.New(9),
|
||||||
VotingPower: 0, //rational.Zero,
|
VotingPower: rational.Zero,
|
||||||
}
|
}
|
||||||
|
|
||||||
candidatesEqual := func(c1, c2 *Candidate) bool {
|
candidatesEqual := func(c1, c2 *Candidate) bool {
|
||||||
|
@ -72,12 +248,11 @@ func TestState(t *testing.T) {
|
||||||
assert.True(candidatesEqual(candidate, resCand))
|
assert.True(candidatesEqual(candidate, resCand))
|
||||||
|
|
||||||
// modify a records, save, and retrieve
|
// modify a records, save, and retrieve
|
||||||
candidate.Liabilities = 99 //rational.New(99)
|
candidate.Liabilities = rational.New(99)
|
||||||
saveCandidate(store, candidate)
|
saveCandidate(store, candidate)
|
||||||
resCand = loadCandidate(store, pk)
|
resCand = loadCandidate(store, pk)
|
||||||
assert.True(candidatesEqual(candidate, resCand))
|
assert.True(candidatesEqual(candidate, resCand))
|
||||||
|
|
||||||
store.Write()
|
|
||||||
// also test that the pubkey has been added to pubkey list
|
// also test that the pubkey has been added to pubkey list
|
||||||
resPks = loadCandidates(store)
|
resPks = loadCandidates(store)
|
||||||
require.Equal(1, len(resPks))
|
require.Equal(1, len(resPks))
|
||||||
|
@ -88,7 +263,7 @@ func TestState(t *testing.T) {
|
||||||
|
|
||||||
bond := &DelegatorBond{
|
bond := &DelegatorBond{
|
||||||
PubKey: pk,
|
PubKey: pk,
|
||||||
Shares: 9, // rational.New(9),
|
Shares: rational.New(9),
|
||||||
}
|
}
|
||||||
|
|
||||||
bondsEqual := func(b1, b2 *DelegatorBond) bool {
|
bondsEqual := func(b1, b2 *DelegatorBond) bool {
|
||||||
|
@ -106,7 +281,7 @@ func TestState(t *testing.T) {
|
||||||
assert.True(bondsEqual(bond, resBond))
|
assert.True(bondsEqual(bond, resBond))
|
||||||
|
|
||||||
//modify a records, save, and retrieve
|
//modify a records, save, and retrieve
|
||||||
bond.Shares = 99 //rational.New(99)
|
bond.Shares = rational.New(99)
|
||||||
saveDelegatorBond(store, delegator, bond)
|
saveDelegatorBond(store, delegator, bond)
|
||||||
resBond = loadDelegatorBond(store, delegator, pk)
|
resBond = loadDelegatorBond(store, delegator, pk)
|
||||||
assert.True(bondsEqual(bond, resBond))
|
assert.True(bondsEqual(bond, resBond))
|
||||||
|
@ -133,7 +308,7 @@ func TestGetValidators(t *testing.T) {
|
||||||
store := initTestStore(t)
|
store := initTestStore(t)
|
||||||
N := 5
|
N := 5
|
||||||
addrs := newAddrs(N)
|
addrs := newAddrs(N)
|
||||||
candidatesFromActors(store, addrs, []int{400, 200, 0, 0, 0})
|
candidatesFromActors(store, addrs, []int64{400, 200, 0, 0, 0})
|
||||||
|
|
||||||
validators := getValidators(store, 5)
|
validators := getValidators(store, 5)
|
||||||
require.Equal(2, len(validators))
|
require.Equal(2, len(validators))
|
||||||
|
|
|
@ -3,9 +3,15 @@ package stake
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
crypto "github.com/tendermint/go-crypto"
|
crypto "github.com/tendermint/go-crypto"
|
||||||
|
dbm "github.com/tendermint/tmlibs/db"
|
||||||
|
"github.com/tendermint/tmlibs/rational"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/store"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -15,6 +21,17 @@ func subspace(prefix []byte) (start, end []byte) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initTestStore(t *testing.T) sdk.KVStore {
|
||||||
|
// Capabilities key to access the main KVStore.
|
||||||
|
db, err := dbm.NewGoLevelDB("stake", "data")
|
||||||
|
require.Nil(t, err)
|
||||||
|
stakeStoreKey := sdk.NewKVStoreKey("stake")
|
||||||
|
ms := store.NewCommitMultiStore(db)
|
||||||
|
ms.MountStoreWithDB(stakeStoreKey, sdk.StoreTypeIAVL, db)
|
||||||
|
ms.LoadLatestVersion()
|
||||||
|
return ms.GetKVStore(stakeStoreKey)
|
||||||
|
}
|
||||||
|
|
||||||
func newAddrs(n int) (addrs []crypto.Address) {
|
func newAddrs(n int) (addrs []crypto.Address) {
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
addrs = append(addrs, []byte(fmt.Sprintf("addr%d", i)))
|
addrs = append(addrs, []byte(fmt.Sprintf("addr%d", i)))
|
||||||
|
@ -49,15 +66,15 @@ var pks = []crypto.PubKey{
|
||||||
|
|
||||||
// NOTE: PubKey is supposed to be the binaryBytes of the crypto.PubKey
|
// NOTE: PubKey is supposed to be the binaryBytes of the crypto.PubKey
|
||||||
// instead this is just being set the address here for testing purposes
|
// instead this is just being set the address here for testing purposes
|
||||||
func candidatesFromActors(store sdk.KVStore, addrs []crypto.Address, amts []int) {
|
func candidatesFromActors(store sdk.KVStore, addrs []crypto.Address, amts []int64) {
|
||||||
for i := 0; i < len(addrs); i++ {
|
for i := 0; i < len(addrs); i++ {
|
||||||
c := &Candidate{
|
c := &Candidate{
|
||||||
Status: Unbonded,
|
Status: Unbonded,
|
||||||
PubKey: pks[i],
|
PubKey: pks[i],
|
||||||
Owner: addrs[i],
|
Owner: addrs[i],
|
||||||
Assets: int64(amts[i]), //rational.New(amts[i]),
|
Assets: rational.New(amts[i]),
|
||||||
Liabilities: int64(amts[i]), //rational.New(amts[i]),
|
Liabilities: rational.New(amts[i]),
|
||||||
VotingPower: int64(amts[i]), //rational.New(amts[i]),
|
VotingPower: rational.New(amts[i]),
|
||||||
}
|
}
|
||||||
saveCandidate(store, c)
|
saveCandidate(store, c)
|
||||||
}
|
}
|
||||||
|
@ -69,9 +86,9 @@ func candidatesFromActorsEmpty(addrs []crypto.Address) (candidates Candidates) {
|
||||||
Status: Unbonded,
|
Status: Unbonded,
|
||||||
PubKey: pks[i],
|
PubKey: pks[i],
|
||||||
Owner: addrs[i],
|
Owner: addrs[i],
|
||||||
Assets: 0, //rational.Zero,
|
Assets: rational.Zero,
|
||||||
Liabilities: 0, //rational.Zero,
|
Liabilities: rational.Zero,
|
||||||
VotingPower: 0, //rational.Zero,
|
VotingPower: rational.Zero,
|
||||||
}
|
}
|
||||||
candidates = append(candidates, c)
|
candidates = append(candidates, c)
|
||||||
}
|
}
|
||||||
|
|
215
x/stake/types.go
215
x/stake/types.go
|
@ -1,21 +1,20 @@
|
||||||
package stake
|
package stake
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
abci "github.com/tendermint/abci/types"
|
||||||
crypto "github.com/tendermint/go-crypto"
|
crypto "github.com/tendermint/go-crypto"
|
||||||
"github.com/tendermint/go-wire"
|
"github.com/tendermint/tmlibs/rational"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cdc = wire.NewCodec()
|
// Params defines the high level settings for staking
|
||||||
|
|
||||||
//nolint
|
|
||||||
type Params struct {
|
type Params struct {
|
||||||
HoldBonded crypto.Address `json:"hold_bonded"` // account where all bonded coins are held
|
HoldBonded crypto.Address `json:"hold_bonded"` // account where all bonded coins are held
|
||||||
HoldUnbonded crypto.Address `json:"hold_unbonded"` // account where all delegated but unbonded coins are held
|
HoldUnbonded crypto.Address `json:"hold_unbonded"` // account where all delegated but unbonded coins are held
|
||||||
|
|
||||||
InflationRateChange int64 `json:"inflation_rate_change"` // XXX maximum annual change in inflation rate
|
InflationRateChange rational.Rational `json:"inflation_rate_change"` // maximum annual change in inflation rate
|
||||||
InflationMax int64 `json:"inflation_max"` // XXX maximum inflation rate
|
InflationMax rational.Rational `json:"inflation_max"` // maximum inflation rate
|
||||||
InflationMin int64 `json:"inflation_min"` // XXX minimum inflation rate
|
InflationMin rational.Rational `json:"inflation_min"` // minimum inflation rate
|
||||||
GoalBonded int64 `json:"goal_bonded"` // XXX Goal of percent bonded atoms
|
GoalBonded rational.Rational `json:"goal_bonded"` // Goal of percent bonded atoms
|
||||||
|
|
||||||
MaxVals uint16 `json:"max_vals"` // maximum number of validators
|
MaxVals uint16 `json:"max_vals"` // maximum number of validators
|
||||||
AllowedBondDenom string `json:"allowed_bond_denom"` // bondable coin denomination
|
AllowedBondDenom string `json:"allowed_bond_denom"` // bondable coin denomination
|
||||||
|
@ -31,10 +30,10 @@ func defaultParams() Params {
|
||||||
return Params{
|
return Params{
|
||||||
HoldBonded: []byte("77777777777777777777777777777777"),
|
HoldBonded: []byte("77777777777777777777777777777777"),
|
||||||
HoldUnbonded: []byte("88888888888888888888888888888888"),
|
HoldUnbonded: []byte("88888888888888888888888888888888"),
|
||||||
InflationRateChange: 13, //rational.New(13, 100),
|
InflationRateChange: rational.New(13, 100),
|
||||||
InflationMax: 20, //rational.New(20, 100),
|
InflationMax: rational.New(20, 100),
|
||||||
InflationMin: 7, //rational.New(7, 100),
|
InflationMin: rational.New(7, 100),
|
||||||
GoalBonded: 67, //rational.New(67, 100),
|
GoalBonded: rational.New(67, 100),
|
||||||
MaxVals: 100,
|
MaxVals: 100,
|
||||||
AllowedBondDenom: "fermion",
|
AllowedBondDenom: "fermion",
|
||||||
GasDeclareCandidacy: 20,
|
GasDeclareCandidacy: 20,
|
||||||
|
@ -44,15 +43,17 @@ func defaultParams() Params {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//_________________________________________________________________________
|
||||||
|
|
||||||
// GlobalState - dynamic parameters of the current state
|
// GlobalState - dynamic parameters of the current state
|
||||||
type GlobalState struct {
|
type GlobalState struct {
|
||||||
TotalSupply int64 `json:"total_supply"` // total supply of all tokens
|
TotalSupply int64 `json:"total_supply"` // total supply of all tokens
|
||||||
BondedShares int64 `json:"bonded_shares"` // sum of all shares distributed for the Bonded Pool
|
BondedShares rational.Rational `json:"bonded_shares"` // sum of all shares distributed for the Bonded Pool
|
||||||
UnbondedShares int64 `json:"unbonded_shares"` // sum of all shares distributed for the Unbonded Pool
|
UnbondedShares rational.Rational `json:"unbonded_shares"` // sum of all shares distributed for the Unbonded Pool
|
||||||
BondedPool int64 `json:"bonded_pool"` // reserve of bonded tokens
|
BondedPool int64 `json:"bonded_pool"` // reserve of bonded tokens
|
||||||
UnbondedPool int64 `json:"unbonded_pool"` // reserve of unbonded tokens held with candidates
|
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
|
InflationLastTime int64 `json:"inflation_last_time"` // block which the last inflation was processed // TODO make time
|
||||||
Inflation int64 `json:"inflation"` // current annual inflation rate
|
Inflation rational.Rational `json:"inflation"` // current annual inflation rate
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX define globalstate interface?
|
// XXX define globalstate interface?
|
||||||
|
@ -60,15 +61,69 @@ type GlobalState struct {
|
||||||
func initialGlobalState() *GlobalState {
|
func initialGlobalState() *GlobalState {
|
||||||
return &GlobalState{
|
return &GlobalState{
|
||||||
TotalSupply: 0,
|
TotalSupply: 0,
|
||||||
BondedShares: 0, //rational.Zero,
|
BondedShares: rational.Zero,
|
||||||
UnbondedShares: 0, //rational.Zero,
|
UnbondedShares: rational.Zero,
|
||||||
BondedPool: 0,
|
BondedPool: 0,
|
||||||
UnbondedPool: 0,
|
UnbondedPool: 0,
|
||||||
InflationLastTime: 0,
|
InflationLastTime: 0,
|
||||||
Inflation: 0, //rational.New(7, 100),
|
Inflation: rational.New(7, 100),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get the bond ratio of the global state
|
||||||
|
func (gs *GlobalState) bondedRatio() rational.Rational {
|
||||||
|
if gs.TotalSupply > 0 {
|
||||||
|
return rational.New(gs.BondedPool, gs.TotalSupply)
|
||||||
|
}
|
||||||
|
return rational.Zero
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the exchange rate of bonded token per issued share
|
||||||
|
func (gs *GlobalState) bondedShareExRate() rational.Rational {
|
||||||
|
if gs.BondedShares.IsZero() {
|
||||||
|
return rational.One
|
||||||
|
}
|
||||||
|
return gs.BondedShares.Inv().Mul(rational.New(gs.BondedPool))
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the exchange rate of unbonded tokens held in candidates per issued share
|
||||||
|
func (gs *GlobalState) unbondedShareExRate() rational.Rational {
|
||||||
|
if gs.UnbondedShares.IsZero() {
|
||||||
|
return rational.One
|
||||||
|
}
|
||||||
|
return gs.UnbondedShares.Inv().Mul(rational.New(gs.UnbondedPool))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gs *GlobalState) addTokensBonded(amount int64) (issuedShares rational.Rational) {
|
||||||
|
issuedShares = gs.bondedShareExRate().Inv().Mul(rational.New(amount)) // (tokens/shares)^-1 * tokens
|
||||||
|
gs.BondedPool += amount
|
||||||
|
gs.BondedShares = gs.BondedShares.Add(issuedShares)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gs *GlobalState) removeSharesBonded(shares rational.Rational) (removedTokens int64) {
|
||||||
|
removedTokens = gs.bondedShareExRate().Mul(shares).Evaluate() // (tokens/shares) * shares
|
||||||
|
gs.BondedShares = gs.BondedShares.Sub(shares)
|
||||||
|
gs.BondedPool -= removedTokens
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gs *GlobalState) addTokensUnbonded(amount int64) (issuedShares rational.Rational) {
|
||||||
|
issuedShares = gs.unbondedShareExRate().Inv().Mul(rational.New(amount)) // (tokens/shares)^-1 * tokens
|
||||||
|
gs.UnbondedShares = gs.UnbondedShares.Add(issuedShares)
|
||||||
|
gs.UnbondedPool += amount
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gs *GlobalState) removeSharesUnbonded(shares rational.Rational) (removedTokens int64) {
|
||||||
|
removedTokens = gs.unbondedShareExRate().Mul(shares).Evaluate() // (tokens/shares) * shares
|
||||||
|
gs.UnbondedShares = gs.UnbondedShares.Sub(shares)
|
||||||
|
gs.UnbondedPool -= removedTokens
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//_______________________________________________________________________________________________________
|
||||||
|
|
||||||
// CandidateStatus - status of a validator-candidate
|
// CandidateStatus - status of a validator-candidate
|
||||||
type CandidateStatus byte
|
type CandidateStatus byte
|
||||||
|
|
||||||
|
@ -87,23 +142,15 @@ const (
|
||||||
// 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.
|
||||||
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
|
||||||
Owner crypto.Address `json:"owner"` // Sender of BondTx - UnbondTx returns here
|
Owner crypto.Address `json:"owner"` // Sender of BondTx - UnbondTx returns here
|
||||||
Assets int64 `json:"assets"` // total shares of a global hold pools TODO custom type PoolShares
|
Assets rational.Rational `json:"assets"` // total shares of a global hold pools TODO custom type PoolShares
|
||||||
Liabilities int64 `json:"liabilities"` // total shares issued to a candidate's delegators TODO custom type DelegatorShares
|
Liabilities rational.Rational `json:"liabilities"` // total shares issued to a candidate's delegators TODO custom type DelegatorShares
|
||||||
VotingPower int64 `json:"voting_power"` // Voting power if considered a validator
|
VotingPower rational.Rational `json:"voting_power"` // Voting power if considered a validator
|
||||||
Description Description `json:"description"` // Description terms for the candidate
|
Description Description `json:"description"` // Description terms for the candidate
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint
|
|
||||||
type Candidates []*Candidate
|
|
||||||
type Validator struct {
|
|
||||||
PubKey crypto.PubKey `json:"pub_key"` // Pubkey of candidate
|
|
||||||
VotingPower int64 `json:"voting_power"` // Voting power if considered a validator
|
|
||||||
}
|
|
||||||
type Validators []Validator
|
|
||||||
|
|
||||||
// Description - description fields for a candidate
|
// Description - description fields for a candidate
|
||||||
type Description struct {
|
type Description struct {
|
||||||
Moniker string `json:"moniker"`
|
Moniker string `json:"moniker"`
|
||||||
|
@ -118,15 +165,95 @@ func NewCandidate(pubKey crypto.PubKey, owner crypto.Address, description Descri
|
||||||
Status: Unbonded,
|
Status: Unbonded,
|
||||||
PubKey: pubKey,
|
PubKey: pubKey,
|
||||||
Owner: owner,
|
Owner: owner,
|
||||||
Assets: 0, // rational.Zero,
|
Assets: rational.Zero,
|
||||||
Liabilities: 0, // rational.Zero,
|
Liabilities: rational.Zero,
|
||||||
VotingPower: 0, //rational.Zero,
|
VotingPower: rational.Zero,
|
||||||
Description: description,
|
Description: description,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint
|
// XXX define candidate interface?
|
||||||
type DelegatorBond struct {
|
|
||||||
PubKey crypto.PubKey `json:"pub_key"`
|
// get the exchange rate of global pool shares over delegator shares
|
||||||
Shares int64 `json:"shares"`
|
func (c *Candidate) delegatorShareExRate() rational.Rational {
|
||||||
|
if c.Liabilities.IsZero() {
|
||||||
|
return rational.One
|
||||||
|
}
|
||||||
|
return c.Assets.Quo(c.Liabilities)
|
||||||
|
}
|
||||||
|
|
||||||
|
// add tokens to a candidate
|
||||||
|
func (c *Candidate) addTokens(amount int64, gs *GlobalState) (issuedDelegatorShares rational.Rational) {
|
||||||
|
|
||||||
|
exRate := c.delegatorShareExRate()
|
||||||
|
|
||||||
|
var receivedGlobalShares rational.Rational
|
||||||
|
if c.Status == Bonded {
|
||||||
|
receivedGlobalShares = gs.addTokensBonded(amount)
|
||||||
|
} else {
|
||||||
|
receivedGlobalShares = gs.addTokensUnbonded(amount)
|
||||||
|
}
|
||||||
|
c.Assets = c.Assets.Add(receivedGlobalShares)
|
||||||
|
|
||||||
|
issuedDelegatorShares = exRate.Mul(receivedGlobalShares)
|
||||||
|
c.Liabilities = c.Liabilities.Add(issuedDelegatorShares)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove shares from a candidate
|
||||||
|
func (c *Candidate) removeShares(shares rational.Rational, gs *GlobalState) (removedTokens int64) {
|
||||||
|
|
||||||
|
globalPoolSharesToRemove := c.delegatorShareExRate().Mul(shares)
|
||||||
|
|
||||||
|
if c.Status == Bonded {
|
||||||
|
removedTokens = gs.removeSharesBonded(globalPoolSharesToRemove)
|
||||||
|
} else {
|
||||||
|
removedTokens = gs.removeSharesUnbonded(globalPoolSharesToRemove)
|
||||||
|
}
|
||||||
|
c.Assets = c.Assets.Sub(globalPoolSharesToRemove)
|
||||||
|
|
||||||
|
c.Liabilities = c.Liabilities.Sub(shares)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validator returns a copy of the Candidate as a Validator.
|
||||||
|
// Should only be called when the Candidate qualifies as a validator.
|
||||||
|
func (c *Candidate) validator() Validator {
|
||||||
|
return Validator{
|
||||||
|
PubKey: c.PubKey,
|
||||||
|
VotingPower: c.VotingPower,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validator is one of the top Candidates
|
||||||
|
type Validator struct {
|
||||||
|
PubKey crypto.PubKey `json:"pub_key"` // Pubkey of candidate
|
||||||
|
VotingPower rational.Rational `json:"voting_power"` // Voting power if considered a validator
|
||||||
|
}
|
||||||
|
|
||||||
|
// ABCIValidator - Get the validator from a bond value
|
||||||
|
func (v Validator) ABCIValidator() (*abci.Validator, error) {
|
||||||
|
pkBytes, err := cdc.MarshalBinary(v.PubKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &abci.Validator{
|
||||||
|
PubKey: pkBytes,
|
||||||
|
Power: v.VotingPower.Evaluate(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//_________________________________________________________________________
|
||||||
|
|
||||||
|
// Candidates - list of Candidates
|
||||||
|
type Candidates []*Candidate
|
||||||
|
|
||||||
|
//_________________________________________________________________________
|
||||||
|
|
||||||
|
// DelegatorBond represents the bond with tokens held by an account. It is
|
||||||
|
// owned by one delegator, and is associated with the voting power of one
|
||||||
|
// pubKey.
|
||||||
|
type DelegatorBond struct {
|
||||||
|
PubKey crypto.PubKey `json:"pub_key"`
|
||||||
|
Shares rational.Rational `json:"shares"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
package stake
|
||||||
|
|
||||||
|
// XXX test global state functions, candidate exchange rate functions etc.
|
Loading…
Reference in New Issue