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
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
wire "github.com/tendermint/go-wire"
|
||||
"github.com/tendermint/tmlibs/rational"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// nolint
|
||||
var (
|
||||
|
||||
// internal wire codec
|
||||
cdc *wire.Codec
|
||||
|
||||
// Keys for store prefixes
|
||||
CandidatesPubKeysKey = []byte{0x01} // key for all candidates' pubkeys
|
||||
ParamKey = []byte{0x02} // key for global parameters relating to staking
|
||||
GlobalStateKey = []byte{0x03} // key for global parameters relating to staking
|
||||
|
||||
// Key prefixes
|
||||
CandidateKeyPrefix = []byte{0x04} // 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
|
||||
DelegatorBondsKeyPrefix = []byte{0x07} // prefix for each key to a delegator's bond
|
||||
CandidateKeyPrefix = []byte{0x04} // prefix for each key to a candidate
|
||||
ValidatorKeyPrefix = []byte{0x05} // prefix for each key to a candidate
|
||||
ValidatorUpdatesKeyPrefix = []byte{0x06} // prefix for each key to a candidate
|
||||
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
|
||||
func GetCandidateKey(pubKey crypto.PubKey) []byte {
|
||||
return append(CandidateKeyPrefix, pubKey.Bytes()...)
|
||||
}
|
||||
|
||||
// GetValidatorKey - get the key for the validator used in the power-store
|
||||
func GetValidatorKey(pubKey crypto.PubKey, power int64) []byte {
|
||||
b := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(b, uint64(power))
|
||||
func GetValidatorKey(pubKey crypto.PubKey, power rational.Rational) []byte {
|
||||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
func GetDelegatorBondKey(delegator crypto.Address, candidate crypto.PubKey) []byte {
|
||||
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
|
||||
func GetDelegatorBondKeyPrefix(delegator crypto.Address) []byte {
|
||||
res, err := cdc.MarshalBinary(&delegator)
|
||||
res, err := cdc.MarshalJSON(&delegator)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -50,7 +65,7 @@ func GetDelegatorBondKeyPrefix(delegator crypto.Address) []byte {
|
|||
|
||||
// GetDelegatorBondsKey - get the key for list of all the delegator's bonds
|
||||
func GetDelegatorBondsKey(delegator crypto.Address) []byte {
|
||||
res, err := cdc.MarshalBinary(&delegator)
|
||||
res, err := cdc.MarshalJSON(&delegator)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -60,15 +75,12 @@ func GetDelegatorBondsKey(delegator crypto.Address) []byte {
|
|||
//---------------------------------------------------------------------
|
||||
|
||||
func loadCandidate(store types.KVStore, pubKey crypto.PubKey) *Candidate {
|
||||
//if pubKey.Empty() {
|
||||
//return nil
|
||||
//}
|
||||
b := store.Get(GetCandidateKey(pubKey))
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
candidate := new(Candidate)
|
||||
err := cdc.UnmarshalBinary(b, candidate)
|
||||
err := cdc.UnmarshalJSON(b, candidate)
|
||||
if err != nil {
|
||||
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) {
|
||||
|
||||
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}
|
||||
saveValidator(store, validator)
|
||||
updateValidator(store, validator)
|
||||
|
||||
b, err := cdc.MarshalBinary(*candidate)
|
||||
b, err := cdc.MarshalJSON(*candidate)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -89,54 +102,67 @@ func saveCandidate(store types.KVStore, candidate *Candidate) {
|
|||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
func loadValidator(store types.KVStore, pubKey crypto.PubKey, votingPower int64) *Validator {
|
||||
b := store.Get(GetValidatorKey(pubKey, votingPower))
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
validator := new(Validator)
|
||||
err := cdc.UnmarshalBinary(b, validator)
|
||||
if err != nil {
|
||||
panic(err) // This error should never occur big problem if does
|
||||
}
|
||||
return validator
|
||||
}
|
||||
//func loadValidator(store types.KVStore, pubKey crypto.PubKey, votingPower rational.Rational) *Validator {
|
||||
//b := store.Get(GetValidatorKey(pubKey, votingPower))
|
||||
//if b == nil {
|
||||
//return nil
|
||||
//}
|
||||
//validator := new(Validator)
|
||||
//err := cdc.UnmarshalJSON(b, validator)
|
||||
//if err != nil {
|
||||
//panic(err) // This error should never occur big problem if does
|
||||
//}
|
||||
//return validator
|
||||
//}
|
||||
|
||||
func saveValidator(store types.KVStore, validator *Validator) {
|
||||
b, err := cdc.MarshalBinary(*validator)
|
||||
// updateValidator - update a validator and create accumulate any changes
|
||||
// in the changed validator substore
|
||||
func updateValidator(store types.KVStore, validator *Validator) {
|
||||
|
||||
b, err := cdc.MarshalJSON(*validator)
|
||||
if err != nil {
|
||||
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)
|
||||
}
|
||||
|
||||
func removeValidator(store types.KVStore, pubKey crypto.PubKey, votingPower int64) {
|
||||
store.Delete(GetValidatorKey(pubKey, votingPower))
|
||||
}
|
||||
func removeValidator(store types.KVStore, pubKey crypto.PubKey) {
|
||||
|
||||
func removeValidatorFromKey(store types.KVStore, pubKey crypto.PubKey) {
|
||||
// remove validator if already there, then add new validator
|
||||
//add validator with zero power to the validator updates
|
||||
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)
|
||||
if candidate != nil {
|
||||
removeValidator(store, pubKey, candidate.VotingPower)
|
||||
store.Delete(GetValidatorKey(pubKey, candidate.VotingPower))
|
||||
}
|
||||
}
|
||||
|
||||
// Validators - get the most recent updated validator set from the
|
||||
// Candidates. These bonds are already sorted by VotingPower from
|
||||
// the UpdateVotingPower function which is the only function which
|
||||
// is to modify the VotingPower
|
||||
func getValidators(store types.KVStore, maxVal int) Validators {
|
||||
// get the most recent updated validator set from the Candidates. These bonds
|
||||
// are already sorted by VotingPower from the UpdateVotingPower function which
|
||||
// is the only function which is to modify the VotingPower
|
||||
func getValidators(store types.KVStore, maxVal int) (validators []Validator) {
|
||||
|
||||
iterator := store.Iterator(subspace(ValidatorKeyPrefix)) //smallest to largest
|
||||
|
||||
validators := make(Validators, maxVal)
|
||||
validators = make([]Validator, maxVal)
|
||||
for i := 0; ; i++ {
|
||||
if !iterator.Valid() || i > maxVal {
|
||||
iterator.Close()
|
||||
|
@ -144,7 +170,7 @@ func getValidators(store types.KVStore, maxVal int) Validators {
|
|||
}
|
||||
valBytes := iterator.Value()
|
||||
var val Validator
|
||||
err := cdc.UnmarshalBinary(valBytes, &val)
|
||||
err := cdc.UnmarshalJSON(valBytes, &val)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -152,7 +178,37 @@ func getValidators(store types.KVStore, maxVal int) Validators {
|
|||
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
|
||||
func loadCandidates(store types.KVStore) (candidates Candidates) {
|
||||
|
||||
//iterator := store.Iterator(subspace(CandidateKeyPrefix)) //smallest to largest
|
||||
//iterator := store.Iterator(CandidateKeyPrefix, []byte(nil)) //smallest to largest
|
||||
iterator := store.Iterator([]byte{}, []byte(nil)) //smallest to largest
|
||||
iterator := store.Iterator(subspace(CandidateKeyPrefix))
|
||||
//iterator := store.Iterator(CandidateKeyPrefix, []byte(nil))
|
||||
//iterator := store.Iterator([]byte{}, []byte(nil))
|
||||
|
||||
for i := 0; ; i++ {
|
||||
if !iterator.Valid() {
|
||||
//panic(fmt.Sprintf("debug i: %v\n", i))
|
||||
iterator.Close()
|
||||
break
|
||||
}
|
||||
for ; iterator.Valid(); iterator.Next() {
|
||||
candidateBytes := iterator.Value()
|
||||
var candidate Candidate
|
||||
err := cdc.UnmarshalBinary(candidateBytes, &candidate)
|
||||
err := cdc.UnmarshalJSON(candidateBytes, &candidate)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
candidates[i] = &candidate
|
||||
iterator.Next()
|
||||
candidates = append(candidates, &candidate)
|
||||
}
|
||||
|
||||
iterator.Close()
|
||||
return candidates
|
||||
}
|
||||
|
||||
|
@ -194,7 +244,7 @@ func loadDelegatorCandidates(store types.KVStore,
|
|||
return nil
|
||||
}
|
||||
|
||||
err := cdc.UnmarshalBinary(candidateBytes, &candidates)
|
||||
err := cdc.UnmarshalJSON(candidateBytes, &candidates)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -212,7 +262,7 @@ func loadDelegatorBond(store types.KVStore,
|
|||
}
|
||||
|
||||
bond := new(DelegatorBond)
|
||||
err := cdc.UnmarshalBinary(delegatorBytes, bond)
|
||||
err := cdc.UnmarshalJSON(delegatorBytes, bond)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -225,7 +275,7 @@ func saveDelegatorBond(store types.KVStore, delegator crypto.Address, bond *Dele
|
|||
if loadDelegatorBond(store, delegator, bond.PubKey) == nil {
|
||||
pks := loadDelegatorCandidates(store, delegator)
|
||||
pks = append(pks, (*bond).PubKey)
|
||||
b, err := cdc.MarshalBinary(pks)
|
||||
b, err := cdc.MarshalJSON(pks)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -233,7 +283,7 @@ func saveDelegatorBond(store types.KVStore, delegator crypto.Address, bond *Dele
|
|||
}
|
||||
|
||||
// now actually save the bond
|
||||
b, err := cdc.MarshalBinary(*bond)
|
||||
b, err := cdc.MarshalJSON(*bond)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -250,7 +300,7 @@ func removeDelegatorBond(store types.KVStore, delegator crypto.Address, candidat
|
|||
pks = append(pks[:i], pks[i+1:]...)
|
||||
}
|
||||
}
|
||||
b, err := cdc.MarshalBinary(pks)
|
||||
b, err := cdc.MarshalJSON(pks)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -261,39 +311,6 @@ func removeDelegatorBond(store types.KVStore, delegator crypto.Address, candidat
|
|||
//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
|
||||
|
@ -303,7 +320,7 @@ func loadParams(store types.KVStore) (params Params) {
|
|||
return defaultParams()
|
||||
}
|
||||
|
||||
err := cdc.UnmarshalBinary(b, ¶ms)
|
||||
err := cdc.UnmarshalJSON(b, ¶ms)
|
||||
if err != nil {
|
||||
panic(err) // This error should never occur big problem if does
|
||||
}
|
||||
|
@ -311,7 +328,7 @@ func loadParams(store types.KVStore) (params Params) {
|
|||
return
|
||||
}
|
||||
func saveParams(store types.KVStore, params Params) {
|
||||
b, err := cdc.MarshalBinary(params)
|
||||
b, err := cdc.MarshalJSON(params)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -327,14 +344,14 @@ func loadGlobalState(store types.KVStore) (gs *GlobalState) {
|
|||
return initialGlobalState()
|
||||
}
|
||||
gs = new(GlobalState)
|
||||
err := cdc.UnmarshalBinary(b, gs)
|
||||
err := cdc.UnmarshalJSON(b, gs)
|
||||
if err != nil {
|
||||
panic(err) // This error should never occur big problem if does
|
||||
}
|
||||
return
|
||||
}
|
||||
func saveGlobalState(store types.KVStore, gs *GlobalState) {
|
||||
b, err := cdc.MarshalBinary(*gs)
|
||||
b, err := cdc.MarshalJSON(*gs)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
|
@ -4,25 +4,201 @@ import (
|
|||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/store"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
dbm "github.com/tendermint/tmlibs/db"
|
||||
"github.com/tendermint/tmlibs/rational"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
// XXX XXX XXX
|
||||
// XXX revive these tests but for the store update proceedure
|
||||
// XXX XXX XXX
|
||||
|
||||
//func TestUpdateVotingPower(t *testing.T) {
|
||||
//assert := assert.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})
|
||||
|
||||
//// 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) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
|
@ -45,9 +221,9 @@ func TestState(t *testing.T) {
|
|||
candidate := &Candidate{
|
||||
Owner: validator,
|
||||
PubKey: pk,
|
||||
Assets: 9, //rational.New(9),
|
||||
Liabilities: 9, // rational.New(9),
|
||||
VotingPower: 0, //rational.Zero,
|
||||
Assets: rational.New(9),
|
||||
Liabilities: rational.New(9),
|
||||
VotingPower: rational.Zero,
|
||||
}
|
||||
|
||||
candidatesEqual := func(c1, c2 *Candidate) bool {
|
||||
|
@ -72,12 +248,11 @@ func TestState(t *testing.T) {
|
|||
assert.True(candidatesEqual(candidate, resCand))
|
||||
|
||||
// modify a records, save, and retrieve
|
||||
candidate.Liabilities = 99 //rational.New(99)
|
||||
candidate.Liabilities = rational.New(99)
|
||||
saveCandidate(store, candidate)
|
||||
resCand = loadCandidate(store, pk)
|
||||
assert.True(candidatesEqual(candidate, resCand))
|
||||
|
||||
store.Write()
|
||||
// also test that the pubkey has been added to pubkey list
|
||||
resPks = loadCandidates(store)
|
||||
require.Equal(1, len(resPks))
|
||||
|
@ -88,7 +263,7 @@ func TestState(t *testing.T) {
|
|||
|
||||
bond := &DelegatorBond{
|
||||
PubKey: pk,
|
||||
Shares: 9, // rational.New(9),
|
||||
Shares: rational.New(9),
|
||||
}
|
||||
|
||||
bondsEqual := func(b1, b2 *DelegatorBond) bool {
|
||||
|
@ -106,7 +281,7 @@ func TestState(t *testing.T) {
|
|||
assert.True(bondsEqual(bond, resBond))
|
||||
|
||||
//modify a records, save, and retrieve
|
||||
bond.Shares = 99 //rational.New(99)
|
||||
bond.Shares = rational.New(99)
|
||||
saveDelegatorBond(store, delegator, bond)
|
||||
resBond = loadDelegatorBond(store, delegator, pk)
|
||||
assert.True(bondsEqual(bond, resBond))
|
||||
|
@ -133,7 +308,7 @@ func TestGetValidators(t *testing.T) {
|
|||
store := initTestStore(t)
|
||||
N := 5
|
||||
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)
|
||||
require.Equal(2, len(validators))
|
||||
|
|
|
@ -3,9 +3,15 @@ package stake
|
|||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
|
@ -15,6 +21,17 @@ func subspace(prefix []byte) (start, end []byte) {
|
|||
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) {
|
||||
for i := 0; i < n; 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
|
||||
// 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++ {
|
||||
c := &Candidate{
|
||||
Status: Unbonded,
|
||||
PubKey: pks[i],
|
||||
Owner: addrs[i],
|
||||
Assets: int64(amts[i]), //rational.New(amts[i]),
|
||||
Liabilities: int64(amts[i]), //rational.New(amts[i]),
|
||||
VotingPower: int64(amts[i]), //rational.New(amts[i]),
|
||||
Assets: rational.New(amts[i]),
|
||||
Liabilities: rational.New(amts[i]),
|
||||
VotingPower: rational.New(amts[i]),
|
||||
}
|
||||
saveCandidate(store, c)
|
||||
}
|
||||
|
@ -69,9 +86,9 @@ func candidatesFromActorsEmpty(addrs []crypto.Address) (candidates Candidates) {
|
|||
Status: Unbonded,
|
||||
PubKey: pks[i],
|
||||
Owner: addrs[i],
|
||||
Assets: 0, //rational.Zero,
|
||||
Liabilities: 0, //rational.Zero,
|
||||
VotingPower: 0, //rational.Zero,
|
||||
Assets: rational.Zero,
|
||||
Liabilities: rational.Zero,
|
||||
VotingPower: rational.Zero,
|
||||
}
|
||||
candidates = append(candidates, c)
|
||||
}
|
||||
|
|
215
x/stake/types.go
215
x/stake/types.go
|
@ -1,21 +1,20 @@
|
|||
package stake
|
||||
|
||||
import (
|
||||
abci "github.com/tendermint/abci/types"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
"github.com/tendermint/go-wire"
|
||||
"github.com/tendermint/tmlibs/rational"
|
||||
)
|
||||
|
||||
var cdc = wire.NewCodec()
|
||||
|
||||
//nolint
|
||||
// Params defines the high level settings for staking
|
||||
type Params struct {
|
||||
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
|
||||
|
||||
InflationRateChange int64 `json:"inflation_rate_change"` // XXX maximum annual change in inflation rate
|
||||
InflationMax int64 `json:"inflation_max"` // XXX maximum inflation rate
|
||||
InflationMin int64 `json:"inflation_min"` // XXX minimum inflation rate
|
||||
GoalBonded int64 `json:"goal_bonded"` // XXX Goal of percent bonded atoms
|
||||
InflationRateChange rational.Rational `json:"inflation_rate_change"` // maximum annual change in inflation rate
|
||||
InflationMax rational.Rational `json:"inflation_max"` // maximum inflation rate
|
||||
InflationMin rational.Rational `json:"inflation_min"` // minimum inflation rate
|
||||
GoalBonded rational.Rational `json:"goal_bonded"` // Goal of percent bonded atoms
|
||||
|
||||
MaxVals uint16 `json:"max_vals"` // maximum number of validators
|
||||
AllowedBondDenom string `json:"allowed_bond_denom"` // bondable coin denomination
|
||||
|
@ -31,10 +30,10 @@ func defaultParams() Params {
|
|||
return Params{
|
||||
HoldBonded: []byte("77777777777777777777777777777777"),
|
||||
HoldUnbonded: []byte("88888888888888888888888888888888"),
|
||||
InflationRateChange: 13, //rational.New(13, 100),
|
||||
InflationMax: 20, //rational.New(20, 100),
|
||||
InflationMin: 7, //rational.New(7, 100),
|
||||
GoalBonded: 67, //rational.New(67, 100),
|
||||
InflationRateChange: rational.New(13, 100),
|
||||
InflationMax: rational.New(20, 100),
|
||||
InflationMin: rational.New(7, 100),
|
||||
GoalBonded: rational.New(67, 100),
|
||||
MaxVals: 100,
|
||||
AllowedBondDenom: "fermion",
|
||||
GasDeclareCandidacy: 20,
|
||||
|
@ -44,15 +43,17 @@ func defaultParams() Params {
|
|||
}
|
||||
}
|
||||
|
||||
//_________________________________________________________________________
|
||||
|
||||
// GlobalState - dynamic parameters of the current state
|
||||
type GlobalState struct {
|
||||
TotalSupply int64 `json:"total_supply"` // total supply of all tokens
|
||||
BondedShares int64 `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
|
||||
BondedPool int64 `json:"bonded_pool"` // reserve of bonded tokens
|
||||
UnbondedPool int64 `json:"unbonded_pool"` // reserve of unbonded tokens held with candidates
|
||||
InflationLastTime int64 `json:"inflation_last_time"` // block which the last inflation was processed // TODO make time
|
||||
Inflation int64 `json:"inflation"` // current annual inflation rate
|
||||
TotalSupply int64 `json:"total_supply"` // total supply of all tokens
|
||||
BondedShares rational.Rational `json:"bonded_shares"` // sum of all shares distributed for the Bonded 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
|
||||
UnbondedPool int64 `json:"unbonded_pool"` // reserve of unbonded tokens held with candidates
|
||||
InflationLastTime int64 `json:"inflation_last_time"` // block which the last inflation was processed // TODO make time
|
||||
Inflation rational.Rational `json:"inflation"` // current annual inflation rate
|
||||
}
|
||||
|
||||
// XXX define globalstate interface?
|
||||
|
@ -60,15 +61,69 @@ type GlobalState struct {
|
|||
func initialGlobalState() *GlobalState {
|
||||
return &GlobalState{
|
||||
TotalSupply: 0,
|
||||
BondedShares: 0, //rational.Zero,
|
||||
UnbondedShares: 0, //rational.Zero,
|
||||
BondedShares: rational.Zero,
|
||||
UnbondedShares: rational.Zero,
|
||||
BondedPool: 0,
|
||||
UnbondedPool: 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
|
||||
type CandidateStatus byte
|
||||
|
||||
|
@ -87,23 +142,15 @@ const (
|
|||
// exchange rate. Voting power can be calculated as total bonds multiplied by
|
||||
// exchange rate.
|
||||
type Candidate struct {
|
||||
Status CandidateStatus `json:"status"` // Bonded status
|
||||
PubKey crypto.PubKey `json:"pub_key"` // Pubkey of candidate
|
||||
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
|
||||
Liabilities int64 `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
|
||||
Description Description `json:"description"` // Description terms for the candidate
|
||||
Status CandidateStatus `json:"status"` // Bonded status
|
||||
PubKey crypto.PubKey `json:"pub_key"` // Pubkey of candidate
|
||||
Owner crypto.Address `json:"owner"` // Sender of BondTx - UnbondTx returns here
|
||||
Assets rational.Rational `json:"assets"` // total shares of a global hold pools TODO custom type PoolShares
|
||||
Liabilities rational.Rational `json:"liabilities"` // total shares issued to a candidate's delegators TODO custom type DelegatorShares
|
||||
VotingPower rational.Rational `json:"voting_power"` // Voting power if considered a validator
|
||||
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
|
||||
type Description struct {
|
||||
Moniker string `json:"moniker"`
|
||||
|
@ -118,15 +165,95 @@ func NewCandidate(pubKey crypto.PubKey, owner crypto.Address, description Descri
|
|||
Status: Unbonded,
|
||||
PubKey: pubKey,
|
||||
Owner: owner,
|
||||
Assets: 0, // rational.Zero,
|
||||
Liabilities: 0, // rational.Zero,
|
||||
VotingPower: 0, //rational.Zero,
|
||||
Assets: rational.Zero,
|
||||
Liabilities: rational.Zero,
|
||||
VotingPower: rational.Zero,
|
||||
Description: description,
|
||||
}
|
||||
}
|
||||
|
||||
//nolint
|
||||
type DelegatorBond struct {
|
||||
PubKey crypto.PubKey `json:"pub_key"`
|
||||
Shares int64 `json:"shares"`
|
||||
// XXX define candidate interface?
|
||||
|
||||
// get the exchange rate of global pool shares over delegator 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