Commit 27024cb4 authored by Heimdall's avatar Heimdall
Browse files

Merge branch 'develop' of gitlab.com:thorchain/thornode into testnet-multichain

parents 154d6682 e3b2b73a
Pipeline #265024733 passed with stages
in 35 minutes and 19 seconds
......@@ -33,7 +33,7 @@ import (
// BlockCacheSize the number of block meta that get store in storage.
const (
BlockCacheSize = 100
BlockCacheSize = 144
MaximumConfirmation = 99999999
MaxAsgardAddresses = 100
// EstimateAverageTxSize for THORChain the estimate tx size is hard code to 250 here , as most of time it will spend 1 input, have 3 output
......@@ -408,19 +408,19 @@ func (c *Client) confirmTx(txHash *chainhash.Hash) bool {
_, err := c.client.GetMempoolEntry(txHash.String())
if err == nil {
return true
} else {
c.logger.Err(err).Msgf("fail to confirm tx(%s) from mempool", txHash.String())
}
// then get raw tx and check if it has confirmations or not
// if no confirmation and not in mempool then invalid
result, err := c.client.GetTransaction(txHash)
_, err = c.client.GetTransaction(txHash)
if err != nil {
if rpcErr, ok := err.(*btcjson.RPCError); ok && rpcErr.Code == btcjson.ErrRPCNoTxInfo {
return false
}
return true
}
if result.Confirmations == 0 {
return false
c.logger.Err(err).Msgf("fail to get tx (%s) from chain , assume it is ok", txHash)
}
return true
}
......
......@@ -34,7 +34,7 @@ import (
// BlockCacheSize the number of block meta that get store in storage.
const (
BlockCacheSize = 100
BlockCacheSize = 144
MaximumConfirmation = 99999999
MaxAsgardAddresses = 100
// EstimateAverageTxSize for THORChain the estimate tx size is hard code to 250 here , as most of time it will spend 1 input, have 3 output
......@@ -408,19 +408,19 @@ func (c *Client) confirmTx(txHash *chainhash.Hash) bool {
_, err := c.client.GetMempoolEntry(txHash.String())
if err == nil {
return true
} else {
c.logger.Err(err).Msgf("fail to confirm tx (%s) from mempool", txHash.String())
}
// then get raw tx and check if it has confirmations or not
// if no confirmation and not in mempool then invalid
result, err := c.client.GetTransaction(txHash)
_, err = c.client.GetTransaction(txHash)
if err != nil {
if rpcErr, ok := err.(*btcjson.RPCError); ok && rpcErr.Code == btcjson.ErrRPCNoTxInfo {
return false
}
return true
}
if result.Confirmations == 0 {
return false
c.logger.Err(err).Msgf("fail to get tx (%s) from chain,assume it is ok", txHash)
}
return true
}
......
......@@ -34,7 +34,7 @@ import (
// BlockCacheSize the number of block meta that get store in storage.
const (
BlockCacheSize = 100
BlockCacheSize = 1440
MaximumConfirmation = 99999999
MaxAsgardAddresses = 100
// EstimateAverageTxSize for THORChain the estimate tx size is hard code to 250 here , as most of time it will spend 1 input, have 3 output
......@@ -410,19 +410,19 @@ func (c *Client) confirmTx(txHash *chainhash.Hash) bool {
_, err := c.client.GetMempoolEntry(txHash.String())
if err == nil {
return true
} else {
c.logger.Err(err).Msgf("fail to confirm tx(%s) from mempool", txHash.String())
}
// then get raw tx and check if it has confirmations or not
// if no confirmation and not in mempool then invalid
result, err := c.client.GetTransaction(txHash)
_, err = c.client.GetTransaction(txHash)
if err != nil {
if rpcErr, ok := err.(*btcjson.RPCError); ok && rpcErr.Code == btcjson.ErrRPCNoTxInfo {
return false
}
return true
}
if result.Confirmations == 0 {
return false
c.logger.Err(err).Msgf("fail to get tx(%s) from chain , assume it is ok", txHash.String())
}
return true
}
......
......@@ -31,7 +31,7 @@ import (
)
const (
BlockCacheSize = 100
BlockCacheSize = 6000
MaxContractGas = 80000
depositEvent = "0xef519b7eb82aaf6ac376a6df2d793843ebfd593de5f1a0601d3cc6ab49ebb395"
transferOutEvent = "0xa9cd03aa3c1b4515114539cd53d22085129d495cb9e9f9af77864526240f1bf7"
......
......@@ -33,7 +33,7 @@ import (
// BlockCacheSize the number of block meta that get store in storage.
const (
BlockCacheSize = 100
BlockCacheSize = 600
MaximumConfirmation = 99999999
MaxAsgardAddresses = 100
// EstimateAverageTxSize for THORChain the estimate tx size is hard code to 250 here , as most of time it will spend 1 input, have 3 output
......@@ -407,18 +407,17 @@ func (c *Client) confirmTx(txHash *chainhash.Hash) bool {
_, err := c.client.GetMempoolEntry(txHash.String())
if err == nil {
return true
} else {
c.logger.Err(err).Msgf("fail to confirm tx(%s) from mempool", txHash.String())
}
// then get raw tx and check if it has confirmations or not
// if no confirmation and not in mempool then invalid
result, err := c.client.GetTransaction(txHash)
_, err = c.client.GetTransaction(txHash)
if err != nil {
if rpcErr, ok := err.(*btcjson.RPCError); ok && rpcErr.Code == btcjson.ErrRPCNoTxInfo {
return false
}
return true
}
if result.Confirmations == 0 {
return false
c.logger.Err(err).Msgf("fail to get tx (%s) from chain", txHash.String())
}
return true
}
......
......@@ -81,6 +81,11 @@ func (t TxIn) GetTotalTransactionValue(asset common.Asset, excludeFrom []common.
if fromAsgard {
continue
}
// skip confirmation counting if it is internal tx
m, err := memo.ParseMemo(item.Memo)
if err == nil && m.IsInternal() {
continue
}
c := item.Coins.GetCoin(asset)
if c.IsEmpty() {
continue
......
0.27.1
\ No newline at end of file
0.28.0
\ No newline at end of file
......@@ -151,7 +151,7 @@ func getHandlerTestWrapperWithVersion(c *C, height int64, withActiveNode, withAc
FundModule(c, ctx, k, AsgardName, 100000000)
c.Assert(mgr.ValidatorMgr().BeginBlock(ctx, constAccessor), IsNil)
c.Assert(mgr.ValidatorMgr().BeginBlock(ctx, constAccessor, nil), IsNil)
return handlerTestWrapper{
ctx: ctx,
......
......@@ -114,7 +114,7 @@ func newYggdrasilHandlerTestHelper(c *C) yggdrasilHandlerTestHelper {
mgr := NewDummyMgr()
mgr.validatorMgr = newValidatorMgrV1(k, mgr.VaultMgr(), mgr.TxOutStore(), mgr.EventMgr())
mgr.slasher = NewSlasherV1(keeper)
c.Assert(mgr.ValidatorMgr().BeginBlock(ctx, constAccessor), IsNil)
c.Assert(mgr.ValidatorMgr().BeginBlock(ctx, constAccessor, nil), IsNil)
asgardVault := GetRandomVault()
asgardVault.Type = AsgardVault
asgardVault.Status = ActiveVault
......
......@@ -14,11 +14,11 @@ func NewValidatorDummyMgr() *ValidatorDummyMgr {
return &ValidatorDummyMgr{}
}
func (vm *ValidatorDummyMgr) BeginBlock(_ cosmos.Context, _ constants.ConstantValues) error {
func (vm *ValidatorDummyMgr) BeginBlock(_ cosmos.Context, _ constants.ConstantValues, _ []string) error {
return kaboom
}
func (vm *ValidatorDummyMgr) EndBlock(_ cosmos.Context, _ Manager, _ constants.ConstantValues, existingValidators []string) []abci.ValidatorUpdate {
func (vm *ValidatorDummyMgr) EndBlock(_ cosmos.Context, _ Manager, _ constants.ConstantValues) []abci.ValidatorUpdate {
return nil
}
......
......@@ -17,10 +17,11 @@ import (
// validatorMgrV1 is to manage a list of validators , and rotate them
type validatorMgrV1 struct {
k keeper.Keeper
vaultMgr NetworkManager
txOutStore TxOutStore
eventMgr EventManager
k keeper.Keeper
vaultMgr NetworkManager
txOutStore TxOutStore
eventMgr EventManager
existingValidators []string
}
// newValidatorMgrV1 create a new instance of validatorMgrV1
......@@ -34,7 +35,10 @@ func newValidatorMgrV1(k keeper.Keeper, vaultMgr NetworkManager, txOutStore TxOu
}
// BeginBlock when block begin
func (vm *validatorMgrV1) BeginBlock(ctx cosmos.Context, constAccessor constants.ConstantValues) error {
func (vm *validatorMgrV1) BeginBlock(ctx cosmos.Context, constAccessor constants.ConstantValues, existingValidators []string) error {
// TODO fix this when we prepare for chaosnet
// the following line is to make sure backward compatibility
vm.existingValidators = []string{}
height := common.BlockHeight(ctx)
if height == genesisBlockHeight {
if err := vm.setupValidatorNodes(ctx, height, constAccessor); err != nil {
......@@ -210,7 +214,7 @@ func (vm *validatorMgrV1) splitNext(ctx cosmos.Context, nas NodeAccounts, asgard
}
// EndBlock when block commit
func (vm *validatorMgrV1) EndBlock(ctx cosmos.Context, mgr Manager, constAccessor constants.ConstantValues, existingValidators []string) []abci.ValidatorUpdate {
func (vm *validatorMgrV1) EndBlock(ctx cosmos.Context, mgr Manager, constAccessor constants.ConstantValues) []abci.ValidatorUpdate {
height := common.BlockHeight(ctx)
activeNodes, err := vm.k.ListActiveNodeAccounts(ctx)
if err != nil {
......@@ -319,7 +323,7 @@ func (vm *validatorMgrV1) EndBlock(ctx cosmos.Context, mgr Manager, constAccesso
caddr := sdk.GetConsAddress(pk).String()
removedNodeKeys = append(removedNodeKeys, na.PubKeySet.Secp256k1)
found := false
for _, exist := range existingValidators {
for _, exist := range vm.existingValidators {
if exist == caddr {
validators = append(validators, abci.Ed25519ValidatorUpdate(pk.Bytes(), 0))
found = true
......
......@@ -45,7 +45,7 @@ func (vts *ValidatorMgrV1TestSuite) TestSetupValidatorNodes(c *C) {
// it should take both of the node as active
vMgr1 := newValidatorMgrV1(k, mgr.VaultMgr(), mgr.TxOutStore(), mgr.EventMgr())
c.Assert(vMgr1.BeginBlock(ctx, constAccessor), IsNil)
c.Assert(vMgr1.BeginBlock(ctx, constAccessor, nil), IsNil)
activeNodes, err := k.ListActiveNodeAccounts(ctx)
c.Assert(err, IsNil)
c.Assert(len(activeNodes) == 2, Equals, true)
......@@ -57,7 +57,7 @@ func (vts *ValidatorMgrV1TestSuite) TestSetupValidatorNodes(c *C) {
// three active nodes and 1 ready nodes, it should take them all
vMgr2 := newValidatorMgrV1(k, mgr.VaultMgr(), mgr.TxOutStore(), mgr.EventMgr())
c.Assert(vMgr2.BeginBlock(ctx, constAccessor), IsNil)
c.Assert(vMgr2.BeginBlock(ctx, constAccessor, nil), IsNil)
activeNodes1, err := k.ListActiveNodeAccounts(ctx)
c.Assert(err, IsNil)
......@@ -93,13 +93,13 @@ func (vts *ValidatorMgrV1TestSuite) TestRagnarokForChaosnet(c *C) {
// trigger ragnarok
ctx = ctx.WithBlockHeight(1024)
c.Assert(vMgr.BeginBlock(ctx, constAccessor), IsNil)
c.Assert(vMgr.BeginBlock(ctx, constAccessor, nil), IsNil)
vault := NewVault(common.BlockHeight(ctx), ActiveVault, AsgardVault, GetRandomPubKey(), common.Chains{common.BNBChain}.Strings(), []ChainContract{})
for _, item := range nodeAccounts {
vault.Membership = append(vault.Membership, item.PubKeySet.Secp256k1.String())
}
c.Assert(k.SetVault(ctx, vault), IsNil)
updates := vMgr.EndBlock(ctx, mgr, constAccessor, []string{})
updates := vMgr.EndBlock(ctx, mgr, constAccessor)
// ragnarok , no one leaves
c.Assert(updates, IsNil)
ragnarokHeight, err := k.GetRagnarokBlockHeight(ctx)
......
This diff is collapsed.
package thorchain
import (
"github.com/blang/semver"
. "gopkg.in/check.v1"
"gitlab.com/thorchain/thornode/common"
"gitlab.com/thorchain/thornode/common/cosmos"
"gitlab.com/thorchain/thornode/constants"
)
type ValidatorMgrV28TestSuite struct{}
var _ = Suite(&ValidatorMgrV28TestSuite{})
func (vts *ValidatorMgrV28TestSuite) SetUpSuite(_ *C) {
SetupConfigForTest()
}
func (vts *ValidatorMgrV28TestSuite) TestSetupValidatorNodes(c *C) {
ctx, k := setupKeeperForTest(c)
ctx = ctx.WithBlockHeight(1)
mgr := NewDummyMgr()
vMgr := newValidatorMgrV28(k, mgr.VaultMgr(), mgr.TxOutStore(), mgr.EventMgr())
c.Assert(vMgr, NotNil)
ver := constants.SWVersion
constAccessor := constants.GetConstantValues(ver)
err := vMgr.setupValidatorNodes(ctx, 0, constAccessor)
c.Assert(err, IsNil)
// no node accounts at all
err = vMgr.setupValidatorNodes(ctx, 1, constAccessor)
c.Assert(err, NotNil)
activeNode := GetRandomNodeAccount(NodeActive)
c.Assert(k.SetNodeAccount(ctx, activeNode), IsNil)
err = vMgr.setupValidatorNodes(ctx, 1, constAccessor)
c.Assert(err, IsNil)
readyNode := GetRandomNodeAccount(NodeReady)
c.Assert(k.SetNodeAccount(ctx, readyNode), IsNil)
// one active node and one ready node on start up
// it should take both of the node as active
vMgr1 := newValidatorMgrV28(k, mgr.VaultMgr(), mgr.TxOutStore(), mgr.EventMgr())
c.Assert(vMgr1.BeginBlock(ctx, constAccessor, nil), IsNil)
activeNodes, err := k.ListActiveNodeAccounts(ctx)
c.Assert(err, IsNil)
c.Assert(len(activeNodes) == 2, Equals, true)
activeNode1 := GetRandomNodeAccount(NodeActive)
activeNode2 := GetRandomNodeAccount(NodeActive)
c.Assert(k.SetNodeAccount(ctx, activeNode1), IsNil)
c.Assert(k.SetNodeAccount(ctx, activeNode2), IsNil)
// three active nodes and 1 ready nodes, it should take them all
vMgr2 := newValidatorMgrV28(k, mgr.VaultMgr(), mgr.TxOutStore(), mgr.EventMgr())
c.Assert(vMgr2.BeginBlock(ctx, constAccessor, nil), IsNil)
activeNodes1, err := k.ListActiveNodeAccounts(ctx)
c.Assert(err, IsNil)
c.Assert(len(activeNodes1) == 4, Equals, true)
}
func (vts *ValidatorMgrV28TestSuite) TestRagnarokForChaosnet(c *C) {
ctx, k := setupKeeperForTest(c)
mgr := NewManagers(k)
c.Assert(mgr.BeginBlock(ctx), IsNil)
vMgr := newValidatorMgrV28(k, mgr.VaultMgr(), mgr.TxOutStore(), mgr.EventMgr())
constAccessor := constants.NewDummyConstants(map[constants.ConstantName]int64{
constants.DesiredValidatorSet: 12,
constants.ArtificialRagnarokBlockHeight: 1024,
constants.BadValidatorRate: 256,
constants.OldValidatorRate: 256,
constants.MinimumNodesForBFT: 4,
constants.ChurnInterval: 256,
constants.ChurnRetryInterval: 720,
constants.AsgardSize: 30,
}, map[constants.ConstantName]bool{
constants.StrictBondLiquidityRatio: false,
}, map[constants.ConstantName]string{})
for i := 0; i < 12; i++ {
node := GetRandomNodeAccount(NodeReady)
c.Assert(k.SetNodeAccount(ctx, node), IsNil)
}
c.Assert(vMgr.setupValidatorNodes(ctx, 1, constAccessor), IsNil)
nodeAccounts, err := k.ListNodeAccountsByStatus(ctx, NodeActive)
c.Assert(err, IsNil)
c.Assert(len(nodeAccounts), Equals, 12)
// trigger ragnarok
ctx = ctx.WithBlockHeight(1024)
c.Assert(vMgr.BeginBlock(ctx, constAccessor, nil), IsNil)
vault := NewVault(common.BlockHeight(ctx), ActiveVault, AsgardVault, GetRandomPubKey(), common.Chains{common.BNBChain}.Strings(), []ChainContract{})
for _, item := range nodeAccounts {
vault.Membership = append(vault.Membership, item.PubKeySet.Secp256k1.String())
}
c.Assert(k.SetVault(ctx, vault), IsNil)
updates := vMgr.EndBlock(ctx, mgr, constAccessor)
// ragnarok , no one leaves
c.Assert(updates, IsNil)
ragnarokHeight, err := k.GetRagnarokBlockHeight(ctx)
c.Assert(err, IsNil)
c.Assert(ragnarokHeight == 1024, Equals, true, Commentf("%d == %d", ragnarokHeight, 1024))
}
func (vts *ValidatorMgrV28TestSuite) TestLowerVersion(c *C) {
ctx, k := setupKeeperForTest(c)
ctx = ctx.WithBlockHeight(1440)
mgr := NewManagers(k)
c.Assert(mgr.BeginBlock(ctx), IsNil)
vMgr := newValidatorMgrV28(k, mgr.VaultMgr(), mgr.TxOutStore(), mgr.EventMgr())
c.Assert(vMgr, NotNil)
c.Assert(vMgr.markLowerVersion(ctx, 360), IsNil)
for i := 0; i < 5; i++ {
activeNode := GetRandomNodeAccount(NodeActive)
activeNode.Version = "0.5.0"
c.Assert(k.SetNodeAccount(ctx, activeNode), IsNil)
}
activeNode1 := GetRandomNodeAccount(NodeActive)
activeNode1.Version = "0.4.0"
c.Assert(k.SetNodeAccount(ctx, activeNode1), IsNil)
c.Assert(vMgr.markLowerVersion(ctx, 360), IsNil)
na, err := k.GetNodeAccount(ctx, activeNode1.NodeAddress)
c.Assert(err, IsNil)
c.Assert(na.LeaveScore, Equals, uint64(143900000000))
}
func (vts *ValidatorMgrV28TestSuite) TestBadActors(c *C) {
ctx, k := setupKeeperForTest(c)
ctx = ctx.WithBlockHeight(1000)
mgr := NewManagers(k)
c.Assert(mgr.BeginBlock(ctx), IsNil)
vMgr := newValidatorMgrV28(k, mgr.VaultMgr(), mgr.TxOutStore(), mgr.EventMgr())
c.Assert(vMgr, NotNil)
// no bad actors with active node accounts
nas, err := vMgr.findBadActors(ctx, 0, 3, 720)
c.Assert(err, IsNil)
c.Assert(nas, HasLen, 0)
activeNode := GetRandomNodeAccount(NodeActive)
c.Assert(k.SetNodeAccount(ctx, activeNode), IsNil)
// no bad actors with active node accounts with no slash points
nas, err = vMgr.findBadActors(ctx, 0, 3, 720)
c.Assert(err, IsNil)
c.Assert(nas, HasLen, 0)
activeNode = GetRandomNodeAccount(NodeActive)
k.SetNodeAccountSlashPoints(ctx, activeNode.NodeAddress, 250)
c.Assert(k.SetNodeAccount(ctx, activeNode), IsNil)
activeNode = GetRandomNodeAccount(NodeActive)
k.SetNodeAccountSlashPoints(ctx, activeNode.NodeAddress, 500)
c.Assert(k.SetNodeAccount(ctx, activeNode), IsNil)
// finds the worse actor
nas, err = vMgr.findBadActors(ctx, 0, 3, 720)
c.Assert(err, IsNil)
c.Assert(nas, HasLen, 1)
c.Check(nas[0].NodeAddress.Equals(activeNode.NodeAddress), Equals, true)
// create really bad actors (crossing the redline)
bad1 := GetRandomNodeAccount(NodeActive)
k.SetNodeAccountSlashPoints(ctx, bad1.NodeAddress, 5000)
c.Assert(k.SetNodeAccount(ctx, bad1), IsNil)
bad2 := GetRandomNodeAccount(NodeActive)
k.SetNodeAccountSlashPoints(ctx, bad2.NodeAddress, 5000)
c.Assert(k.SetNodeAccount(ctx, bad2), IsNil)
nas, err = vMgr.findBadActors(ctx, 0, 3, 720)
c.Assert(err, IsNil)
c.Assert(nas, HasLen, 2, Commentf("%d", len(nas)))
// inconsistent order, workaround
var count int
for _, bad := range nas {
if bad.Equals(bad1) || bad.Equals(bad2) {
count += 1
}
}
c.Check(count, Equals, 2)
}
func (vts *ValidatorMgrV28TestSuite) TestFindBadActors(c *C) {
ctx, k := setupKeeperForTest(c)
ctx = ctx.WithBlockHeight(1000)
mgr := NewManagers(k)
c.Assert(mgr.BeginBlock(ctx), IsNil)
vMgr := newValidatorMgrV28(k, mgr.VaultMgr(), mgr.TxOutStore(), mgr.EventMgr())
c.Assert(vMgr, NotNil)
activeNode := GetRandomNodeAccount(NodeActive)
c.Assert(k.SetNodeAccount(ctx, activeNode), IsNil)
k.SetNodeAccountSlashPoints(ctx, activeNode.NodeAddress, 50)
nodeAccounts, err := vMgr.findBadActors(ctx, 100, 3, 500)
c.Assert(err, IsNil)
c.Assert(nodeAccounts, HasLen, 0)
activeNode1 := GetRandomNodeAccount(NodeActive)
activeNode1.StatusSince = 900
c.Assert(k.SetNodeAccount(ctx, activeNode1), IsNil)
k.SetNodeAccountSlashPoints(ctx, activeNode1.NodeAddress, 200)
// not a full cycle yet, so even it has a lot slash points , doesn't mark as bad
nodeAccounts, err = vMgr.findBadActors(ctx, 100, 3, 500)
c.Assert(err, IsNil)
c.Assert(nodeAccounts, HasLen, 0)
activeNode2 := GetRandomNodeAccount(NodeActive)
c.Assert(k.SetNodeAccount(ctx, activeNode2), IsNil)
k.SetNodeAccountSlashPoints(ctx, activeNode2.NodeAddress, 2000)
activeNode3 := GetRandomNodeAccount(NodeActive)
activeNode3.StatusSince = 1000
c.Assert(k.SetNodeAccount(ctx, activeNode3), IsNil)
k.SetNodeAccountSlashPoints(ctx, activeNode3.NodeAddress, 2000)
ctx = ctx.WithBlockHeight(2000)
// node 3 is worse than node 2, so node 3 should be marked as bad
nodeAccounts, err = vMgr.findBadActors(ctx, 100, 3, 500)
c.Assert(err, IsNil)
c.Assert(nodeAccounts, HasLen, 1)
c.Assert(nodeAccounts.Contains(activeNode3), Equals, true)
}
func (vts *ValidatorMgrV28TestSuite) TestRagnarokBond(c *C) {
ctx, k := setupKeeperForTest(c)
ctx = ctx.WithBlockHeight(1)
ver := constants.SWVersion
mgr := NewDummyMgr()
vMgr := newValidatorMgrV28(k, mgr.VaultMgr(), mgr.TxOutStore(), mgr.EventMgr())
c.Assert(vMgr, NotNil)
constAccessor := constants.GetConstantValues(ver)
err := vMgr.setupValidatorNodes(ctx, 0, constAccessor)
c.Assert(err, IsNil)
activeNode := GetRandomNodeAccount(NodeActive)
activeNode.Bond = cosmos.NewUint(100)
c.Assert(k.SetNodeAccount(ctx, activeNode), IsNil)
disabledNode := GetRandomNodeAccount(NodeDisabled)
disabledNode.Bond = cosmos.ZeroUint()
c.Assert(k.SetNodeAccount(ctx, disabledNode), IsNil)
// no unbonding for first 10
c.Assert(vMgr.ragnarokBond(ctx, 1, mgr), IsNil)
activeNode, err = k.GetNodeAccount(ctx, activeNode.NodeAddress)
c.Assert(err, IsNil)
c.Check(activeNode.Bond.Equal(cosmos.NewUint(100)), Equals, true)
c.Assert(vMgr.ragnarokBond(ctx, 11, mgr), IsNil)
activeNode, err = k.GetNodeAccount(ctx, activeNode.NodeAddress)
c.Assert(err, IsNil)
c.Check(activeNode.Bond.Equal(cosmos.NewUint(90)), Equals, true)
items, err := mgr.TxOutStore().GetOutboundItems(ctx)
c.Assert(err, IsNil)
c.Check(items, HasLen, 0, Commentf("Len %d", items))
mgr.TxOutStore().ClearOutboundItems(ctx)
c.Assert(vMgr.ragnarokBond(ctx, 12, mgr), IsNil)
activeNode, err = k.GetNodeAccount(ctx, activeNode.NodeAddress)
c.Assert(err, IsNil)
c.Check(activeNode.Bond.Equal(cosmos.NewUint(72)), Equals, true)
items, err = mgr.TxOutStore().GetOutboundItems(ctx)
c.Assert(err, IsNil)
c.Check(items, HasLen, 0, Commentf("Len %d", items))
}
func (vts *ValidatorMgrV28TestSuite) TestGetChangedNodes(c *C) {
ctx, k := setupKeeperForTest(c)
ctx = ctx.WithBlockHeight(1)
ver := constants.SWVersion
mgr := NewDummyMgr()
vMgr := newValidatorMgrV28(k, mgr.VaultMgr(), mgr.TxOutStore(), mgr.EventMgr())
c.Assert(vMgr, NotNil)
constAccessor := constants.GetConstantValues(ver)
err := vMgr.setupValidatorNodes(ctx, 0, constAccessor)