parent
c2ddc582c4
commit
7d4528e623
139
x/stake/store.go
139
x/stake/store.go
|
@ -1,14 +1,133 @@
|
|||
package stake
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
"github.com/tendermint/go-wire"
|
||||
"github.com/tendermint/tmlibs/rational"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
/////////////////////////////////////////////////////////// temp types
|
||||
|
||||
//nolint
|
||||
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
|
||||
|
||||
MaxVals uint16 `json:"max_vals"` // maximum number of validators
|
||||
AllowedBondDenom string `json:"allowed_bond_denom"` // bondable coin denomination
|
||||
|
||||
// gas costs for txs
|
||||
GasDeclareCandidacy int64 `json:"gas_declare_candidacy"`
|
||||
GasEditCandidacy int64 `json:"gas_edit_candidacy"`
|
||||
GasDelegate int64 `json:"gas_delegate"`
|
||||
GasUnbond int64 `json:"gas_unbond"`
|
||||
}
|
||||
|
||||
func defaultParams() Params {
|
||||
return Params{
|
||||
HoldBonded: []byte("77777777777777777777777777777777"),
|
||||
HoldUnbonded: []byte("88888888888888888888888888888888"),
|
||||
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,
|
||||
GasEditCandidacy: 20,
|
||||
GasDelegate: 20,
|
||||
GasUnbond: 20,
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// XXX define globalstate interface?
|
||||
|
||||
func initialGlobalState() *GlobalState {
|
||||
return &GlobalState{
|
||||
TotalSupply: 0,
|
||||
BondedShares: rational.Zero,
|
||||
UnbondedShares: rational.Zero,
|
||||
BondedPool: 0,
|
||||
UnbondedPool: 0,
|
||||
InflationLastTime: 0,
|
||||
Inflation: rational.New(7, 100),
|
||||
}
|
||||
}
|
||||
|
||||
// CandidateStatus - status of a validator-candidate
|
||||
type CandidateStatus byte
|
||||
|
||||
const (
|
||||
// nolint
|
||||
Bonded CandidateStatus = 0x00
|
||||
Unbonded CandidateStatus = 0x01
|
||||
Revoked CandidateStatus = 0x02
|
||||
)
|
||||
|
||||
// Candidate defines the total amount of bond shares and their exchange rate to
|
||||
// coins. Accumulation of interest is modelled as an in increase in the
|
||||
// exchange rate, and slashing as a decrease. When coins are delegated to this
|
||||
// candidate, the candidate is credited with a DelegatorBond whose number of
|
||||
// bond shares is based on the amount of coins delegated divided by the current
|
||||
// exchange rate. Voting power can be calculated as total bonds multiplied by
|
||||
// exchange rate.
|
||||
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
|
||||
}
|
||||
|
||||
// Description - description fields for a candidate
|
||||
type Description struct {
|
||||
Moniker string `json:"moniker"`
|
||||
Identity string `json:"identity"`
|
||||
Website string `json:"website"`
|
||||
Details string `json:"details"`
|
||||
}
|
||||
|
||||
// NewCandidate - initialize a new candidate
|
||||
func NewCandidate(pubKey crypto.PubKey, owner crypto.Address, description Description) *Candidate {
|
||||
return &Candidate{
|
||||
Status: Unbonded,
|
||||
PubKey: pubKey,
|
||||
Owner: owner,
|
||||
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"`
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////j
|
||||
|
||||
// nolint
|
||||
var (
|
||||
// Keys for store prefixes
|
||||
|
@ -93,7 +212,7 @@ func loadCandidate(store types.KVStore, pubKey crypto.PubKey) *Candidate {
|
|||
return nil
|
||||
}
|
||||
candidate := new(Candidate)
|
||||
err := json.Unmarshal(b, candidate)
|
||||
err := wire.UnmarshalBinary(b, candidate)
|
||||
if err != nil {
|
||||
panic(err) // This error should never occure big problem if does
|
||||
}
|
||||
|
@ -108,7 +227,7 @@ func saveCandidate(store types.KVStore, candidate *Candidate) {
|
|||
saveCandidatesPubKeys(store, append(pks, candidate.PubKey))
|
||||
}
|
||||
|
||||
b, err := json.Marshal(*candidate)
|
||||
b, err := wire.MarshalBinary(*candidate)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -158,7 +277,7 @@ func loadDelegatorBond(store types.KVStore,
|
|||
}
|
||||
|
||||
bond := new(DelegatorBond)
|
||||
err := json.Unmarshal(delegatorBytes, bond)
|
||||
err := wire.UnmarshalBinary(delegatorBytes, bond)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -179,7 +298,7 @@ func saveDelegatorBond(store types.KVStore, delegator crypto.Address, bond *Dele
|
|||
}
|
||||
|
||||
// now actually save the bond
|
||||
b, err := json.Marshal(*bond)
|
||||
b, err := wire.MarshalBinary(*bond)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -250,7 +369,7 @@ func loadParams(store types.KVStore) (params Params) {
|
|||
return defaultParams()
|
||||
}
|
||||
|
||||
err := json.Unmarshal(b, ¶ms)
|
||||
err := wire.UnmarshalBinary(b, ¶ms)
|
||||
if err != nil {
|
||||
panic(err) // This error should never occure big problem if does
|
||||
}
|
||||
|
@ -258,7 +377,7 @@ func loadParams(store types.KVStore) (params Params) {
|
|||
return
|
||||
}
|
||||
func saveParams(store types.KVStore, params Params) {
|
||||
b, err := json.Marshal(params)
|
||||
b, err := wire.MarshalBinary(params)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -274,14 +393,14 @@ func loadGlobalState(store types.KVStore) (gs *GlobalState) {
|
|||
return initialGlobalState()
|
||||
}
|
||||
gs = new(GlobalState)
|
||||
err := json.Unmarshal(b, gs)
|
||||
err := wire.UnmarshalBinary(b, gs)
|
||||
if err != nil {
|
||||
panic(err) // This error should never occure big problem if does
|
||||
}
|
||||
return
|
||||
}
|
||||
func saveGlobalState(store types.KVStore, gs *GlobalState) {
|
||||
b, err := json.Marshal(*gs)
|
||||
b, err := wire.MarshalBinary(*gs)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
"github.com/tendermint/go-wire"
|
||||
dbm "github.com/tendermint/tmlibs/db"
|
||||
"github.com/tendermint/tmlibs/rational"
|
||||
)
|
||||
|
||||
func newPubKey(pk string) (res crypto.PubKey, err error) {
|
||||
|
@ -38,6 +38,8 @@ func TestState(t *testing.T) {
|
|||
multiStore.SetSubstoreLoader(stakeStoreKey, stakeLoader)
|
||||
multiStore.LoadLatestVersion()
|
||||
store := multiStore.GetKVStore(stakeStoreKey)
|
||||
wire.RegisterInterface((*crypto.PubKey)(nil), nil)
|
||||
wire.RegisterConcrete(crypto.PubKeyEd25519{}, "crypto/PubKeyEd25519", nil)
|
||||
|
||||
//delegator := crypto.Address{[]byte("addressdelegator")}
|
||||
//validator := crypto.Address{[]byte("addressvalidator")}
|
||||
|
@ -54,9 +56,9 @@ func TestState(t *testing.T) {
|
|||
candidate := &Candidate{
|
||||
Owner: validator,
|
||||
PubKey: pk,
|
||||
Assets: rational.New(9),
|
||||
Liabilities: rational.New(9),
|
||||
VotingPower: rational.Zero,
|
||||
Assets: 9, //rational.New(9),
|
||||
Liabilities: 9, // rational.New(9),
|
||||
VotingPower: 0, //rational.Zero,
|
||||
}
|
||||
|
||||
candidatesEqual := func(c1, c2 *Candidate) bool {
|
||||
|
@ -81,7 +83,7 @@ func TestState(t *testing.T) {
|
|||
assert.True(candidatesEqual(candidate, resCand))
|
||||
|
||||
// modify a records, save, and retrieve
|
||||
candidate.Liabilities = rational.New(99)
|
||||
candidate.Liabilities = 99 //rational.New(99)
|
||||
saveCandidate(store, candidate)
|
||||
resCand = loadCandidate(store, pk)
|
||||
assert.True(candidatesEqual(candidate, resCand))
|
||||
|
@ -96,7 +98,7 @@ func TestState(t *testing.T) {
|
|||
|
||||
bond := &DelegatorBond{
|
||||
PubKey: pk,
|
||||
Shares: rational.New(9),
|
||||
Shares: 9, // rational.New(9),
|
||||
}
|
||||
|
||||
bondsEqual := func(b1, b2 *DelegatorBond) bool {
|
||||
|
@ -114,7 +116,7 @@ func TestState(t *testing.T) {
|
|||
assert.True(bondsEqual(bond, resBond))
|
||||
|
||||
//modify a records, save, and retrieve
|
||||
bond.Shares = rational.New(99)
|
||||
bond.Shares = 99 //rational.New(99)
|
||||
saveDelegatorBond(store, delegator, bond)
|
||||
resBond = loadDelegatorBond(store, delegator, pk)
|
||||
assert.True(bondsEqual(bond, resBond))
|
||||
|
|
832
x/stake/types.go
832
x/stake/types.go
|
@ -1,418 +1,418 @@
|
|||
package stake
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"sort"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
wire "github.com/tendermint/go-wire"
|
||||
"github.com/tendermint/tmlibs/rational"
|
||||
)
|
||||
|
||||
// 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 rational.Rat `json:"inflation_rate_change"` // maximum annual change in inflation rate
|
||||
InflationMax rational.Rat `json:"inflation_max"` // maximum inflation rate
|
||||
InflationMin rational.Rat `json:"inflation_min"` // minimum inflation rate
|
||||
GoalBonded rational.Rat `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
|
||||
|
||||
// gas costs for txs
|
||||
GasDeclareCandidacy int64 `json:"gas_declare_candidacy"`
|
||||
GasEditCandidacy int64 `json:"gas_edit_candidacy"`
|
||||
GasDelegate int64 `json:"gas_delegate"`
|
||||
GasUnbond int64 `json:"gas_unbond"`
|
||||
}
|
||||
|
||||
func defaultParams() Params {
|
||||
return Params{
|
||||
HoldBonded: []byte("77777777777777777777777777777777"),
|
||||
HoldUnbonded: []byte("88888888888888888888888888888888"),
|
||||
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,
|
||||
GasEditCandidacy: 20,
|
||||
GasDelegate: 20,
|
||||
GasUnbond: 20,
|
||||
}
|
||||
}
|
||||
|
||||
//_________________________________________________________________________
|
||||
|
||||
// GlobalState - dynamic parameters of the current state
|
||||
type GlobalState struct {
|
||||
TotalSupply int64 `json:"total_supply"` // total supply of all tokens
|
||||
BondedShares rational.Rat `json:"bonded_shares"` // sum of all shares distributed for the Bonded Pool
|
||||
UnbondedShares rational.Rat `json:"unbonded_shares"` // sum of all shares distributed for the Unbonded Pool
|
||||
BondedPool int64 `json:"bonded_pool"` // reserve of bonded tokens
|
||||
UnbondedPool int64 `json:"unbonded_pool"` // reserve of unbonded tokens held with candidates
|
||||
InflationLastTime int64 `json:"inflation_last_time"` // block which the last inflation was processed // TODO make time
|
||||
Inflation rational.Rat `json:"inflation"` // current annual inflation rate
|
||||
}
|
||||
|
||||
// XXX define globalstate interface?
|
||||
|
||||
func initialGlobalState() *GlobalState {
|
||||
return &GlobalState{
|
||||
TotalSupply: 0,
|
||||
BondedShares: rational.Zero,
|
||||
UnbondedShares: rational.Zero,
|
||||
BondedPool: 0,
|
||||
UnbondedPool: 0,
|
||||
InflationLastTime: 0,
|
||||
Inflation: rational.New(7, 100),
|
||||
}
|
||||
}
|
||||
|
||||
// get the bond ratio of the global state
|
||||
func (gs *GlobalState) bondedRatio() rational.Rat {
|
||||
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.Rat {
|
||||
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.Rat {
|
||||
if gs.UnbondedShares.IsZero() {
|
||||
return rational.One
|
||||
}
|
||||
return gs.UnbondedShares.Inv().Mul(rational.New(gs.UnbondedPool))
|
||||
}
|
||||
|
||||
func (gs *GlobalState) addTokensBonded(amount int64) (issuedShares rational.Rat) {
|
||||
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.Rat) (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.Rat) {
|
||||
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.Rat) (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
|
||||
|
||||
const (
|
||||
// nolint
|
||||
Bonded CandidateStatus = 0x00
|
||||
Unbonded CandidateStatus = 0x01
|
||||
Revoked CandidateStatus = 0x02
|
||||
)
|
||||
|
||||
// Candidate defines the total amount of bond shares and their exchange rate to
|
||||
// coins. Accumulation of interest is modelled as an in increase in the
|
||||
// exchange rate, and slashing as a decrease. When coins are delegated to this
|
||||
// candidate, the candidate is credited with a DelegatorBond whose number of
|
||||
// bond shares is based on the amount of coins delegated divided by the current
|
||||
// exchange rate. Voting power can be calculated as total bonds multiplied by
|
||||
// exchange rate.
|
||||
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 rational.Rat `json:"assets"` // total shares of a global hold pools TODO custom type PoolShares
|
||||
Liabilities rational.Rat `json:"liabilities"` // total shares issued to a candidate's delegators TODO custom type DelegatorShares
|
||||
VotingPower rational.Rat `json:"voting_power"` // Voting power if considered a validator
|
||||
Description Description `json:"description"` // Description terms for the candidate
|
||||
}
|
||||
|
||||
// Description - description fields for a candidate
|
||||
type Description struct {
|
||||
Moniker string `json:"moniker"`
|
||||
Identity string `json:"identity"`
|
||||
Website string `json:"website"`
|
||||
Details string `json:"details"`
|
||||
}
|
||||
|
||||
// NewCandidate - initialize a new candidate
|
||||
func NewCandidate(pubKey crypto.PubKey, owner crypto.Address, description Description) *Candidate {
|
||||
return &Candidate{
|
||||
Status: Unbonded,
|
||||
PubKey: pubKey,
|
||||
Owner: owner,
|
||||
Assets: rational.Zero,
|
||||
Liabilities: rational.Zero,
|
||||
VotingPower: rational.Zero,
|
||||
Description: description,
|
||||
}
|
||||
}
|
||||
|
||||
// XXX define candidate interface?
|
||||
|
||||
// get the exchange rate of global pool shares over delegator shares
|
||||
func (c *Candidate) delegatorShareExRate() rational.Rat {
|
||||
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.Rat) {
|
||||
|
||||
exRate := c.delegatorShareExRate()
|
||||
|
||||
var receivedGlobalShares rational.Rat
|
||||
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.Rat, 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(*c)
|
||||
}
|
||||
|
||||
// Validator is one of the top Candidates
|
||||
type Validator Candidate
|
||||
|
||||
// ABCIValidator - Get the validator from a bond value
|
||||
func (v Validator) ABCIValidator() *abci.Validator {
|
||||
pk, err := wire.MarshalBinary(v.PubKey)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &abci.Validator{
|
||||
PubKey: pk,
|
||||
Power: v.VotingPower.Evaluate(),
|
||||
}
|
||||
}
|
||||
|
||||
//_________________________________________________________________________
|
||||
|
||||
// TODO replace with sorted multistore functionality
|
||||
|
||||
// Candidates - list of Candidates
|
||||
type Candidates []*Candidate
|
||||
|
||||
var _ sort.Interface = Candidates{} //enforce the sort interface at compile time
|
||||
|
||||
// nolint - sort interface functions
|
||||
func (cs Candidates) Len() int { return len(cs) }
|
||||
func (cs Candidates) Swap(i, j int) { cs[i], cs[j] = cs[j], cs[i] }
|
||||
func (cs Candidates) Less(i, j int) bool {
|
||||
vp1, vp2 := cs[i].VotingPower, cs[j].VotingPower
|
||||
pk1, pk2 := cs[i].PubKey.Bytes(), cs[j].PubKey.Bytes()
|
||||
|
||||
//note that all ChainId and App must be the same for a group of candidates
|
||||
if vp1 != vp2 {
|
||||
return vp1.GT(vp2)
|
||||
}
|
||||
return bytes.Compare(pk1, pk2) == -1
|
||||
}
|
||||
|
||||
// Sort - Sort the array of bonded values
|
||||
func (cs Candidates) Sort() {
|
||||
sort.Sort(cs)
|
||||
}
|
||||
|
||||
// update the voting power and save
|
||||
func (cs Candidates) updateVotingPower(store types.KVStore, gs *GlobalState, params Params) Candidates {
|
||||
|
||||
// update voting power
|
||||
for _, c := range cs {
|
||||
if !c.VotingPower.Equal(c.Assets) {
|
||||
c.VotingPower = c.Assets
|
||||
}
|
||||
}
|
||||
cs.Sort()
|
||||
for i, c := range cs {
|
||||
// truncate the power
|
||||
if i >= int(params.MaxVals) {
|
||||
c.VotingPower = rational.Zero
|
||||
if c.Status == Bonded {
|
||||
// XXX to replace this with handler.bondedToUnbondePool function
|
||||
// XXX waiting for logic with new SDK to update account balance here
|
||||
tokens := gs.removeSharesBonded(c.Assets)
|
||||
c.Assets = gs.addTokensUnbonded(tokens)
|
||||
c.Status = Unbonded
|
||||
}
|
||||
} else {
|
||||
c.Status = Bonded
|
||||
}
|
||||
saveCandidate(store, c)
|
||||
}
|
||||
return cs
|
||||
}
|
||||
|
||||
// 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 (cs Candidates) Validators() Validators {
|
||||
|
||||
//test if empty
|
||||
if len(cs) == 1 {
|
||||
if cs[0].VotingPower.IsZero() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
validators := make(Validators, len(cs))
|
||||
for i, c := range cs {
|
||||
if c.VotingPower.IsZero() { //exit as soon as the first Voting power set to zero is found
|
||||
return validators[:i]
|
||||
}
|
||||
validators[i] = c.validator()
|
||||
}
|
||||
|
||||
return validators
|
||||
}
|
||||
|
||||
//_________________________________________________________________________
|
||||
|
||||
// Validators - list of Validators
|
||||
type Validators []Validator
|
||||
|
||||
var _ sort.Interface = Validators{} //enforce the sort interface at compile time
|
||||
|
||||
// nolint - sort interface functions
|
||||
func (vs Validators) Len() int { return len(vs) }
|
||||
func (vs Validators) Swap(i, j int) { vs[i], vs[j] = vs[j], vs[i] }
|
||||
func (vs Validators) Less(i, j int) bool {
|
||||
pk1, pk2 := vs[i].PubKey.Bytes(), vs[j].PubKey.Bytes()
|
||||
return bytes.Compare(pk1, pk2) == -1
|
||||
}
|
||||
|
||||
// Sort - Sort validators by pubkey
|
||||
func (vs Validators) Sort() {
|
||||
sort.Sort(vs)
|
||||
}
|
||||
|
||||
// determine all updated validators between two validator sets
|
||||
func (vs Validators) validatorsUpdated(vs2 Validators) (updated []*abci.Validator) {
|
||||
|
||||
//first sort the validator sets
|
||||
vs.Sort()
|
||||
vs2.Sort()
|
||||
|
||||
max := len(vs) + len(vs2)
|
||||
updated = make([]*abci.Validator, max)
|
||||
i, j, n := 0, 0, 0 //counters for vs loop, vs2 loop, updated element
|
||||
|
||||
for i < len(vs) && j < len(vs2) {
|
||||
|
||||
if !vs[i].PubKey.Equals(vs2[j].PubKey) {
|
||||
// pk1 > pk2, a new validator was introduced between these pubkeys
|
||||
if bytes.Compare(vs[i].PubKey.Bytes(), vs2[j].PubKey.Bytes()) == 1 {
|
||||
updated[n] = vs2[j].ABCIValidator()
|
||||
n++
|
||||
j++
|
||||
continue
|
||||
} // else, the old validator has been removed
|
||||
updated[n] = &abci.Validator{vs[i].PubKey.Bytes(), 0}
|
||||
n++
|
||||
i++
|
||||
continue
|
||||
}
|
||||
|
||||
if vs[i].VotingPower != vs2[j].VotingPower {
|
||||
updated[n] = vs2[j].ABCIValidator()
|
||||
n++
|
||||
}
|
||||
j++
|
||||
i++
|
||||
}
|
||||
|
||||
// add any excess validators in set 2
|
||||
for ; j < len(vs2); j, n = j+1, n+1 {
|
||||
updated[n] = vs2[j].ABCIValidator()
|
||||
}
|
||||
|
||||
// remove any excess validators left in set 1
|
||||
for ; i < len(vs); i, n = i+1, n+1 {
|
||||
updated[n] = &abci.Validator{vs[i].PubKey.Bytes(), 0}
|
||||
}
|
||||
|
||||
return updated[:n]
|
||||
}
|
||||
|
||||
// UpdateValidatorSet - Updates the voting power for the candidate set and
|
||||
// returns the subset of validators which have been updated for Tendermint
|
||||
func UpdateValidatorSet(store types.KVStore, gs *GlobalState, params Params) (change []*abci.Validator, err error) {
|
||||
|
||||
// get the validators before update
|
||||
candidates := loadCandidates(store)
|
||||
|
||||
v1 := candidates.Validators()
|
||||
v2 := candidates.updateVotingPower(store, gs, params).Validators()
|
||||
|
||||
change = v1.validatorsUpdated(v2)
|
||||
return
|
||||
}
|
||||
|
||||
//_________________________________________________________________________
|
||||
|
||||
// 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.Rat `json:"shares"`
|
||||
}
|
||||
//import (
|
||||
//"bytes"
|
||||
//"sort"
|
||||
|
||||
//"github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
//abci "github.com/tendermint/abci/types"
|
||||
//crypto "github.com/tendermint/go-crypto"
|
||||
//wire "github.com/tendermint/go-wire"
|
||||
//"github.com/tendermint/tmlibs/rational"
|
||||
//)
|
||||
|
||||
//// 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 rational.Rat `json:"inflation_rate_change"` // maximum annual change in inflation rate
|
||||
//InflationMax rational.Rat `json:"inflation_max"` // maximum inflation rate
|
||||
//InflationMin rational.Rat `json:"inflation_min"` // minimum inflation rate
|
||||
//GoalBonded rational.Rat `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
|
||||
|
||||
//// gas costs for txs
|
||||
//GasDeclareCandidacy int64 `json:"gas_declare_candidacy"`
|
||||
//GasEditCandidacy int64 `json:"gas_edit_candidacy"`
|
||||
//GasDelegate int64 `json:"gas_delegate"`
|
||||
//GasUnbond int64 `json:"gas_unbond"`
|
||||
//}
|
||||
|
||||
//func defaultParams() Params {
|
||||
//return Params{
|
||||
//HoldBonded: []byte("77777777777777777777777777777777"),
|
||||
//HoldUnbonded: []byte("88888888888888888888888888888888"),
|
||||
//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,
|
||||
//GasEditCandidacy: 20,
|
||||
//GasDelegate: 20,
|
||||
//GasUnbond: 20,
|
||||
//}
|
||||
//}
|
||||
|
||||
////_________________________________________________________________________
|
||||
|
||||
//// GlobalState - dynamic parameters of the current state
|
||||
//type GlobalState struct {
|
||||
//TotalSupply int64 `json:"total_supply"` // total supply of all tokens
|
||||
//BondedShares rational.Rat `json:"bonded_shares"` // sum of all shares distributed for the Bonded Pool
|
||||
//UnbondedShares rational.Rat `json:"unbonded_shares"` // sum of all shares distributed for the Unbonded Pool
|
||||
//BondedPool int64 `json:"bonded_pool"` // reserve of bonded tokens
|
||||
//UnbondedPool int64 `json:"unbonded_pool"` // reserve of unbonded tokens held with candidates
|
||||
//InflationLastTime int64 `json:"inflation_last_time"` // block which the last inflation was processed // TODO make time
|
||||
//Inflation rational.Rat `json:"inflation"` // current annual inflation rate
|
||||
//}
|
||||
|
||||
//// XXX define globalstate interface?
|
||||
|
||||
//func initialGlobalState() *GlobalState {
|
||||
//return &GlobalState{
|
||||
//TotalSupply: 0,
|
||||
//BondedShares: rational.Zero,
|
||||
//UnbondedShares: rational.Zero,
|
||||
//BondedPool: 0,
|
||||
//UnbondedPool: 0,
|
||||
//InflationLastTime: 0,
|
||||
//Inflation: rational.New(7, 100),
|
||||
//}
|
||||
//}
|
||||
|
||||
//// get the bond ratio of the global state
|
||||
//func (gs *GlobalState) bondedRatio() rational.Rat {
|
||||
//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.Rat {
|
||||
//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.Rat {
|
||||
//if gs.UnbondedShares.IsZero() {
|
||||
//return rational.One
|
||||
//}
|
||||
//return gs.UnbondedShares.Inv().Mul(rational.New(gs.UnbondedPool))
|
||||
//}
|
||||
|
||||
//func (gs *GlobalState) addTokensBonded(amount int64) (issuedShares rational.Rat) {
|
||||
//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.Rat) (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.Rat) {
|
||||
//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.Rat) (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
|
||||
|
||||
//const (
|
||||
//// nolint
|
||||
//Bonded CandidateStatus = 0x00
|
||||
//Unbonded CandidateStatus = 0x01
|
||||
//Revoked CandidateStatus = 0x02
|
||||
//)
|
||||
|
||||
//// Candidate defines the total amount of bond shares and their exchange rate to
|
||||
//// coins. Accumulation of interest is modelled as an in increase in the
|
||||
//// exchange rate, and slashing as a decrease. When coins are delegated to this
|
||||
//// candidate, the candidate is credited with a DelegatorBond whose number of
|
||||
//// bond shares is based on the amount of coins delegated divided by the current
|
||||
//// exchange rate. Voting power can be calculated as total bonds multiplied by
|
||||
//// exchange rate.
|
||||
//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 rational.Rat `json:"assets"` // total shares of a global hold pools TODO custom type PoolShares
|
||||
//Liabilities rational.Rat `json:"liabilities"` // total shares issued to a candidate's delegators TODO custom type DelegatorShares
|
||||
//VotingPower rational.Rat `json:"voting_power"` // Voting power if considered a validator
|
||||
//Description Description `json:"description"` // Description terms for the candidate
|
||||
//}
|
||||
|
||||
//// Description - description fields for a candidate
|
||||
//type Description struct {
|
||||
//Moniker string `json:"moniker"`
|
||||
//Identity string `json:"identity"`
|
||||
//Website string `json:"website"`
|
||||
//Details string `json:"details"`
|
||||
//}
|
||||
|
||||
//// NewCandidate - initialize a new candidate
|
||||
//func NewCandidate(pubKey crypto.PubKey, owner crypto.Address, description Description) *Candidate {
|
||||
//return &Candidate{
|
||||
//Status: Unbonded,
|
||||
//PubKey: pubKey,
|
||||
//Owner: owner,
|
||||
//Assets: rational.Zero,
|
||||
//Liabilities: rational.Zero,
|
||||
//VotingPower: rational.Zero,
|
||||
//Description: description,
|
||||
//}
|
||||
//}
|
||||
|
||||
//// XXX define candidate interface?
|
||||
|
||||
//// get the exchange rate of global pool shares over delegator shares
|
||||
//func (c *Candidate) delegatorShareExRate() rational.Rat {
|
||||
//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.Rat) {
|
||||
|
||||
//exRate := c.delegatorShareExRate()
|
||||
|
||||
//var receivedGlobalShares rational.Rat
|
||||
//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.Rat, 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(*c)
|
||||
//}
|
||||
|
||||
//// Validator is one of the top Candidates
|
||||
//type Validator Candidate
|
||||
|
||||
//// ABCIValidator - Get the validator from a bond value
|
||||
//func (v Validator) ABCIValidator() *abci.Validator {
|
||||
//pk, err := wire.MarshalBinary(v.PubKey)
|
||||
//if err != nil {
|
||||
//panic(err)
|
||||
//}
|
||||
|
||||
//return &abci.Validator{
|
||||
//PubKey: pk,
|
||||
//Power: v.VotingPower.Evaluate(),
|
||||
//}
|
||||
//}
|
||||
|
||||
////_________________________________________________________________________
|
||||
|
||||
//// TODO replace with sorted multistore functionality
|
||||
|
||||
//// Candidates - list of Candidates
|
||||
//type Candidates []*Candidate
|
||||
|
||||
//var _ sort.Interface = Candidates{} //enforce the sort interface at compile time
|
||||
|
||||
//// nolint - sort interface functions
|
||||
//func (cs Candidates) Len() int { return len(cs) }
|
||||
//func (cs Candidates) Swap(i, j int) { cs[i], cs[j] = cs[j], cs[i] }
|
||||
//func (cs Candidates) Less(i, j int) bool {
|
||||
//vp1, vp2 := cs[i].VotingPower, cs[j].VotingPower
|
||||
//pk1, pk2 := cs[i].PubKey.Bytes(), cs[j].PubKey.Bytes()
|
||||
|
||||
////note that all ChainId and App must be the same for a group of candidates
|
||||
//if vp1 != vp2 {
|
||||
//return vp1.GT(vp2)
|
||||
//}
|
||||
//return bytes.Compare(pk1, pk2) == -1
|
||||
//}
|
||||
|
||||
//// Sort - Sort the array of bonded values
|
||||
//func (cs Candidates) Sort() {
|
||||
//sort.Sort(cs)
|
||||
//}
|
||||
|
||||
//// update the voting power and save
|
||||
//func (cs Candidates) updateVotingPower(store types.KVStore, gs *GlobalState, params Params) Candidates {
|
||||
|
||||
//// update voting power
|
||||
//for _, c := range cs {
|
||||
//if !c.VotingPower.Equal(c.Assets) {
|
||||
//c.VotingPower = c.Assets
|
||||
//}
|
||||
//}
|
||||
//cs.Sort()
|
||||
//for i, c := range cs {
|
||||
//// truncate the power
|
||||
//if i >= int(params.MaxVals) {
|
||||
//c.VotingPower = rational.Zero
|
||||
//if c.Status == Bonded {
|
||||
//// XXX to replace this with handler.bondedToUnbondePool function
|
||||
//// XXX waiting for logic with new SDK to update account balance here
|
||||
//tokens := gs.removeSharesBonded(c.Assets)
|
||||
//c.Assets = gs.addTokensUnbonded(tokens)
|
||||
//c.Status = Unbonded
|
||||
//}
|
||||
//} else {
|
||||
//c.Status = Bonded
|
||||
//}
|
||||
//saveCandidate(store, c)
|
||||
//}
|
||||
//return cs
|
||||
//}
|
||||
|
||||
//// 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 (cs Candidates) Validators() Validators {
|
||||
|
||||
////test if empty
|
||||
//if len(cs) == 1 {
|
||||
//if cs[0].VotingPower.IsZero() {
|
||||
//return nil
|
||||
//}
|
||||
//}
|
||||
|
||||
//validators := make(Validators, len(cs))
|
||||
//for i, c := range cs {
|
||||
//if c.VotingPower.IsZero() { //exit as soon as the first Voting power set to zero is found
|
||||
//return validators[:i]
|
||||
//}
|
||||
//validators[i] = c.validator()
|
||||
//}
|
||||
|
||||
//return validators
|
||||
//}
|
||||
|
||||
////_________________________________________________________________________
|
||||
|
||||
//// Validators - list of Validators
|
||||
//type Validators []Validator
|
||||
|
||||
//var _ sort.Interface = Validators{} //enforce the sort interface at compile time
|
||||
|
||||
//// nolint - sort interface functions
|
||||
//func (vs Validators) Len() int { return len(vs) }
|
||||
//func (vs Validators) Swap(i, j int) { vs[i], vs[j] = vs[j], vs[i] }
|
||||
//func (vs Validators) Less(i, j int) bool {
|
||||
//pk1, pk2 := vs[i].PubKey.Bytes(), vs[j].PubKey.Bytes()
|
||||
//return bytes.Compare(pk1, pk2) == -1
|
||||
//}
|
||||
|
||||
//// Sort - Sort validators by pubkey
|
||||
//func (vs Validators) Sort() {
|
||||
//sort.Sort(vs)
|
||||
//}
|
||||
|
||||
//// determine all updated validators between two validator sets
|
||||
//func (vs Validators) validatorsUpdated(vs2 Validators) (updated []*abci.Validator) {
|
||||
|
||||
////first sort the validator sets
|
||||
//vs.Sort()
|
||||
//vs2.Sort()
|
||||
|
||||
//max := len(vs) + len(vs2)
|
||||
//updated = make([]*abci.Validator, max)
|
||||
//i, j, n := 0, 0, 0 //counters for vs loop, vs2 loop, updated element
|
||||
|
||||
//for i < len(vs) && j < len(vs2) {
|
||||
|
||||
//if !vs[i].PubKey.Equals(vs2[j].PubKey) {
|
||||
//// pk1 > pk2, a new validator was introduced between these pubkeys
|
||||
//if bytes.Compare(vs[i].PubKey.Bytes(), vs2[j].PubKey.Bytes()) == 1 {
|
||||
//updated[n] = vs2[j].ABCIValidator()
|
||||
//n++
|
||||
//j++
|
||||
//continue
|
||||
//} // else, the old validator has been removed
|
||||
//updated[n] = &abci.Validator{vs[i].PubKey.Bytes(), 0}
|
||||
//n++
|
||||
//i++
|
||||
//continue
|
||||
//}
|
||||
|
||||
//if vs[i].VotingPower != vs2[j].VotingPower {
|
||||
//updated[n] = vs2[j].ABCIValidator()
|
||||
//n++
|
||||
//}
|
||||
//j++
|
||||
//i++
|
||||
//}
|
||||
|
||||
//// add any excess validators in set 2
|
||||
//for ; j < len(vs2); j, n = j+1, n+1 {
|
||||
//updated[n] = vs2[j].ABCIValidator()
|
||||
//}
|
||||
|
||||
//// remove any excess validators left in set 1
|
||||
//for ; i < len(vs); i, n = i+1, n+1 {
|
||||
//updated[n] = &abci.Validator{vs[i].PubKey.Bytes(), 0}
|
||||
//}
|
||||
|
||||
//return updated[:n]
|
||||
//}
|
||||
|
||||
//// UpdateValidatorSet - Updates the voting power for the candidate set and
|
||||
//// returns the subset of validators which have been updated for Tendermint
|
||||
//func UpdateValidatorSet(store types.KVStore, gs *GlobalState, params Params) (change []*abci.Validator, err error) {
|
||||
|
||||
//// get the validators before update
|
||||
//candidates := loadCandidates(store)
|
||||
|
||||
//v1 := candidates.Validators()
|
||||
//v2 := candidates.updateVotingPower(store, gs, params).Validators()
|
||||
|
||||
//change = v1.validatorsUpdated(v2)
|
||||
//return
|
||||
//}
|
||||
|
||||
////_________________________________________________________________________
|
||||
|
||||
//// 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.Rat `json:"shares"`
|
||||
//}
|
||||
|
|
Loading…
Reference in New Issue