From 514470b4d6b2cb8dbcb690fc406b15eeffbc63c9 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 20 Feb 2018 15:55:53 +0000 Subject: [PATCH] working porting rational --- types/rational.go | 21 ++++---- x/stake/store.go | 11 ++--- x/stake/store_test.go | 46 +++++++++--------- x/stake/test_common.go | 13 +++-- x/stake/types.go | 106 ++++++++++++++++++++--------------------- 5 files changed, 100 insertions(+), 97 deletions(-) diff --git a/types/rational.go b/types/rational.go index 65020d510c..c85fcdef75 100644 --- a/types/rational.go +++ b/types/rational.go @@ -10,14 +10,19 @@ import ( wire "github.com/tendermint/go-wire" ) -var cdc *wire.Codec - -func init() { - cdc = wire.NewCodec() +// add rational codec elements to provided codec +func RationalCodec(cdc *wire.Codec) *wire.Codec { cdc.RegisterInterface((*Rational)(nil), nil) cdc.RegisterConcrete(Rat{}, "rat", nil) + return cdc } +// "that's one big rat!" +// ______ +// / / /\ \____oo +// __ /___...._____ _\o +// __| |_ |_ + // Rat - extend big.Rat type Rat struct { *big.Rat `json:"rat"` @@ -45,12 +50,12 @@ var _ Rational = Rat{} // enforce at compile time // nolint - common values var ( - Zero = Rat{big.NewRat(0, 1)} - One = Rat{big.NewRat(1, 1)} + ZeroRat = Rat{big.NewRat(0, 1)} + OneRat = Rat{big.NewRat(1, 1)} ) // New - create a new Rat from integers -func New(Numerator int64, Denominator ...int64) Rat { +func NewRational(Numerator int64, Denominator ...int64) Rat { switch len(Denominator) { case 0: return Rat{big.NewRat(Numerator, 1)} @@ -62,7 +67,7 @@ func New(Numerator int64, Denominator ...int64) Rat { } //NewFromDecimal - create a rational from decimal string or integer string -func NewFromDecimal(decimalStr string) (f Rat, err error) { +func NewRationlFromDecimal(decimalStr string) (f Rat, err error) { // first extract any negative symbol neg := false diff --git a/x/stake/store.go b/x/stake/store.go index 68bfe58cf3..54073875cd 100644 --- a/x/stake/store.go +++ b/x/stake/store.go @@ -3,7 +3,6 @@ package stake import ( crypto "github.com/tendermint/go-crypto" wire "github.com/tendermint/go-wire" - "github.com/tendermint/tmlibs/rational" "github.com/cosmos/cosmos-sdk/types" ) @@ -29,8 +28,8 @@ var ( func init() { cdc = wire.NewCodec() - cdc.RegisterInterface((*rational.Rational)(nil), nil) // XXX make like crypto.RegisterWire() - cdc.RegisterConcrete(rational.Rat{}, "rat", nil) + cdc.RegisterInterface((*types.Rational)(nil), nil) // XXX make like crypto.RegisterWire() + cdc.RegisterConcrete(types.Rat{}, "rat", nil) crypto.RegisterWire(cdc) } @@ -40,7 +39,7 @@ func GetCandidateKey(pubKey crypto.PubKey) []byte { } // GetValidatorKey - get the key for the validator used in the power-store -func GetValidatorKey(pubKey crypto.PubKey, power rational.Rational) []byte { +func GetValidatorKey(pubKey crypto.PubKey, power types.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 } @@ -111,7 +110,7 @@ func removeCandidate(store types.KVStore, pubKey crypto.PubKey) { //--------------------------------------------------------------------- -//func loadValidator(store types.KVStore, pubKey crypto.PubKey, votingPower rational.Rational) *Validator { +//func loadValidator(store types.KVStore, pubKey crypto.PubKey, votingPower types.Rational) *Validator { //b := store.Get(GetValidatorKey(pubKey, votingPower)) //if b == nil { //return nil @@ -143,7 +142,7 @@ func updateValidator(store types.KVStore, validator *Validator) { func removeValidator(store types.KVStore, pubKey crypto.PubKey) { //add validator with zero power to the validator updates - b, err := cdc.MarshalJSON(Validator{pubKey, rational.Zero}) + b, err := cdc.MarshalJSON(Validator{pubKey, types.Zero}) if err != nil { panic(err) } diff --git a/x/stake/store_test.go b/x/stake/store_test.go index 7f99c8171b..3956b2379b 100644 --- a/x/stake/store_test.go +++ b/x/stake/store_test.go @@ -4,8 +4,8 @@ import ( "bytes" "testing" + "github.com/cosmos/cosmos-sdk/types" crypto "github.com/tendermint/go-crypto" - "github.com/tendermint/tmlibs/rational" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -26,12 +26,12 @@ import ( //candidates := candidatesFromActors(actors, []int64{400, 200, 100, 10, 1}) //// test a basic change in voting power -//candidates[0].Assets = rational.New(500) +//candidates[0].Assets = types.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[1].Assets = types.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]) @@ -46,11 +46,11 @@ import ( //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() +//v1 := (&Candidate{PubKey: pks[0], VotingPower: types.New(10)}).validator() +//v2 := (&Candidate{PubKey: pks[1], VotingPower: types.New(10)}).validator() +//v3 := (&Candidate{PubKey: pks[2], VotingPower: types.New(10)}).validator() +//v4 := (&Candidate{PubKey: pks[3], VotingPower: types.New(10)}).validator() +//v5 := (&Candidate{PubKey: pks[4], VotingPower: types.New(10)}).validator() //// test from nothing to something //vs1 := []Validator{} @@ -75,14 +75,14 @@ import ( //require.Zero(len(changed)) //// test single value change -//vs2[2].VotingPower = rational.One +//vs2[2].VotingPower = types.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) +//vs2[0].VotingPower = types.New(11) +//vs2[2].VotingPower = types.New(5) //changed = vs1.validatorsUpdated(vs2) //require.Equal(2, len(changed)) //testChange(t, vs2[0], changed[0]) @@ -118,7 +118,7 @@ import ( //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 +//// test many types of changes //vs2 = []Validator{v1, v3, v4, v5} //vs2[2].VotingPower = types.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 { @@ -141,11 +141,11 @@ import ( //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) +//candidates[0].Assets = types.New(10) +//candidates[1].Assets = types.New(600) +//candidates[2].Assets = types.New(1000) +//candidates[3].Assets = types.One +//candidates[4].Assets = types.New(10) //for _, c := range candidates { //saveCandidate(store, c) //} @@ -179,9 +179,9 @@ func TestState(t *testing.T) { candidate := &Candidate{ Owner: validator, PubKey: pk, - Assets: rational.New(9), - Liabilities: rational.New(9), - VotingPower: rational.Zero, + Assets: types.New(9), + Liabilities: types.New(9), + VotingPower: types.Zero, } candidatesEqual := func(c1, c2 *Candidate) bool { @@ -207,7 +207,7 @@ func TestState(t *testing.T) { assert.True(candidatesEqual(candidate, resCand), "%#v \n %#v", resCand, candidate) // modify a records, save, and retrieve - candidate.Liabilities = rational.New(99) + candidate.Liabilities = types.New(99) saveCandidate(store, candidate) resCand = loadCandidate(store, pk) assert.True(candidatesEqual(candidate, resCand)) @@ -222,7 +222,7 @@ func TestState(t *testing.T) { bond := &DelegatorBond{ PubKey: pk, - Shares: rational.New(9), + Shares: types.New(9), } bondsEqual := func(b1, b2 *DelegatorBond) bool { @@ -240,7 +240,7 @@ func TestState(t *testing.T) { assert.True(bondsEqual(bond, resBond)) //modify a records, save, and retrieve - bond.Shares = rational.New(99) + bond.Shares = types.New(99) saveDelegatorBond(store, delegator, bond) resBond = loadDelegatorBond(store, delegator, pk) assert.True(bondsEqual(bond, resBond)) diff --git a/x/stake/test_common.go b/x/stake/test_common.go index 51f60c69c5..7628fbd1bd 100644 --- a/x/stake/test_common.go +++ b/x/stake/test_common.go @@ -9,7 +9,6 @@ import ( 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" @@ -74,9 +73,9 @@ func candidatesFromActors(store sdk.KVStore, addrs []crypto.Address, amts []int6 Status: Unbonded, PubKey: pks[i], Owner: addrs[i], - Assets: rational.New(amts[i]), - Liabilities: rational.New(amts[i]), - VotingPower: rational.New(amts[i]), + Assets: sdk.New(amts[i]), + Liabilities: sdk.New(amts[i]), + VotingPower: sdk.New(amts[i]), } saveCandidate(store, c) } @@ -88,9 +87,9 @@ func candidatesFromActorsEmpty(addrs []crypto.Address) (candidates Candidates) { Status: Unbonded, PubKey: pks[i], Owner: addrs[i], - Assets: rational.Zero, - Liabilities: rational.Zero, - VotingPower: rational.Zero, + Assets: sdk.Zero, + Liabilities: sdk.Zero, + VotingPower: sdk.Zero, } candidates = append(candidates, c) } diff --git a/x/stake/types.go b/x/stake/types.go index f615f188c0..2d2632674a 100644 --- a/x/stake/types.go +++ b/x/stake/types.go @@ -1,9 +1,9 @@ package stake import ( + sdk "github.com/cosmos/cosmos-sdk/types" abci "github.com/tendermint/abci/types" crypto "github.com/tendermint/go-crypto" - "github.com/tendermint/tmlibs/rational" ) // Params defines the high level settings for staking @@ -11,10 +11,10 @@ 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.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 + InflationRateChange sdk.Rational `json:"inflation_rate_change"` // maximum annual change in inflation rate + InflationMax sdk.Rational `json:"inflation_max"` // maximum inflation rate + InflationMin sdk.Rational `json:"inflation_min"` // minimum inflation rate + GoalBonded sdk.Rational `json:"goal_bonded"` // Goal of percent bonded atoms MaxVals uint16 `json:"max_vals"` // maximum number of validators AllowedBondDenom string `json:"allowed_bond_denom"` // bondable coin denomination @@ -30,10 +30,10 @@ 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), + InflationRateChange: sdk.New(13, 100), + InflationMax: sdk.New(20, 100), + InflationMin: sdk.New(7, 100), + GoalBonded: sdk.New(67, 100), MaxVals: 100, AllowedBondDenom: "fermion", GasDeclareCandidacy: 20, @@ -47,13 +47,13 @@ func defaultParams() Params { // GlobalState - dynamic parameters of the current state type GlobalState struct { - 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 + TotalSupply int64 `json:"total_supply"` // total supply of all tokens + BondedShares sdk.Rational `json:"bonded_shares"` // sum of all shares distributed for the Bonded Pool + UnbondedShares sdk.Rational `json:"unbonded_shares"` // sum of all shares distributed for the Unbonded Pool + BondedPool int64 `json:"bonded_pool"` // reserve of bonded tokens + UnbondedPool int64 `json:"unbonded_pool"` // reserve of unbonded tokens held with candidates + InflationLastTime int64 `json:"inflation_last_time"` // block which the last inflation was processed // TODO make time + Inflation sdk.Rational `json:"inflation"` // current annual inflation rate } // XXX define globalstate interface? @@ -61,61 +61,61 @@ type GlobalState struct { func initialGlobalState() *GlobalState { return &GlobalState{ TotalSupply: 0, - BondedShares: rational.Zero, - UnbondedShares: rational.Zero, + BondedShares: sdk.Zero, + UnbondedShares: sdk.Zero, BondedPool: 0, UnbondedPool: 0, InflationLastTime: 0, - Inflation: rational.New(7, 100), + Inflation: sdk.New(7, 100), } } // get the bond ratio of the global state -func (gs *GlobalState) bondedRatio() rational.Rational { +func (gs *GlobalState) bondedRatio() sdk.Rational { if gs.TotalSupply > 0 { - return rational.New(gs.BondedPool, gs.TotalSupply) + return sdk.New(gs.BondedPool, gs.TotalSupply) } - return rational.Zero + return sdk.Zero } // get the exchange rate of bonded token per issued share -func (gs *GlobalState) bondedShareExRate() rational.Rational { +func (gs *GlobalState) bondedShareExRate() sdk.Rational { if gs.BondedShares.IsZero() { - return rational.One + return sdk.One } - return gs.BondedShares.Inv().Mul(rational.New(gs.BondedPool)) + return gs.BondedShares.Inv().Mul(sdk.New(gs.BondedPool)) } // get the exchange rate of unbonded tokens held in candidates per issued share -func (gs *GlobalState) unbondedShareExRate() rational.Rational { +func (gs *GlobalState) unbondedShareExRate() sdk.Rational { if gs.UnbondedShares.IsZero() { - return rational.One + return sdk.One } - return gs.UnbondedShares.Inv().Mul(rational.New(gs.UnbondedPool)) + return gs.UnbondedShares.Inv().Mul(sdk.New(gs.UnbondedPool)) } -func (gs *GlobalState) addTokensBonded(amount int64) (issuedShares rational.Rational) { - issuedShares = gs.bondedShareExRate().Inv().Mul(rational.New(amount)) // (tokens/shares)^-1 * tokens +func (gs *GlobalState) addTokensBonded(amount int64) (issuedShares sdk.Rational) { + issuedShares = gs.bondedShareExRate().Inv().Mul(sdk.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) { +func (gs *GlobalState) removeSharesBonded(shares sdk.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 +func (gs *GlobalState) addTokensUnbonded(amount int64) (issuedShares sdk.Rational) { + issuedShares = gs.unbondedShareExRate().Inv().Mul(sdk.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) { +func (gs *GlobalState) removeSharesUnbonded(shares sdk.Rational) (removedTokens int64) { removedTokens = gs.unbondedShareExRate().Mul(shares).Evaluate() // (tokens/shares) * shares gs.UnbondedShares = gs.UnbondedShares.Sub(shares) gs.UnbondedPool -= removedTokens @@ -142,13 +142,13 @@ 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 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 + 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 sdk.Rational `json:"assets"` // total shares of a global hold pools TODO custom type PoolShares + Liabilities sdk.Rational `json:"liabilities"` // total shares issued to a candidate's delegators TODO custom type DelegatorShares + VotingPower sdk.Rational `json:"voting_power"` // Voting power if considered a validator + Description Description `json:"description"` // Description terms for the candidate } // Description - description fields for a candidate @@ -165,9 +165,9 @@ func NewCandidate(pubKey crypto.PubKey, owner crypto.Address, description Descri Status: Unbonded, PubKey: pubKey, Owner: owner, - Assets: rational.Zero, - Liabilities: rational.Zero, - VotingPower: rational.Zero, + Assets: sdk.Zero, + Liabilities: sdk.Zero, + VotingPower: sdk.Zero, Description: description, } } @@ -175,19 +175,19 @@ func NewCandidate(pubKey crypto.PubKey, owner crypto.Address, description Descri // XXX define candidate interface? // get the exchange rate of global pool shares over delegator shares -func (c *Candidate) delegatorShareExRate() rational.Rational { +func (c *Candidate) delegatorShareExRate() sdk.Rational { if c.Liabilities.IsZero() { - return rational.One + return sdk.One } return c.Assets.Quo(c.Liabilities) } // add tokens to a candidate -func (c *Candidate) addTokens(amount int64, gs *GlobalState) (issuedDelegatorShares rational.Rational) { +func (c *Candidate) addTokens(amount int64, gs *GlobalState) (issuedDelegatorShares sdk.Rational) { exRate := c.delegatorShareExRate() - var receivedGlobalShares rational.Rational + var receivedGlobalShares sdk.Rational if c.Status == Bonded { receivedGlobalShares = gs.addTokensBonded(amount) } else { @@ -201,7 +201,7 @@ func (c *Candidate) addTokens(amount int64, gs *GlobalState) (issuedDelegatorSha } // remove shares from a candidate -func (c *Candidate) removeShares(shares rational.Rational, gs *GlobalState) (removedTokens int64) { +func (c *Candidate) removeShares(shares sdk.Rational, gs *GlobalState) (removedTokens int64) { globalPoolSharesToRemove := c.delegatorShareExRate().Mul(shares) @@ -227,8 +227,8 @@ func (c *Candidate) validator() Validator { // Validator is one of the top Candidates type Validator struct { - PubKey crypto.PubKey `json:"pub_key"` // Pubkey of candidate - VotingPower rational.Rational `json:"voting_power"` // Voting power if considered a validator + PubKey crypto.PubKey `json:"pub_key"` // Pubkey of candidate + VotingPower sdk.Rational `json:"voting_power"` // Voting power if considered a validator } // ABCIValidator - Get the validator from a bond value @@ -254,6 +254,6 @@ type Candidates []*Candidate // 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"` + PubKey crypto.PubKey `json:"pub_key"` + Shares sdk.Rational `json:"shares"` }