porting handler, refactoring mapper/types
This commit is contained in:
parent
e8cea08978
commit
59b10d33c1
|
@ -13,24 +13,8 @@ import (
|
||||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
"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
|
// separated for testing
|
||||||
func InitState(key, value string, store sdk.KVStore) error {
|
func InitState(ctx sdk.Context, key, value string) error {
|
||||||
|
|
||||||
params := loadParams(store)
|
params := loadParams(store)
|
||||||
switch key {
|
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 {
|
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
|
||||||
|
|
||||||
params := loadParams(store)
|
res := sdk.Result{}
|
||||||
params := loadGlobalState(store)
|
|
||||||
|
|
||||||
|
err := msg.ValidateBasic()
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// return the fee for each tx type
|
||||||
if ctx.IsCheckTx() {
|
if ctx.IsCheckTx() {
|
||||||
|
// XXX: add some tags so we can search it!
|
||||||
err = tx.ValidateBasic()
|
|
||||||
if err != nil {
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
res := sdk.Result{}
|
|
||||||
|
|
||||||
// return the fee for each tx type
|
|
||||||
switch txInner := tx.Unwrap().(type) {
|
switch txInner := tx.Unwrap().(type) {
|
||||||
case TxDeclareCandidacy:
|
case TxDeclareCandidacy:
|
||||||
return sdk.NewCheck(params.GasDeclareCandidacy, "")
|
return sdk.NewCheck(params.GasDeclareCandidacy, "")
|
||||||
|
@ -89,11 +70,9 @@ func NewHandler(ck bank.CoinKeeper) sdk.Handler {
|
||||||
return sdk.NewCheck(params.GasDelegate, "")
|
return sdk.NewCheck(params.GasDelegate, "")
|
||||||
case TxUnbond:
|
case TxUnbond:
|
||||||
return sdk.NewCheck(params.GasUnbond, "")
|
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
|
// TODO: remove redundancy
|
||||||
|
@ -108,32 +87,26 @@ func NewHandler(ck bank.CoinKeeper) sdk.Handler {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
params := loadParams(store)
|
keeper := NewKeeper(ctx, stakeKey)
|
||||||
deliverer := deliver{
|
transact := NewTransact(ctx, ck)
|
||||||
store: store,
|
|
||||||
sender: sender,
|
|
||||||
params: params,
|
|
||||||
ck: ck,
|
|
||||||
gs: gs,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the transaction
|
// Run the transaction
|
||||||
switch _tx := tx.Unwrap().(type) {
|
switch _tx := tx.Unwrap().(type) {
|
||||||
case TxDeclareCandidacy:
|
case TxDeclareCandidacy:
|
||||||
res.GasUsed = params.GasDeclareCandidacy
|
res.GasUsed = params.GasDeclareCandidacy
|
||||||
return res, deliverer.declareCandidacy(_tx)
|
return res, transact.declareCandidacy(_tx)
|
||||||
case TxEditCandidacy:
|
case TxEditCandidacy:
|
||||||
res.GasUsed = params.GasEditCandidacy
|
res.GasUsed = params.GasEditCandidacy
|
||||||
return res, deliverer.editCandidacy(_tx)
|
return res, transact.editCandidacy(_tx)
|
||||||
case TxDelegate:
|
case TxDelegate:
|
||||||
res.GasUsed = params.GasDelegate
|
res.GasUsed = params.GasDelegate
|
||||||
return res, deliverer.delegate(_tx)
|
return res, transact.delegate(_tx)
|
||||||
case TxUnbond:
|
case TxUnbond:
|
||||||
//context with hold account permissions
|
//context with hold account permissions
|
||||||
params := loadParams(store)
|
params := loadParams(store)
|
||||||
res.GasUsed = params.GasUnbond
|
res.GasUsed = params.GasUnbond
|
||||||
//ctx2 := ctx.WithPermissions(params.HoldBonded) //TODO remove this line if non-permissioned ctx works
|
//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
|
return
|
||||||
}
|
}
|
||||||
|
@ -150,47 +123,57 @@ func getTxSender(ctx sdk.Context) (sender crypto.Address, err error) {
|
||||||
|
|
||||||
//_____________________________________________________________________
|
//_____________________________________________________________________
|
||||||
|
|
||||||
type deliver struct {
|
// common fields to all transactions
|
||||||
store sdk.KVStore
|
type transact struct {
|
||||||
sender crypto.Address
|
sender crypto.Address
|
||||||
params Params
|
keeper Keeper
|
||||||
ck bank.CoinKeeper
|
coinKeeper bank.CoinKeeper
|
||||||
gs *GlobalState
|
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
|
// helper functions
|
||||||
// TODO move from deliver with new SDK should only be dependant on store to send coins in NEW SDK
|
// 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
|
// 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
|
// replace bonded shares with unbonded shares
|
||||||
tokens := d.gs.removeSharesBonded(candidate.Assets)
|
tokens := tr.gs.removeSharesBonded(candidate.Assets)
|
||||||
candidate.Assets = d.gs.addTokensUnbonded(tokens)
|
candidate.Assets = tr.gs.addTokensUnbonded(tokens)
|
||||||
candidate.Status = Unbonded
|
candidate.Status = Unbonded
|
||||||
|
|
||||||
return d.transfer(d.params.HoldBonded, d.params.HoldUnbonded,
|
return tr.transfer(tr.params.HoldBonded, tr.params.HoldUnbonded,
|
||||||
sdk.Coins{{d.params.AllowedBondDenom, tokens}})
|
sdk.Coins{{tr.params.AllowedBondDenom, tokens}})
|
||||||
}
|
}
|
||||||
|
|
||||||
// move a candidates asset pool from unbonded to bonded pool
|
// 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
|
// replace bonded shares with unbonded shares
|
||||||
tokens := d.gs.removeSharesUnbonded(candidate.Assets)
|
tokens := tr.gs.removeSharesUnbonded(candidate.Assets)
|
||||||
candidate.Assets = d.gs.addTokensBonded(tokens)
|
candidate.Assets = tr.gs.addTokensBonded(tokens)
|
||||||
candidate.Status = Bonded
|
candidate.Status = Bonded
|
||||||
|
|
||||||
return d.transfer(d.params.HoldUnbonded, d.params.HoldBonded,
|
return tr.transfer(tr.params.HoldUnbonded, tr.params.HoldBonded,
|
||||||
sdk.Coins{{d.params.AllowedBondDenom, tokens}})
|
sdk.Coins{{tr.params.AllowedBondDenom, tokens}})
|
||||||
}
|
}
|
||||||
|
|
||||||
// return an error if the bonds coins are incorrect
|
// return an error if the bonds coins are incorrect
|
||||||
func checkDenom(tx BondUpdate, store sdk.KVStore) error {
|
func checkDenom(keeper Keeper, tx BondUpdate) error {
|
||||||
if tx.Bond.Denom != loadParams(store).AllowedBondDenom {
|
if tx.Bond.Denom != keeper.loadParams().AllowedBondDenom {
|
||||||
return fmt.Errorf("Invalid coin denomination")
|
return fmt.Errorf("Invalid coin denomination")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -200,46 +183,46 @@ func checkDenom(tx BondUpdate, store sdk.KVStore) error {
|
||||||
|
|
||||||
// These functions assume everything has been authenticated,
|
// These functions assume everything has been authenticated,
|
||||||
// now we just perform action and save
|
// 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
|
// 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 {
|
if candidate != nil {
|
||||||
return fmt.Errorf("cannot bond to pubkey which is already declared candidacy"+
|
return fmt.Errorf("cannot bond to pubkey which is already declared candidacy"+
|
||||||
" PubKey %v already registered with %v candidate address",
|
" PubKey %v already registered with %v candidate address",
|
||||||
candidate.PubKey, candidate.Owner)
|
candidate.PubKey, candidate.Owner)
|
||||||
}
|
}
|
||||||
err := checkDenom(tx.BondUpdate, d.store)
|
err := checkDenom(tx.BondUpdate, tr.keeper)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// XXX end of old check tx
|
// XXX end of old check tx
|
||||||
|
|
||||||
// create and save the empty candidate
|
// create and save the empty candidate
|
||||||
bond := loadCandidate(d.store, tx.PubKey)
|
bond := tr.keeper.loadCandidate(tx.PubKey)
|
||||||
if bond != nil {
|
if bond != nil {
|
||||||
return ErrCandidateExistsAddr()
|
return ErrCandidateExistsAddr()
|
||||||
}
|
}
|
||||||
candidate := NewCandidate(tx.PubKey, d.sender, tx.Description)
|
candidate := NewCandidate(tx.PubKey, tr.sender, tx.Description)
|
||||||
saveCandidate(d.store, candidate)
|
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
|
// the candidate account and global shares are updated within here
|
||||||
txDelegate := TxDelegate{tx.BondUpdate}
|
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 must already be registered
|
||||||
candidate := loadCandidate(d.store, tx.PubKey)
|
candidate := tr.keeper.loadCandidate(tx.PubKey)
|
||||||
if candidate == nil { // does PubKey exist
|
if candidate == nil { // does PubKey exist
|
||||||
return fmt.Errorf("cannot delegate to non-existant PubKey %v", tx.PubKey)
|
return fmt.Errorf("cannot delegate to non-existant PubKey %v", tx.PubKey)
|
||||||
}
|
}
|
||||||
// XXX end of old check tx
|
// XXX end of old check tx
|
||||||
|
|
||||||
// Get the pubKey bond account
|
// Get the pubKey bond account
|
||||||
candidate := loadCandidate(d.store, tx.PubKey)
|
candidate := tr.keeper.loadCandidate(tx.PubKey)
|
||||||
if candidate == nil {
|
if candidate == nil {
|
||||||
return ErrBondNotNominated()
|
return ErrBondNotNominated()
|
||||||
}
|
}
|
||||||
|
@ -261,31 +244,31 @@ func (d deliver) editCandidacy(tx TxEditCandidacy) error {
|
||||||
candidate.Description.Details = tx.Description.Details
|
candidate.Description.Details = tx.Description.Details
|
||||||
}
|
}
|
||||||
|
|
||||||
saveCandidate(d.store, candidate)
|
tr.keeper.saveCandidate(candidate)
|
||||||
return nil
|
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
|
if candidate == nil { // does PubKey exist
|
||||||
return fmt.Errorf("cannot delegate to non-existant PubKey %v", tx.PubKey)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// end of old check tx
|
// end of old check tx
|
||||||
|
|
||||||
// Get the pubKey bond account
|
// Get the pubKey bond account
|
||||||
candidate := loadCandidate(d.store, tx.PubKey)
|
candidate := tr.keeper.loadCandidate(tx.PubKey)
|
||||||
if candidate == nil {
|
if candidate == nil {
|
||||||
return ErrBondNotNominated()
|
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
|
if candidate.Status == Revoked { //candidate has been withdrawn
|
||||||
return ErrBondNotNominated()
|
return ErrBondNotNominated()
|
||||||
|
@ -293,20 +276,20 @@ func (d deliver) delegateWithCandidate(tx TxDelegate, candidate *Candidate) erro
|
||||||
|
|
||||||
var poolAccount crypto.Address
|
var poolAccount crypto.Address
|
||||||
if candidate.Status == Bonded {
|
if candidate.Status == Bonded {
|
||||||
poolAccount = d.params.HoldBonded
|
poolAccount = tr.params.HoldBonded
|
||||||
} else {
|
} 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
|
// 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get or create the delegator bond
|
// 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 {
|
if bond == nil {
|
||||||
bond = &DelegatorBond{
|
bond = &DelegatorBond{
|
||||||
PubKey: tx.PubKey,
|
PubKey: tx.PubKey,
|
||||||
|
@ -315,17 +298,17 @@ func (d deliver) delegateWithCandidate(tx TxDelegate, candidate *Candidate) erro
|
||||||
}
|
}
|
||||||
|
|
||||||
// Account new shares, save
|
// Account new shares, save
|
||||||
bond.Shares = bond.Shares.Add(candidate.addTokens(tx.Bond.Amount, d.gs))
|
bond.Shares = bond.Shares.Add(candidate.addTokens(tx.Bond.Amount, tr.gs))
|
||||||
saveCandidate(d.store, candidate)
|
tr.keeper.saveCandidate(candidate)
|
||||||
saveDelegatorBond(d.store, d.sender, bond)
|
tr.keeper.saveDelegatorBond(tr.sender, bond)
|
||||||
saveGlobalState(d.store, d.gs)
|
tr.keeper.saveGlobalState(tr.gs)
|
||||||
return nil
|
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
|
// 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)
|
sharesStr := viper.GetString(tx.Shares)
|
||||||
if bond.Shares.LT(sdk.ZeroRat) { // bond shares < tx shares
|
if bond.Shares.LT(sdk.ZeroRat) { // bond shares < tx shares
|
||||||
return fmt.Errorf("no shares in account to unbond")
|
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
|
// XXX end of old checkTx
|
||||||
|
|
||||||
// get delegator bond
|
// get delegator bond
|
||||||
bond := loadDelegatorBond(d.store, d.sender, tx.PubKey)
|
bond := tr.keeper.loadDelegatorBond(tr.sender, tx.PubKey)
|
||||||
if bond == nil {
|
if bond == nil {
|
||||||
return ErrNoDelegatorForAddress()
|
return ErrNoDelegatorForAddress()
|
||||||
}
|
}
|
||||||
|
@ -372,7 +355,7 @@ func (d deliver) unbond(tx TxUnbond) error {
|
||||||
bond.Shares = bond.Shares.Sub(shares)
|
bond.Shares = bond.Shares.Sub(shares)
|
||||||
|
|
||||||
// get pubKey candidate
|
// get pubKey candidate
|
||||||
candidate := loadCandidate(d.store, tx.PubKey)
|
candidate := tr.keeper.loadCandidate(tx.PubKey)
|
||||||
if candidate == nil {
|
if candidate == nil {
|
||||||
return ErrNoCandidateForAddress()
|
return ErrNoCandidateForAddress()
|
||||||
}
|
}
|
||||||
|
@ -382,28 +365,28 @@ func (d deliver) unbond(tx TxUnbond) error {
|
||||||
|
|
||||||
// if the bond is the owner of the candidate then
|
// if the bond is the owner of the candidate then
|
||||||
// trigger a revoke candidacy
|
// trigger a revoke candidacy
|
||||||
if d.sender.Equals(candidate.Owner) &&
|
if tr.sender.Equals(candidate.Owner) &&
|
||||||
candidate.Status != Revoked {
|
candidate.Status != Revoked {
|
||||||
revokeCandidacy = true
|
revokeCandidacy = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove the bond
|
// remove the bond
|
||||||
removeDelegatorBond(d.store, d.sender, tx.PubKey)
|
tr.keeper.removeDelegatorBond(tr.sender, tx.PubKey)
|
||||||
} else {
|
} else {
|
||||||
saveDelegatorBond(d.store, d.sender, bond)
|
tr.keeper.saveDelegatorBond(tr.sender, bond)
|
||||||
}
|
}
|
||||||
|
|
||||||
// transfer coins back to account
|
// transfer coins back to account
|
||||||
var poolAccount crypto.Address
|
var poolAccount crypto.Address
|
||||||
if candidate.Status == Bonded {
|
if candidate.Status == Bonded {
|
||||||
poolAccount = d.params.HoldBonded
|
poolAccount = tr.params.HoldBonded
|
||||||
} else {
|
} else {
|
||||||
poolAccount = d.params.HoldUnbonded
|
poolAccount = tr.params.HoldUnbonded
|
||||||
}
|
}
|
||||||
|
|
||||||
returnCoins := candidate.removeShares(shares, d.gs)
|
returnCoins := candidate.removeShares(shares, tr.gs)
|
||||||
err := d.transfer(poolAccount, d.sender,
|
err := tr.transfer(poolAccount, tr.sender,
|
||||||
sdk.Coins{{d.params.AllowedBondDenom, returnCoins}})
|
sdk.Coins{{tr.params.AllowedBondDenom, returnCoins}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -413,7 +396,7 @@ func (d deliver) unbond(tx TxUnbond) error {
|
||||||
|
|
||||||
// change the share types to unbonded if they were not already
|
// change the share types to unbonded if they were not already
|
||||||
if candidate.Status == Bonded {
|
if candidate.Status == Bonded {
|
||||||
err = d.bondedToUnbondedPool(candidate)
|
err = tr.bondedToUnbondedPool(candidate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -425,11 +408,11 @@ func (d deliver) unbond(tx TxUnbond) error {
|
||||||
|
|
||||||
// deduct shares from the candidate and save
|
// deduct shares from the candidate and save
|
||||||
if candidate.Liabilities.IsZero() {
|
if candidate.Liabilities.IsZero() {
|
||||||
removeCandidate(d.store, tx.PubKey)
|
tr.keeper.removeCandidate(tx.PubKey)
|
||||||
} else {
|
} else {
|
||||||
saveCandidate(d.store, candidate)
|
tr.keeper.saveCandidate(candidate)
|
||||||
}
|
}
|
||||||
|
|
||||||
saveGlobalState(d.store, d.gs)
|
tr.keeper.saveGlobalState(tr.gs)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,12 +7,8 @@ import (
|
||||||
"github.com/cosmos/cosmos-sdk/types"
|
"github.com/cosmos/cosmos-sdk/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// nolint
|
//nolint
|
||||||
var (
|
var (
|
||||||
|
|
||||||
// internal wire codec
|
|
||||||
cdc *wire.Codec
|
|
||||||
|
|
||||||
// Keys for store prefixes
|
// Keys for store prefixes
|
||||||
CandidatesPubKeysKey = []byte{0x01} // key for all candidates' pubkeys
|
CandidatesPubKeysKey = []byte{0x01} // key for all candidates' pubkeys
|
||||||
ParamKey = []byte{0x02} // key for global parameters relating to staking
|
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
|
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
|
// GetCandidateKey - get the key for the candidate with pubKey
|
||||||
func GetCandidateKey(pubKey crypto.PubKey) []byte {
|
func GetCandidateKey(pubKey crypto.PubKey) []byte {
|
||||||
return append(CandidateKeyPrefix, pubKey.Bytes()...)
|
return append(CandidateKeyPrefix, pubKey.Bytes()...)
|
||||||
|
@ -72,10 +61,28 @@ func GetDelegatorBondsKey(delegator crypto.Address) []byte {
|
||||||
return append(DelegatorBondsKeyPrefix, res...)
|
return append(DelegatorBondsKeyPrefix, res...)
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//___________________________________________________________________________
|
||||||
|
|
||||||
func loadCandidate(store types.KVStore, pubKey crypto.PubKey) *Candidate {
|
// keeper of the staking store
|
||||||
b := store.Get(GetCandidateKey(pubKey))
|
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 {
|
if b == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -87,31 +94,31 @@ func loadCandidate(store types.KVStore, pubKey crypto.PubKey) *Candidate {
|
||||||
return 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
|
// 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}
|
validator := &Validator{candidate.PubKey, candidate.VotingPower}
|
||||||
updateValidator(store, validator)
|
updateValidator(k.store, validator)
|
||||||
|
|
||||||
b, err := cdc.MarshalJSON(*candidate)
|
b, err := cdc.MarshalJSON(*candidate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
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
|
// XXX should only remove validator if we know candidate is a validator
|
||||||
removeValidator(store, pubKey)
|
removeValidator(k.store, pubKey)
|
||||||
store.Delete(GetCandidateKey(pubKey))
|
k.store.Delete(GetCandidateKey(pubKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//___________________________________________________________________________
|
||||||
|
|
||||||
//func loadValidator(store types.KVStore, pubKey crypto.PubKey, votingPower types.Rational) *Validator {
|
//func loadValidator(k.store types.KVStore, pubKey crypto.PubKey, votingPower types.Rational) *Validator {
|
||||||
//b := store.Get(GetValidatorKey(pubKey, votingPower))
|
//b := k.store.Get(GetValidatorKey(pubKey, votingPower))
|
||||||
//if b == nil {
|
//if b == nil {
|
||||||
//return nil
|
//return nil
|
||||||
//}
|
//}
|
||||||
|
@ -125,7 +132,7 @@ func removeCandidate(store types.KVStore, pubKey crypto.PubKey) {
|
||||||
|
|
||||||
// updateValidator - update a validator and create accumulate any changes
|
// updateValidator - update a validator and create accumulate any changes
|
||||||
// in the changed validator substore
|
// in the changed validator substore
|
||||||
func updateValidator(store types.KVStore, validator *Validator) {
|
func (k Keeper) updateValidator(validator *Validator) {
|
||||||
|
|
||||||
b, err := cdc.MarshalJSON(*validator)
|
b, err := cdc.MarshalJSON(*validator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -133,34 +140,34 @@ func updateValidator(store types.KVStore, validator *Validator) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// add to the validators to update list if necessary
|
// 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
|
// 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
|
//add validator with zero power to the validator updates
|
||||||
b, err := cdc.MarshalJSON(Validator{pubKey, types.ZeroRat})
|
b, err := cdc.MarshalJSON(Validator{pubKey, types.ZeroRat})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
store.Set(GetValidatorUpdatesKey(pubKey), b)
|
k.store.Set(GetValidatorUpdatesKey(pubKey), b)
|
||||||
|
|
||||||
// now actually delete from the validator set
|
// now actually delete from the validator set
|
||||||
candidate := loadCandidate(store, pubKey)
|
candidate := loadCandidate(k.store, pubKey)
|
||||||
if candidate != nil {
|
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
|
// get the most recent updated validator set from the Candidates. These bonds
|
||||||
// are already sorted by VotingPower from the UpdateVotingPower function which
|
// are already sorted by VotingPower from the UpdateVotingPower function which
|
||||||
// is the only function which is to modify the VotingPower
|
// 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)
|
validators = make([]Validator, maxVal)
|
||||||
for i := 0; ; i++ {
|
for i := 0; ; i++ {
|
||||||
|
@ -181,12 +188,12 @@ func getValidators(store types.KVStore, maxVal int) (validators []Validator) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//_________________________________________________________________________
|
||||||
|
|
||||||
// get the most updated validators
|
// 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() {
|
for ; iterator.Valid(); iterator.Next() {
|
||||||
valBytes := iterator.Value()
|
valBytes := iterator.Value()
|
||||||
|
@ -203,10 +210,10 @@ func getValidatorUpdates(store types.KVStore) (updates []Validator) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove all validator update entries
|
// remove all validator update entries
|
||||||
func clearValidatorUpdates(store types.KVStore, maxVal int) {
|
func (k Keeper) clearValidatorUpdates(maxVal int) {
|
||||||
iterator := store.Iterator(subspace(ValidatorUpdatesKeyPrefix))
|
iterator := k.store.Iterator(subspace(ValidatorUpdatesKeyPrefix))
|
||||||
for ; iterator.Valid(); iterator.Next() {
|
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()
|
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
|
// 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 := k.store.Iterator(subspace(CandidateKeyPrefix))
|
||||||
//iterator := store.Iterator(CandidateKeyPrefix, []byte(nil))
|
//iterator := k.store.Iterator(CandidateKeyPrefix, []byte(nil))
|
||||||
//iterator := store.Iterator([]byte{}, []byte(nil))
|
//iterator := k.store.Iterator([]byte{}, []byte(nil))
|
||||||
|
|
||||||
for ; iterator.Valid(); iterator.Next() {
|
for ; iterator.Valid(); iterator.Next() {
|
||||||
candidateBytes := iterator.Value()
|
candidateBytes := iterator.Value()
|
||||||
|
@ -233,13 +240,12 @@ func loadCandidates(store types.KVStore) (candidates Candidates) {
|
||||||
return candidates
|
return candidates
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//_____________________________________________________________________
|
||||||
|
|
||||||
// load the pubkeys of all candidates a delegator is delegated too
|
// load the pubkeys of all candidates a delegator is delegated too
|
||||||
func loadDelegatorCandidates(store types.KVStore,
|
func (k Keeper) loadDelegatorCandidates(delegator crypto.Address) (candidates []crypto.PubKey) {
|
||||||
delegator crypto.Address) (candidates []crypto.PubKey) {
|
|
||||||
|
|
||||||
candidateBytes := store.Get(GetDelegatorBondsKey(delegator))
|
candidateBytes := k.store.Get(GetDelegatorBondsKey(delegator))
|
||||||
if candidateBytes == nil {
|
if candidateBytes == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -251,12 +257,12 @@ func loadDelegatorCandidates(store types.KVStore,
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//_____________________________________________________________________
|
||||||
|
|
||||||
func loadDelegatorBond(store types.KVStore,
|
func (k Keeper) loadDelegatorBond(delegator crypto.Address,
|
||||||
delegator crypto.Address, candidate crypto.PubKey) *DelegatorBond {
|
candidate crypto.PubKey) *DelegatorBond {
|
||||||
|
|
||||||
delegatorBytes := store.Get(GetDelegatorBondKey(delegator, candidate))
|
delegatorBytes := k.store.Get(GetDelegatorBondKey(delegator, candidate))
|
||||||
if delegatorBytes == nil {
|
if delegatorBytes == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -269,17 +275,18 @@ func loadDelegatorBond(store types.KVStore,
|
||||||
return bond
|
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 a new bond add to the list of bonds
|
||||||
if loadDelegatorBond(store, delegator, bond.PubKey) == nil {
|
if loadDelegatorBond(k.store, delegator, bond.PubKey) == nil {
|
||||||
pks := loadDelegatorCandidates(store, delegator)
|
pks := loadDelegatorCandidates(k.store, delegator)
|
||||||
pks = append(pks, (*bond).PubKey)
|
pks = append(pks, (*bond).PubKey)
|
||||||
b, err := cdc.MarshalJSON(pks)
|
b, err := cdc.MarshalJSON(pks)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
store.Set(GetDelegatorBondsKey(delegator), b)
|
k.store.Set(GetDelegatorBondsKey(delegator), b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// now actually save the bond
|
// now actually save the bond
|
||||||
|
@ -287,14 +294,14 @@ func saveDelegatorBond(store types.KVStore, delegator crypto.Address, bond *Dele
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
store.Set(GetDelegatorBondKey(delegator, bond.PubKey), b)
|
k.store.Set(GetDelegatorBondKey(delegator, bond.PubKey), b)
|
||||||
//updateDelegatorBonds(store, delegator)
|
//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!
|
// TODO use list queries on multistore to remove iterations here!
|
||||||
// first remove from the list of bonds
|
// first remove from the list of bonds
|
||||||
pks := loadDelegatorCandidates(store, delegator)
|
pks := loadDelegatorCandidates(k.store, delegator)
|
||||||
for i, pk := range pks {
|
for i, pk := range pks {
|
||||||
if candidate.Equals(pk) {
|
if candidate.Equals(pk) {
|
||||||
pks = append(pks[:i], pks[i+1:]...)
|
pks = append(pks[:i], pks[i+1:]...)
|
||||||
|
@ -304,18 +311,18 @@ func removeDelegatorBond(store types.KVStore, delegator crypto.Address, candidat
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
store.Set(GetDelegatorBondsKey(delegator), b)
|
k.store.Set(GetDelegatorBondsKey(delegator), b)
|
||||||
|
|
||||||
// now remove the actual bond
|
// now remove the actual bond
|
||||||
store.Delete(GetDelegatorBondKey(delegator, candidate))
|
k.store.Delete(GetDelegatorBondKey(delegator, candidate))
|
||||||
//updateDelegatorBonds(store, delegator)
|
//updateDelegatorBonds(store, delegator)
|
||||||
}
|
}
|
||||||
|
|
||||||
//_______________________________________________________________________
|
//_______________________________________________________________________
|
||||||
|
|
||||||
// load/save the global staking params
|
// load/save the global staking params
|
||||||
func loadParams(store types.KVStore) (params Params) {
|
func (k Keeper) loadParams() (params Params) {
|
||||||
b := store.Get(ParamKey)
|
b := k.store.Get(ParamKey)
|
||||||
if b == nil {
|
if b == nil {
|
||||||
return defaultParams()
|
return defaultParams()
|
||||||
}
|
}
|
||||||
|
@ -324,22 +331,21 @@ func loadParams(store types.KVStore) (params Params) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err) // This error should never occur big problem if does
|
panic(err) // This error should never occur big problem if does
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
func saveParams(store types.KVStore, params Params) {
|
func (k Keeper) saveParams(params Params) {
|
||||||
b, err := cdc.MarshalJSON(params)
|
b, err := cdc.MarshalJSON(params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
store.Set(ParamKey, b)
|
k.store.Set(ParamKey, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
//_______________________________________________________________________
|
//_______________________________________________________________________
|
||||||
|
|
||||||
// load/save the global staking state
|
// load/save the global staking state
|
||||||
func loadGlobalState(store types.KVStore) (gs *GlobalState) {
|
func (k Keeper) loadGlobalState() (gs *GlobalState) {
|
||||||
b := store.Get(GlobalStateKey)
|
b := k.store.Get(GlobalStateKey)
|
||||||
if b == nil {
|
if b == nil {
|
||||||
return initialGlobalState()
|
return initialGlobalState()
|
||||||
}
|
}
|
||||||
|
@ -350,10 +356,11 @@ func loadGlobalState(store types.KVStore) (gs *GlobalState) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
func saveGlobalState(store types.KVStore, gs *GlobalState) {
|
|
||||||
|
func (k Keeper) saveGlobalState(gs *GlobalState) {
|
||||||
b, err := cdc.MarshalJSON(*gs)
|
b, err := cdc.MarshalJSON(*gs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
store.Set(GlobalStateKey, b)
|
k.store.Set(GlobalStateKey, b)
|
||||||
}
|
}
|
|
@ -8,9 +8,6 @@ import (
|
||||||
|
|
||||||
// Params defines the high level settings for staking
|
// Params defines the high level settings for staking
|
||||||
type Params struct {
|
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
|
InflationRateChange sdk.Rational `json:"inflation_rate_change"` // maximum annual change in inflation rate
|
||||||
InflationMax sdk.Rational `json:"inflation_max"` // maximum inflation rate
|
InflationMax sdk.Rational `json:"inflation_max"` // maximum inflation rate
|
||||||
InflationMin sdk.Rational `json:"inflation_min"` // minimum inflation rate
|
InflationMin sdk.Rational `json:"inflation_min"` // minimum inflation rate
|
||||||
|
@ -28,8 +25,6 @@ type Params struct {
|
||||||
|
|
||||||
func defaultParams() Params {
|
func defaultParams() Params {
|
||||||
return Params{
|
return Params{
|
||||||
HoldBonded: []byte("77777777777777777777777777777777"),
|
|
||||||
HoldUnbonded: []byte("88888888888888888888888888888888"),
|
|
||||||
InflationRateChange: sdk.NewRat(13, 100),
|
InflationRateChange: sdk.NewRat(13, 100),
|
||||||
InflationMax: sdk.NewRat(20, 100),
|
InflationMax: sdk.NewRat(20, 100),
|
||||||
InflationMin: sdk.NewRat(7, 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))
|
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) {
|
func (gs *GlobalState) addTokensBonded(amount int64) (issuedShares sdk.Rational) {
|
||||||
issuedShares = gs.bondedShareExRate().Inv().Mul(sdk.NewRat(amount)) // (tokens/shares)^-1 * tokens
|
issuedShares = gs.bondedShareExRate().Inv().Mul(sdk.NewRat(amount)) // (tokens/shares)^-1 * tokens
|
||||||
gs.BondedPool += amount
|
gs.BondedPool += amount
|
||||||
|
|
Loading…
Reference in New Issue