gettin' stakin' tests up to snuff
This commit is contained in:
parent
3cb5bdb166
commit
3f0d7edb06
|
@ -1,6 +1,9 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
)
|
||||
|
@ -8,6 +11,18 @@ import (
|
|||
// Address in go-crypto style
|
||||
type Address = cmn.HexBytes
|
||||
|
||||
// create an Address from a string
|
||||
func GetAddress(address string) (addr Address, err error) {
|
||||
if len(address) == 0 {
|
||||
return addr, errors.New("must use provide address")
|
||||
}
|
||||
bz, err := hex.DecodeString(address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return Address(bz), nil
|
||||
}
|
||||
|
||||
// Account is a standard account using a sequence number for replay protection
|
||||
// and a pubkey for authentication.
|
||||
type Account interface {
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
crypto "github.com/tendermint/go-crypto"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/builder"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/wire" // XXX fix
|
||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||
)
|
||||
|
@ -79,7 +80,7 @@ func GetCmdQueryCandidate(cdc *wire.Codec, storeName string) *cobra.Command {
|
|||
Short: "Query a validator-candidate account",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
addr, err := GetAddress(viper.GetString(FlagValidatorAddr))
|
||||
addr, err := sdk.GetAddress(viper.GetString(FlagValidatorAddr))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -119,7 +120,7 @@ func GetCmdQueryDelegatorBond(cdc *wire.Codec, storeName string) *cobra.Command
|
|||
Short: "Query a delegators bond based on address and candidate pubkey",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
addr, err := GetAddress(viper.GetString(FlagValidatorAddr))
|
||||
addr, err := sdk.GetAddress(viper.GetString(FlagValidatorAddr))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
flag "github.com/spf13/pflag"
|
||||
"github.com/spf13/viper"
|
||||
|
@ -60,7 +59,7 @@ func GetCmdDeclareCandidacy(cdc *wire.Codec) *cobra.Command {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
addr, err := GetAddress(viper.GetString(FlagAddress))
|
||||
addr, err := sdk.GetAddress(viper.GetString(FlagAddress))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -103,7 +102,7 @@ func GetCmdEditCandidacy(cdc *wire.Codec) *cobra.Command {
|
|||
Short: "edit and existing validator-candidate account",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
addr, err := GetAddress(viper.GetString(FlagAddress))
|
||||
addr, err := sdk.GetAddress(viper.GetString(FlagAddress))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -142,7 +141,7 @@ func GetCmdDelegate(cdc *wire.Codec) *cobra.Command {
|
|||
return err
|
||||
}
|
||||
|
||||
addr, err := GetAddress(viper.GetString(FlagAddress))
|
||||
addr, err := sdk.GetAddress(viper.GetString(FlagAddress))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -186,7 +185,7 @@ func GetCmdUnbond(cdc *wire.Codec) *cobra.Command {
|
|||
}
|
||||
}
|
||||
|
||||
addr, err := GetAddress(viper.GetString(FlagAddress))
|
||||
addr, err := sdk.GetAddress(viper.GetString(FlagAddress))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -211,7 +210,8 @@ func GetCmdUnbond(cdc *wire.Codec) *cobra.Command {
|
|||
|
||||
//______________________________________________________________________________________
|
||||
|
||||
// GetPubKey - create the pubkey from a pubkey string
|
||||
// create the pubkey from a pubkey string
|
||||
// TODO move to a better reusable place
|
||||
func GetPubKey(pubKeyStr string) (pk crypto.PubKey, err error) {
|
||||
|
||||
if len(pubKeyStr) == 0 {
|
||||
|
@ -232,15 +232,3 @@ func GetPubKey(pubKeyStr string) (pk crypto.PubKey, err error) {
|
|||
pk = pkEd.Wrap()
|
||||
return
|
||||
}
|
||||
|
||||
// GetPubKey - create an Address from a pubkey string
|
||||
func GetAddress(address string) (addr sdk.Address, err error) {
|
||||
if len(address) == 0 {
|
||||
return addr, errors.New("must use provide address")
|
||||
}
|
||||
bz, err := hex.DecodeString(address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return sdk.Address(bz), nil
|
||||
}
|
||||
|
|
|
@ -10,154 +10,113 @@ import (
|
|||
crypto "github.com/tendermint/go-crypto"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
coin "github.com/cosmos/cosmos-sdk/x/bank" // XXX fix
|
||||
)
|
||||
|
||||
//______________________________________________________________________
|
||||
|
||||
func initAccounts(n int, amount int64) ([]sdk.Address, map[string]int64) {
|
||||
// XXX delete need to init accounts in the transact!
|
||||
func initAccounts(amount int64) map[string]int64 {
|
||||
accStore := map[string]int64{}
|
||||
senders := newAddrs(n)
|
||||
for _, sender := range senders {
|
||||
accStore[string(sender.Address)] = amount
|
||||
for _, addr := range addrs {
|
||||
accStore[string(addr)] = amount
|
||||
}
|
||||
return senders, accStore
|
||||
return accStore
|
||||
}
|
||||
|
||||
func newTestMsgDeclareCandidacy(amt int64, pubKey crypto.PubKey, address sdk.Address) MsgDeclareCandidacy {
|
||||
func newTestMsgDeclareCandidacy(address sdk.Address, pubKey crypto.PubKey, amt int64) MsgDeclareCandidacy {
|
||||
return MsgDeclareCandidacy{
|
||||
MsgAddr: NewMsgAddr(address),
|
||||
PubKey: pubKey,
|
||||
Bond: coin.Coin{"fermion", amt},
|
||||
Description{},
|
||||
MsgAddr: NewMsgAddr(address),
|
||||
PubKey: pubKey,
|
||||
Bond: sdk.Coin{"fermion", amt},
|
||||
Description: Description{},
|
||||
}
|
||||
}
|
||||
|
||||
func newTestMsgDelegate(amt int64, address sdk.Address) MsgDelegate {
|
||||
return MsgDelegate{
|
||||
MsgAddr: NewMsgAddr(address),
|
||||
Bond: coin.Coin{"fermion", amt},
|
||||
Bond: sdk.Coin{"fermion", amt},
|
||||
}
|
||||
}
|
||||
|
||||
func newMsgUnbond(shares string, pubKey crypto.PubKey) MsgUnbond {
|
||||
return MsgUnbond{
|
||||
PubKey: pubKey,
|
||||
Shares: shares,
|
||||
}
|
||||
}
|
||||
|
||||
func paramsNoInflation() Params {
|
||||
return Params{
|
||||
InflationRateChange: sdk.ZeroRat,
|
||||
InflationMax: sdk.ZeroRat,
|
||||
InflationMin: sdk.ZeroRat,
|
||||
GoalBonded: sdk.New(67, 100),
|
||||
MaxVals: 100,
|
||||
BondDenom: "fermion",
|
||||
GasDeclareCandidacy: 20,
|
||||
GasEditCandidacy: 20,
|
||||
GasDelegate: 20,
|
||||
GasUnbond: 20,
|
||||
}
|
||||
}
|
||||
|
||||
func newTestTransact(t, sender sdk.Address, isCheckTx bool) transact {
|
||||
store, mapper, coinKeeper := createTestInput(t, isCheckTx)
|
||||
params := paramsNoInflation()
|
||||
mapper.saveParams(params)
|
||||
newTransact(ctx, sender, mapper, coinKeeper)
|
||||
}
|
||||
|
||||
func TestDuplicatesMsgDeclareCandidacy(t *testing.T) {
|
||||
senders, accStore := initAccounts(2, 1000) // for accounts
|
||||
accStore := initAccounts(1000) // for accounts
|
||||
_, deliverer := createTestInput(t, addrs[0], false)
|
||||
_, checker := createTestInput(t, addrs[0], true)
|
||||
|
||||
deliverer := newDeliver(t, senders[0], accStore)
|
||||
checker := check{
|
||||
store: deliverer.store,
|
||||
sender: senders[0],
|
||||
}
|
||||
|
||||
txDeclareCandidacy := newTestMsgDeclareCandidacy(10, pks[0])
|
||||
txDeclareCandidacy := newTestMsgDeclareCandidacy(addrs[0], pks[0], 10)
|
||||
got := deliverer.declareCandidacy(txDeclareCandidacy)
|
||||
assert.NoError(t, got, "expected no error on runMsgDeclareCandidacy")
|
||||
|
||||
// one sender can bond to two different pubKeys
|
||||
txDeclareCandidacy.PubKey = pks[1]
|
||||
// one sender can bond to two different addresses
|
||||
txDeclareCandidacy.Address = addrs[1]
|
||||
err := checker.declareCandidacy(txDeclareCandidacy)
|
||||
assert.Nil(t, err, "didn't expected error on checkTx")
|
||||
|
||||
// two senders cant bond to the same pubkey
|
||||
checker.sender = senders[1]
|
||||
txDeclareCandidacy.PubKey = pks[0]
|
||||
// two addrs cant bond to the same pubkey
|
||||
checker.sender = addrs[1]
|
||||
txDeclareCandidacy.Address = addrs[0]
|
||||
err = checker.declareCandidacy(txDeclareCandidacy)
|
||||
assert.NotNil(t, err, "expected error on checkTx")
|
||||
}
|
||||
|
||||
func TestIncrementsMsgDelegate(t *testing.T) {
|
||||
initSender := int64(1000)
|
||||
senders, accStore := initAccounts(1, initSender) // for accounts
|
||||
deliverer := newDeliver(t, senders[0], accStore)
|
||||
accStore := initAccounts(initSender) // for accounts
|
||||
mapper, deliverer := createTestInput(t, addrs[0], false)
|
||||
|
||||
// first declare candidacy
|
||||
bondAmount := int64(10)
|
||||
txDeclareCandidacy := newTestMsgDeclareCandidacy(bondAmount, pks[0])
|
||||
txDeclareCandidacy := newTestMsgDeclareCandidacy(addrs[0], pks[0], bondAmount)
|
||||
got := deliverer.declareCandidacy(txDeclareCandidacy)
|
||||
assert.NoError(t, got, "expected declare candidacy tx to be ok, got %v", got)
|
||||
expectedBond := bondAmount // 1 since we send 1 at the start of loop,
|
||||
|
||||
// just send the same txbond multiple times
|
||||
holder := deliverer.params.HoldUnbonded // XXX this should be HoldBonded, new SDK updates
|
||||
txDelegate := newTestMsgDelegate(bondAmount, pks[0])
|
||||
txDelegate := newTestMsgDelegate(bondAmount, addrs[0])
|
||||
for i := 0; i < 5; i++ {
|
||||
got := deliverer.delegate(txDelegate)
|
||||
assert.NoError(t, got, "expected tx %d to be ok, got %v", i, got)
|
||||
|
||||
//Check that the accounts and the bond account have the appropriate values
|
||||
candidates := loadCandidates(deliverer.store)
|
||||
candidates := mapper.loadCandidates()
|
||||
expectedBond += bondAmount
|
||||
expectedSender := initSender - expectedBond
|
||||
gotBonded := candidates[0].Liabilities.Evaluate()
|
||||
gotHolder := accStore[string(holder.Address)]
|
||||
gotSender := accStore[string(deliverer.sender.Address)]
|
||||
gotSender := accStore[string(deliverer.sender)]
|
||||
assert.Equal(t, expectedBond, gotBonded, "i: %v, %v, %v", i, expectedBond, gotBonded)
|
||||
assert.Equal(t, expectedBond, gotHolder, "i: %v, %v, %v", i, expectedBond, gotHolder)
|
||||
assert.Equal(t, expectedSender, gotSender, "i: %v, %v, %v", i, expectedSender, gotSender)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIncrementsMsgUnbond(t *testing.T) {
|
||||
initSender := int64(0)
|
||||
senders, accStore := initAccounts(1, initSender) // for accounts
|
||||
deliverer := newDeliver(t, senders[0], accStore)
|
||||
accStore := initAccounts(initSender) // for accounts
|
||||
mapper, deliverer := createTestInput(t, addrs[0], false)
|
||||
|
||||
// set initial bond
|
||||
initBond := int64(1000)
|
||||
accStore[string(deliverer.sender.Address)] = initBond
|
||||
got := deliverer.declareCandidacy(newTestMsgDeclareCandidacy(initBond, pks[0]))
|
||||
accStore[string(deliverer.sender)] = initBond
|
||||
got := deliverer.declareCandidacy(newTestMsgDeclareCandidacy(addrs[0], pks[0], initBond))
|
||||
assert.NoError(t, got, "expected initial bond tx to be ok, got %v", got)
|
||||
|
||||
// just send the same txunbond multiple times
|
||||
holder := deliverer.params.HoldUnbonded // XXX new SDK, this should be HoldBonded
|
||||
|
||||
// XXX use decimals here
|
||||
unbondShares, unbondSharesStr := int64(10), "10"
|
||||
txUndelegate := newMsgUnbond(unbondSharesStr, pks[0])
|
||||
txUndelegate := NewMsgUnbond(addrs[0], unbondSharesStr)
|
||||
nUnbonds := 5
|
||||
for i := 0; i < nUnbonds; i++ {
|
||||
got := deliverer.unbond(txUndelegate)
|
||||
assert.NoError(t, got, "expected tx %d to be ok, got %v", i, got)
|
||||
|
||||
//Check that the accounts and the bond account have the appropriate values
|
||||
candidates := loadCandidates(deliverer.store)
|
||||
candidates := mapper.loadCandidates()
|
||||
expectedBond := initBond - int64(i+1)*unbondShares // +1 since we send 1 at the start of loop
|
||||
expectedSender := initSender + (initBond - expectedBond)
|
||||
gotBonded := candidates[0].Liabilities.Evaluate()
|
||||
gotHolder := accStore[string(holder.Address)]
|
||||
gotSender := accStore[string(deliverer.sender.Address)]
|
||||
gotSender := accStore[string(deliverer.sender)]
|
||||
|
||||
assert.Equal(t, expectedBond, gotBonded, "%v, %v", expectedBond, gotBonded)
|
||||
assert.Equal(t, expectedBond, gotHolder, "%v, %v", expectedBond, gotHolder)
|
||||
assert.Equal(t, expectedSender, gotSender, "%v, %v", expectedSender, gotSender)
|
||||
}
|
||||
|
||||
|
@ -171,7 +130,7 @@ func TestIncrementsMsgUnbond(t *testing.T) {
|
|||
}
|
||||
for _, c := range errorCases {
|
||||
unbondShares := strconv.Itoa(int(c))
|
||||
txUndelegate := newMsgUnbond(unbondShares, pks[0])
|
||||
txUndelegate := NewMsgUnbond(addrs[0], unbondShares)
|
||||
got = deliverer.unbond(txUndelegate)
|
||||
assert.Error(t, got, "expected unbond tx to fail")
|
||||
}
|
||||
|
@ -179,51 +138,51 @@ func TestIncrementsMsgUnbond(t *testing.T) {
|
|||
leftBonded := initBond - unbondShares*int64(nUnbonds)
|
||||
|
||||
// should be unable to unbond one more than we have
|
||||
txUndelegate = newMsgUnbond(strconv.Itoa(int(leftBonded)+1), pks[0])
|
||||
txUndelegate = NewMsgUnbond(addrs[0], strconv.Itoa(int(leftBonded)+1))
|
||||
got = deliverer.unbond(txUndelegate)
|
||||
assert.Error(t, got, "expected unbond tx to fail")
|
||||
|
||||
// should be able to unbond just what we have
|
||||
txUndelegate = newMsgUnbond(strconv.Itoa(int(leftBonded)), pks[0])
|
||||
txUndelegate = NewMsgUnbond(addrs[0], strconv.Itoa(int(leftBonded)))
|
||||
got = deliverer.unbond(txUndelegate)
|
||||
assert.NoError(t, got, "expected unbond tx to pass")
|
||||
}
|
||||
|
||||
func TestMultipleMsgDeclareCandidacy(t *testing.T) {
|
||||
initSender := int64(1000)
|
||||
senders, accStore := initAccounts(3, initSender)
|
||||
pubKeys := []crypto.PubKey{pks[0], pks[1], pks[2]}
|
||||
deliverer := newDeliver(t, senders[0], accStore)
|
||||
accStore := initAccounts(initSender)
|
||||
addrs := []sdk.Address{addrs[0], addrs[1], addrs[2]}
|
||||
mapper, deliverer := createTestInput(t, addrs[0], false)
|
||||
|
||||
// bond them all
|
||||
for i, sender := range senders {
|
||||
txDeclareCandidacy := newTestMsgDeclareCandidacy(10, pubKeys[i])
|
||||
deliverer.sender = sender
|
||||
for i, addr := range addrs {
|
||||
txDeclareCandidacy := newTestMsgDeclareCandidacy(addrs[i], pks[i], 10)
|
||||
deliverer.sender = addr
|
||||
got := deliverer.declareCandidacy(txDeclareCandidacy)
|
||||
assert.NoError(t, got, "expected tx %d to be ok, got %v", i, got)
|
||||
|
||||
//Check that the account is bonded
|
||||
candidates := loadCandidates(deliverer.store)
|
||||
candidates := mapper.loadCandidates()
|
||||
val := candidates[i]
|
||||
balanceGot, balanceExpd := accStore[string(val.Owner.Address)], initSender-10
|
||||
balanceGot, balanceExpd := accStore[string(val.Address)], initSender-10
|
||||
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, balanceExpd, balanceGot, "expected account to have %d, got %d", balanceExpd, balanceGot)
|
||||
}
|
||||
|
||||
// unbond them all
|
||||
for i, sender := range senders {
|
||||
candidatePre := loadCandidate(deliverer.store, pubKeys[i])
|
||||
txUndelegate := newMsgUnbond("10", pubKeys[i])
|
||||
deliverer.sender = sender
|
||||
for i, addr := range addrs {
|
||||
candidatePre := mapper.loadCandidate(addrs[i])
|
||||
txUndelegate := NewMsgUnbond(addrs[i], "10")
|
||||
deliverer.sender = addr
|
||||
got := deliverer.unbond(txUndelegate)
|
||||
assert.NoError(t, got, "expected tx %d to be ok, got %v", i, got)
|
||||
|
||||
//Check that the account is unbonded
|
||||
candidates := loadCandidates(deliverer.store)
|
||||
assert.Equal(t, len(senders)-(i+1), len(candidates), "expected %d candidates got %d", len(senders)-(i+1), len(candidates))
|
||||
candidates := mapper.loadCandidates()
|
||||
assert.Equal(t, len(addrs)-(i+1), len(candidates), "expected %d candidates got %d", len(addrs)-(i+1), len(candidates))
|
||||
|
||||
candidatePost := loadCandidate(deliverer.store, pubKeys[i])
|
||||
candidatePost := mapper.loadCandidate(addrs[i])
|
||||
balanceGot, balanceExpd := accStore[string(candidatePre.Owner.Address)], initSender
|
||||
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)
|
||||
|
@ -231,58 +190,58 @@ func TestMultipleMsgDeclareCandidacy(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestMultipleMsgDelegate(t *testing.T) {
|
||||
accounts, accStore := initAccounts(3, 1000)
|
||||
sender, delegators := accounts[0], accounts[1:]
|
||||
deliverer := newDeliver(t, sender, accStore)
|
||||
accStore := initAccounts(1000)
|
||||
sender, delegators := addrs[0], addrs[1:]
|
||||
mapper, deliverer := createTestInput(t, addrs[0], false)
|
||||
|
||||
//first make a candidate
|
||||
txDeclareCandidacy := newTestMsgDeclareCandidacy(10, pks[0])
|
||||
txDeclareCandidacy := newTestMsgDeclareCandidacy(addrs[0], pks[0], 10)
|
||||
got := deliverer.declareCandidacy(txDeclareCandidacy)
|
||||
require.NoError(t, got, "expected tx to be ok, got %v", got)
|
||||
|
||||
// delegate multiple parties
|
||||
for i, delegator := range delegators {
|
||||
txDelegate := newTestMsgDelegate(10, pks[0])
|
||||
txDelegate := newTestMsgDelegate(10, addrs[0])
|
||||
deliverer.sender = delegator
|
||||
got := deliverer.delegate(txDelegate)
|
||||
require.NoError(t, got, "expected tx %d to be ok, got %v", i, got)
|
||||
|
||||
//Check that the account is bonded
|
||||
bond := loadDelegatorBond(deliverer.store, delegator, pks[0])
|
||||
bond := mapper.loadDelegatorBond(delegator, addrs[0])
|
||||
assert.NotNil(t, bond, "expected delegatee bond %d to exist", bond)
|
||||
}
|
||||
|
||||
// unbond them all
|
||||
for i, delegator := range delegators {
|
||||
txUndelegate := newMsgUnbond("10", pks[0])
|
||||
txUndelegate := NewMsgUnbond(addrs[0], "10")
|
||||
deliverer.sender = delegator
|
||||
got := deliverer.unbond(txUndelegate)
|
||||
require.NoError(t, got, "expected tx %d to be ok, got %v", i, got)
|
||||
|
||||
//Check that the account is unbonded
|
||||
bond := loadDelegatorBond(deliverer.store, delegator, pks[0])
|
||||
bond := mapper.loadDelegatorBond(delegator, addrs[0])
|
||||
assert.Nil(t, bond, "expected delegatee bond %d to be nil", bond)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVoidCandidacy(t *testing.T) {
|
||||
accounts, accStore := initAccounts(2, 1000) // for accounts
|
||||
sender, delegator := accounts[0], accounts[1]
|
||||
deliverer := newDeliver(t, sender, accStore)
|
||||
accStore := initAccounts(1000) // for accounts
|
||||
sender, delegator := addrs[0], addrs[1]
|
||||
_, deliverer := createTestInput(t, addrs[0], false)
|
||||
|
||||
// create the candidate
|
||||
txDeclareCandidacy := newTestMsgDeclareCandidacy(10, pks[0])
|
||||
txDeclareCandidacy := newTestMsgDeclareCandidacy(addrs[0], pks[0], 10)
|
||||
got := deliverer.declareCandidacy(txDeclareCandidacy)
|
||||
require.NoError(t, got, "expected no error on runMsgDeclareCandidacy")
|
||||
|
||||
// bond a delegator
|
||||
txDelegate := newTestMsgDelegate(10, pks[0])
|
||||
txDelegate := newTestMsgDelegate(10, addrs[0])
|
||||
deliverer.sender = delegator
|
||||
got = deliverer.delegate(txDelegate)
|
||||
require.NoError(t, got, "expected ok, got %v", got)
|
||||
|
||||
// unbond the candidates bond portion
|
||||
txUndelegate := newMsgUnbond("10", pks[0])
|
||||
txUndelegate := NewMsgUnbond(addrs[0], "10")
|
||||
deliverer.sender = sender
|
||||
got = deliverer.unbond(txUndelegate)
|
||||
require.NoError(t, got, "expected no error on runMsgDeclareCandidacy")
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -26,12 +26,12 @@ import (
|
|||
//candidates := candidatesFromActors(actors, []int64{400, 200, 100, 10, 1})
|
||||
|
||||
//// test a basic change in voting power
|
||||
//candidates[0].Assets = types.NewRat(500)
|
||||
//candidates[0].Assets = sdk.NewRat(500)
|
||||
//candidates.updateVotingPower(store, gs, params)
|
||||
//assert.Equal(int64(500), candidates[0].VotingPower.Evaluate(), "%v", candidates[0])
|
||||
|
||||
//// test a swap in voting power
|
||||
//candidates[1].Assets = types.NewRat(600)
|
||||
//candidates[1].Assets = sdk.NewRat(600)
|
||||
//candidates.updateVotingPower(store, gs, params)
|
||||
//assert.Equal(int64(600), candidates[0].VotingPower.Evaluate(), "%v", candidates[0])
|
||||
//assert.Equal(int64(500), candidates[1].VotingPower.Evaluate(), "%v", candidates[1])
|
||||
|
@ -46,11 +46,11 @@ import (
|
|||
//func TestValidatorsChanged(t *testing.T) {
|
||||
//require := require.New(t)
|
||||
|
||||
//v1 := (&Candidate{PubKey: pks[0], VotingPower: types.NewRat(10)}).validator()
|
||||
//v2 := (&Candidate{PubKey: pks[1], VotingPower: types.NewRat(10)}).validator()
|
||||
//v3 := (&Candidate{PubKey: pks[2], VotingPower: types.NewRat(10)}).validator()
|
||||
//v4 := (&Candidate{PubKey: pks[3], VotingPower: types.NewRat(10)}).validator()
|
||||
//v5 := (&Candidate{PubKey: pks[4], VotingPower: types.NewRat(10)}).validator()
|
||||
//v1 := (&Candidate{PubKey: pks[0], VotingPower: sdk.NewRat(10)}).validator()
|
||||
//v2 := (&Candidate{PubKey: pks[1], VotingPower: sdk.NewRat(10)}).validator()
|
||||
//v3 := (&Candidate{PubKey: pks[2], VotingPower: sdk.NewRat(10)}).validator()
|
||||
//v4 := (&Candidate{PubKey: pks[3], VotingPower: sdk.NewRat(10)}).validator()
|
||||
//v5 := (&Candidate{PubKey: pks[4], VotingPower: sdk.NewRat(10)}).validator()
|
||||
|
||||
//// test from nothing to something
|
||||
//vs1 := []Validator{}
|
||||
|
@ -75,14 +75,14 @@ import (
|
|||
//require.ZeroRat(len(changed))
|
||||
|
||||
//// test single value change
|
||||
//vs2[2].VotingPower = types.OneRat
|
||||
//vs2[2].VotingPower = sdk.OneRat
|
||||
//changed = vs1.validatorsUpdated(vs2)
|
||||
//require.Equal(1, len(changed))
|
||||
//testChange(t, vs2[2], changed[0])
|
||||
|
||||
//// test multiple value change
|
||||
//vs2[0].VotingPower = types.NewRat(11)
|
||||
//vs2[2].VotingPower = types.NewRat(5)
|
||||
//vs2[0].VotingPower = sdk.NewRat(11)
|
||||
//vs2[2].VotingPower = sdk.NewRat(5)
|
||||
//changed = vs1.validatorsUpdated(vs2)
|
||||
//require.Equal(2, len(changed))
|
||||
//testChange(t, vs2[0], changed[0])
|
||||
|
@ -118,7 +118,7 @@ import (
|
|||
//testRemove(t, vs1[1], changed[0])
|
||||
//testRemove(t, vs1[2], changed[1])
|
||||
|
||||
//// test many types of changes //vs2 = []Validator{v1, v3, v4, v5} //vs2[2].VotingPower = types.NewRat(11) //changed = vs1.validatorsUpdated(vs2) //require.Equal(4, len(changed), "%v", changed) // change 1, remove 1, add 2 //testRemove(t, vs1[1], changed[0]) //testChange(t, vs2[1], changed[1]) //testChange(t, vs2[2], changed[2]) //testChange(t, vs2[3], changed[3]) //} //func TestUpdateValidatorSet(t *testing.T) { //assert, require := assert.New(t), require.New(t) //store := initTestStore(t) //params := loadParams(store) //gs := loadGlobalState(store) //N := 5
|
||||
//// test many sdk of changes //vs2 = []Validator{v1, v3, v4, v5} //vs2[2].VotingPower = sdk.NewRat(11) //changed = vs1.validatorsUpdated(vs2) //require.Equal(4, len(changed), "%v", changed) // change 1, remove 1, add 2 //testRemove(t, vs1[1], changed[0]) //testChange(t, vs2[1], changed[1]) //testChange(t, vs2[2], changed[2]) //testChange(t, vs2[3], changed[3]) //} //func TestUpdateValidatorSet(t *testing.T) { //assert, require := assert.New(t), require.New(t) //store := initTestStore(t) //params := loadParams(store) //gs := loadGlobalState(store) //N := 5
|
||||
//actors := newAddrs(N)
|
||||
//candidates := candidatesFromActors(actors, []int64{400, 200, 100, 10, 1})
|
||||
//for _, c := range candidates {
|
||||
|
@ -141,11 +141,11 @@ import (
|
|||
//assert.Equal(int64(0), candidates[4].VotingPower.Evaluate())
|
||||
|
||||
//// mess with the power's of the candidates and test
|
||||
//candidates[0].Assets = types.NewRat(10)
|
||||
//candidates[1].Assets = types.NewRat(600)
|
||||
//candidates[2].Assets = types.NewRat(1000)
|
||||
//candidates[3].Assets = types.OneRat
|
||||
//candidates[4].Assets = types.NewRat(10)
|
||||
//candidates[0].Assets = sdk.NewRat(10)
|
||||
//candidates[1].Assets = sdk.NewRat(600)
|
||||
//candidates[2].Assets = sdk.NewRat(1000)
|
||||
//candidates[3].Assets = sdk.OneRat
|
||||
//candidates[4].Assets = sdk.NewRat(10)
|
||||
//for _, c := range candidates {
|
||||
//saveCandidate(store, c)
|
||||
//}
|
||||
|
@ -161,12 +161,10 @@ import (
|
|||
//}
|
||||
|
||||
func TestState(t *testing.T) {
|
||||
store := createTestInput(t)
|
||||
mapper, _ := createTestInput(t, nil, false)
|
||||
|
||||
//delegator := crypto.Address{[]byte("addressdelegator")}
|
||||
//validator := crypto.Address{[]byte("addressvalidator")}
|
||||
delegator := []byte("addressdelegator")
|
||||
validator := []byte("addressvalidator")
|
||||
addrDel := sdk.Address([]byte("addressdelegator"))
|
||||
addrVal := sdk.Address([]byte("addressvalidator"))
|
||||
//pk := newPubKey("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AFB57")
|
||||
pk := crypto.GenPrivKeyEd25519().PubKey()
|
||||
|
||||
|
@ -175,52 +173,52 @@ func TestState(t *testing.T) {
|
|||
|
||||
// XXX expand to include both liabilities and assets use/test all candidate fields
|
||||
candidate := &Candidate{
|
||||
Owner: validator,
|
||||
Address: addrVal,
|
||||
PubKey: pk,
|
||||
Assets: types.NewRat(9),
|
||||
Liabilities: types.NewRat(9),
|
||||
VotingPower: types.ZeroRat,
|
||||
Assets: sdk.NewRat(9),
|
||||
Liabilities: sdk.NewRat(9),
|
||||
VotingPower: sdk.ZeroRat,
|
||||
}
|
||||
|
||||
candidatesEqual := func(c1, c2 *Candidate) bool {
|
||||
return c1.Status == c2.Status &&
|
||||
c1.PubKey.Equals(c2.PubKey) &&
|
||||
bytes.Equal(c1.Owner, c2.Owner) &&
|
||||
bytes.Equal(c1.Address, c2.Address) &&
|
||||
c1.Assets.Equal(c2.Assets) &&
|
||||
c1.Liabilities.Equal(c2.Liabilities) &&
|
||||
c1.VotingPower.Equal(c2.VotingPower) &&
|
||||
c1.Description == c2.Description
|
||||
}
|
||||
|
||||
// check the empty store first
|
||||
resCand := loadCandidate(store, pk)
|
||||
// check the empty mapper first
|
||||
resCand := mapper.loadCandidate(addrVal)
|
||||
assert.Nil(t, resCand)
|
||||
resPks := loadCandidates(store)
|
||||
resPks := mapper.loadCandidates()
|
||||
assert.Zero(t, len(resPks))
|
||||
|
||||
// set and retrieve a record
|
||||
saveCandidate(store, candidate)
|
||||
resCand = loadCandidate(store, pk)
|
||||
mapper.saveCandidate(candidate)
|
||||
resCand = mapper.loadCandidate(addrVal)
|
||||
//assert.Equal(candidate, resCand)
|
||||
assert.True(t, candidatesEqual(candidate, resCand), "%#v \n %#v", resCand, candidate)
|
||||
|
||||
// modify a records, save, and retrieve
|
||||
candidate.Liabilities = types.NewRat(99)
|
||||
saveCandidate(store, candidate)
|
||||
resCand = loadCandidate(store, pk)
|
||||
candidate.Liabilities = sdk.NewRat(99)
|
||||
mapper.saveCandidate(candidate)
|
||||
resCand = mapper.loadCandidate(addrVal)
|
||||
assert.True(t, candidatesEqual(candidate, resCand))
|
||||
|
||||
// also test that the pubkey has been added to pubkey list
|
||||
resPks = loadCandidates(store)
|
||||
resPks = mapper.loadCandidates()
|
||||
require.Equal(t, 1, len(resPks))
|
||||
assert.Equal(t, pk, resPks[0].PubKey)
|
||||
assert.Equal(t, addrVal, resPks[0].PubKey)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Bond checks
|
||||
|
||||
bond := &DelegatorBond{
|
||||
PubKey: pk,
|
||||
Shares: types.NewRat(9),
|
||||
Address: addrDel,
|
||||
Shares: sdk.NewRat(9),
|
||||
}
|
||||
|
||||
bondsEqual := func(b1, b2 *DelegatorBond) bool {
|
||||
|
@ -228,19 +226,19 @@ func TestState(t *testing.T) {
|
|||
b1.Shares == b2.Shares
|
||||
}
|
||||
|
||||
//check the empty store first
|
||||
resBond := loadDelegatorBond(store, delegator, pk)
|
||||
//check the empty mapper first
|
||||
resBond := mapper.loadDelegatorBond(addrDel, addrVal)
|
||||
assert.Nil(t, resBond)
|
||||
|
||||
//Set and retrieve a record
|
||||
saveDelegatorBond(store, delegator, bond)
|
||||
resBond = loadDelegatorBond(store, delegator, pk)
|
||||
mapper.saveDelegatorBond(addrDel, bond)
|
||||
resBond = mapper.loadDelegatorBond(addrDel, addrVal)
|
||||
assert.True(t, bondsEqual(bond, resBond))
|
||||
|
||||
//modify a records, save, and retrieve
|
||||
bond.Shares = types.NewRat(99)
|
||||
saveDelegatorBond(store, delegator, bond)
|
||||
resBond = loadDelegatorBond(store, delegator, pk)
|
||||
bond.Shares = sdk.NewRat(99)
|
||||
mapper.saveDelegatorBond(addrDel, bond)
|
||||
resBond = mapper.loadDelegatorBond(addrDel, addrVal)
|
||||
assert.True(t, bondsEqual(bond, resBond))
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -248,25 +246,25 @@ func TestState(t *testing.T) {
|
|||
|
||||
params := defaultParams()
|
||||
|
||||
//check that the empty store loads the default
|
||||
resParams := loadParams(store)
|
||||
//check that the empty mapper loads the default
|
||||
resParams := mapper.loadParams()
|
||||
assert.Equal(t, params, resParams)
|
||||
|
||||
//modify a params, save, and retrieve
|
||||
params.MaxVals = 777
|
||||
saveParams(store, params)
|
||||
resParams = loadParams(store)
|
||||
mapper.saveParams(params)
|
||||
resParams = mapper.loadParams()
|
||||
assert.Equal(t, params, resParams)
|
||||
}
|
||||
|
||||
func TestGetValidators(t *testing.T) {
|
||||
store, ctx, key := createTestInput(t, false)
|
||||
mapper, _ := createTestInput(t, nil, false)
|
||||
N := 5
|
||||
addrs := newAddrs(N)
|
||||
candidatesFromActors(store, addrs, []int64{400, 200, 0, 0, 0})
|
||||
candidatesFromAddrs(mapper, addrs, []int64{400, 200, 0, 0, 0})
|
||||
|
||||
validators := getValidators(store, 5)
|
||||
validators := mapper.getValidators(5)
|
||||
require.Equal(t, 2, len(validators))
|
||||
assert.Equal(t, pks[0], validators[0].PubKey)
|
||||
assert.Equal(t, pks[1], validators[1].PubKey)
|
||||
assert.Equal(t, addrs[0], validators[0].Address)
|
||||
assert.Equal(t, addrs[1], validators[1].Address)
|
||||
}
|
||||
|
|
|
@ -2,17 +2,21 @@ package stake
|
|||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
oldwire "github.com/tendermint/go-wire"
|
||||
dbm "github.com/tendermint/tmlibs/db"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/examples/basecoin/types"
|
||||
"github.com/cosmos/cosmos-sdk/store"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/wire"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
)
|
||||
|
||||
func subspace(prefix []byte) (start, end []byte) {
|
||||
|
@ -22,25 +26,83 @@ func subspace(prefix []byte) (start, end []byte) {
|
|||
return prefix, end
|
||||
}
|
||||
|
||||
func createTestInput(t *testing.T, isCheckTx bool) (sdk.KVStore, sdk.Context, sdk.StoreKey) {
|
||||
// custom tx codec
|
||||
// TODO: use new go-wire
|
||||
func makeTestCodec() *wire.Codec {
|
||||
|
||||
const msgTypeSend = 0x1
|
||||
const msgTypeIssue = 0x2
|
||||
const msgTypeDeclareCandidacy = 0x3
|
||||
const msgTypeEditCandidacy = 0x4
|
||||
const msgTypeDelegate = 0x5
|
||||
const msgTypeUnbond = 0x6
|
||||
var _ = oldwire.RegisterInterface(
|
||||
struct{ sdk.Msg }{},
|
||||
oldwire.ConcreteType{bank.SendMsg{}, msgTypeSend},
|
||||
oldwire.ConcreteType{bank.IssueMsg{}, msgTypeIssue},
|
||||
oldwire.ConcreteType{MsgDeclareCandidacy{}, msgTypeDeclareCandidacy},
|
||||
oldwire.ConcreteType{MsgEditCandidacy{}, msgTypeEditCandidacy},
|
||||
oldwire.ConcreteType{MsgDelegate{}, msgTypeDelegate},
|
||||
oldwire.ConcreteType{MsgUnbond{}, msgTypeUnbond},
|
||||
)
|
||||
|
||||
const accTypeApp = 0x1
|
||||
var _ = oldwire.RegisterInterface(
|
||||
struct{ sdk.Account }{},
|
||||
oldwire.ConcreteType{&types.AppAccount{}, accTypeApp},
|
||||
)
|
||||
cdc := wire.NewCodec()
|
||||
|
||||
// cdc.RegisterInterface((*sdk.Msg)(nil), nil)
|
||||
// bank.RegisterWire(cdc) // Register bank.[SendMsg,IssueMsg] types.
|
||||
// crypto.RegisterWire(cdc) // Register crypto.[PubKey,PrivKey,Signature] types.
|
||||
return cdc
|
||||
}
|
||||
|
||||
func paramsNoInflation() Params {
|
||||
return Params{
|
||||
InflationRateChange: sdk.ZeroRat,
|
||||
InflationMax: sdk.ZeroRat,
|
||||
InflationMin: sdk.ZeroRat,
|
||||
GoalBonded: sdk.NewRat(67, 100),
|
||||
MaxVals: 100,
|
||||
BondDenom: "fermion",
|
||||
GasDeclareCandidacy: 20,
|
||||
GasEditCandidacy: 20,
|
||||
GasDelegate: 20,
|
||||
GasUnbond: 20,
|
||||
}
|
||||
}
|
||||
|
||||
// hogpodge of all sorts of input required for testing
|
||||
//func createTestInput(t *testing.T, sender sdk.Address, isCheckTx bool) (sdk.KVStore, sdk.Context, sdk.StoreKey, Mapper, bank.CoinKeeper, transact) {
|
||||
func createTestInput(t *testing.T, sender sdk.Address, isCheckTx bool) (Mapper, transact) {
|
||||
db := dbm.NewMemDB()
|
||||
key := sdk.NewKVStoreKey("stake")
|
||||
keyMain := sdk.NewKVStoreKey("main")
|
||||
keyStake := sdk.NewKVStoreKey("stake")
|
||||
|
||||
ms := store.NewCommitMultiStore(db)
|
||||
ms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db)
|
||||
ms.MountStoreWithDB(keyStake, sdk.StoreTypeIAVL, db)
|
||||
err := ms.LoadLatestVersion()
|
||||
require.Nil(t, err)
|
||||
|
||||
ctx := sdk.NewContext(ms, abci.Header{ChainID: "foochainid"}, isCheckTx, nil)
|
||||
store := ms.GetKVStore(key)
|
||||
return store, ctx, key
|
||||
}
|
||||
store := ms.GetKVStore(keyStake)
|
||||
|
||||
func newAddrs(n int) (addrs []crypto.Address) {
|
||||
for i := 0; i < n; i++ {
|
||||
addrs = append(addrs, []byte(fmt.Sprintf("addr%d", i)))
|
||||
}
|
||||
return
|
||||
cdc := makeTestCodec()
|
||||
mapper := NewMapper(ctx, cdc, keyStake)
|
||||
|
||||
accountMapper := auth.NewAccountMapperSealed(
|
||||
keyMain, // target store
|
||||
&auth.BaseAccount{}, // prototype
|
||||
)
|
||||
ck := bank.NewCoinKeeper(accountMapper)
|
||||
|
||||
params := paramsNoInflation()
|
||||
mapper.saveParams(params)
|
||||
tr := newTransact(ctx, sender, mapper, ck)
|
||||
|
||||
return mapper, tr
|
||||
}
|
||||
|
||||
func newPubKey(pk string) (res crypto.PubKey) {
|
||||
|
@ -54,8 +116,8 @@ func newPubKey(pk string) (res crypto.PubKey) {
|
|||
return pkEd.Wrap()
|
||||
}
|
||||
|
||||
// dummy pubkeys used for testing
|
||||
var pks = []crypto.PubKey{
|
||||
newPubKey("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AFB50"),
|
||||
newPubKey("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AFB51"),
|
||||
newPubKey("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AFB52"),
|
||||
newPubKey("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AFB53"),
|
||||
|
@ -65,12 +127,34 @@ var pks = []crypto.PubKey{
|
|||
newPubKey("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AFB57"),
|
||||
newPubKey("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AFB58"),
|
||||
newPubKey("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AFB59"),
|
||||
newPubKey("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AFB60"),
|
||||
}
|
||||
|
||||
// for incode address generation
|
||||
func testAddr(addr string) sdk.Address {
|
||||
res, err := sdk.GetAddress("0XA58856F0FD53BF058B4909A21AEC019107BA6160")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// dummy addresses used for testing
|
||||
var addrs = []sdk.Address{
|
||||
testAddr("0XA58856F0FD53BF058B4909A21AEC019107BA6160"),
|
||||
testAddr("0XA58856F0FD53BF058B4909A21AEC019107BA6161"),
|
||||
testAddr("0XA58856F0FD53BF058B4909A21AEC019107BA6162"),
|
||||
testAddr("0XA58856F0FD53BF058B4909A21AEC019107BA6163"),
|
||||
testAddr("0XA58856F0FD53BF058B4909A21AEC019107BA6164"),
|
||||
testAddr("0XA58856F0FD53BF058B4909A21AEC019107BA6165"),
|
||||
testAddr("0XA58856F0FD53BF058B4909A21AEC019107BA6166"),
|
||||
testAddr("0XA58856F0FD53BF058B4909A21AEC019107BA6167"),
|
||||
testAddr("0XA58856F0FD53BF058B4909A21AEC019107BA6168"),
|
||||
testAddr("0XA58856F0FD53BF058B4909A21AEC019107BA6169"),
|
||||
}
|
||||
|
||||
// NOTE: PubKey is supposed to be the binaryBytes of the crypto.PubKey
|
||||
// instead this is just being set the address here for testing purposes
|
||||
func candidatesFromActors(store sdk.KVStore, addrs []crypto.Address, amts []int64) {
|
||||
func candidatesFromAddrs(mapper Mapper, addrs []crypto.Address, amts []int64) {
|
||||
for i := 0; i < len(addrs); i++ {
|
||||
c := &Candidate{
|
||||
Status: Unbonded,
|
||||
|
@ -80,12 +164,10 @@ func candidatesFromActors(store sdk.KVStore, addrs []crypto.Address, amts []int6
|
|||
Liabilities: sdk.NewRat(amts[i]),
|
||||
VotingPower: sdk.NewRat(amts[i]),
|
||||
}
|
||||
saveCandidate(store, c)
|
||||
mapper.saveCandidate(c)
|
||||
}
|
||||
}
|
||||
|
||||
func saveCandidate(store sdk.KVStore, c *Candidate) {} // TODO
|
||||
|
||||
func candidatesFromActorsEmpty(addrs []crypto.Address) (candidates Candidates) {
|
||||
for i := 0; i < len(addrs); i++ {
|
||||
c := &Candidate{
|
||||
|
|
|
@ -49,8 +49,9 @@ func (msg MsgAddr) ValidateBasic() sdk.Error {
|
|||
type MsgDeclareCandidacy struct {
|
||||
MsgAddr
|
||||
Description
|
||||
Bond sdk.Coin `json:"bond"`
|
||||
PubKey crypto.PubKey `json:"pubkey"`
|
||||
Bond sdk.Coin `json:"bond"`
|
||||
Address sdk.Address `json:"address"`
|
||||
PubKey crypto.PubKey `json:"pubkey"`
|
||||
}
|
||||
|
||||
func NewMsgDeclareCandidacy(address sdk.Address, pubkey crypto.PubKey, bond sdk.Coin, description Description) MsgDeclareCandidacy {
|
||||
|
@ -58,6 +59,7 @@ func NewMsgDeclareCandidacy(address sdk.Address, pubkey crypto.PubKey, bond sdk.
|
|||
MsgAddr: NewMsgAddr(address),
|
||||
Description: description,
|
||||
Bond: bond,
|
||||
Address: address,
|
||||
PubKey: pubkey,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue