sunny refactor compiling

This commit is contained in:
rigelrozanski 2018-03-20 22:21:18 +01:00
parent 93173e9fdd
commit 13835f084f
14 changed files with 606 additions and 601 deletions

View File

@ -49,7 +49,7 @@ type Params struct {
GoalBonded rational.Rational // Goal of percent bonded atoms GoalBonded rational.Rational // Goal of percent bonded atoms
ReserveTax rational.Rational // Tax collected on all fees ReserveTax rational.Rational // Tax collected on all fees
MaxVals uint16 // maximum number of validators MaxValidators uint16 // maximum number of validators
BondDenom string // bondable coin denomination BondDenom string // bondable coin denomination
// gas costs for txs // gas costs for txs

View File

@ -45,7 +45,7 @@ func GetCmdQueryCandidates(cdc *wire.Codec, storeName string) *cobra.Command {
Short: "Query for the set of validator-candidates pubkeys", Short: "Query for the set of validator-candidates pubkeys",
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
key := PrefixedKey(stake.Name, stake.CandidatesAddrKey) key := PrefixedKey(stake.MsgType, stake.CandidatesAddrKey)
res, err := builder.Query(key, storeName) res, err := builder.Query(key, storeName)
if err != nil { if err != nil {
@ -85,7 +85,7 @@ func GetCmdQueryCandidate(cdc *wire.Codec, storeName string) *cobra.Command {
return err return err
} }
key := PrefixedKey(stake.Name, stake.GetCandidateKey(addr)) key := PrefixedKey(stake.MsgType, stake.GetCandidateKey(addr))
res, err := builder.Query(key, storeName) res, err := builder.Query(key, storeName)
if err != nil { if err != nil {
@ -131,7 +131,7 @@ func GetCmdQueryDelegatorBond(cdc *wire.Codec, storeName string) *cobra.Command
} }
delegator := crypto.Address(bz) delegator := crypto.Address(bz)
key := PrefixedKey(stake.Name, stake.GetDelegatorBondKey(delegator, addr, cdc)) key := PrefixedKey(stake.MsgType, stake.GetDelegatorBondKey(delegator, addr, cdc))
res, err := builder.Query(key, storeName) res, err := builder.Query(key, storeName)
if err != nil { if err != nil {
@ -173,7 +173,7 @@ func GetCmdQueryDelegatorBonds(cdc *wire.Codec, storeName string) *cobra.Command
} }
delegator := crypto.Address(bz) delegator := crypto.Address(bz)
key := PrefixedKey(stake.Name, stake.GetDelegatorBondsKey(delegator, cdc)) key := PrefixedKey(stake.MsgType, stake.GetDelegatorBondsKey(delegator, cdc))
res, err := builder.Query(key, storeName) res, err := builder.Query(key, storeName)
if err != nil { if err != nil {

View File

@ -19,10 +19,11 @@ import (
// nolint // nolint
const ( const (
FlagAddress = "address" FlagAddressDelegator = "addressD"
FlagPubKey = "pubkey" FlagAddressCandidate = "addressC"
FlagAmount = "amount" FlagPubKey = "pubkey"
FlagShares = "shares" FlagAmount = "amount"
FlagShares = "shares"
FlagMoniker = "moniker" FlagMoniker = "moniker"
FlagIdentity = "keybase-sig" FlagIdentity = "keybase-sig"
@ -36,6 +37,7 @@ var (
fsAmount = flag.NewFlagSet("", flag.ContinueOnError) fsAmount = flag.NewFlagSet("", flag.ContinueOnError)
fsShares = flag.NewFlagSet("", flag.ContinueOnError) fsShares = flag.NewFlagSet("", flag.ContinueOnError)
fsCandidate = flag.NewFlagSet("", flag.ContinueOnError) fsCandidate = flag.NewFlagSet("", flag.ContinueOnError)
fsDelegator = flag.NewFlagSet("", flag.ContinueOnError)
) )
func init() { func init() {
@ -45,7 +47,8 @@ func init() {
fsCandidate.String(FlagMoniker, "", "validator-candidate name") fsCandidate.String(FlagMoniker, "", "validator-candidate name")
fsCandidate.String(FlagIdentity, "", "optional keybase signature") fsCandidate.String(FlagIdentity, "", "optional keybase signature")
fsCandidate.String(FlagWebsite, "", "optional website") fsCandidate.String(FlagWebsite, "", "optional website")
fsCandidate.String(FlagDetails, "", "optional detailed description space") fsCandidate.String(FlagAddressCandidate, "", "hex address of the validator/candidate")
fsDelegator.String(FlagAddressDelegator, "", "hex address of the delegator")
} }
//TODO refactor to common functionality //TODO refactor to common functionality
@ -69,7 +72,7 @@ func GetCmdDeclareCandidacy(cdc *wire.Codec) *cobra.Command {
if err != nil { if err != nil {
return err return err
} }
addr, err := sdk.GetAddress(viper.GetString(FlagAddress)) candidateAddr, err := sdk.GetAddress(viper.GetString(FlagAddressCandidate))
if err != nil { if err != nil {
return err return err
} }
@ -86,7 +89,7 @@ func GetCmdDeclareCandidacy(cdc *wire.Codec) *cobra.Command {
Website: viper.GetString(FlagWebsite), Website: viper.GetString(FlagWebsite),
Details: viper.GetString(FlagDetails), Details: viper.GetString(FlagDetails),
} }
msg := stake.NewMsgDeclareCandidacy(addr, pk, amount, description) msg := stake.NewMsgDeclareCandidacy(candidateAddr, pk, amount, description)
name, pass, err := getNamePassword() name, pass, err := getNamePassword()
if err != nil { if err != nil {
@ -117,7 +120,7 @@ func GetCmdEditCandidacy(cdc *wire.Codec) *cobra.Command {
Short: "edit and existing validator-candidate account", Short: "edit and existing validator-candidate account",
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
addr, err := sdk.GetAddress(viper.GetString(FlagAddress)) candidateAddr, err := sdk.GetAddress(viper.GetString(FlagAddressCandidate))
if err != nil { if err != nil {
return err return err
} }
@ -127,7 +130,7 @@ func GetCmdEditCandidacy(cdc *wire.Codec) *cobra.Command {
Website: viper.GetString(FlagWebsite), Website: viper.GetString(FlagWebsite),
Details: viper.GetString(FlagDetails), Details: viper.GetString(FlagDetails),
} }
msg := stake.NewMsgEditCandidacy(addr, description) msg := stake.NewMsgEditCandidacy(candidateAddr, description)
name, pass, err := getNamePassword() name, pass, err := getNamePassword()
if err != nil { if err != nil {
@ -161,12 +164,13 @@ func GetCmdDelegate(cdc *wire.Codec) *cobra.Command {
return err return err
} }
addr, err := sdk.GetAddress(viper.GetString(FlagAddress)) delegatorAddr, err := sdk.GetAddress(viper.GetString(FlagAddressDelegator))
candidateAddr, err := sdk.GetAddress(viper.GetString(FlagAddressCandidate))
if err != nil { if err != nil {
return err return err
} }
msg := stake.NewMsgDelegate(addr, amount) msg := stake.NewMsgDelegate(delegatorAddr, candidateAddr, amount)
name, pass, err := getNamePassword() name, pass, err := getNamePassword()
if err != nil { if err != nil {
@ -186,6 +190,7 @@ func GetCmdDelegate(cdc *wire.Codec) *cobra.Command {
cmd.Flags().AddFlagSet(fsPk) cmd.Flags().AddFlagSet(fsPk)
cmd.Flags().AddFlagSet(fsAmount) cmd.Flags().AddFlagSet(fsAmount)
cmd.Flags().AddFlagSet(fsDelegator)
return cmd return cmd
} }
@ -210,12 +215,13 @@ func GetCmdUnbond(cdc *wire.Codec) *cobra.Command {
} }
} }
addr, err := sdk.GetAddress(viper.GetString(FlagAddress)) delegatorAddr, err := sdk.GetAddress(viper.GetString(FlagAddressDelegator))
candidateAddr, err := sdk.GetAddress(viper.GetString(FlagAddressCandidate))
if err != nil { if err != nil {
return err return err
} }
msg := stake.NewMsgUnbond(addr, sharesStr) msg := stake.NewMsgUnbond(delegatorAddr, candidateAddr, sharesStr)
name, pass, err := getNamePassword() name, pass, err := getNamePassword()
if err != nil { if err != nil {
@ -235,6 +241,7 @@ func GetCmdUnbond(cdc *wire.Codec) *cobra.Command {
cmd.Flags().AddFlagSet(fsPk) cmd.Flags().AddFlagSet(fsPk)
cmd.Flags().AddFlagSet(fsShares) cmd.Flags().AddFlagSet(fsShares)
cmd.Flags().AddFlagSet(fsDelegator)
return cmd return cmd
} }

View File

@ -91,7 +91,10 @@ func ErrNoDelegatorForAddress() sdk.Error {
return newError(CodeInvalidValidator, "Delegator does not contain validator bond") return newError(CodeInvalidValidator, "Delegator does not contain validator bond")
} }
func ErrInsufficientFunds() sdk.Error { func ErrInsufficientFunds() sdk.Error {
return newError(CodeInvalidValidator, "Insufficient bond shares") return newError(CodeInvalidInput, "Insufficient bond shares")
}
func ErrBadShares() sdk.Error {
return newError(CodeInvalidInput, "bad shares provided as input, must be MAX or decimal")
} }
func ErrBadRemoveValidator() sdk.Error { func ErrBadRemoveValidator() sdk.Error {
return newError(CodeInvalidValidator, "Error removing validator") return newError(CodeInvalidValidator, "Error removing validator")

View File

@ -80,27 +80,6 @@ func NewHandler(k Keeper, ck bank.CoinKeeper) sdk.Handler {
//sender := signers[0] //sender := signers[0]
//} //}
//_____________________________________________________________________
// helper functions
// move a candidates asset pool from bonded to unbonded pool
func (k Keeper) bondedToUnbondedPool(ctx sdk.Context, candidate *Candidate) {
// replace bonded shares with unbonded shares
tokens := k.getGlobalState(ctx).removeSharesBonded(candidate.Assets)
candidate.Assets = k.getGlobalState(ctx).addTokensUnbonded(tokens)
candidate.Status = Unbonded
}
// move a candidates asset pool from unbonded to bonded pool
func (k Keeper) unbondedToBondedPool(ctx sdk.Context, candidate *Candidate) {
// replace unbonded shares with bonded shares
tokens := k.getGlobalState(ctx).removeSharesUnbonded(candidate.Assets)
candidate.Assets = k.getGlobalState(ctx).addTokensBonded(tokens)
candidate.Status = Bonded
}
//_____________________________________________________________________ //_____________________________________________________________________
// These functions assume everything has been authenticated, // These functions assume everything has been authenticated,
@ -109,11 +88,12 @@ func (k Keeper) unbondedToBondedPool(ctx sdk.Context, candidate *Candidate) {
func (k Keeper) handleMsgDeclareCandidacy(ctx sdk.Context, msg MsgDeclareCandidacy) sdk.Result { func (k Keeper) handleMsgDeclareCandidacy(ctx sdk.Context, msg MsgDeclareCandidacy) sdk.Result {
// check to see if the pubkey or sender has been registered before // check to see if the pubkey or sender has been registered before
if k.getCandidate(msg.Address) != nil { _, found := k.getCandidate(ctx, msg.CandidateAddr)
return ErrCandidateExistsAddr() if found {
return ErrCandidateExistsAddr().Result()
} }
if msg.bond.Denom != k.getParams().BondDenom { if msg.Bond.Denom != k.getParams(ctx).BondDenom {
return ErrBadBondingDenom() return ErrBadBondingDenom().Result()
} }
if ctx.IsCheckTx() { if ctx.IsCheckTx() {
return sdk.Result{ return sdk.Result{
@ -121,19 +101,19 @@ func (k Keeper) handleMsgDeclareCandidacy(ctx sdk.Context, msg MsgDeclareCandida
} }
} }
candidate := NewCandidate(msg.PubKey, msg.Address, msg.Description) candidate := NewCandidate(msg.CandidateAddr, msg.PubKey, msg.Description)
k.setCandidate(candidate) k.setCandidate(ctx, candidate)
// move coins from the msg.Address account to a (self-bond) delegator account // move coins from the msg.Address 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 := NewMsgDelegate(msg.Address, msg.Bond) return k.delegateWithCandidate(ctx, msg.CandidateAddr, msg.Bond, candidate).Result()
return delegateWithCandidate(txDelegate, candidate)
} }
func (k Keeper) handleMsgEditCandidacy(ctx sdk.Context, msg MsgEditCandidacy) sdk.Result { func (k Keeper) handleMsgEditCandidacy(ctx sdk.Context, msg MsgEditCandidacy) sdk.Result {
// candidate must already be registered // candidate must already be registered
if k.getCandidate(msg.Address) == nil { candidate, found := k.getCandidate(ctx, msg.CandidateAddr)
if !found {
return ErrBadCandidateAddr().Result() return ErrBadCandidateAddr().Result()
} }
if ctx.IsCheckTx() { if ctx.IsCheckTx() {
@ -141,16 +121,11 @@ func (k Keeper) handleMsgEditCandidacy(ctx sdk.Context, msg MsgEditCandidacy) sd
GasUsed: GasEditCandidacy, GasUsed: GasEditCandidacy,
} }
} }
// Get the pubKey bond account
candidate := k.getCandidate(msg.Address)
if candidate == nil {
return ErrBondNotNominated().Result()
}
if candidate.Status == Unbonded { //candidate has been withdrawn if candidate.Status == Unbonded { //candidate has been withdrawn
return ErrBondNotNominated().Result() return ErrBondNotNominated().Result()
} }
// XXX move to types
//check and edit any of the editable terms //check and edit any of the editable terms
if msg.Description.Moniker != "" { if msg.Description.Moniker != "" {
candidate.Description.Moniker = msg.Description.Moniker candidate.Description.Moniker = msg.Description.Moniker
@ -165,16 +140,17 @@ func (k Keeper) handleMsgEditCandidacy(ctx sdk.Context, msg MsgEditCandidacy) sd
candidate.Description.Details = msg.Description.Details candidate.Description.Details = msg.Description.Details
} }
k.setCandidate(candidate) k.setCandidate(ctx, candidate)
return nil return sdk.Result{}
} }
func (k Keeper) handleMsgDelegate(ctx sdk.Context, msg MsgDelegate) sdk.Result { func (k Keeper) handleMsgDelegate(ctx sdk.Context, msg MsgDelegate) sdk.Result {
if k.getCandidate(msg.Address) == nil { candidate, found := k.getCandidate(ctx, msg.CandidateAddr)
if !found {
return ErrBadCandidateAddr().Result() return ErrBadCandidateAddr().Result()
} }
if msg.bond.Denom != k.getParams().BondDenom { if msg.Bond.Denom != k.getParams(ctx).BondDenom {
return ErrBadBondingDenom().Result() return ErrBadBondingDenom().Result()
} }
if ctx.IsCheckTx() { if ctx.IsCheckTx() {
@ -182,17 +158,10 @@ func (k Keeper) handleMsgDelegate(ctx sdk.Context, msg MsgDelegate) sdk.Result {
GasUsed: GasDelegate, GasUsed: GasDelegate,
} }
} }
return k.delegateWithCandidate(ctx, msg.DelegatorAddr, msg.Bond, candidate).Result()
// Get the pubKey bond account
candidate := k.getCandidate(msg.Address)
if candidate == nil {
return ErrBondNotNominated().Result()
}
return tr.delegateWithCandidate(msg, candidate).Result()
} }
func (k Keeper) delegateWithCandidate(ctx sdk.Context, candidateAddr, delegatorAddr sdk.Address, func (k Keeper) delegateWithCandidate(ctx sdk.Context, delegatorAddr sdk.Address,
bondAmt sdk.Coin, candidate Candidate) sdk.Error { bondAmt sdk.Coin, candidate Candidate) sdk.Error {
if candidate.Status == Revoked { //candidate has been withdrawn if candidate.Status == Revoked { //candidate has been withdrawn
@ -200,63 +169,43 @@ func (k Keeper) delegateWithCandidate(ctx sdk.Context, candidateAddr, delegatorA
} }
// Get or create the delegator bond // Get or create the delegator bond
bond := k.getDelegatorBond(tr.sender, canad) existingBond, found := k.getDelegatorBond(ctx, delegatorAddr, candidate.Address)
if bond == nil { if !found {
bond = &DelegatorBond{ existingBond = DelegatorBond{
CandidateAddr: delegatorAddr, DelegatorAddr: delegatorAddr,
DelegatorAddr: candidateAddr, CandidateAddr: candidate.Address,
Shares: sdk.ZeroRat, Shares: sdk.ZeroRat,
} }
} }
// Account new shares, save // Account new shares, save
err := BondCoins(bond, candidate, msg.Bond) err := k.BondCoins(ctx, existingBond, candidate, bondAmt)
if err != nil { if err != nil {
return err.Result() return err
} }
k.setDelegatorBond(tr.sender, bond) k.setDelegatorBond(ctx, existingBond)
k.setCandidate(candidate) k.setCandidate(ctx, candidate)
k.setGlobalState(tr.gs)
return nil return nil
} }
// Perform all the actions required to bond tokens to a delegator bond from their account // Perform all the actions required to bond tokens to a delegator bond from their account
func (k Keeper) BondCoins(ctx sdk.Context, bond DelegatorBond, amount sdk.Coin) sdk.Error { func (k Keeper) BondCoins(ctx sdk.Context, bond DelegatorBond, candidate Candidate, amount sdk.Coin) sdk.Error {
_, err := k.coinKeeper.SubtractCoins(ctx, bond.DelegatorAddr, sdk.Coins{amount}) _, err := k.coinKeeper.SubtractCoins(ctx, bond.DelegatorAddr, sdk.Coins{amount})
if err != nil { if err != nil {
return err return err
} }
newShares := candidate.addTokens(tokens.Amount, tr.gs) newShares := k.candidateAddTokens(ctx, candidate, amount.Amount)
bond.Shares = bond.Shares.Add(newShares) bond.Shares = bond.Shares.Add(newShares)
k.SetDelegatorBond() k.setDelegatorBond(ctx, bond)
return nil
}
// Perform all the actions required to bond tokens to a delegator bond from their account
func (k Keeper) UnbondCoins(ctx sdk.Context, bond *DelegatorBond, candidate *Candidate, shares sdk.Rat) sdk.Error {
// subtract bond tokens from delegator bond
if bond.Shares.LT(shares) {
return sdk.ErrInsufficientFunds("") //XXX variables inside
}
bond.Shares = bond.Shares.Sub(shares)
returnAmount := candidate.removeShares(shares, tr.gs)
returnCoins := sdk.Coins{{tr.params.BondDenom, returnAmount}}
_, err := tr.coinKeeper.AddCoins(ctx, candidate.Address, returnCoins)
if err != nil {
return err
}
return nil return nil
} }
func (k Keeper) handleMsgUnbond(ctx sdk.Context, msg MsgUnbond) sdk.Result { func (k Keeper) handleMsgUnbond(ctx sdk.Context, msg MsgUnbond) sdk.Result {
// check if bond has any shares in it unbond // check if bond has any shares in it unbond
bond := k.getDelegatorBond(sender, msg.Address) bond, found := k.getDelegatorBond(ctx, msg.DelegatorAddr, msg.CandidateAddr)
if bond == nil { if !found {
return ErrNoDelegatorForAddress().Result() return ErrNoDelegatorForAddress().Result()
} }
if !bond.Shares.GT(sdk.ZeroRat) { // bond shares < msg shares if !bond.Shares.GT(sdk.ZeroRat) { // bond shares < msg shares
@ -301,8 +250,8 @@ func (k Keeper) handleMsgUnbond(ctx sdk.Context, msg MsgUnbond) sdk.Result {
bond.Shares = bond.Shares.Sub(shares) bond.Shares = bond.Shares.Sub(shares)
// get pubKey candidate // get pubKey candidate
candidate := k.getCandidate(msg.Address) candidate, found := k.getCandidate(ctx, msg.CandidateAddr)
if candidate == nil { if !found {
return ErrNoCandidateForAddress().Result() return ErrNoCandidateForAddress().Result()
} }
@ -311,41 +260,59 @@ func (k Keeper) handleMsgUnbond(ctx sdk.Context, msg MsgUnbond) sdk.Result {
// 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 bytes.Equal(tr.sender, candidate.Address) && if bytes.Equal(bond.DelegatorAddr, candidate.Address) &&
candidate.Status != Revoked { candidate.Status != Revoked {
revokeCandidacy = true revokeCandidacy = true
} }
// remove the bond // remove the bond
k.removeDelegatorBond(ctx, msg.Address) k.removeDelegatorBond(ctx, bond)
} else { } else {
k.setDelegatorBond(tr.sender, bond) k.setDelegatorBond(ctx, bond)
} }
// Add the coins // Add the coins
returnAmount := candidate.removeShares(shares, tr.gs) returnAmount := k.candidateRemoveShares(ctx, candidate, shares)
returnCoins := sdk.Coins{{tr.params.BondDenom, returnAmount}} returnCoins := sdk.Coins{{k.getParams(ctx).BondDenom, returnAmount}}
tr.coinKeeper.AddCoins(ctx, tr.sender, returnCoins) k.coinKeeper.AddCoins(ctx, bond.DelegatorAddr, returnCoins)
// lastly if an revoke candidate if necessary // lastly if an revoke candidate if necessary
if revokeCandidacy { if revokeCandidacy {
// 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 {
tr.bondedToUnbondedPool(candidate) k.bondedToUnbondedPool(ctx, candidate)
} }
// lastly update the status // lastly update the status
candidate.Status = Revoked candidate.Status = Revoked
} }
// deduct shares from the candidate and save // deduct shares from the candidate
if candidate.Liabilities.IsZero() { if candidate.Liabilities.IsZero() {
k.removeCandidate(msg.Address) k.removeCandidate(ctx, candidate.Address)
} else { } else {
k.setCandidate(candidate) k.setCandidate(ctx, candidate)
} }
k.setGlobalState(tr.gs)
return sdk.Result{} return sdk.Result{}
} }
// XXX where this used
// Perform all the actions required to bond tokens to a delegator bond from their account
func (k Keeper) UnbondCoins(ctx sdk.Context, bond DelegatorBond, candidate Candidate, shares sdk.Rat) sdk.Error {
// subtract bond tokens from delegator bond
if bond.Shares.LT(shares) {
return sdk.ErrInsufficientFunds("") //XXX variables inside
}
bond.Shares = bond.Shares.Sub(shares)
returnAmount := k.candidateRemoveShares(ctx, candidate, shares)
returnCoins := sdk.Coins{{k.getParams(ctx).BondDenom, returnAmount}}
_, err := k.coinKeeper.AddCoins(ctx, candidate.Address, returnCoins)
if err != nil {
return err
}
return nil
}

View File

@ -1,247 +1,248 @@
package stake package stake
import ( //import (
"strconv" //"strconv"
"testing" //"testing"
"github.com/stretchr/testify/assert" //"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" //"github.com/stretchr/testify/require"
crypto "github.com/tendermint/go-crypto" //crypto "github.com/tendermint/go-crypto"
sdk "github.com/cosmos/cosmos-sdk/types" //sdk "github.com/cosmos/cosmos-sdk/types"
) //)
//______________________________________________________________________ ////______________________________________________________________________
func newTestMsgDeclareCandidacy(address sdk.Address, pubKey crypto.PubKey, amt int64) MsgDeclareCandidacy { //func newTestMsgDeclareCandidacy(address sdk.Address, pubKey crypto.PubKey, amt int64) MsgDeclareCandidacy {
return MsgDeclareCandidacy{ //return MsgDeclareCandidacy{
MsgAddr: NewMsgAddr(address), //Description: Description{},
Description: Description{}, //CandidateAddr: address,
Bond: sdk.Coin{"fermion", amt}, //Bond: sdk.Coin{"fermion", amt},
PubKey: pubKey, //PubKey: pubKey,
} //}
} //}
func newTestMsgDelegate(amt int64, address sdk.Address) MsgDelegate { //func newTestMsgDelegate(amt int64, delegatorAddr, candidateAddr sdk.Address) MsgDelegate {
return MsgDelegate{ //return MsgDelegate{
MsgAddr: NewMsgAddr(address), //DelegatorAddr: delegatorAddr,
Bond: sdk.Coin{"fermion", amt}, //CandidateAddr: candidateAddr,
} //Bond: sdk.Coin{"fermion", amt},
} //}
//}
func TestDuplicatesMsgDeclareCandidacy(t *testing.T) { //func TestDuplicatesMsgDeclareCandidacy(t *testing.T) {
_, _, _, deliverer := createTestInput(t, addrs[0], false, 1000) //ctxDeliver, _, keeper := createTestInput(t, addrs[0], false, 1000)
_, _, _, checker := createTestInput(t, addrs[0], true, 1000) //ctxCheck, _, keeper := createTestInput(t, addrs[0], true, 1000)
msgDeclareCandidacy := newTestMsgDeclareCandidacy(addrs[0], pks[0], 10) //msgDeclareCandidacy := newTestMsgDeclareCandidacy(addrs[0], pks[0], 10)
got := deliverer.declareCandidacy(msgDeclareCandidacy) //got := deliverer.declareCandidacy(msgDeclareCandidacy)
assert.NoError(t, got, "expected no error on runMsgDeclareCandidacy") //assert.NoError(t, got, "expected no error on runMsgDeclareCandidacy")
// one sender can bond to two different addresses //// one sender can bond to two different addresses
msgDeclareCandidacy.Address = addrs[1] //msgDeclareCandidacy.Address = addrs[1]
err := checker.declareCandidacy(msgDeclareCandidacy) //err := checker.declareCandidacy(msgDeclareCandidacy)
assert.Nil(t, err, "didn't expected error on checkTx") //assert.Nil(t, err, "didn't expected error on checkTx")
// two addrs cant bond to the same pubkey //// two addrs cant bond to the same pubkey
checker.sender = addrs[1] //checker.sender = addrs[1]
msgDeclareCandidacy.Address = addrs[0] //msgDeclareCandidacy.Address = addrs[0]
err = checker.declareCandidacy(msgDeclareCandidacy) //err = checker.declareCandidacy(msgDeclareCandidacy)
assert.NotNil(t, err, "expected error on checkTx") //assert.NotNil(t, err, "expected error on checkTx")
} //}
func TestIncrementsMsgDelegate(t *testing.T) { //func TestIncrementsMsgDelegate(t *testing.T) {
_, _, mapper, deliverer := createTestInput(t, addrs[0], false, 1000) //_, _, mapper, deliverer := createTestInput(t, addrs[0], false, 1000)
// first declare candidacy //// first declare candidacy
bondAmount := int64(10) //bondAmount := int64(10)
msgDeclareCandidacy := newTestMsgDeclareCandidacy(addrs[0], pks[0], bondAmount) //msgDeclareCandidacy := newTestMsgDeclareCandidacy(addrs[0], pks[0], bondAmount)
got := deliverer.declareCandidacy(msgDeclareCandidacy) //got := deliverer.declareCandidacy(msgDeclareCandidacy)
assert.NoError(t, got, "expected declare candidacy msg to be ok, got %v", got) //assert.NoError(t, got, "expected declare candidacy msg to be ok, got %v", got)
expectedBond := bondAmount // 1 since we send 1 at the start of loop, //expectedBond := bondAmount // 1 since we send 1 at the start of loop,
// just send the same msgbond multiple times //// just send the same msgbond multiple times
msgDelegate := newTestMsgDelegate(bondAmount, addrs[0]) //msgDelegate := newTestMsgDelegate(bondAmount, addrs[0])
for i := 0; i < 5; i++ { //for i := 0; i < 5; i++ {
got := deliverer.delegate(msgDelegate) //got := deliverer.delegate(msgDelegate)
assert.NoError(t, got, "expected msg %d to be ok, got %v", i, got) //assert.NoError(t, got, "expected msg %d to be ok, got %v", i, got)
//Check that the accounts and the bond account have the appropriate values ////Check that the accounts and the bond account have the appropriate values
candidates := mapper.getCandidates() //candidates := mapper.getCandidates()
expectedBond += bondAmount //expectedBond += bondAmount
//expectedSender := initSender - expectedBond ////expectedSender := initSender - expectedBond
gotBonded := candidates[0].Liabilities.Evaluate() //gotBonded := candidates[0].Liabilities.Evaluate()
//gotSender := accStore[string(deliverer.sender)] //XXX use StoreMapper ////gotSender := accStore[string(deliverer.sender)] //XXX use StoreMapper
assert.Equal(t, expectedBond, gotBonded, "i: %v, %v, %v", i, expectedBond, gotBonded) //assert.Equal(t, expectedBond, gotBonded, "i: %v, %v, %v", i, expectedBond, gotBonded)
//assert.Equal(t, expectedSender, gotSender, "i: %v, %v, %v", i, expectedSender, gotSender) // XXX fix ////assert.Equal(t, expectedSender, gotSender, "i: %v, %v, %v", i, expectedSender, gotSender) // XXX fix
} //}
} //}
func TestIncrementsMsgUnbond(t *testing.T) { //func TestIncrementsMsgUnbond(t *testing.T) {
_, _, mapper, deliverer := createTestInput(t, addrs[0], false, 0) //_, _, mapper, deliverer := createTestInput(t, addrs[0], false, 0)
// set initial bond //// set initial bond
initBond := int64(1000) //initBond := int64(1000)
//accStore[string(deliverer.sender)] = initBond //XXX use StoreMapper ////accStore[string(deliverer.sender)] = initBond //XXX use StoreMapper
got := deliverer.declareCandidacy(newTestMsgDeclareCandidacy(addrs[0], pks[0], initBond)) //got := deliverer.declareCandidacy(newTestMsgDeclareCandidacy(addrs[0], pks[0], initBond))
assert.NoError(t, got, "expected initial bond msg to be ok, got %v", got) //assert.NoError(t, got, "expected initial bond msg to be ok, got %v", got)
// just send the same msgunbond multiple times //// just send the same msgunbond multiple times
// XXX use decimals here //// XXX use decimals here
unbondShares, unbondSharesStr := int64(10), "10" //unbondShares, unbondSharesStr := int64(10), "10"
msgUndelegate := NewMsgUnbond(addrs[0], unbondSharesStr) //msgUndelegate := NewMsgUnbond(addrs[0], unbondSharesStr)
nUnbonds := 5 //nUnbonds := 5
for i := 0; i < nUnbonds; i++ { //for i := 0; i < nUnbonds; i++ {
got := deliverer.unbond(msgUndelegate) //got := deliverer.unbond(msgUndelegate)
assert.NoError(t, got, "expected msg %d to be ok, got %v", i, got) //assert.NoError(t, got, "expected msg %d to be ok, got %v", i, got)
//Check that the accounts and the bond account have the appropriate values ////Check that the accounts and the bond account have the appropriate values
candidates := mapper.getCandidates() //candidates := mapper.getCandidates()
expectedBond := initBond - int64(i+1)*unbondShares // +1 since we send 1 at the start of loop //expectedBond := initBond - int64(i+1)*unbondShares // +1 since we send 1 at the start of loop
//expectedSender := initSender + (initBond - expectedBond) ////expectedSender := initSender + (initBond - expectedBond)
gotBonded := candidates[0].Liabilities.Evaluate() //gotBonded := candidates[0].Liabilities.Evaluate()
//gotSender := accStore[string(deliverer.sender)] // XXX use storemapper ////gotSender := accStore[string(deliverer.sender)] // XXX use storemapper
assert.Equal(t, expectedBond, gotBonded, "%v, %v", expectedBond, gotBonded) //assert.Equal(t, expectedBond, gotBonded, "%v, %v", expectedBond, gotBonded)
//assert.Equal(t, expectedSender, gotSender, "%v, %v", expectedSender, gotSender) //XXX fix ////assert.Equal(t, expectedSender, gotSender, "%v, %v", expectedSender, gotSender) //XXX fix
} //}
// these are more than we have bonded now //// these are more than we have bonded now
errorCases := []int64{ //errorCases := []int64{
//1<<64 - 1, // more than int64 ////1<<64 - 1, // more than int64
//1<<63 + 1, // more than int64 ////1<<63 + 1, // more than int64
1<<63 - 1, //1<<63 - 1,
1 << 31, //1 << 31,
initBond, //initBond,
} //}
for _, c := range errorCases { //for _, c := range errorCases {
unbondShares := strconv.Itoa(int(c)) //unbondShares := strconv.Itoa(int(c))
msgUndelegate := NewMsgUnbond(addrs[0], unbondShares) //msgUndelegate := NewMsgUnbond(addrs[0], unbondShares)
got = deliverer.unbond(msgUndelegate) //got = deliverer.unbond(msgUndelegate)
assert.Error(t, got, "expected unbond msg to fail") //assert.Error(t, got, "expected unbond msg to fail")
} //}
leftBonded := initBond - unbondShares*int64(nUnbonds) //leftBonded := initBond - unbondShares*int64(nUnbonds)
// should be unable to unbond one more than we have //// should be unable to unbond one more than we have
msgUndelegate = NewMsgUnbond(addrs[0], strconv.Itoa(int(leftBonded)+1)) //msgUndelegate = NewMsgUnbond(addrs[0], strconv.Itoa(int(leftBonded)+1))
got = deliverer.unbond(msgUndelegate) //got = deliverer.unbond(msgUndelegate)
assert.Error(t, got, "expected unbond msg to fail") //assert.Error(t, got, "expected unbond msg to fail")
// should be able to unbond just what we have //// should be able to unbond just what we have
msgUndelegate = NewMsgUnbond(addrs[0], strconv.Itoa(int(leftBonded))) //msgUndelegate = NewMsgUnbond(addrs[0], strconv.Itoa(int(leftBonded)))
got = deliverer.unbond(msgUndelegate) //got = deliverer.unbond(msgUndelegate)
assert.NoError(t, got, "expected unbond msg to pass") //assert.NoError(t, got, "expected unbond msg to pass")
} //}
func TestMultipleMsgDeclareCandidacy(t *testing.T) { //func TestMultipleMsgDeclareCandidacy(t *testing.T) {
initSender := int64(1000) //initSender := int64(1000)
ctx, accStore, mapper, deliverer := createTestInput(t, addrs[0], false, initSender) //ctx, accStore, mapper, deliverer := createTestInput(t, addrs[0], false, initSender)
addrs := []sdk.Address{addrs[0], addrs[1], addrs[2]} //addrs := []sdk.Address{addrs[0], addrs[1], addrs[2]}
// bond them all //// bond them all
for i, addr := range addrs { //for i, addr := range addrs {
msgDeclareCandidacy := newTestMsgDeclareCandidacy(addrs[i], pks[i], 10) //msgDeclareCandidacy := newTestMsgDeclareCandidacy(addrs[i], pks[i], 10)
deliverer.sender = addr //deliverer.sender = addr
got := deliverer.declareCandidacy(msgDeclareCandidacy) //got := deliverer.declareCandidacy(msgDeclareCandidacy)
assert.NoError(t, got, "expected msg %d to be ok, got %v", i, got) //assert.NoError(t, got, "expected msg %d to be ok, got %v", i, got)
//Check that the account is bonded ////Check that the account is bonded
candidates := mapper.getCandidates() //candidates := mapper.getCandidates()
require.Equal(t, i, len(candidates)) //require.Equal(t, i, len(candidates))
val := candidates[i] //val := candidates[i]
balanceExpd := initSender - 10 //balanceExpd := initSender - 10
balanceGot := accStore.GetAccount(ctx, val.Address).GetCoins() //balanceGot := accStore.GetAccount(ctx, val.Address).GetCoins()
assert.Equal(t, i+1, len(candidates), "expected %d candidates got %d, candidates: %v", i+1, len(candidates), candidates) //assert.Equal(t, i+1, len(candidates), "expected %d candidates got %d, candidates: %v", i+1, len(candidates), candidates)
assert.Equal(t, 10, int(val.Liabilities.Evaluate()), "expected %d shares, got %d", 10, val.Liabilities) //assert.Equal(t, 10, int(val.Liabilities.Evaluate()), "expected %d shares, got %d", 10, val.Liabilities)
assert.Equal(t, balanceExpd, balanceGot, "expected account to have %d, got %d", balanceExpd, balanceGot) //assert.Equal(t, balanceExpd, balanceGot, "expected account to have %d, got %d", balanceExpd, balanceGot)
} //}
// unbond them all //// unbond them all
for i, addr := range addrs { //for i, addr := range addrs {
candidatePre := mapper.getCandidate(addrs[i]) //candidatePre := mapper.getCandidate(addrs[i])
msgUndelegate := NewMsgUnbond(addrs[i], "10") //msgUndelegate := NewMsgUnbond(addrs[i], "10")
deliverer.sender = addr //deliverer.sender = addr
got := deliverer.unbond(msgUndelegate) //got := deliverer.unbond(msgUndelegate)
assert.NoError(t, got, "expected msg %d to be ok, got %v", i, got) //assert.NoError(t, got, "expected msg %d to be ok, got %v", i, got)
//Check that the account is unbonded ////Check that the account is unbonded
candidates := mapper.getCandidates() //candidates := mapper.getCandidates()
assert.Equal(t, len(addrs)-(i+1), len(candidates), "expected %d candidates got %d", len(addrs)-(i+1), len(candidates)) //assert.Equal(t, len(addrs)-(i+1), len(candidates), "expected %d candidates got %d", len(addrs)-(i+1), len(candidates))
candidatePost := mapper.getCandidate(addrs[i]) //candidatePost := mapper.getCandidate(addrs[i])
balanceExpd := initSender //balanceExpd := initSender
balanceGot := accStore.GetAccount(ctx, candidatePre.Address).GetCoins() //balanceGot := accStore.GetAccount(ctx, candidatePre.Address).GetCoins()
assert.Nil(t, candidatePost, "expected nil candidate retrieve, got %d", 0, candidatePost) //assert.Nil(t, candidatePost, "expected nil candidate retrieve, got %d", 0, candidatePost)
assert.Equal(t, balanceExpd, balanceGot, "expected account to have %d, got %d", balanceExpd, balanceGot) //assert.Equal(t, balanceExpd, balanceGot, "expected account to have %d, got %d", balanceExpd, balanceGot)
} //}
} //}
func TestMultipleMsgDelegate(t *testing.T) { //func TestMultipleMsgDelegate(t *testing.T) {
sender, delegators := addrs[0], addrs[1:] //sender, delegators := addrs[0], addrs[1:]
_, _, mapper, deliverer := createTestInput(t, addrs[0], false, 1000) //_, _, mapper, deliverer := createTestInput(t, addrs[0], false, 1000)
//first make a candidate ////first make a candidate
msgDeclareCandidacy := newTestMsgDeclareCandidacy(sender, pks[0], 10) //msgDeclareCandidacy := newTestMsgDeclareCandidacy(sender, pks[0], 10)
got := deliverer.declareCandidacy(msgDeclareCandidacy) //got := deliverer.declareCandidacy(msgDeclareCandidacy)
require.NoError(t, got, "expected msg to be ok, got %v", got) //require.NoError(t, got, "expected msg to be ok, got %v", got)
// delegate multiple parties //// delegate multiple parties
for i, delegator := range delegators { //for i, delegator := range delegators {
msgDelegate := newTestMsgDelegate(10, sender) //msgDelegate := newTestMsgDelegate(10, sender)
deliverer.sender = delegator //deliverer.sender = delegator
got := deliverer.delegate(msgDelegate) //got := deliverer.delegate(msgDelegate)
require.NoError(t, got, "expected msg %d to be ok, got %v", i, got) //require.NoError(t, got, "expected msg %d to be ok, got %v", i, got)
//Check that the account is bonded ////Check that the account is bonded
bond := mapper.getDelegatorBond(delegator, sender) //bond := mapper.getDelegatorBond(delegator, sender)
assert.NotNil(t, bond, "expected delegatee bond %d to exist", bond) //assert.NotNil(t, bond, "expected delegatee bond %d to exist", bond)
} //}
// unbond them all //// unbond them all
for i, delegator := range delegators { //for i, delegator := range delegators {
msgUndelegate := NewMsgUnbond(sender, "10") //msgUndelegate := NewMsgUnbond(sender, "10")
deliverer.sender = delegator //deliverer.sender = delegator
got := deliverer.unbond(msgUndelegate) //got := deliverer.unbond(msgUndelegate)
require.NoError(t, got, "expected msg %d to be ok, got %v", i, got) //require.NoError(t, got, "expected msg %d to be ok, got %v", i, got)
//Check that the account is unbonded ////Check that the account is unbonded
bond := mapper.getDelegatorBond(delegator, sender) //bond := mapper.getDelegatorBond(delegator, sender)
assert.Nil(t, bond, "expected delegatee bond %d to be nil", bond) //assert.Nil(t, bond, "expected delegatee bond %d to be nil", bond)
} //}
} //}
func TestVoidCandidacy(t *testing.T) { //func TestVoidCandidacy(t *testing.T) {
sender, delegator := addrs[0], addrs[1] //sender, delegator := addrs[0], addrs[1]
_, _, _, deliverer := createTestInput(t, addrs[0], false, 1000) //_, _, _, deliverer := createTestInput(t, addrs[0], false, 1000)
// create the candidate //// create the candidate
msgDeclareCandidacy := newTestMsgDeclareCandidacy(addrs[0], pks[0], 10) //msgDeclareCandidacy := newTestMsgDeclareCandidacy(addrs[0], pks[0], 10)
got := deliverer.declareCandidacy(msgDeclareCandidacy) //got := deliverer.declareCandidacy(msgDeclareCandidacy)
require.NoError(t, got, "expected no error on runMsgDeclareCandidacy") //require.NoError(t, got, "expected no error on runMsgDeclareCandidacy")
// bond a delegator //// bond a delegator
msgDelegate := newTestMsgDelegate(10, addrs[0]) //msgDelegate := newTestMsgDelegate(10, addrs[0])
deliverer.sender = delegator //deliverer.sender = delegator
got = deliverer.delegate(msgDelegate) //got = deliverer.delegate(msgDelegate)
require.NoError(t, got, "expected ok, got %v", got) //require.NoError(t, got, "expected ok, got %v", got)
// unbond the candidates bond portion //// unbond the candidates bond portion
msgUndelegate := NewMsgUnbond(addrs[0], "10") //msgUndelegate := NewMsgUnbond(addrs[0], "10")
deliverer.sender = sender //deliverer.sender = sender
got = deliverer.unbond(msgUndelegate) //got = deliverer.unbond(msgUndelegate)
require.NoError(t, got, "expected no error on runMsgDeclareCandidacy") //require.NoError(t, got, "expected no error on runMsgDeclareCandidacy")
// test that this pubkey cannot yet be bonded too //// test that this pubkey cannot yet be bonded too
deliverer.sender = delegator //deliverer.sender = delegator
got = deliverer.delegate(msgDelegate) //got = deliverer.delegate(msgDelegate)
assert.Error(t, got, "expected error, got %v", got) //assert.Error(t, got, "expected error, got %v", got)
// test that the delegator can still withdraw their bonds //// test that the delegator can still withdraw their bonds
got = deliverer.unbond(msgUndelegate) //got = deliverer.unbond(msgUndelegate)
require.NoError(t, got, "expected no error on runMsgDeclareCandidacy") //require.NoError(t, got, "expected no error on runMsgDeclareCandidacy")
// verify that the pubkey can now be reused //// verify that the pubkey can now be reused
got = deliverer.declareCandidacy(msgDeclareCandidacy) //got = deliverer.declareCandidacy(msgDeclareCandidacy)
assert.NoError(t, got, "expected ok, got %v", got) //assert.NoError(t, got, "expected ok, got %v", got)
} //}

View File

@ -84,39 +84,39 @@ func NewKeeper(ctx sdk.Context, cdc *wire.Codec, key sdk.StoreKey, ck bank.CoinK
} }
//XXX load/save -> get/set //XXX load/save -> get/set
func (m Keeper) getCandidate(ctx sdk.Context, addr sdk.Address) (candidate Candidate) { func (k Keeper) getCandidate(ctx sdk.Context, addr sdk.Address) (candidate Candidate, found bool) {
store := ctx.KVStore(storeKey) store := ctx.KVStore(k.storeKey)
b := store.Get(GetCandidateKey(addr)) b := store.Get(GetCandidateKey(addr))
if b == nil { if b == nil {
return nil return candidate, false
} }
err := m.cdc.UnmarshalJSON(b, &candidate) err := k.cdc.UnmarshalJSON(b, &candidate)
if err != nil { if err != nil {
panic(err) // This error should never occur big problem if does panic(err)
} }
return return candidate, true
} }
func (m Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) {
store := ctx.KVStore(storeKey) store := ctx.KVStore(k.storeKey)
// XXX should only remove validator if we know candidate is a validator // XXX should only remove validator if we know candidate is a validator
m.removeValidator(candidate.Address) k.removeValidator(ctx, candidate.Address)
validator := &Validator{candidate.Address, candidate.VotingPower} validator := Validator{candidate.Address, candidate.VotingPower}
m.updateValidator(validator) k.updateValidator(ctx, validator)
b, err := m.cdc.MarshalJSON(candidate) b, err := k.cdc.MarshalJSON(candidate)
if err != nil { if err != nil {
panic(err) panic(err)
} }
store.Set(GetCandidateKey(candidate.Address), b) store.Set(GetCandidateKey(candidate.Address), b)
} }
func (m Keeper) removeCandidate(ctx sdk.Context, candidateAddr sdk.Address) { func (k Keeper) removeCandidate(ctx sdk.Context, candidateAddr sdk.Address) {
store := ctx.KVStore(storeKey) store := ctx.KVStore(k.storeKey)
// XXX should only remove validator if we know candidate is a validator // XXX should only remove validator if we know candidate is a validator
m.removeValidator(candidateAddr) k.removeValidator(ctx, candidateAddr)
store.Delete(GetCandidateKey(candidateAddr)) store.Delete(GetCandidateKey(candidateAddr))
} }
@ -137,10 +137,10 @@ func (m Keeper) removeCandidate(ctx sdk.Context, candidateAddr sdk.Address) {
// 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 (m Keeper) updateValidator(ctx sdk.Context, validator Validator) { func (k Keeper) updateValidator(ctx sdk.Context, validator Validator) {
store := ctx.KVStore(storeKey) store := ctx.KVStore(k.storeKey)
b, err := m.cdc.MarshalJSON(validator) b, err := k.cdc.MarshalJSON(validator)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -149,31 +149,31 @@ func (m Keeper) updateValidator(ctx sdk.Context, validator Validator) {
store.Set(GetValidatorUpdatesKey(validator.Address), b) store.Set(GetValidatorUpdatesKey(validator.Address), b)
// update the list ordered by voting power // update the list ordered by voting power
store.Set(GetValidatorKey(validator.Address, validator.VotingPower, m.cdc), b) store.Set(GetValidatorKey(validator.Address, validator.VotingPower, k.cdc), b)
} }
func (m Keeper) removeValidator(ctx sdk.Context, address sdk.Address) { func (k Keeper) removeValidator(ctx sdk.Context, address sdk.Address) {
store := ctx.KVStore(storeKey) store := ctx.KVStore(k.storeKey)
//add validator with zero power to the validator updates //add validator with zero power to the validator updates
b, err := m.cdc.MarshalJSON(Validator{address, sdk.ZeroRat}) b, err := k.cdc.MarshalJSON(Validator{address, sdk.ZeroRat})
if err != nil { if err != nil {
panic(err) panic(err)
} }
store.Set(GetValidatorUpdatesKey(address), b) store.Set(GetValidatorUpdatesKey(address), b)
// now actually delete from the validator set // now actually delete from the validator set
candidate := m.getCandidate(address) candidate, found := k.getCandidate(ctx, address)
if candidate != nil { if found {
store.Delete(GetValidatorKey(address, candidate.VotingPower, m.cdc)) store.Delete(GetValidatorKey(address, candidate.VotingPower, k.cdc))
} }
} }
// 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 (m Keeper) getValidators(ctx sdk.Context, maxVal uint16) (validators []Validator) { func (k Keeper) getValidators(ctx sdk.Context, maxVal uint16) (validators []Validator) {
store := ctx.KVStore(storeKey) store := ctx.KVStore(k.storeKey)
iterator := store.Iterator(subspace(ValidatorKeyPrefix)) //smallest to largest iterator := store.Iterator(subspace(ValidatorKeyPrefix)) //smallest to largest
@ -185,7 +185,7 @@ func (m Keeper) getValidators(ctx sdk.Context, maxVal uint16) (validators []Vali
} }
valBytes := iterator.Value() valBytes := iterator.Value()
var val Validator var val Validator
err := m.cdc.UnmarshalJSON(valBytes, &val) err := k.cdc.UnmarshalJSON(valBytes, &val)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -199,15 +199,15 @@ func (m Keeper) getValidators(ctx sdk.Context, maxVal uint16) (validators []Vali
//_________________________________________________________________________ //_________________________________________________________________________
// get the most updated validators // get the most updated validators
func (m Keeper) getValidatorUpdates(ctx sdk.Context) (updates []Validator) { func (k Keeper) getValidatorUpdates(ctx sdk.Context) (updates []Validator) {
store := ctx.KVStore(storeKey) store := ctx.KVStore(k.storeKey)
iterator := store.Iterator(subspace(ValidatorUpdatesKeyPrefix)) //smallest to largest iterator := store.Iterator(subspace(ValidatorUpdatesKeyPrefix)) //smallest to largest
for ; iterator.Valid(); iterator.Next() { for ; iterator.Valid(); iterator.Next() {
valBytes := iterator.Value() valBytes := iterator.Value()
var val Validator var val Validator
err := m.cdc.UnmarshalJSON(valBytes, &val) err := k.cdc.UnmarshalJSON(valBytes, &val)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -219,8 +219,8 @@ func (m Keeper) getValidatorUpdates(ctx sdk.Context) (updates []Validator) {
} }
// remove all validator update entries // remove all validator update entries
func (m Keeper) clearValidatorUpdates(ctx sdk.Context, maxVal int) { func (k Keeper) clearValidatorUpdates(ctx sdk.Context, maxVal int) {
store := ctx.KVStore(storeKey) store := ctx.KVStore(k.storeKey)
iterator := store.Iterator(subspace(ValidatorUpdatesKeyPrefix)) iterator := 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 store.Delete(iterator.Key()) // XXX write test for this, may need to be in a second loop
@ -230,22 +230,19 @@ func (m Keeper) clearValidatorUpdates(ctx sdk.Context, maxVal int) {
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// getCandidates - get the active list of all candidates TODO replace with multistore // getCandidates - get the active list of all candidates
func (m Keeper) getCandidates(ctx sdk.Context) (candidates Candidates) { func (k Keeper) getCandidates(ctx sdk.Context) (candidates Candidates) {
store := ctx.KVStore(storeKey) store := ctx.KVStore(k.storeKey)
iterator := store.Iterator(subspace(CandidateKeyPrefix)) iterator := store.Iterator(subspace(CandidateKeyPrefix))
//iterator := store.Iterator(CandidateKeyPrefix, []byte(nil))
//iterator := store.Iterator([]byte{}, []byte(nil))
for ; iterator.Valid(); iterator.Next() { for ; iterator.Valid(); iterator.Next() {
candidateBytes := iterator.Value() candidateBytes := iterator.Value()
var candidate Candidate var candidate Candidate
err := m.cdc.UnmarshalJSON(candidateBytes, &candidate) err := k.cdc.UnmarshalJSON(candidateBytes, &candidate)
if err != nil { if err != nil {
panic(err) panic(err)
} }
candidates = append(candidates, &candidate) candidates = append(candidates, candidate)
} }
iterator.Close() iterator.Close()
return candidates return candidates
@ -253,17 +250,17 @@ func (m Keeper) getCandidates(ctx sdk.Context) (candidates Candidates) {
//_____________________________________________________________________ //_____________________________________________________________________
// XXX use a store iterator to get // XXX use a store iterator here instead
//// load the pubkeys of all candidates a delegator is delegated too //// load the pubkeys of all candidates a delegator is delegated too
//func (m Keeper) getDelegatorCandidates(ctx sdk.Context, delegator sdk.Address) (candidateAddrs []sdk.Address) { //func (k Keeper) getDelegatorCandidates(ctx sdk.Context, delegator sdk.Address) (candidateAddrs []sdk.Address) {
//store := ctx.KVStore(storeKey) //store := ctx.KVStore(k.storeKey)
//candidateBytes := store.Get(GetDelegatorBondsKey(delegator, m.cdc)) //candidateBytes := store.Get(GetDelegatorBondsKey(delegator, k.cdc))
//if candidateBytes == nil { //if candidateBytes == nil {
//return nil //return nil
//} //}
//err := m.cdc.UnmarshalJSON(candidateBytes, &candidateAddrs) //err := k.cdc.UnmarshalJSON(candidateBytes, &candidateAddrs)
//if err != nil { //if err != nil {
//panic(err) //panic(err)
//} //}
@ -272,126 +269,229 @@ func (m Keeper) getCandidates(ctx sdk.Context) (candidates Candidates) {
//_____________________________________________________________________ //_____________________________________________________________________
func (m Keeper) getDelegatorBond(ctx sdk.Context, func (k Keeper) getDelegatorBond(ctx sdk.Context,
delegator, candidate sdk.Address) (bond DelegatorBond) { delegatorAddr, candidateAddr sdk.Address) (bond DelegatorBond, found bool) {
store := ctx.KVStore(storeKey) store := ctx.KVStore(k.storeKey)
delegatorBytes := store.Get(GetDelegatorBondKey(delegator, candidate, m.cdc)) delegatorBytes := store.Get(GetDelegatorBondKey(delegatorAddr, candidateAddr, k.cdc))
if delegatorBytes == nil { if delegatorBytes == nil {
return nil return bond, false
} }
err := m.cdc.UnmarshalJSON(delegatorBytes, &bond) err := k.cdc.UnmarshalJSON(delegatorBytes, &bond)
if err != nil { if err != nil {
panic(err) panic(err)
} }
return bond return bond, true
} }
func (m Keeper) setDelegatorBond(ctx sdk.Context, bond DelegatorBond) { func (k Keeper) setDelegatorBond(ctx sdk.Context, bond DelegatorBond) {
store := ctx.KVStore(storeKey) store := ctx.KVStore(k.storeKey)
// XXX use store iterator // XXX use store iterator
// if a new bond add to the list of bonds // if a new bond add to the list of bonds
//if m.getDelegatorBond(delegator, bond.Address) == nil { //if k.getDelegatorBond(delegator, bond.Address) == nil {
//pks := m.getDelegatorCandidates(delegator) //pks := k.getDelegatorCandidates(delegator)
//pks = append(pks, bond.Address) //pks = append(pks, bond.Address)
//b, err := m.cdc.MarshalJSON(pks) //b, err := k.cdc.MarshalJSON(pks)
//if err != nil { //if err != nil {
//panic(err) //panic(err)
//} //}
//store.Set(GetDelegatorBondsKey(delegator, m.cdc), b) //store.Set(GetDelegatorBondsKey(delegator, k.cdc), b)
//} //}
// now actually save the bond // now actually save the bond
b, err := m.cdc.MarshalJSON(bond) b, err := k.cdc.MarshalJSON(bond)
if err != nil { if err != nil {
panic(err) panic(err)
} }
store.Set(GetDelegatorBondKey(delegator, bond.Address, m.cdc), b) store.Set(GetDelegatorBondKey(bond.DelegatorAddr, bond.CandidateAddr, k.cdc), b)
} }
func (m Keeper) removeDelegatorBond(ctx sdk.Context, bond DelegatorBond) { func (k Keeper) removeDelegatorBond(ctx sdk.Context, bond DelegatorBond) {
store := ctx.KVStore(storeKey) store := ctx.KVStore(k.storeKey)
// XXX use store iterator // XXX use store iterator
// 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
//addrs := m.getDelegatorCandidates(delegator) //addrs := k.getDelegatorCandidates(delegator)
//for i, addr := range addrs { //for i, addr := range addrs {
//if bytes.Equal(candidateAddr, addr) { //if bytes.Equal(candidateAddr, addr) {
//addrs = append(addrs[:i], addrs[i+1:]...) //addrs = append(addrs[:i], addrs[i+1:]...)
//} //}
//} //}
//b, err := m.cdc.MarshalJSON(addrs) //b, err := k.cdc.MarshalJSON(addrs)
//if err != nil { //if err != nil {
//panic(err) //panic(err)
//} //}
//store.Set(GetDelegatorBondsKey(delegator, m.cdc), b) //store.Set(GetDelegatorBondsKey(delegator, k.cdc), b)
// now remove the actual bond // now remove the actual bond
store.Delete(GetDelegatorBondKey(bond.delegatorAddr, bond.candidateAddr, m.cdc)) store.Delete(GetDelegatorBondKey(bond.DelegatorAddr, bond.CandidateAddr, k.cdc))
//updateDelegatorBonds(store, delegator) //XXX remove? //updateDelegatorBonds(store, delegator) //XXX remove?
} }
//_______________________________________________________________________ //_______________________________________________________________________
// load/save the global staking params // load/save the global staking params
func (m Keeper) getParams(ctx sdk.Context) (params Params) { func (k Keeper) getParams(ctx sdk.Context) (params Params) {
// check if cached before anything // check if cached before anything
if m.params != (Params{}) { if k.params != (Params{}) {
return m.params return k.params
} }
store := ctx.KVStore(storeKey) store := ctx.KVStore(k.storeKey)
b := store.Get(ParamKey) b := store.Get(ParamKey)
if b == nil { if b == nil {
return defaultParams() return defaultParams()
} }
err := m.cdc.UnmarshalJSON(b, &params) err := k.cdc.UnmarshalJSON(b, &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 (m Keeper) setParams(ctx sdk.Context, params Params) { func (k Keeper) setParams(ctx sdk.Context, params Params) {
store := ctx.KVStore(storeKey) store := ctx.KVStore(k.storeKey)
b, err := m.cdc.MarshalJSON(params) b, err := k.cdc.MarshalJSON(params)
if err != nil { if err != nil {
panic(err) panic(err)
} }
store.Set(ParamKey, b) store.Set(ParamKey, b)
m.params = Params{} // clear the cache k.params = Params{} // clear the cache
} }
//_______________________________________________________________________ //_______________________________________________________________________
// XXX nothing is this Keeper should return a pointer...!!!!!! // XXX nothing is this Keeper should return a pointer...!!!!!!
// load/save the global staking state // load/save the global staking state
func (m Keeper) getGlobalState(ctx sdk.Context) (gs GlobalState) { func (k Keeper) getGlobalState(ctx sdk.Context) (gs GlobalState) {
// check if cached before anything // check if cached before anything
if m.gs != nil { if k.gs != (GlobalState{}) {
return m.gs return k.gs
} }
store := ctx.KVStore(storeKey) store := ctx.KVStore(k.storeKey)
b := store.Get(GlobalStateKey) b := store.Get(GlobalStateKey)
if b == nil { if b == nil {
return initialGlobalState() return initialGlobalState()
} }
gs = new(GlobalState) err := k.cdc.UnmarshalJSON(b, &gs)
err := m.cdc.UnmarshalJSON(b, &gs)
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 (m Keeper) setGlobalState(ctx sdk.Context, gs GlobalState) { func (k Keeper) setGlobalState(ctx sdk.Context, gs GlobalState) {
store := ctx.KVStore(storeKey) store := ctx.KVStore(k.storeKey)
b, err := m.cdc.MarshalJSON(gs) b, err := k.cdc.MarshalJSON(gs)
if err != nil { if err != nil {
panic(err) panic(err)
} }
store.Set(GlobalStateKey, b) store.Set(GlobalStateKey, b)
m.gs = GlobalState{} // clear the cache k.gs = GlobalState{} // clear the cache
}
//_______________________________________________________________________
//TODO make these next two functions more efficient should be reading and writting to state ye know
// move a candidates asset pool from bonded to unbonded pool
func (k Keeper) bondedToUnbondedPool(ctx sdk.Context, candidate Candidate) {
// replace bonded shares with unbonded shares
tokens := k.removeSharesBonded(ctx, candidate.Assets)
candidate.Assets = k.addTokensUnbonded(ctx, tokens)
candidate.Status = Unbonded
k.setCandidate(ctx, candidate)
}
// move a candidates asset pool from unbonded to bonded pool
func (k Keeper) unbondedToBondedPool(ctx sdk.Context, candidate Candidate) {
// replace unbonded shares with bonded shares
tokens := k.removeSharesUnbonded(ctx, candidate.Assets)
candidate.Assets = k.addTokensBonded(ctx, tokens)
candidate.Status = Bonded
k.setCandidate(ctx, candidate)
}
// XXX expand to include the function of actually transfering the tokens
//XXX CONFIRM that use of the exRate is correct with Zarko Spec!
func (k Keeper) addTokensBonded(ctx sdk.Context, amount int64) (issuedShares sdk.Rat) {
gs := k.getGlobalState(ctx)
issuedShares = gs.bondedShareExRate().Inv().Mul(sdk.NewRat(amount)) // (tokens/shares)^-1 * tokens
gs.BondedPool += amount
gs.BondedShares = gs.BondedShares.Add(issuedShares)
k.setGlobalState(ctx, gs)
return
}
//XXX CONFIRM that use of the exRate is correct with Zarko Spec!
func (k Keeper) removeSharesBonded(ctx sdk.Context, shares sdk.Rat) (removedTokens int64) {
gs := k.getGlobalState(ctx)
removedTokens = gs.bondedShareExRate().Mul(shares).Evaluate() // (tokens/shares) * shares
gs.BondedShares = gs.BondedShares.Sub(shares)
gs.BondedPool -= removedTokens
k.setGlobalState(ctx, gs)
return
}
//XXX CONFIRM that use of the exRate is correct with Zarko Spec!
func (k Keeper) addTokensUnbonded(ctx sdk.Context, amount int64) (issuedShares sdk.Rat) {
gs := k.getGlobalState(ctx)
issuedShares = gs.unbondedShareExRate().Inv().Mul(sdk.NewRat(amount)) // (tokens/shares)^-1 * tokens
gs.UnbondedShares = gs.UnbondedShares.Add(issuedShares)
gs.UnbondedPool += amount
k.setGlobalState(ctx, gs)
return
}
//XXX CONFIRM that use of the exRate is correct with Zarko Spec!
func (k Keeper) removeSharesUnbonded(ctx sdk.Context, shares sdk.Rat) (removedTokens int64) {
gs := k.getGlobalState(ctx)
removedTokens = gs.unbondedShareExRate().Mul(shares).Evaluate() // (tokens/shares) * shares
gs.UnbondedShares = gs.UnbondedShares.Sub(shares)
gs.UnbondedPool -= removedTokens
k.setGlobalState(ctx, gs)
return
}
// add tokens to a candidate
func (k Keeper) candidateAddTokens(ctx sdk.Context, candidate Candidate, amount int64) (issuedDelegatorShares sdk.Rat) {
gs := k.getGlobalState(ctx)
exRate := candidate.delegatorShareExRate()
var receivedGlobalShares sdk.Rat
if candidate.Status == Bonded {
receivedGlobalShares = k.addTokensBonded(ctx, amount)
} else {
receivedGlobalShares = k.addTokensUnbonded(ctx, amount)
}
candidate.Assets = candidate.Assets.Add(receivedGlobalShares)
issuedDelegatorShares = exRate.Mul(receivedGlobalShares)
candidate.Liabilities = candidate.Liabilities.Add(issuedDelegatorShares)
k.setGlobalState(ctx, gs) // TODO cache GlobalState?
return
}
// remove shares from a candidate
func (k Keeper) candidateRemoveShares(ctx sdk.Context, candidate Candidate, shares sdk.Rat) (createdCoins int64) {
gs := k.getGlobalState(ctx)
//exRate := candidate.delegatorShareExRate() //XXX make sure not used
globalPoolSharesToRemove := candidate.delegatorShareExRate().Mul(shares)
if candidate.Status == Bonded {
createdCoins = k.removeSharesBonded(ctx, globalPoolSharesToRemove)
} else {
createdCoins = k.removeSharesUnbonded(ctx, globalPoolSharesToRemove)
}
candidate.Assets = candidate.Assets.Sub(globalPoolSharesToRemove)
candidate.Liabilities = candidate.Liabilities.Sub(shares)
k.setGlobalState(ctx, gs) // TODO cache GlobalState?
return
} }

View File

@ -37,7 +37,7 @@ import (
//assert.Equal(int64(500), candidates[1].VotingPower.Evaluate(), "%v", candidates[1]) //assert.Equal(int64(500), candidates[1].VotingPower.Evaluate(), "%v", candidates[1])
//// test the max validators term //// test the max validators term
//params.MaxVals = 4 //params.MaxValidators = 4
//setParams(store, params) //setParams(store, params)
//candidates.updateVotingPower(store, gs, params) //candidates.updateVotingPower(store, gs, params)
//assert.Equal(int64(0), candidates[4].VotingPower.Evaluate(), "%v", candidates[4]) //assert.Equal(int64(0), candidates[4].VotingPower.Evaluate(), "%v", candidates[4])
@ -131,7 +131,7 @@ import (
//require.Equal(0, len(change), "%v", change) // change 1, remove 1, add 2 //require.Equal(0, len(change), "%v", change) // change 1, remove 1, add 2
//// test the max value and test again //// test the max value and test again
//params.MaxVals = 4 //params.MaxValidators = 4
//setParams(store, params) //setParams(store, params)
//change, err = UpdateValidatorSet(store, gs, params) //change, err = UpdateValidatorSet(store, gs, params)
//require.Nil(err) //require.Nil(err)
@ -161,7 +161,7 @@ import (
//} //}
func TestState(t *testing.T) { func TestState(t *testing.T) {
_, _, keeper, _ := createTestInput(t, nil, false, 0) ctx, _, keeper := createTestInput(t, nil, false, 0)
addrDel := sdk.Address([]byte("addressdelegator")) addrDel := sdk.Address([]byte("addressdelegator"))
addrVal := sdk.Address([]byte("addressvalidator")) addrVal := sdk.Address([]byte("addressvalidator"))
@ -172,7 +172,7 @@ func TestState(t *testing.T) {
// Candidate checks // Candidate checks
// XXX expand to include both liabilities and assets use/test all candidate fields // XXX expand to include both liabilities and assets use/test all candidate fields
candidate := &Candidate{ candidate := Candidate{
Address: addrVal, Address: addrVal,
PubKey: pk, PubKey: pk,
Assets: sdk.NewRat(9), Assets: sdk.NewRat(9),
@ -180,7 +180,7 @@ func TestState(t *testing.T) {
VotingPower: sdk.ZeroRat, VotingPower: sdk.ZeroRat,
} }
candidatesEqual := func(c1, c2 *Candidate) bool { candidatesEqual := func(c1, c2 Candidate) bool {
return c1.Status == c2.Status && return c1.Status == c2.Status &&
c1.PubKey.Equals(c2.PubKey) && c1.PubKey.Equals(c2.PubKey) &&
bytes.Equal(c1.Address, c2.Address) && bytes.Equal(c1.Address, c2.Address) &&
@ -191,54 +191,59 @@ func TestState(t *testing.T) {
} }
// check the empty keeper first // check the empty keeper first
resCand := keeper.getCandidate(addrVal) _, found := keeper.getCandidate(ctx, addrVal)
assert.Nil(t, resCand) assert.False(t, found)
resPks := keeper.getCandidates() resPks := keeper.getCandidates(ctx)
assert.Zero(t, len(resPks)) assert.Zero(t, len(resPks))
// set and retrieve a record // set and retrieve a record
keeper.setCandidate(candidate) keeper.setCandidate(ctx, candidate)
resCand = keeper.getCandidate(addrVal) resCand, found := keeper.getCandidate(ctx, addrVal)
//assert.Equal(candidate, resCand) assert.True(t, found)
assert.True(t, candidatesEqual(candidate, resCand), "%#v \n %#v", resCand, candidate) assert.True(t, candidatesEqual(candidate, resCand), "%#v \n %#v", resCand, candidate)
// modify a records, save, and retrieve // modify a records, save, and retrieve
candidate.Liabilities = sdk.NewRat(99) candidate.Liabilities = sdk.NewRat(99)
keeper.setCandidate(candidate) keeper.setCandidate(ctx, candidate)
resCand = keeper.getCandidate(addrVal) resCand, found = keeper.getCandidate(ctx, addrVal)
assert.True(t, found)
assert.True(t, candidatesEqual(candidate, resCand)) assert.True(t, candidatesEqual(candidate, resCand))
// also test that the pubkey has been added to pubkey list // also test that the pubkey has been added to pubkey list
resPks = keeper.getCandidates() resPks = keeper.getCandidates(ctx)
require.Equal(t, 1, len(resPks)) require.Equal(t, 1, len(resPks))
assert.Equal(t, addrVal, resPks[0].PubKey) assert.Equal(t, addrVal, resPks[0].PubKey)
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// Bond checks // Bond checks
bond := &DelegatorBond{ bond := DelegatorBond{
Address: addrDel, DelegatorAddr: addrDel,
Shares: sdk.NewRat(9), CandidateAddr: addrVal,
Shares: sdk.NewRat(9),
} }
bondsEqual := func(b1, b2 *DelegatorBond) bool { bondsEqual := func(b1, b2 DelegatorBond) bool {
return bytes.Equal(b1.Address, b2.Address) && return bytes.Equal(b1.DelegatorAddr, b2.DelegatorAddr) &&
bytes.Equal(b1.CandidateAddr, b2.CandidateAddr) &&
b1.Shares == b2.Shares b1.Shares == b2.Shares
} }
//check the empty keeper first //check the empty keeper first
resBond := keeper.getDelegatorBond(addrDel, addrVal) _, found = keeper.getDelegatorBond(ctx, addrDel, addrVal)
assert.Nil(t, resBond) assert.False(t, found)
//Set and retrieve a record //Set and retrieve a record
keeper.setDelegatorBond(addrDel, bond) keeper.setDelegatorBond(ctx, bond)
resBond = keeper.getDelegatorBond(addrDel, addrVal) resBond, found := keeper.getDelegatorBond(ctx, addrDel, addrVal)
assert.True(t, found)
assert.True(t, bondsEqual(bond, resBond)) assert.True(t, bondsEqual(bond, resBond))
//modify a records, save, and retrieve //modify a records, save, and retrieve
bond.Shares = sdk.NewRat(99) bond.Shares = sdk.NewRat(99)
keeper.setDelegatorBond(addrDel, bond) keeper.setDelegatorBond(ctx, bond)
resBond = keeper.getDelegatorBond(addrDel, addrVal) resBond, found = keeper.getDelegatorBond(ctx, addrDel, addrVal)
assert.True(t, found)
assert.True(t, bondsEqual(bond, resBond)) assert.True(t, bondsEqual(bond, resBond))
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -247,21 +252,21 @@ func TestState(t *testing.T) {
params := defaultParams() params := defaultParams()
//check that the empty keeper loads the default //check that the empty keeper loads the default
resParams := keeper.getParams() resParams := keeper.getParams(ctx)
assert.Equal(t, params, resParams) assert.Equal(t, params, resParams)
//modify a params, save, and retrieve //modify a params, save, and retrieve
params.MaxVals = 777 params.MaxValidators = 777
keeper.setParams(params) keeper.setParams(ctx, params)
resParams = keeper.getParams() resParams = keeper.getParams(ctx)
assert.Equal(t, params, resParams) assert.Equal(t, params, resParams)
} }
func TestGetValidators(t *testing.T) { func TestGetValidators(t *testing.T) {
_, _, keeper, _ := createTestInput(t, nil, false, 0) ctx, _, keeper := createTestInput(t, nil, false, 0)
candidatesFromAddrs(keeper, addrs, []int64{400, 200, 0, 0, 0}) candidatesFromAddrs(ctx, keeper, addrs, []int64{400, 200, 0, 0, 0})
validators := keeper.getValidators(5) validators := keeper.getValidators(ctx, 5)
require.Equal(t, 2, len(validators)) require.Equal(t, 2, len(validators))
assert.Equal(t, addrs[0], validators[0].Address) assert.Equal(t, addrs[0], validators[0].Address)
assert.Equal(t, addrs[1], validators[1].Address) assert.Equal(t, addrs[1], validators[1].Address)

View File

@ -20,8 +20,8 @@ var _, _, _, _ sdk.Msg = &MsgDeclareCandidacy{}, &MsgEditCandidacy{}, &MsgDelega
type MsgDeclareCandidacy struct { type MsgDeclareCandidacy struct {
Description Description
CandidateAddr sdk.Address `json:"address"` CandidateAddr sdk.Address `json:"address"`
Bond sdk.Coin `json:"bond"`
PubKey crypto.PubKey `json:"pubkey"` PubKey crypto.PubKey `json:"pubkey"`
Bond sdk.Coin `json:"bond"`
} }
func NewMsgDeclareCandidacy(candidateAddr sdk.Address, pubkey crypto.PubKey, func NewMsgDeclareCandidacy(candidateAddr sdk.Address, pubkey crypto.PubKey,
@ -29,8 +29,8 @@ func NewMsgDeclareCandidacy(candidateAddr sdk.Address, pubkey crypto.PubKey,
return MsgDeclareCandidacy{ return MsgDeclareCandidacy{
Description: description, Description: description,
CandidateAddr: candidateAddr, CandidateAddr: candidateAddr,
Bond: bond,
PubKey: pubkey, PubKey: pubkey,
Bond: bond,
} }
} }
@ -39,7 +39,7 @@ func (msg MsgDeclareCandidacy) Type() string { return
func (msg MsgDeclareCandidacy) Get(key interface{}) (value interface{}) { return nil } func (msg MsgDeclareCandidacy) Get(key interface{}) (value interface{}) { return nil }
func (msg MsgDeclareCandidacy) GetSigners() []sdk.Address { return []sdk.Address{msg.CandidateAddr} } func (msg MsgDeclareCandidacy) GetSigners() []sdk.Address { return []sdk.Address{msg.CandidateAddr} }
func (msg MsgDeclareCandidacy) String() string { func (msg MsgDeclareCandidacy) String() string {
return fmt.Sprintf("CandidateAddr{Address: %v}", msg.Address) // XXX fix return fmt.Sprintf("CandidateAddr{Address: %v}", msg.CandidateAddr) // XXX fix
} }
// get the bytes for the message signer to sign on // get the bytes for the message signer to sign on
@ -53,11 +53,11 @@ func (msg MsgDeclareCandidacy) GetSignBytes() []byte {
// quick validity check // quick validity check
func (msg MsgDeclareCandidacy) ValidateBasic() sdk.Error { func (msg MsgDeclareCandidacy) ValidateBasic() sdk.Error {
if msg.Address == nil { if msg.CandidateAddr == nil {
return ErrCandidateEmpty() return ErrCandidateEmpty()
} }
if msg.Bond.Denom <= 0 { if msg.Bond.Amount <= 0 {
return sdk.ErrInvalidCoins(coins) return sdk.ErrInvalidCoins(sdk.Coins{msg.Bond})
} }
empty := Description{} empty := Description{}
if msg.Description == empty { if msg.Description == empty {
@ -74,10 +74,10 @@ type MsgEditCandidacy struct {
CandidateAddr sdk.Address `json:"address"` CandidateAddr sdk.Address `json:"address"`
} }
func NewMsgEditCandidacy(address sdk.Address, description Description) MsgEditCandidacy { func NewMsgEditCandidacy(candidateAddr sdk.Address, description Description) MsgEditCandidacy {
return MsgEditCandidacy{ return MsgEditCandidacy{
Description: description, Description: description,
Address: address, CandidateAddr: candidateAddr,
} }
} }
@ -86,7 +86,7 @@ func (msg MsgEditCandidacy) Type() string { return Ms
func (msg MsgEditCandidacy) Get(key interface{}) (value interface{}) { return nil } func (msg MsgEditCandidacy) Get(key interface{}) (value interface{}) { return nil }
func (msg MsgEditCandidacy) GetSigners() []sdk.Address { return []sdk.Address{msg.CandidateAddr} } func (msg MsgEditCandidacy) GetSigners() []sdk.Address { return []sdk.Address{msg.CandidateAddr} }
func (msg MsgEditCandidacy) String() string { func (msg MsgEditCandidacy) String() string {
return fmt.Sprintf("CandidateAddr{Address: %v}", msg.Address) // XXX fix return fmt.Sprintf("CandidateAddr{Address: %v}", msg.CandidateAddr) // XXX fix
} }
// get the bytes for the message signer to sign on // get the bytes for the message signer to sign on
@ -100,12 +100,9 @@ func (msg MsgEditCandidacy) GetSignBytes() []byte {
// quick validity check // quick validity check
func (msg MsgEditCandidacy) ValidateBasic() sdk.Error { func (msg MsgEditCandidacy) ValidateBasic() sdk.Error {
if msg.Address == nil { if msg.CandidateAddr == nil {
return ErrCandidateEmpty() return ErrCandidateEmpty()
} }
if err != nil {
return err
}
empty := Description{} empty := Description{}
if msg.Description == empty { if msg.Description == empty {
return newError(CodeInvalidInput, "Transaction must include some information to modify") return newError(CodeInvalidInput, "Transaction must include some information to modify")
@ -155,8 +152,8 @@ func (msg MsgDelegate) ValidateBasic() sdk.Error {
if msg.CandidateAddr == nil { if msg.CandidateAddr == nil {
return ErrBadCandidateAddr() return ErrBadCandidateAddr()
} }
if msg.Bond.Denom <= 0 { if msg.Bond.Amount <= 0 {
return sdk.ErrInvalidCoins(coins) return sdk.ErrInvalidCoins(sdk.Coins{msg.Bond})
} }
return nil return nil
} }
@ -204,7 +201,7 @@ func (msg MsgUnbond) ValidateBasic() sdk.Error {
return ErrBadCandidateAddr() return ErrBadCandidateAddr()
} }
if msg.Shares != "MAX" { if msg.Shares != "MAX" {
shares, err = sdk.NewRatFromDecimal(msg.Shares) _, err := sdk.NewRatFromDecimal(msg.Shares)
if err != nil { if err != nil {
return ErrBadShares() return ErrBadShares()
} }

View File

@ -23,39 +23,40 @@ var (
coinNegNotAtoms = sdk.Coin{"foo", -10000} coinNegNotAtoms = sdk.Coin{"foo", -10000}
) )
func TestMsgAddrValidateBasic(t *testing.T) { //TODO add these tests to one of some of the types
tests := []struct { //func TestMsgAddrValidateBasic(t *testing.T) {
name string //tests := []struct {
address sdk.Address //name string
wantErr bool //address sdk.Address
}{ //wantErr bool
{"basic good", addrs[0], false}, //}{
{"empty delegator", sdk.Address{}, true}, //{"basic good", addrs[0], false},
} //{"empty delegator", sdk.Address{}, true},
//}
for _, tc := range tests { //for _, tc := range tests {
tx := NewMsgAddr(tc.address) //tx := NewMsgAddr(tc.address)
assert.Equal(t, tc.wantErr, tx.ValidateBasic() != nil, //assert.Equal(t, tc.wantErr, tx.ValidateBasic() != nil,
"test: %v, tx.ValidateBasic: %v", tc.name, tx.ValidateBasic()) //"test: %v, tx.ValidateBasic: %v", tc.name, tx.ValidateBasic())
} //}
} //}
func TestValidateCoin(t *testing.T) { //func TestValidateCoin(t *testing.T) {
tests := []struct { //tests := []struct {
name string //name string
coin sdk.Coin //coin sdk.Coin
wantErr bool //wantErr bool
}{ //}{
{"basic good", coinPos, false}, //{"basic good", coinPos, false},
{"zero coin", coinZero, true}, //{"zero coin", coinZero, true},
{"neg coin", coinNeg, true}, //{"neg coin", coinNeg, true},
} //}
for _, tc := range tests { //for _, tc := range tests {
assert.Equal(t, tc.wantErr, validateCoin(tc.coin) != nil, //assert.Equal(t, tc.wantErr, validateCoin(tc.coin) != nil,
"test: %v, tx.ValidateBasic: %v", tc.name, validateCoin(tc.coin)) //"test: %v, tx.ValidateBasic: %v", tc.name, validateCoin(tc.coin))
} //}
} //}
func TestSerializeMsg(t *testing.T) { func TestSerializeMsg(t *testing.T) {
@ -68,8 +69,8 @@ func TestSerializeMsg(t *testing.T) {
}{ }{
{NewMsgDeclareCandidacy(addrs[0], pks[0], bond, Description{})}, {NewMsgDeclareCandidacy(addrs[0], pks[0], bond, Description{})},
{NewMsgEditCandidacy(addrs[0], Description{})}, {NewMsgEditCandidacy(addrs[0], Description{})},
{NewMsgDelegate(addrs[0], bond)}, {NewMsgDelegate(addrs[0], addrs[1], bond)},
{NewMsgUnbond(addrs[0], strconv.Itoa(bondAmt))}, {NewMsgUnbond(addrs[0], addrs[1], strconv.Itoa(bondAmt))},
} }
for i, tc := range tests { for i, tc := range tests {

View File

@ -65,20 +65,16 @@ func paramsNoInflation() Params {
InflationMax: sdk.ZeroRat, InflationMax: sdk.ZeroRat,
InflationMin: sdk.ZeroRat, InflationMin: sdk.ZeroRat,
GoalBonded: sdk.NewRat(67, 100), GoalBonded: sdk.NewRat(67, 100),
MaxVals: 100, MaxValidators: 100,
BondDenom: "fermion", BondDenom: "fermion",
GasDeclareCandidacy: 20,
GasEditCandidacy: 20,
GasDelegate: 20,
GasUnbond: 20,
} }
} }
// hogpodge of all sorts of input required for testing // hogpodge of all sorts of input required for testing
func createTestInput(t *testing.T, sender sdk.Address, isCheckTx bool, initCoins int64) (sdk.Context, sdk.AccountMapper, Mapper, transact) { func createTestInput(t *testing.T, sender sdk.Address, isCheckTx bool, initCoins int64) (sdk.Context, sdk.AccountMapper, Keeper) {
db := dbm.NewMemDB() db := dbm.NewMemDB()
keyStake := sdk.NewKVStoreKey("stake") keyStake := sdk.NewKVStoreKey("stake")
keyMain := keyStake //sdk.NewKVStoreKey("main") //XXX fix multistore keyMain := keyStake //sdk.NewKVStoreKey("main") //TODO fix multistore
ms := store.NewCommitMultiStore(db) ms := store.NewCommitMultiStore(db)
ms.MountStoreWithDB(keyStake, sdk.StoreTypeIAVL, db) ms.MountStoreWithDB(keyStake, sdk.StoreTypeIAVL, db)
@ -86,26 +82,23 @@ func createTestInput(t *testing.T, sender sdk.Address, isCheckTx bool, initCoins
require.Nil(t, err) require.Nil(t, err)
ctx := sdk.NewContext(ms, abci.Header{ChainID: "foochainid"}, isCheckTx, nil) ctx := sdk.NewContext(ms, abci.Header{ChainID: "foochainid"}, isCheckTx, nil)
cdc := makeTestCodec() cdc := makeTestCodec()
mapper := NewMapper(ctx, cdc, keyStake)
accountMapper := auth.NewAccountMapperSealed( accountMapper := auth.NewAccountMapperSealed(
keyMain, // target store keyMain, // target store
&auth.BaseAccount{}, // prototype &auth.BaseAccount{}, // prototype
) )
ck := bank.NewCoinKeeper(accountMapper) ck := bank.NewCoinKeeper(accountMapper)
keeper := NewKeeper(ctx, cdc, keyStake, ck)
params := paramsNoInflation() params := paramsNoInflation()
mapper.setParams(params) keeper.setParams(ctx, params)
// fill all the addresses with some coins // fill all the addresses with some coins
for _, addr := range addrs { for _, addr := range addrs {
ck.AddCoins(ctx, addr, sdk.Coins{{params.BondDenom, initCoins}}) ck.AddCoins(ctx, addr, sdk.Coins{{params.BondDenom, initCoins}})
} }
tr := newTransact(ctx, sender, mapper, ck) return ctx, accountMapper, keeper
return ctx, accountMapper, mapper, tr
} }
func newPubKey(pk string) (res crypto.PubKey) { func newPubKey(pk string) (res crypto.PubKey) {
@ -157,9 +150,9 @@ var addrs = []sdk.Address{
// NOTE: PubKey is supposed to be the binaryBytes of the crypto.PubKey // NOTE: PubKey is supposed to be the binaryBytes of the crypto.PubKey
// instead this is just being set the address here for testing purposes // instead this is just being set the address here for testing purposes
func candidatesFromAddrs(mapper Mapper, addrs []crypto.Address, amts []int64) { func candidatesFromAddrs(ctx sdk.Context, keeper Keeper, addrs []crypto.Address, amts []int64) {
for i := 0; i < len(amts); i++ { for i := 0; i < len(amts); i++ {
c := &Candidate{ c := Candidate{
Status: Unbonded, Status: Unbonded,
PubKey: pks[i], PubKey: pks[i],
Address: addrs[i], Address: addrs[i],
@ -167,13 +160,13 @@ func candidatesFromAddrs(mapper Mapper, addrs []crypto.Address, amts []int64) {
Liabilities: sdk.NewRat(amts[i]), Liabilities: sdk.NewRat(amts[i]),
VotingPower: sdk.NewRat(amts[i]), VotingPower: sdk.NewRat(amts[i]),
} }
mapper.setCandidate(c) keeper.setCandidate(ctx, c)
} }
} }
func candidatesFromAddrsEmpty(addrs []crypto.Address) (candidates Candidates) { func candidatesFromAddrsEmpty(addrs []crypto.Address) (candidates Candidates) {
for i := 0; i < len(addrs); i++ { for i := 0; i < len(addrs); i++ {
c := &Candidate{ c := Candidate{
Status: Unbonded, Status: Unbonded,
PubKey: pks[i], PubKey: pks[i],
Address: addrs[i], Address: addrs[i],

View File

@ -6,21 +6,21 @@ import (
) )
// Tick - called at the end of every block // Tick - called at the end of every block
func Tick(ctx sdk.Context, m Mapper) (change []*abci.Validator, err error) { func Tick(ctx sdk.Context, k Keeper) (change []*abci.Validator, err error) {
// retrieve params // retrieve params
params := m.getParams() params := k.getParams(ctx)
gs := m.getGlobalState() gs := k.getGlobalState(ctx)
height := ctx.BlockHeight() height := ctx.BlockHeight()
// Process Validator Provisions // Process Validator Provisions
// XXX right now just process every 5 blocks, in new SDK make hourly // XXX right now just process every 5 blocks, in new SDK make hourly
if gs.InflationLastTime+5 <= height { if gs.InflationLastTime+5 <= height {
gs.InflationLastTime = height gs.InflationLastTime = height
processProvisions(m, gs, params) processProvisions(ctx, k, gs, params)
} }
newVals := m.getValidators(params.MaxVals) newVals := k.getValidators(ctx, params.MaxValidators)
// XXX determine change from old validators, set to change // XXX determine change from old validators, set to change
_ = newVals _ = newVals
return change, nil return change, nil
@ -29,7 +29,7 @@ func Tick(ctx sdk.Context, m Mapper) (change []*abci.Validator, err error) {
var hrsPerYr = sdk.NewRat(8766) // as defined by a julian year of 365.25 days var hrsPerYr = sdk.NewRat(8766) // as defined by a julian year of 365.25 days
// process provisions for an hour period // process provisions for an hour period
func processProvisions(m Mapper, gs *GlobalState, params Params) { func processProvisions(ctx sdk.Context, k Keeper, gs GlobalState, params Params) {
gs.Inflation = nextInflation(gs, params).Round(1000000000) gs.Inflation = nextInflation(gs, params).Round(1000000000)
@ -46,11 +46,11 @@ func processProvisions(m Mapper, gs *GlobalState, params Params) {
// XXX XXX XXX XXX XXX XXX XXX XXX XXX // XXX XXX XXX XXX XXX XXX XXX XXX XXX
// save the params // save the params
m.setGlobalState(gs) k.setGlobalState(ctx, gs)
} }
// get the next inflation rate for the hour // get the next inflation rate for the hour
func nextInflation(gs *GlobalState, params Params) (inflation sdk.Rat) { func nextInflation(gs GlobalState, params Params) (inflation sdk.Rat) {
// The target annual inflation rate is recalculated for each previsions cycle. The // The target annual inflation rate is recalculated for each previsions cycle. The
// inflation is also subject to a rate change (positive of negative) depending or // inflation is also subject to a rate change (positive of negative) depending or

View File

@ -8,9 +8,9 @@ import (
) )
func TestGetInflation(t *testing.T) { func TestGetInflation(t *testing.T) {
_, _, mapper, _ := createTestInput(t, nil, false, 0) ctx, _, keeper := createTestInput(t, nil, false, 0)
params := mapper.getParams() params := keeper.getParams(ctx)
gs := mapper.getGlobalState() gs := keeper.getGlobalState(ctx)
// Governing Mechanism: // Governing Mechanism:
// bondedRatio = BondedPool / TotalSupply // bondedRatio = BondedPool / TotalSupply
@ -53,9 +53,9 @@ func TestGetInflation(t *testing.T) {
} }
func TestProcessProvisions(t *testing.T) { func TestProcessProvisions(t *testing.T) {
_, _, mapper, _ := createTestInput(t, nil, false, 0) ctx, _, keeper := createTestInput(t, nil, false, 0)
params := mapper.getParams() params := keeper.getParams(ctx)
gs := mapper.getGlobalState() gs := keeper.getGlobalState(ctx)
// create some candidates some bonded, some unbonded // create some candidates some bonded, some unbonded
candidates := candidatesFromAddrsEmpty(addrs) candidates := candidatesFromAddrsEmpty(addrs)
@ -65,8 +65,8 @@ func TestProcessProvisions(t *testing.T) {
} }
mintedTokens := int64((i + 1) * 10000000) mintedTokens := int64((i + 1) * 10000000)
gs.TotalSupply += mintedTokens gs.TotalSupply += mintedTokens
candidate.addTokens(mintedTokens, gs) keeper.candidateAddTokens(ctx, candidate, mintedTokens)
mapper.setCandidate(candidate) keeper.setCandidate(ctx, candidate)
} }
var totalSupply int64 = 550000000 var totalSupply int64 = 550000000
var bondedShares int64 = 150000000 var bondedShares int64 = 150000000
@ -92,7 +92,7 @@ func TestProcessProvisions(t *testing.T) {
expProvisions := (expInflation.Mul(sdk.NewRat(gs.TotalSupply)).Quo(hrsPerYr)).Evaluate() expProvisions := (expInflation.Mul(sdk.NewRat(gs.TotalSupply)).Quo(hrsPerYr)).Evaluate()
startBondedPool := gs.BondedPool startBondedPool := gs.BondedPool
startTotalSupply := gs.TotalSupply startTotalSupply := gs.TotalSupply
processProvisions(mapper, gs, params) processProvisions(ctx, keeper, gs, params)
assert.Equal(t, startBondedPool+expProvisions, gs.BondedPool) assert.Equal(t, startBondedPool+expProvisions, gs.BondedPool)
assert.Equal(t, startTotalSupply+expProvisions, gs.TotalSupply) assert.Equal(t, startTotalSupply+expProvisions, gs.TotalSupply)
} }

View File

@ -42,8 +42,8 @@ type GlobalState struct {
// XXX define globalstate interface? // XXX define globalstate interface?
func initialGlobalState() *GlobalState { func initialGlobalState() GlobalState {
return &GlobalState{ return GlobalState{
TotalSupply: 0, TotalSupply: 0,
BondedShares: sdk.ZeroRat, BondedShares: sdk.ZeroRat,
UnbondedShares: sdk.ZeroRat, UnbondedShares: sdk.ZeroRat,
@ -55,7 +55,7 @@ func initialGlobalState() *GlobalState {
} }
// get the bond ratio of the global state // get the bond ratio of the global state
func (gs *GlobalState) bondedRatio() sdk.Rat { func (gs GlobalState) bondedRatio() sdk.Rat {
if gs.TotalSupply > 0 { if gs.TotalSupply > 0 {
return sdk.NewRat(gs.BondedPool, gs.TotalSupply) return sdk.NewRat(gs.BondedPool, gs.TotalSupply)
} }
@ -63,7 +63,7 @@ func (gs *GlobalState) bondedRatio() sdk.Rat {
} }
// get the exchange rate of bonded token per issued share // get the exchange rate of bonded token per issued share
func (gs *GlobalState) bondedShareExRate() sdk.Rat { func (gs GlobalState) bondedShareExRate() sdk.Rat {
if gs.BondedShares.IsZero() { if gs.BondedShares.IsZero() {
return sdk.OneRat return sdk.OneRat
} }
@ -71,48 +71,13 @@ func (gs *GlobalState) bondedShareExRate() sdk.Rat {
} }
// get the exchange rate of unbonded tokens held in candidates per issued share // get the exchange rate of unbonded tokens held in candidates per issued share
func (gs *GlobalState) unbondedShareExRate() sdk.Rat { func (gs GlobalState) unbondedShareExRate() sdk.Rat {
if gs.UnbondedShares.IsZero() { if gs.UnbondedShares.IsZero() {
return sdk.OneRat return sdk.OneRat
} }
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
//XXX CONFIRM that use of the exRate is correct with Zarko Spec!
func (gs *GlobalState) addTokensBonded(amount int64) (issuedShares sdk.Rat) {
issuedShares = gs.bondedShareExRate().Inv().Mul(sdk.NewRat(amount)) // (tokens/shares)^-1 * tokens
gs.BondedPool += amount
gs.BondedShares = gs.BondedShares.Add(issuedShares)
return
}
//XXX CONFIRM that use of the exRate is correct with Zarko Spec!
func (gs *GlobalState) removeSharesBonded(shares sdk.Rat) (removedTokens int64) {
removedTokens = gs.bondedShareExRate().Mul(shares).Evaluate() // (tokens/shares) * shares
gs.BondedShares = gs.BondedShares.Sub(shares)
gs.BondedPool -= removedTokens
return
}
//XXX CONFIRM that use of the exRate is correct with Zarko Spec!
func (gs *GlobalState) addTokensUnbonded(amount int64) (issuedShares sdk.Rat) {
issuedShares = gs.unbondedShareExRate().Inv().Mul(sdk.NewRat(amount)) // (tokens/shares)^-1 * tokens
gs.UnbondedShares = gs.UnbondedShares.Add(issuedShares)
gs.UnbondedPool += amount
return
}
//XXX CONFIRM that use of the exRate is correct with Zarko Spec!
func (gs *GlobalState) removeSharesUnbonded(shares sdk.Rat) (removedTokens int64) {
removedTokens = gs.unbondedShareExRate().Mul(shares).Evaluate() // (tokens/shares) * shares
gs.UnbondedShares = gs.UnbondedShares.Sub(shares)
gs.UnbondedPool -= removedTokens
return
}
//_______________________________________________________________________________________________________ //_______________________________________________________________________________________________________
// CandidateStatus - status of a validator-candidate // CandidateStatus - status of a validator-candidate
@ -151,8 +116,8 @@ type Description struct {
} }
// NewCandidate - initialize a new candidate // NewCandidate - initialize a new candidate
func NewCandidate(address sdk.Address, pubKey crypto.PubKey, description Description) *Candidate { func NewCandidate(address sdk.Address, pubKey crypto.PubKey, description Description) Candidate {
return &Candidate{ return Candidate{
Status: Unbonded, Status: Unbonded,
Address: address, Address: address,
PubKey: pubKey, PubKey: pubKey,
@ -164,50 +129,16 @@ func NewCandidate(address sdk.Address, pubKey crypto.PubKey, description Descrip
} }
// get the exchange rate of global pool shares over delegator shares // get the exchange rate of global pool shares over delegator shares
func (c *Candidate) delegatorShareExRate() sdk.Rat { func (c Candidate) delegatorShareExRate() sdk.Rat {
if c.Liabilities.IsZero() { if c.Liabilities.IsZero() {
return sdk.OneRat return sdk.OneRat
} }
return c.Assets.Quo(c.Liabilities) return c.Assets.Quo(c.Liabilities)
} }
// add tokens to a candidate
func (c *Candidate) addTokens(amount int64, gs *GlobalState) (issuedDelegatorShares sdk.Rat) {
exRate := c.delegatorShareExRate()
var receivedGlobalShares sdk.Rat
if c.Status == Bonded {
receivedGlobalShares = gs.addTokensBonded(amount)
} else {
receivedGlobalShares = gs.addTokensUnbonded(amount)
}
c.Assets = c.Assets.Add(receivedGlobalShares)
issuedDelegatorShares = exRate.Mul(receivedGlobalShares)
c.Liabilities = c.Liabilities.Add(issuedDelegatorShares)
return
}
// remove shares from a candidate
func (c *Candidate) removeShares(shares sdk.Rat, gs *GlobalState) (createdCoins int64) {
globalPoolSharesToRemove := c.delegatorShareExRate().Mul(shares)
if c.Status == Bonded {
createdCoins = gs.removeSharesBonded(globalPoolSharesToRemove)
} else {
createdCoins = gs.removeSharesUnbonded(globalPoolSharesToRemove)
}
c.Assets = c.Assets.Sub(globalPoolSharesToRemove)
c.Liabilities = c.Liabilities.Sub(shares)
return
}
// Validator returns a copy of the Candidate as a Validator. // Validator returns a copy of the Candidate as a Validator.
// Should only be called when the Candidate qualifies as a validator. // Should only be called when the Candidate qualifies as a validator.
func (c *Candidate) validator() Validator { func (c Candidate) validator() Validator {
return Validator{ return Validator{
Address: c.Address, // XXX !!! Address: c.Address, // XXX !!!
VotingPower: c.VotingPower, VotingPower: c.VotingPower,
@ -242,7 +173,7 @@ func (v Validator) ABCIValidator() (*abci.Validator, error) {
//_________________________________________________________________________ //_________________________________________________________________________
// Candidates - list of Candidates // Candidates - list of Candidates
type Candidates []*Candidate type Candidates []Candidate
//_________________________________________________________________________ //_________________________________________________________________________
@ -251,7 +182,7 @@ type Candidates []*Candidate
// pubKey. // pubKey.
// TODO better way of managing space // TODO better way of managing space
type DelegatorBond struct { type DelegatorBond struct {
Address sdk.Address `json:"address"` DelegatorAddr sdk.Address `json:"delegatoraddr"`
CandidateAddr sdk.Address `json:"candidate_addr"` CandidateAddr sdk.Address `json:"candidate_addr"`
Shares sdk.Rat `json:"shares"` Shares sdk.Rat `json:"shares"`
} }