From f4e8f9f6af4df96df4d71919a66fb53a6b862822 Mon Sep 17 00:00:00 2001 From: jiangzehua <1092431698@qq.com> Date: Wed, 17 Jun 2020 19:33:38 +0800 Subject: [PATCH] Modify to process CR proposal withdraw transaction first --- blockchain/txvalidator.go | 3 ++- blockchain/txvalidator_test.go | 2 +- cr/state/committee_test.go | 25 ++++++++++++++++++++++++- cr/state/committeeaction.go | 19 +++++++++++++++++++ mempool/txpool.go | 1 + 5 files changed, 47 insertions(+), 3 deletions(-) diff --git a/blockchain/txvalidator.go b/blockchain/txvalidator.go index 6030f26d8..4c8a22c26 100644 --- a/blockchain/txvalidator.go +++ b/blockchain/txvalidator.go @@ -2233,7 +2233,8 @@ func (b *BlockChain) checkCRCProposalTransaction(txn *Transaction, return errors.New("budgets exceeds 10% of CRC committee balance") } else if amount > b.crCommittee.CRCCurrentStageAmount- b.crCommittee.CRCCommitteeUsedAmount-proposalsUsedAmount { - return errors.New("budgets exceeds the balance of CRC committee") + return errors.New(fmt.Sprintf("budgets exceeds the balance of CRC committee, tx hash:%s, budgets:%s, need <= %s", + txn.Hash().String(), amount, b.crCommittee.CRCCurrentStageAmount-b.crCommittee.CRCCommitteeUsedAmount-proposalsUsedAmount)) } else if amount < 0 { return errors.New("budgets is invalid") } diff --git a/blockchain/txvalidator_test.go b/blockchain/txvalidator_test.go index b4d2cc2e4..0a808e8d0 100644 --- a/blockchain/txvalidator_test.go +++ b/blockchain/txvalidator_test.go @@ -2557,7 +2557,7 @@ func (s *txValidatorTestSuite) TestCheckCRCProposalTransaction() { s.Chain.crCommittee.CRCCurrentStageAmount = common.Fixed64(100 * 1e8) s.Chain.crCommittee.CRCCommitteeUsedAmount = common.Fixed64(99 * 1e8) err = s.Chain.checkCRCProposalTransaction(txn, tenureHeight, 0) - s.EqualError(err, "budgets exceeds the balance of CRC committee") + s.Error(err, "budgets exceeds the balance of CRC committee") s.Chain.crCommittee.CRCCommitteeUsedAmount = common.Fixed64(0) diff --git a/cr/state/committee_test.go b/cr/state/committee_test.go index a96af92cd..c89d98081 100644 --- a/cr/state/committee_test.go +++ b/cr/state/committee_test.go @@ -1,7 +1,7 @@ // Copyright (c) 2017-2020 The Elastos Foundation // Use of this source code is governed by an MIT // license that can be found in the LICENSE file. -// +// package state @@ -17,6 +17,29 @@ import ( "github.com/stretchr/testify/assert" ) +func TestSortTransactions(t *testing.T) { + txs := []*types.Transaction{ + &types.Transaction{TxType: types.CoinBase}, + &types.Transaction{TxType: types.TransferAsset}, + &types.Transaction{TxType: types.TransferAsset}, + &types.Transaction{TxType: types.CRCProposalTracking}, + &types.Transaction{TxType: types.CRCProposalWithdraw}, + &types.Transaction{TxType: types.CRCProposalWithdraw}, + &types.Transaction{TxType: types.TransferAsset}, + &types.Transaction{TxType: types.CRCProposalWithdraw}, + } + + sortTransactions(txs[1:]) + assert.Equal(t, txs[0].TxType.Name(), "CoinBase") + assert.Equal(t, txs[1].TxType.Name(), "CRCProposalWithdraw") + assert.Equal(t, txs[2].TxType.Name(), "CRCProposalWithdraw") + assert.Equal(t, txs[3].TxType.Name(), "CRCProposalWithdraw") + assert.Equal(t, txs[4].TxType.Name(), "TransferAsset") + assert.Equal(t, txs[5].TxType.Name(), "TransferAsset") + assert.Equal(t, txs[6].TxType.Name(), "CRCProposalTracking") + assert.Equal(t, txs[7].TxType.Name(), "TransferAsset") +} + func TestNewCRCommittee(t *testing.T) { committee := NewCommittee(&config.DefaultParams) diff --git a/cr/state/committeeaction.go b/cr/state/committeeaction.go index a68cd19ae..304f08108 100644 --- a/cr/state/committeeaction.go +++ b/cr/state/committeeaction.go @@ -7,6 +7,7 @@ package state import ( "bytes" + "sort" "github.com/elastos/Elastos.ELA/common" "github.com/elastos/Elastos.ELA/core/types" @@ -19,11 +20,29 @@ import ( // packed into a block. Then loop through the transactions to update CR // state and votes according to transactions content. func (c *Committee) processTransactions(txs []*types.Transaction, height uint32) { + sortedTxs := make([]*types.Transaction, 0) + if len(txs) < 1 { + return + } for _, tx := range txs { + sortedTxs = append(sortedTxs, tx) + } + sortTransactions(sortedTxs[1:]) + for _, tx := range sortedTxs { c.processTransaction(tx, height) } } +// sortTransactions purpose is to process some transaction first. +func sortTransactions(txs []*types.Transaction) { + sort.Slice(txs, func(i, j int) bool { + if txs[i].IsCRCProposalWithdrawTx() { + return true + } + return !txs[j].IsCRCProposalWithdrawTx() + }) +} + // processTransaction take a transaction and the height it has been packed into // a block, then update producers state and votes according to the transaction // content. diff --git a/mempool/txpool.go b/mempool/txpool.go index 48ab65dc5..fe53068a8 100644 --- a/mempool/txpool.go +++ b/mempool/txpool.go @@ -254,6 +254,7 @@ func (mp *TxPool) checkAndCleanAllTransactions() { log.Warn("[checkAndCleanAllTransactions] check transaction context failed,", err) deleteCount++ mp.doRemoveTransaction(tx) + continue } if tx.IsCRCProposalTx() { blockchain.RecordCRCProposalAmount(&proposalsUsedAmount, tx)