porting handler, refactoring mapper/types

This commit is contained in:
rigelrozanski 2018-02-28 16:27:07 +00:00
parent e8cea08978
commit 59b10d33c1
4 changed files with 170 additions and 182 deletions

View File

@ -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
}

View File

@ -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)
}

View File

@ -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