diff --git a/x/stake/handler.go b/x/stake/handler.go index 3ade6a927c..7865fe0762 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -13,24 +13,8 @@ import ( "github.com/cosmos/cosmos-sdk/x/bank" ) -//_______________________________________________________________________ - -// DelegatedProofOfStake - interface to enforce delegation stake -type delegatedProofOfStake interface { - declareCandidacy(TxDeclareCandidacy) error - editCandidacy(TxEditCandidacy) error - delegate(TxDelegate) error - unbond(TxUnbond) error -} - -type coinSend interface { - transferFn(sender, receiver crypto.Address, coins sdk.Coins) error -} - -//_______________________________________________________________________ - // separated for testing -func InitState(key, value string, store sdk.KVStore) error { +func InitState(ctx sdk.Context, key, value string) error { params := loadParams(store) switch key { @@ -64,22 +48,19 @@ func InitState(key, value string, store sdk.KVStore) error { //_______________________________________________________________________ -func NewHandler(ck bank.CoinKeeper) sdk.Handler { +func NewHandler(stakeKey sdk.StoreKey, ck bank.CoinKeeper) sdk.Handler { return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { - params := loadParams(store) - params := loadGlobalState(store) + res := sdk.Result{} + err := msg.ValidateBasic() + if err != nil { + return res, err + } + + // return the fee for each tx type if ctx.IsCheckTx() { - - err = tx.ValidateBasic() - if err != nil { - return res, err - } - - res := sdk.Result{} - - // return the fee for each tx type + // XXX: add some tags so we can search it! switch txInner := tx.Unwrap().(type) { case TxDeclareCandidacy: return sdk.NewCheck(params.GasDeclareCandidacy, "") @@ -89,11 +70,9 @@ func NewHandler(ck bank.CoinKeeper) sdk.Handler { return sdk.NewCheck(params.GasDelegate, "") case TxUnbond: return sdk.NewCheck(params.GasUnbond, "") + default: + return sdk.ErrUnknownTxType(tx) } - - // TODO: add some tags so we can search it! - return sdk.ErrUnknownTxType(tx) - //return sdk.Result{} // TODO } // TODO: remove redundancy @@ -108,32 +87,26 @@ func NewHandler(ck bank.CoinKeeper) sdk.Handler { return } - params := loadParams(store) - deliverer := deliver{ - store: store, - sender: sender, - params: params, - ck: ck, - gs: gs, - } + keeper := NewKeeper(ctx, stakeKey) + transact := NewTransact(ctx, ck) // Run the transaction switch _tx := tx.Unwrap().(type) { case TxDeclareCandidacy: res.GasUsed = params.GasDeclareCandidacy - return res, deliverer.declareCandidacy(_tx) + return res, transact.declareCandidacy(_tx) case TxEditCandidacy: res.GasUsed = params.GasEditCandidacy - return res, deliverer.editCandidacy(_tx) + return res, transact.editCandidacy(_tx) case TxDelegate: res.GasUsed = params.GasDelegate - return res, deliverer.delegate(_tx) + 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 - return res, deliverer.unbond(_tx) + return res, transact.unbond(_tx) } return } @@ -150,47 +123,57 @@ func getTxSender(ctx sdk.Context) (sender crypto.Address, err error) { //_____________________________________________________________________ -type deliver struct { - store sdk.KVStore - sender crypto.Address - params Params - ck bank.CoinKeeper - gs *GlobalState +// common fields to all transactions +type transact struct { + sender crypto.Address + keeper Keeper + coinKeeper bank.CoinKeeper + params Params + gs *GlobalState } -var _ delegatedProofOfStake = deliver{} // enforce interface at compile time +// XXX move keeper creation to application? +func newTransact(ctx sdk.Context, keeper Keeper, ck bank.CoinKeeper) transact { + return transact{ + sender: sender, + keeper: keeper, + coinKeeper: ck, + params: keeper.loadParams(), + gs: keeper.loadGlobalState(), + } +} //_____________________________________________________________________ // helper functions // TODO move from deliver with new SDK should only be dependant on store to send coins in NEW SDK // move a candidates asset pool from bonded to unbonded pool -func (d deliver) bondedToUnbondedPool(candidate *Candidate) error { +func (tr transact) bondedToUnbondedPool(candidate *Candidate) error { // replace bonded shares with unbonded shares - tokens := d.gs.removeSharesBonded(candidate.Assets) - candidate.Assets = d.gs.addTokensUnbonded(tokens) + tokens := tr.gs.removeSharesBonded(candidate.Assets) + candidate.Assets = tr.gs.addTokensUnbonded(tokens) candidate.Status = Unbonded - return d.transfer(d.params.HoldBonded, d.params.HoldUnbonded, - sdk.Coins{{d.params.AllowedBondDenom, tokens}}) + return tr.transfer(tr.params.HoldBonded, tr.params.HoldUnbonded, + sdk.Coins{{tr.params.AllowedBondDenom, tokens}}) } // move a candidates asset pool from unbonded to bonded pool -func (d deliver) unbondedToBondedPool(candidate *Candidate) error { +func (tr transact) unbondedToBondedPool(candidate *Candidate) error { // replace bonded shares with unbonded shares - tokens := d.gs.removeSharesUnbonded(candidate.Assets) - candidate.Assets = d.gs.addTokensBonded(tokens) + tokens := tr.gs.removeSharesUnbonded(candidate.Assets) + candidate.Assets = tr.gs.addTokensBonded(tokens) candidate.Status = Bonded - return d.transfer(d.params.HoldUnbonded, d.params.HoldBonded, - sdk.Coins{{d.params.AllowedBondDenom, tokens}}) + return tr.transfer(tr.params.HoldUnbonded, tr.params.HoldBonded, + sdk.Coins{{tr.params.AllowedBondDenom, tokens}}) } // return an error if the bonds coins are incorrect -func checkDenom(tx BondUpdate, store sdk.KVStore) error { - if tx.Bond.Denom != loadParams(store).AllowedBondDenom { +func checkDenom(keeper Keeper, tx BondUpdate) error { + if tx.Bond.Denom != keeper.loadParams().AllowedBondDenom { return fmt.Errorf("Invalid coin denomination") } return nil @@ -200,46 +183,46 @@ func checkDenom(tx BondUpdate, store sdk.KVStore) error { // These functions assume everything has been authenticated, // now we just perform action and save -func (d deliver) declareCandidacy(tx TxDeclareCandidacy) error { +func (tr transact) declareCandidacy(tx TxDeclareCandidacy) error { // check to see if the pubkey or sender has been registered before - candidate := loadCandidate(d.store, tx.PubKey) + candidate := tr.keeper.loadCandidate(tx.PubKey) if candidate != 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, d.store) + err := checkDenom(tx.BondUpdate, tr.keeper) if err != nil { return err } // XXX end of old check tx // create and save the empty candidate - bond := loadCandidate(d.store, tx.PubKey) + bond := tr.keeper.loadCandidate(tx.PubKey) if bond != nil { return ErrCandidateExistsAddr() } - candidate := NewCandidate(tx.PubKey, d.sender, tx.Description) - saveCandidate(d.store, candidate) + candidate := NewCandidate(tx.PubKey, tr.sender, tx.Description) + tr.keeper.saveCandidate(candidate) - // move coins from the d.sender account to a (self-bond) delegator account + // move coins from the tr.sender account to a (self-bond) delegator account // the candidate account and global shares are updated within here txDelegate := TxDelegate{tx.BondUpdate} - return d.delegateWithCandidate(txDelegate, candidate) + return tr.delegateWithCandidate(txDelegate, candidate) } -func (d deliver) editCandidacy(tx TxEditCandidacy) error { +func (tr transact) editCandidacy(tx TxEditCandidacy) error { // candidate must already be registered - candidate := loadCandidate(d.store, tx.PubKey) + candidate := tr.keeper.loadCandidate(tx.PubKey) if candidate == nil { // does PubKey exist return fmt.Errorf("cannot delegate to non-existant PubKey %v", tx.PubKey) } // XXX end of old check tx // Get the pubKey bond account - candidate := loadCandidate(d.store, tx.PubKey) + candidate := tr.keeper.loadCandidate(tx.PubKey) if candidate == nil { return ErrBondNotNominated() } @@ -261,31 +244,31 @@ func (d deliver) editCandidacy(tx TxEditCandidacy) error { candidate.Description.Details = tx.Description.Details } - saveCandidate(d.store, candidate) + tr.keeper.saveCandidate(candidate) return nil } -func (d deliver) delegate(tx TxDelegate) error { +func (tr transact) delegate(tx TxDelegate) error { - candidate := loadCandidate(c.store, tx.PubKey) + candidate := tr.keeper.loadCandidate(tx.PubKey) if candidate == nil { // does PubKey exist return fmt.Errorf("cannot delegate to non-existant PubKey %v", tx.PubKey) } - err := checkDenom(tx.BondUpdate, c.store) + err := checkDenom(tx.BondUpdate, tr.keeper) if err != nil { return err } // end of old check tx // Get the pubKey bond account - candidate := loadCandidate(d.store, tx.PubKey) + candidate := tr.keeper.loadCandidate(tx.PubKey) if candidate == nil { return ErrBondNotNominated() } - return d.delegateWithCandidate(tx, candidate) + return tr.delegateWithCandidate(tx, candidate) } -func (d deliver) delegateWithCandidate(tx TxDelegate, candidate *Candidate) error { +func (tr transact) delegateWithCandidate(tx TxDelegate, candidate *Candidate) error { if candidate.Status == Revoked { //candidate has been withdrawn return ErrBondNotNominated() @@ -293,20 +276,20 @@ func (d deliver) delegateWithCandidate(tx TxDelegate, candidate *Candidate) erro var poolAccount crypto.Address if candidate.Status == Bonded { - poolAccount = d.params.HoldBonded + poolAccount = tr.params.HoldBonded } else { - poolAccount = d.params.HoldUnbonded + poolAccount = tr.params.HoldUnbonded } - // TODO maybe refactor into GlobalState.addBondedTokens(), maybe with new SDK + // XXX refactor all steps like this into GlobalState.addBondedTokens() // Move coins from the delegator account to the bonded pool account - err := d.transfer(d.sender, poolAccount, sdk.Coins{tx.Bond}) + err := tr.transfer(tr.sender, poolAccount, sdk.Coins{tx.Bond}) if err != nil { return err } // Get or create the delegator bond - bond := loadDelegatorBond(d.store, d.sender, tx.PubKey) + bond := tr.keeper.loadDelegatorBond(tr.sender, tx.PubKey) if bond == nil { bond = &DelegatorBond{ PubKey: tx.PubKey, @@ -315,17 +298,17 @@ func (d deliver) delegateWithCandidate(tx TxDelegate, candidate *Candidate) erro } // Account new shares, save - bond.Shares = bond.Shares.Add(candidate.addTokens(tx.Bond.Amount, d.gs)) - saveCandidate(d.store, candidate) - saveDelegatorBond(d.store, d.sender, bond) - saveGlobalState(d.store, d.gs) + 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) return nil } -func (d deliver) unbond(tx TxUnbond) error { +func (tr transact) unbond(tx TxUnbond) error { // check if bond has any shares in it unbond - bond := loadDelegatorBond(d.store, d.sender, tx.PubKey) + bond := tr.keeper.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") @@ -348,7 +331,7 @@ func (d deliver) unbond(tx TxUnbond) error { // XXX end of old checkTx // get delegator bond - bond := loadDelegatorBond(d.store, d.sender, tx.PubKey) + bond := tr.keeper.loadDelegatorBond(tr.sender, tx.PubKey) if bond == nil { return ErrNoDelegatorForAddress() } @@ -372,7 +355,7 @@ func (d deliver) unbond(tx TxUnbond) error { bond.Shares = bond.Shares.Sub(shares) // get pubKey candidate - candidate := loadCandidate(d.store, tx.PubKey) + candidate := tr.keeper.loadCandidate(tx.PubKey) if candidate == nil { return ErrNoCandidateForAddress() } @@ -382,28 +365,28 @@ func (d deliver) unbond(tx TxUnbond) error { // if the bond is the owner of the candidate then // trigger a revoke candidacy - if d.sender.Equals(candidate.Owner) && + if tr.sender.Equals(candidate.Owner) && candidate.Status != Revoked { revokeCandidacy = true } // remove the bond - removeDelegatorBond(d.store, d.sender, tx.PubKey) + tr.keeper.removeDelegatorBond(tr.sender, tx.PubKey) } else { - saveDelegatorBond(d.store, d.sender, bond) + tr.keeper.saveDelegatorBond(tr.sender, bond) } // transfer coins back to account var poolAccount crypto.Address if candidate.Status == Bonded { - poolAccount = d.params.HoldBonded + poolAccount = tr.params.HoldBonded } else { - poolAccount = d.params.HoldUnbonded + poolAccount = tr.params.HoldUnbonded } - returnCoins := candidate.removeShares(shares, d.gs) - err := d.transfer(poolAccount, d.sender, - sdk.Coins{{d.params.AllowedBondDenom, returnCoins}}) + returnCoins := candidate.removeShares(shares, tr.gs) + err := tr.transfer(poolAccount, tr.sender, + sdk.Coins{{tr.params.AllowedBondDenom, returnCoins}}) if err != nil { return err } @@ -413,7 +396,7 @@ func (d deliver) unbond(tx TxUnbond) error { // change the share types to unbonded if they were not already if candidate.Status == Bonded { - err = d.bondedToUnbondedPool(candidate) + err = tr.bondedToUnbondedPool(candidate) if err != nil { return err } @@ -425,11 +408,11 @@ func (d deliver) unbond(tx TxUnbond) error { // deduct shares from the candidate and save if candidate.Liabilities.IsZero() { - removeCandidate(d.store, tx.PubKey) + tr.keeper.removeCandidate(tx.PubKey) } else { - saveCandidate(d.store, candidate) + tr.keeper.saveCandidate(candidate) } - saveGlobalState(d.store, d.gs) + tr.keeper.saveGlobalState(tr.gs) return nil } diff --git a/x/stake/mapper.go b/x/stake/keeper.go similarity index 66% rename from x/stake/mapper.go rename to x/stake/keeper.go index 59f8aa78a9..b7b58cf0ee 100644 --- a/x/stake/mapper.go +++ b/x/stake/keeper.go @@ -7,12 +7,8 @@ import ( "github.com/cosmos/cosmos-sdk/types" ) -// nolint +//nolint var ( - - // internal wire codec - cdc *wire.Codec - // Keys for store prefixes CandidatesPubKeysKey = []byte{0x01} // key for all candidates' pubkeys ParamKey = []byte{0x02} // key for global parameters relating to staking @@ -26,13 +22,6 @@ var ( DelegatorBondsKeyPrefix = []byte{0x08} // prefix for each key to a delegator's bond ) -func init() { - cdc = wire.NewCodec() - cdc.RegisterInterface((*types.Rational)(nil), nil) // XXX make like crypto.RegisterWire() - cdc.RegisterConcrete(types.Rat{}, "rat", nil) - crypto.RegisterWire(cdc) -} - // GetCandidateKey - get the key for the candidate with pubKey func GetCandidateKey(pubKey crypto.PubKey) []byte { return append(CandidateKeyPrefix, pubKey.Bytes()...) @@ -72,10 +61,28 @@ func GetDelegatorBondsKey(delegator crypto.Address) []byte { return append(DelegatorBondsKeyPrefix, res...) } -//--------------------------------------------------------------------- +//___________________________________________________________________________ -func loadCandidate(store types.KVStore, pubKey crypto.PubKey) *Candidate { - b := store.Get(GetCandidateKey(pubKey)) +// keeper of the staking store +type Keeper struct { + store types.KVStore + cdc *wire.Codec +} + +func NewKeeper(ctx sdk.Context, key sdk.StoreKey) Keeper { + cdc := wire.NewCodec() + cdc.RegisterInterface((*types.Rational)(nil), nil) // XXX make like crypto.RegisterWire() + cdc.RegisterConcrete(types.Rat{}, "rat", nil) + crypto.RegisterWire(cdc) + + return StakeKeeper{ + store: ctx.KVStore(k.key), + cdc: cdc, + } +} + +func (k Keeper) loadCandidate(pubKey crypto.PubKey) *Candidate { + b := k.store.Get(GetCandidateKey(pubKey)) if b == nil { return nil } @@ -87,31 +94,31 @@ func loadCandidate(store types.KVStore, pubKey crypto.PubKey) *Candidate { return candidate } -func saveCandidate(store types.KVStore, candidate *Candidate) { +func (k Keeper) saveCandidate(candidate *Candidate) { // XXX should only remove validator if we know candidate is a validator - removeValidator(store, candidate.PubKey) + removeValidator(k.store, candidate.PubKey) validator := &Validator{candidate.PubKey, candidate.VotingPower} - updateValidator(store, validator) + updateValidator(k.store, validator) b, err := cdc.MarshalJSON(*candidate) if err != nil { panic(err) } - store.Set(GetCandidateKey(candidate.PubKey), b) + k.store.Set(GetCandidateKey(candidate.PubKey), b) } -func removeCandidate(store types.KVStore, pubKey crypto.PubKey) { +func (k Keeper) removeCandidate(pubKey crypto.PubKey) { // XXX should only remove validator if we know candidate is a validator - removeValidator(store, pubKey) - store.Delete(GetCandidateKey(pubKey)) + removeValidator(k.store, pubKey) + k.store.Delete(GetCandidateKey(pubKey)) } -//--------------------------------------------------------------------- +//___________________________________________________________________________ -//func loadValidator(store types.KVStore, pubKey crypto.PubKey, votingPower types.Rational) *Validator { -//b := store.Get(GetValidatorKey(pubKey, votingPower)) +//func loadValidator(k.store types.KVStore, pubKey crypto.PubKey, votingPower types.Rational) *Validator { +//b := k.store.Get(GetValidatorKey(pubKey, votingPower)) //if b == nil { //return nil //} @@ -125,7 +132,7 @@ func removeCandidate(store types.KVStore, pubKey crypto.PubKey) { // updateValidator - update a validator and create accumulate any changes // in the changed validator substore -func updateValidator(store types.KVStore, validator *Validator) { +func (k Keeper) updateValidator(validator *Validator) { b, err := cdc.MarshalJSON(*validator) if err != nil { @@ -133,34 +140,34 @@ func updateValidator(store types.KVStore, validator *Validator) { } // add to the validators to update list if necessary - store.Set(GetValidatorUpdatesKey(validator.PubKey), b) + k.store.Set(GetValidatorUpdatesKey(validator.PubKey), b) // update the list ordered by voting power - store.Set(GetValidatorKey(validator.PubKey, validator.VotingPower), b) + k.store.Set(GetValidatorKey(validator.PubKey, validator.VotingPower), b) } -func removeValidator(store types.KVStore, pubKey crypto.PubKey) { +func (k Keeper) removeValidator(pubKey crypto.PubKey) { //add validator with zero power to the validator updates b, err := cdc.MarshalJSON(Validator{pubKey, types.ZeroRat}) if err != nil { panic(err) } - store.Set(GetValidatorUpdatesKey(pubKey), b) + k.store.Set(GetValidatorUpdatesKey(pubKey), b) // now actually delete from the validator set - candidate := loadCandidate(store, pubKey) + candidate := loadCandidate(k.store, pubKey) if candidate != nil { - store.Delete(GetValidatorKey(pubKey, candidate.VotingPower)) + k.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 getValidators(store types.KVStore, maxVal int) (validators []Validator) { +func (k Keeper) getValidators(maxVal int) (validators []Validator) { - iterator := store.Iterator(subspace(ValidatorKeyPrefix)) //smallest to largest + iterator := k.store.Iterator(subspace(ValidatorKeyPrefix)) //smallest to largest validators = make([]Validator, maxVal) for i := 0; ; i++ { @@ -181,12 +188,12 @@ func getValidators(store types.KVStore, maxVal int) (validators []Validator) { return } -//--------------------------------------------------------------------- +//_________________________________________________________________________ // get the most updated validators -func getValidatorUpdates(store types.KVStore) (updates []Validator) { +func (k Keeper) getValidatorUpdates() (updates []Validator) { - iterator := store.Iterator(subspace(ValidatorUpdatesKeyPrefix)) //smallest to largest + iterator := k.store.Iterator(subspace(ValidatorUpdatesKeyPrefix)) //smallest to largest for ; iterator.Valid(); iterator.Next() { valBytes := iterator.Value() @@ -203,10 +210,10 @@ func getValidatorUpdates(store types.KVStore) (updates []Validator) { } // remove all validator update entries -func clearValidatorUpdates(store types.KVStore, maxVal int) { - iterator := store.Iterator(subspace(ValidatorUpdatesKeyPrefix)) +func (k Keeper) clearValidatorUpdates(maxVal int) { + iterator := k.store.Iterator(subspace(ValidatorUpdatesKeyPrefix)) for ; iterator.Valid(); iterator.Next() { - store.Delete(iterator.Key()) // XXX write test for this, may need to be in a second loop + k.store.Delete(iterator.Key()) // XXX write test for this, may need to be in a second loop } iterator.Close() } @@ -214,11 +221,11 @@ func clearValidatorUpdates(store types.KVStore, maxVal int) { //--------------------------------------------------------------------- // loadCandidates - get the active list of all candidates TODO replace with multistore -func loadCandidates(store types.KVStore) (candidates Candidates) { +func (k Keeper) loadCandidates() (candidates Candidates) { - iterator := store.Iterator(subspace(CandidateKeyPrefix)) - //iterator := store.Iterator(CandidateKeyPrefix, []byte(nil)) - //iterator := store.Iterator([]byte{}, []byte(nil)) + iterator := k.store.Iterator(subspace(CandidateKeyPrefix)) + //iterator := k.store.Iterator(CandidateKeyPrefix, []byte(nil)) + //iterator := k.store.Iterator([]byte{}, []byte(nil)) for ; iterator.Valid(); iterator.Next() { candidateBytes := iterator.Value() @@ -233,13 +240,12 @@ func loadCandidates(store types.KVStore) (candidates Candidates) { return candidates } -//--------------------------------------------------------------------- +//_____________________________________________________________________ // load the pubkeys of all candidates a delegator is delegated too -func loadDelegatorCandidates(store types.KVStore, - delegator crypto.Address) (candidates []crypto.PubKey) { +func (k Keeper) loadDelegatorCandidates(delegator crypto.Address) (candidates []crypto.PubKey) { - candidateBytes := store.Get(GetDelegatorBondsKey(delegator)) + candidateBytes := k.store.Get(GetDelegatorBondsKey(delegator)) if candidateBytes == nil { return nil } @@ -251,12 +257,12 @@ func loadDelegatorCandidates(store types.KVStore, return } -//--------------------------------------------------------------------- +//_____________________________________________________________________ -func loadDelegatorBond(store types.KVStore, - delegator crypto.Address, candidate crypto.PubKey) *DelegatorBond { +func (k Keeper) loadDelegatorBond(delegator crypto.Address, + candidate crypto.PubKey) *DelegatorBond { - delegatorBytes := store.Get(GetDelegatorBondKey(delegator, candidate)) + delegatorBytes := k.store.Get(GetDelegatorBondKey(delegator, candidate)) if delegatorBytes == nil { return nil } @@ -269,17 +275,18 @@ func loadDelegatorBond(store types.KVStore, return bond } -func saveDelegatorBond(store types.KVStore, delegator crypto.Address, bond *DelegatorBond) { +func (k Keeper) saveDelegatorBond(delegator crypto.Address, + bond *DelegatorBond) { // if a new bond add to the list of bonds - if loadDelegatorBond(store, delegator, bond.PubKey) == nil { - pks := loadDelegatorCandidates(store, delegator) + if loadDelegatorBond(k.store, delegator, bond.PubKey) == nil { + pks := loadDelegatorCandidates(k.store, delegator) pks = append(pks, (*bond).PubKey) b, err := cdc.MarshalJSON(pks) if err != nil { panic(err) } - store.Set(GetDelegatorBondsKey(delegator), b) + k.store.Set(GetDelegatorBondsKey(delegator), b) } // now actually save the bond @@ -287,14 +294,14 @@ func saveDelegatorBond(store types.KVStore, delegator crypto.Address, bond *Dele if err != nil { panic(err) } - store.Set(GetDelegatorBondKey(delegator, bond.PubKey), b) + k.store.Set(GetDelegatorBondKey(delegator, bond.PubKey), b) //updateDelegatorBonds(store, delegator) } -func removeDelegatorBond(store types.KVStore, delegator crypto.Address, candidate crypto.PubKey) { +func (k Keeper) 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(store, delegator) + pks := loadDelegatorCandidates(k.store, delegator) for i, pk := range pks { if candidate.Equals(pk) { pks = append(pks[:i], pks[i+1:]...) @@ -304,18 +311,18 @@ func removeDelegatorBond(store types.KVStore, delegator crypto.Address, candidat if err != nil { panic(err) } - store.Set(GetDelegatorBondsKey(delegator), b) + k.store.Set(GetDelegatorBondsKey(delegator), b) // now remove the actual bond - store.Delete(GetDelegatorBondKey(delegator, candidate)) + k.store.Delete(GetDelegatorBondKey(delegator, candidate)) //updateDelegatorBonds(store, delegator) } //_______________________________________________________________________ // load/save the global staking params -func loadParams(store types.KVStore) (params Params) { - b := store.Get(ParamKey) +func (k Keeper) loadParams() (params Params) { + b := k.store.Get(ParamKey) if b == nil { return defaultParams() } @@ -324,22 +331,21 @@ func loadParams(store types.KVStore) (params Params) { if err != nil { panic(err) // This error should never occur big problem if does } - return } -func saveParams(store types.KVStore, params Params) { +func (k Keeper) saveParams(params Params) { b, err := cdc.MarshalJSON(params) if err != nil { panic(err) } - store.Set(ParamKey, b) + k.store.Set(ParamKey, b) } //_______________________________________________________________________ // load/save the global staking state -func loadGlobalState(store types.KVStore) (gs *GlobalState) { - b := store.Get(GlobalStateKey) +func (k Keeper) loadGlobalState() (gs *GlobalState) { + b := k.store.Get(GlobalStateKey) if b == nil { return initialGlobalState() } @@ -350,10 +356,11 @@ func loadGlobalState(store types.KVStore) (gs *GlobalState) { } return } -func saveGlobalState(store types.KVStore, gs *GlobalState) { + +func (k Keeper) saveGlobalState(gs *GlobalState) { b, err := cdc.MarshalJSON(*gs) if err != nil { panic(err) } - store.Set(GlobalStateKey, b) + k.store.Set(GlobalStateKey, b) } diff --git a/x/stake/mapper_test.go b/x/stake/keeper_test.go similarity index 100% rename from x/stake/mapper_test.go rename to x/stake/keeper_test.go diff --git a/x/stake/types.go b/x/stake/types.go index 1a184e1d9f..ccaf7c1b07 100644 --- a/x/stake/types.go +++ b/x/stake/types.go @@ -8,9 +8,6 @@ import ( // 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 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 @@ -28,8 +25,6 @@ type Params struct { func defaultParams() Params { return Params{ - HoldBonded: []byte("77777777777777777777777777777777"), - HoldUnbonded: []byte("88888888888888888888888888888888"), InflationRateChange: sdk.NewRat(13, 100), InflationMax: sdk.NewRat(20, 100), InflationMin: sdk.NewRat(7, 100), @@ -94,6 +89,9 @@ func (gs *GlobalState) unbondedShareExRate() sdk.Rational { return gs.UnbondedShares.Inv().Mul(sdk.NewRat(gs.UnbondedPool)) } +// XXX XXX XXX +// expand to include the function of actually transfering the tokens + func (gs *GlobalState) addTokensBonded(amount int64) (issuedShares sdk.Rational) { issuedShares = gs.bondedShareExRate().Inv().Mul(sdk.NewRat(amount)) // (tokens/shares)^-1 * tokens gs.BondedPool += amount