cosmos-sdk/x/stake/handler_test.go

250 lines
9.8 KiB
Go
Raw Normal View History

2018-02-23 15:57:31 -08:00
package stake
2018-03-29 07:49:18 -07:00
import (
"strconv"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
crypto "github.com/tendermint/go-crypto"
sdk "github.com/cosmos/cosmos-sdk/types"
)
//______________________________________________________________________
func newTestMsgDeclareCandidacy(address sdk.Address, pubKey crypto.PubKey, amt int64) MsgDeclareCandidacy {
return MsgDeclareCandidacy{
Description: Description{},
CandidateAddr: address,
Bond: sdk.Coin{"fermion", amt},
PubKey: pubKey,
}
}
func newTestMsgDelegate(amt int64, delegatorAddr, candidateAddr sdk.Address) MsgDelegate {
return MsgDelegate{
DelegatorAddr: delegatorAddr,
CandidateAddr: candidateAddr,
Bond: sdk.Coin{"fermion", amt},
}
}
func TestDuplicatesMsgDeclareCandidacy(t *testing.T) {
2018-04-01 09:05:58 -07:00
ctx, _, keeper := createTestInput(t, false, 1000)
2018-03-29 07:49:18 -07:00
msgDeclareCandidacy := newTestMsgDeclareCandidacy(addrs[0], pks[0], 10)
2018-03-30 10:28:51 -07:00
got := handleMsgDeclareCandidacy(ctx, msgDeclareCandidacy, keeper)
assert.True(t, got.IsOK(), "%v", got)
2018-04-01 09:05:58 -07:00
// one candidate cannot bond twice
2018-03-30 10:28:51 -07:00
msgDeclareCandidacy.PubKey = pks[1]
got = handleMsgDeclareCandidacy(ctx, msgDeclareCandidacy, keeper)
assert.False(t, got.IsOK(), "%v", got)
2018-03-29 07:49:18 -07:00
}
func TestIncrementsMsgDelegate(t *testing.T) {
2018-04-01 09:05:58 -07:00
initBond := int64(1000)
ctx, accMapper, keeper := createTestInput(t, false, initBond)
params := keeper.GetParams(ctx)
2018-03-29 07:49:18 -07:00
bondAmount := int64(10)
2018-04-01 09:05:58 -07:00
candidateAddr, delegatorAddr := addrs[0], addrs[1]
// first declare candidacy
msgDeclareCandidacy := newTestMsgDeclareCandidacy(candidateAddr, pks[0], bondAmount)
got := handleMsgDeclareCandidacy(ctx, msgDeclareCandidacy, keeper)
assert.True(t, got.IsOK(), "expected declare candidacy msg to be ok, got %v", got)
expectedBond := bondAmount
2018-03-29 07:49:18 -07:00
// just send the same msgbond multiple times
2018-04-01 09:05:58 -07:00
msgDelegate := newTestMsgDelegate(bondAmount, delegatorAddr, candidateAddr)
2018-03-29 07:49:18 -07:00
for i := 0; i < 5; i++ {
2018-04-01 09:05:58 -07:00
got := handleMsgDelegate(ctx, msgDelegate, keeper)
2018-04-03 12:15:08 -07:00
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
2018-03-29 07:49:18 -07:00
//Check that the accounts and the bond account have the appropriate values
2018-04-01 09:05:58 -07:00
candidates := keeper.GetCandidates(ctx, 100)
2018-03-29 07:49:18 -07:00
expectedBond += bondAmount
2018-04-01 09:05:58 -07:00
expectedDelegator := initBond - expectedBond
2018-03-29 07:49:18 -07:00
gotBonded := candidates[0].Liabilities.Evaluate()
2018-04-01 09:05:58 -07:00
gotDelegator := accMapper.GetAccount(ctx, delegatorAddr).GetCoins().AmountOf(params.BondDenom)
2018-04-03 12:15:08 -07:00
require.Equal(t, expectedBond, gotBonded, "i: %v, %v, %v", i, expectedBond, gotBonded)
require.Equal(t, expectedDelegator, gotDelegator, "i: %v, %v, %v", i, expectedDelegator, gotDelegator) // XXX fix
2018-03-29 07:49:18 -07:00
}
}
func TestIncrementsMsgUnbond(t *testing.T) {
initBond := int64(1000)
2018-04-01 09:05:58 -07:00
ctx, accMapper, keeper := createTestInput(t, false, initBond)
params := keeper.GetParams(ctx)
// declare candidacy, delegate
candidateAddr, delegatorAddr := addrs[0], addrs[1]
msgDeclareCandidacy := newTestMsgDeclareCandidacy(candidateAddr, pks[0], initBond)
got := handleMsgDeclareCandidacy(ctx, msgDeclareCandidacy, keeper)
assert.True(t, got.IsOK(), "expected declare-candidacy to be ok, got %v", got)
msgDelegate := newTestMsgDelegate(initBond, delegatorAddr, candidateAddr)
got = handleMsgDelegate(ctx, msgDelegate, keeper)
assert.True(t, got.IsOK(), "expected delegation to be ok, got %v", got)
2018-03-29 07:49:18 -07:00
2018-04-01 09:05:58 -07:00
// just send the same msgUnbond multiple times
// TODO use decimals here
2018-03-29 07:49:18 -07:00
unbondShares, unbondSharesStr := int64(10), "10"
2018-04-01 09:05:58 -07:00
msgUnbond := NewMsgUnbond(delegatorAddr, candidateAddr, unbondSharesStr)
numUnbonds := 5
for i := 0; i < numUnbonds; i++ {
got := handleMsgUnbond(ctx, msgUnbond, keeper)
2018-04-03 12:15:08 -07:00
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
2018-03-29 07:49:18 -07:00
//Check that the accounts and the bond account have the appropriate values
2018-04-01 09:05:58 -07:00
candidate, found := keeper.GetCandidate(ctx, candidateAddr)
require.True(t, found)
expectedBond := initBond - int64(i+1)*unbondShares
expectedDelegator := initBond - expectedBond
gotBonded := candidate.Liabilities.Evaluate()
gotDelegator := accMapper.GetAccount(ctx, delegatorAddr).GetCoins().AmountOf(params.BondDenom)
2018-03-29 07:49:18 -07:00
2018-04-03 12:15:08 -07:00
require.Equal(t, expectedBond, gotBonded, "%v, %v", expectedBond, gotBonded)
require.Equal(t, expectedDelegator, gotDelegator, "%v, %v", expectedDelegator, gotDelegator)
2018-03-29 07:49:18 -07:00
}
// these are more than we have bonded now
errorCases := []int64{
//1<<64 - 1, // more than int64
//1<<63 + 1, // more than int64
1<<63 - 1,
1 << 31,
initBond,
}
for _, c := range errorCases {
unbondShares := strconv.Itoa(int(c))
2018-04-01 09:05:58 -07:00
msgUnbond := NewMsgUnbond(delegatorAddr, candidateAddr, unbondShares)
got = handleMsgUnbond(ctx, msgUnbond, keeper)
2018-04-03 12:15:08 -07:00
require.False(t, got.IsOK(), "expected unbond msg to fail")
2018-03-29 07:49:18 -07:00
}
2018-04-01 09:05:58 -07:00
leftBonded := initBond - unbondShares*int64(numUnbonds)
2018-03-29 07:49:18 -07:00
// should be unable to unbond one more than we have
2018-04-01 09:05:58 -07:00
msgUnbond = NewMsgUnbond(delegatorAddr, candidateAddr, strconv.Itoa(int(leftBonded)+1))
got = handleMsgUnbond(ctx, msgUnbond, keeper)
assert.False(t, got.IsOK(), "expected unbond msg to fail")
2018-03-29 07:49:18 -07:00
// should be able to unbond just what we have
2018-04-01 09:05:58 -07:00
msgUnbond = NewMsgUnbond(delegatorAddr, candidateAddr, strconv.Itoa(int(leftBonded)))
got = handleMsgUnbond(ctx, msgUnbond, keeper)
assert.True(t, got.IsOK(), "expected unbond msg to pass")
2018-03-29 07:49:18 -07:00
}
func TestMultipleMsgDeclareCandidacy(t *testing.T) {
2018-04-01 09:05:58 -07:00
initBond := int64(1000)
ctx, accMapper, keeper := createTestInput(t, false, initBond)
params := keeper.GetParams(ctx)
candidateAddrs := []sdk.Address{addrs[0], addrs[1], addrs[2]}
2018-03-29 07:49:18 -07:00
// bond them all
2018-04-01 09:05:58 -07:00
for i, candidateAddr := range candidateAddrs {
msgDeclareCandidacy := newTestMsgDeclareCandidacy(candidateAddr, pks[i], 10)
got := handleMsgDeclareCandidacy(ctx, msgDeclareCandidacy, keeper)
2018-04-03 12:15:08 -07:00
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
2018-03-29 07:49:18 -07:00
//Check that the account is bonded
2018-04-01 09:05:58 -07:00
candidates := keeper.GetCandidates(ctx, 100)
2018-03-29 07:49:18 -07:00
require.Equal(t, i, len(candidates))
val := candidates[i]
2018-04-01 09:05:58 -07:00
balanceExpd := initBond - 10
balanceGot := accMapper.GetAccount(ctx, val.Address).GetCoins().AmountOf(params.BondDenom)
2018-04-03 12:15:08 -07:00
require.Equal(t, i+1, len(candidates), "expected %d candidates got %d, candidates: %v", i+1, len(candidates), candidates)
require.Equal(t, 10, int(val.Liabilities.Evaluate()), "expected %d shares, got %d", 10, val.Liabilities)
require.Equal(t, balanceExpd, balanceGot, "expected account to have %d, got %d", balanceExpd, balanceGot)
2018-03-29 07:49:18 -07:00
}
// unbond them all
2018-04-01 09:05:58 -07:00
for i, candidateAddr := range candidateAddrs {
candidatePre, found := keeper.GetCandidate(ctx, candidateAddr)
require.True(t, found)
msgUnbond := NewMsgUnbond(candidateAddr, candidateAddr, "10") // self-delegation
got := handleMsgUnbond(ctx, msgUnbond, keeper)
2018-04-03 12:15:08 -07:00
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
2018-03-29 07:49:18 -07:00
//Check that the account is unbonded
2018-04-01 09:05:58 -07:00
candidates := keeper.GetCandidates(ctx, 100)
2018-04-03 12:15:08 -07:00
require.Equal(t, len(candidateAddrs)-(i+1), len(candidates),
2018-04-01 09:05:58 -07:00
"expected %d candidates got %d", len(candidateAddrs)-(i+1), len(candidates))
candidatePost, found := keeper.GetCandidate(ctx, candidateAddr)
require.True(t, found)
balanceExpd := initBond
balanceGot := accMapper.GetAccount(ctx, candidatePre.Address).GetCoins().AmountOf(params.BondDenom)
2018-04-03 12:15:08 -07:00
require.Nil(t, candidatePost, "expected nil candidate retrieve, got %d", 0, candidatePost)
require.Equal(t, balanceExpd, balanceGot, "expected account to have %d, got %d", balanceExpd, balanceGot)
2018-03-29 07:49:18 -07:00
}
}
func TestMultipleMsgDelegate(t *testing.T) {
2018-04-01 09:05:58 -07:00
ctx, _, keeper := createTestInput(t, false, 0)
candidateAddr, delegatorAddrs := addrs[0], addrs[1:]
2018-03-29 07:49:18 -07:00
//first make a candidate
2018-04-01 09:05:58 -07:00
msgDeclareCandidacy := newTestMsgDeclareCandidacy(candidateAddr, pks[0], 10)
got := handleMsgDeclareCandidacy(ctx, msgDeclareCandidacy, keeper)
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
2018-03-29 07:49:18 -07:00
// delegate multiple parties
2018-04-01 09:05:58 -07:00
for i, delegatorAddr := range delegatorAddrs {
msgDelegate := newTestMsgDelegate(10, delegatorAddr, candidateAddr)
got := handleMsgDelegate(ctx, msgDelegate, keeper)
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
2018-03-29 07:49:18 -07:00
//Check that the account is bonded
2018-04-01 09:05:58 -07:00
bond, found := keeper.getDelegatorBond(ctx, delegatorAddr, candidateAddr)
require.True(t, found)
2018-04-03 12:15:08 -07:00
require.NotNil(t, bond, "expected delegatee bond %d to exist", bond)
2018-03-29 07:49:18 -07:00
}
// unbond them all
2018-04-01 09:05:58 -07:00
for i, delegatorAddr := range delegatorAddrs {
msgUnbond := NewMsgUnbond(delegatorAddr, candidateAddr, "10")
got := handleMsgUnbond(ctx, msgUnbond, keeper)
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
2018-03-29 07:49:18 -07:00
//Check that the account is unbonded
2018-04-01 09:05:58 -07:00
_, found := keeper.getDelegatorBond(ctx, delegatorAddr, candidateAddr)
require.False(t, found)
2018-03-29 07:49:18 -07:00
}
}
func TestVoidCandidacy(t *testing.T) {
2018-04-01 09:05:58 -07:00
candidateAddr, delegatorAddr := addrs[0], addrs[1]
ctx, _, keeper := createTestInput(t, false, 0)
2018-03-29 07:49:18 -07:00
// create the candidate
2018-04-01 09:05:58 -07:00
msgDeclareCandidacy := newTestMsgDeclareCandidacy(candidateAddr, pks[0], 10)
got := handleMsgDeclareCandidacy(ctx, msgDeclareCandidacy, keeper)
require.True(t, got.IsOK(), "expected no error on runMsgDeclareCandidacy")
2018-03-29 07:49:18 -07:00
// bond a delegator
2018-04-01 09:05:58 -07:00
msgDelegate := newTestMsgDelegate(10, delegatorAddr, candidateAddr)
got = handleMsgDelegate(ctx, msgDelegate, keeper)
require.True(t, got.IsOK(), "expected ok, got %v", got)
2018-03-29 07:49:18 -07:00
// unbond the candidates bond portion
2018-04-01 09:05:58 -07:00
msgUnbond := NewMsgUnbond(delegatorAddr, candidateAddr, "10")
got = handleMsgUnbond(ctx, msgUnbond, keeper)
require.True(t, got.IsOK(), "expected no error on runMsgDeclareCandidacy")
2018-03-29 07:49:18 -07:00
// test that this pubkey cannot yet be bonded too
2018-04-01 09:05:58 -07:00
got = handleMsgDelegate(ctx, msgDelegate, keeper)
assert.False(t, got.IsOK(), "expected error, got %v", got)
2018-03-29 07:49:18 -07:00
// test that the delegator can still withdraw their bonds
2018-04-01 09:05:58 -07:00
got = handleMsgUnbond(ctx, msgUnbond, keeper)
require.True(t, got.IsOK(), "expected no error on runMsgDeclareCandidacy")
2018-03-29 07:49:18 -07:00
// verify that the pubkey can now be reused
2018-04-01 09:05:58 -07:00
got = handleMsgDeclareCandidacy(ctx, msgDeclareCandidacy, keeper)
assert.True(t, got.IsOK(), "expected ok, got %v", got)
2018-03-29 07:49:18 -07:00
}