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