mirror of https://github.com/poanetwork/quorum.git
Merge pull request #14 from bas-vk/votetxpriority
core/types,core/quorum: give vote transactions priority
This commit is contained in:
commit
70a49efaf6
|
@ -60,7 +60,7 @@ func (ps *pendingState) applyTransaction(tx *types.Transaction, bc *core.BlockCh
|
||||||
return nil, logs
|
return nil, logs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ps *pendingState) applyTransactions(txs *types.TransactionsByPriceAndNonce, mux *event.TypeMux, bc *core.BlockChain, cc *core.ChainConfig) (types.Transactions, types.Transactions) {
|
func (ps *pendingState) applyTransactions(txs *types.TransactionsByPriorityAndNonce, mux *event.TypeMux, bc *core.BlockChain, cc *core.ChainConfig) (types.Transactions, types.Transactions) {
|
||||||
var (
|
var (
|
||||||
lowGasTxs types.Transactions
|
lowGasTxs types.Transactions
|
||||||
failedTxs types.Transactions
|
failedTxs types.Transactions
|
||||||
|
|
|
@ -24,14 +24,10 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
// Block voting contract is deployed on BlockVotingContractAddress in the genesis block.
|
|
||||||
BlockVotingContractAddress = common.HexToAddress("0x0000000000000000000000000000000000000020")
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Create bindings with: go run cmd/abigen/main.go -abi <definition> -pkg quorum -type VotingContract > core/quorum/binding.go
|
// Create bindings with: go run cmd/abigen/main.go -abi <definition> -pkg quorum -type VotingContract > core/quorum/binding.go
|
||||||
ABI = `[{"constant":false,"inputs":[{"name":"threshold","type":"uint256"}],"name":"setVoteThreshold","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"removeBlockMaker","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"voterCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"canCreateBlocks","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"voteThreshold","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"height","type":"uint256"}],"name":"getCanonHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"height","type":"uint256"},{"name":"hash","type":"bytes32"}],"name":"vote","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"addBlockMaker","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"removeVoter","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"height","type":"uint256"},{"name":"n","type":"uint256"}],"name":"getEntry","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"addr","type":"address"}],"name":"isVoter","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"canVote","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"blockMakerCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"getSize","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"addr","type":"address"}],"name":"isBlockMaker","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"addVoter","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"blockNumber","type":"uint256"},{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"Vote","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"","type":"address"}],"name":"AddVoter","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"","type":"address"}],"name":"RemovedVoter","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"","type":"address"}],"name":"AddBlockMaker","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"","type":"address"}],"name":"RemovedBlockMaker","type":"event"}]`
|
ABI = `[{"constant":false,"inputs":[{"name":"threshold","type":"uint256"}],"name":"setVoteThreshold","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"removeBlockMaker","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"voterCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"canCreateBlocks","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"voteThreshold","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"height","type":"uint256"}],"name":"getCanonHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"height","type":"uint256"},{"name":"hash","type":"bytes32"}],"name":"vote","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"addBlockMaker","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"removeVoter","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"height","type":"uint256"},{"name":"n","type":"uint256"}],"name":"getEntry","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"addr","type":"address"}],"name":"isVoter","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"canVote","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"blockMakerCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"getSize","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"addr","type":"address"}],"name":"isBlockMaker","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"addVoter","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"blockNumber","type":"uint256"},{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"Vote","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"","type":"address"}],"name":"AddVoter","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"","type":"address"}],"name":"RemovedVoter","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"","type":"address"}],"name":"AddBlockMaker","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"","type":"address"}],"name":"RemovedBlockMaker","type":"event"}]`
|
||||||
|
@ -105,7 +101,7 @@ func NewBlockVoting(bc *core.BlockChain, chainConfig *core.ChainConfig, txpool *
|
||||||
func (bv *BlockVoting) resetPendingState(parent *types.Block) {
|
func (bv *BlockVoting) resetPendingState(parent *types.Block) {
|
||||||
statedb, _, err := bv.bc.StateAt(parent.Root())
|
statedb, _, err := bv.bc.StateAt(parent.Root())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("State corrupt: ", err))
|
panic(fmt.Sprintf("State corrupt: %v", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
ps := &pendingState{
|
ps := &pendingState{
|
||||||
|
@ -118,7 +114,7 @@ func (bv *BlockVoting) resetPendingState(parent *types.Block) {
|
||||||
|
|
||||||
ps.gp.AddGas(ps.header.GasLimit)
|
ps.gp.AddGas(ps.header.GasLimit)
|
||||||
|
|
||||||
txs := types.NewTransactionsByPriceAndNonce(bv.txpool.Pending())
|
txs := types.NewTransactionsByPriorityAndNonce(bv.txpool.Pending())
|
||||||
|
|
||||||
lowGasTxs, failedTxs := ps.applyTransactions(txs, bv.mux, bv.bc, bv.cc)
|
lowGasTxs, failedTxs := ps.applyTransactions(txs, bv.mux, bv.bc, bv.cc)
|
||||||
bv.txpool.RemoveBatch(lowGasTxs)
|
bv.txpool.RemoveBatch(lowGasTxs)
|
||||||
|
@ -165,14 +161,14 @@ func (bv *BlockVoting) Start(client *rpc.Client, strat BlockMakerStrategy, voteK
|
||||||
bv.vk = voteKey
|
bv.vk = voteKey
|
||||||
|
|
||||||
ethClient := ethclient.NewClient(client)
|
ethClient := ethclient.NewClient(client)
|
||||||
callContract, err := NewVotingContractCaller(BlockVotingContractAddress, ethClient)
|
callContract, err := NewVotingContractCaller(params.QuorumVotingContractAddr, ethClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
bv.callContract = callContract
|
bv.callContract = callContract
|
||||||
|
|
||||||
if voteKey != nil {
|
if voteKey != nil {
|
||||||
contract, err := NewVotingContract(BlockVotingContractAddress, ethClient)
|
contract, err := NewVotingContract(params.QuorumVotingContractAddr, ethClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -290,7 +286,7 @@ func (bv *BlockVoting) run(strat BlockMakerStrategy) {
|
||||||
func (bv *BlockVoting) applyTransaction(tx *types.Transaction) {
|
func (bv *BlockVoting) applyTransaction(tx *types.Transaction) {
|
||||||
acc, _ := tx.From()
|
acc, _ := tx.From()
|
||||||
txs := map[common.Address]types.Transactions{acc: types.Transactions{tx}}
|
txs := map[common.Address]types.Transactions{acc: types.Transactions{tx}}
|
||||||
txset := types.NewTransactionsByPriceAndNonce(txs)
|
txset := types.NewTransactionsByPriorityAndNonce(txs)
|
||||||
|
|
||||||
bv.pStateMu.Lock()
|
bv.pStateMu.Lock()
|
||||||
bv.pState.applyTransactions(txset, bv.mux, bv.bc, bv.cc)
|
bv.pState.applyTransactions(txset, bv.mux, bv.bc, bv.cc)
|
||||||
|
@ -342,9 +338,6 @@ func (bv *BlockVoting) createBlock() (*types.Block, error) {
|
||||||
l.BlockHash = header.Hash()
|
l.BlockHash = header.Hash()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//for _, log := range logs {
|
|
||||||
// log.BlockHash = header.Hash()
|
|
||||||
//}
|
|
||||||
|
|
||||||
header.Bloom = types.CreateBloom(receipts)
|
header.Bloom = types.CreateBloom(receipts)
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/quorum"
|
"github.com/ethereum/go-ethereum/core/quorum"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -60,7 +61,7 @@ func genesisBlock(voteThreshold int) string {
|
||||||
addrVoteKey1.Hex(),
|
addrVoteKey1.Hex(),
|
||||||
addrVoteKey2.Hex(),
|
addrVoteKey2.Hex(),
|
||||||
addrBlockMaker1.Hex(),
|
addrBlockMaker1.Hex(),
|
||||||
quorum.BlockVotingContractAddress.Hex(),
|
params.QuorumVotingContractAddr.Hex(),
|
||||||
quorum.RuntimeCode,
|
quorum.RuntimeCode,
|
||||||
voteThreshold,
|
voteThreshold,
|
||||||
)
|
)
|
||||||
|
|
|
@ -28,6 +28,7 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -461,6 +462,41 @@ type TransactionsByPriceAndNonce struct {
|
||||||
heads TxByPrice // Next transaction for each unique account (price heap)
|
heads TxByPrice // Next transaction for each unique account (price heap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TransactionsByPriorityAndNonce struct {
|
||||||
|
txs map[common.Address]Transactions
|
||||||
|
heads TxByPriority
|
||||||
|
}
|
||||||
|
|
||||||
|
// TxByPriority implements both sort and the heap interface, making it useful
|
||||||
|
// for all at once sorting as well as individual adding and removing elements.
|
||||||
|
//
|
||||||
|
// It will prioritise transaction to the voting contract.
|
||||||
|
type TxByPriority Transactions
|
||||||
|
|
||||||
|
func (s TxByPriority) Len() int { return len(s) }
|
||||||
|
func (s TxByPriority) Less(i, j int) bool {
|
||||||
|
var (
|
||||||
|
iRecipient = s[i].data.Recipient
|
||||||
|
jRecipient = s[j].data.Recipient
|
||||||
|
)
|
||||||
|
|
||||||
|
// in case iReceipt is towards the voting contract and jRecipient is not towards the voting contract
|
||||||
|
// iReceipt is "smaller".
|
||||||
|
return iRecipient != nil && *iRecipient == params.QuorumVotingContractAddr && (jRecipient == nil || *jRecipient != params.QuorumVotingContractAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s TxByPriority) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||||
|
func (s *TxByPriority) Push(x interface{}) {
|
||||||
|
*s = append(*s, x.(*Transaction))
|
||||||
|
}
|
||||||
|
func (s *TxByPriority) Pop() interface{} {
|
||||||
|
old := *s
|
||||||
|
n := len(old)
|
||||||
|
x := old[n-1]
|
||||||
|
*s = old[0 : n-1]
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
// NewTransactionsByPriceAndNonce creates a transaction set that can retrieve
|
// NewTransactionsByPriceAndNonce creates a transaction set that can retrieve
|
||||||
// price sorted transactions in a nonce-honouring way.
|
// price sorted transactions in a nonce-honouring way.
|
||||||
//
|
//
|
||||||
|
@ -482,6 +518,46 @@ func NewTransactionsByPriceAndNonce(txs map[common.Address]Transactions) *Transa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewTransactionsByPriorityAndNonce creates a transaction set that can retrieve
|
||||||
|
// vote tx sorted transactions in a nonce-honouring way.
|
||||||
|
//
|
||||||
|
// Note, the input map is reowned so the caller should not interact any more with
|
||||||
|
// it after providing it to the constructor.
|
||||||
|
func NewTransactionsByPriorityAndNonce(txs map[common.Address]Transactions) *TransactionsByPriorityAndNonce {
|
||||||
|
heads := make(TxByPriority, 0, len(txs))
|
||||||
|
for acc, accTxs := range txs {
|
||||||
|
heads = append(heads, accTxs[0])
|
||||||
|
txs[acc] = accTxs[1:]
|
||||||
|
}
|
||||||
|
heap.Init(&heads)
|
||||||
|
|
||||||
|
return &TransactionsByPriorityAndNonce{
|
||||||
|
txs: txs,
|
||||||
|
heads: heads,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TransactionsByPriorityAndNonce) Peek() *Transaction {
|
||||||
|
if len(t.heads) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return t.heads[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TransactionsByPriorityAndNonce) Shift() {
|
||||||
|
acc, _ := t.heads[0].From()
|
||||||
|
if txs, ok := t.txs[acc]; ok && len(txs) > 0 {
|
||||||
|
t.heads[0], t.txs[acc] = txs[0], txs[1:]
|
||||||
|
heap.Fix(&t.heads, 0)
|
||||||
|
} else {
|
||||||
|
heap.Pop(&t.heads)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TransactionsByPriorityAndNonce) Pop() {
|
||||||
|
heap.Pop(&t.heads)
|
||||||
|
}
|
||||||
|
|
||||||
// Peek returns the next transaction by price.
|
// Peek returns the next transaction by price.
|
||||||
func (t *TransactionsByPriceAndNonce) Peek() *Transaction {
|
func (t *TransactionsByPriceAndNonce) Peek() *Transaction {
|
||||||
if len(t.heads) == 0 {
|
if len(t.heads) == 0 {
|
||||||
|
|
|
@ -20,7 +20,9 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"math/rand"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
@ -118,6 +120,92 @@ func TestRecipientNormal(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTransactionsByPriorityNonceSort(t *testing.T) {
|
||||||
|
votingContractAddr := common.HexToAddress("0x0000000000000000000000000000000000000020")
|
||||||
|
|
||||||
|
// Generate a batch of accounts to start with
|
||||||
|
keys := make([]*ecdsa.PrivateKey, 50)
|
||||||
|
for i := 0; i < len(keys); i++ {
|
||||||
|
keys[i], _ = crypto.GenerateKey()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a batch of transactions with overlapping values, but shifted nonces
|
||||||
|
groups := map[common.Address]Transactions{}
|
||||||
|
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
for start, key := range keys {
|
||||||
|
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
var tx *Transaction
|
||||||
|
switch rand.Int() % 3 {
|
||||||
|
case 0:
|
||||||
|
tx, _ = NewTransaction(uint64(i), votingContractAddr, big.NewInt(100), big.NewInt(100), big.NewInt(int64(start+1)), nil).SignECDSA(key)
|
||||||
|
case 1:
|
||||||
|
tx, _ = NewTransaction(uint64(i), common.Address{}, big.NewInt(100), big.NewInt(100), big.NewInt(int64(start+1)), nil).SignECDSA(key)
|
||||||
|
default:
|
||||||
|
tx, _ = NewContractCreation(uint64(i), common.Big0, common.MaxBig, common.Big0, []byte{0}).SignECDSA(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
groups[addr] = append(groups[addr], tx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
txset := NewTransactionsByPriorityAndNonce(groups)
|
||||||
|
|
||||||
|
txs := Transactions{}
|
||||||
|
for {
|
||||||
|
if tx := txset.Peek(); tx != nil {
|
||||||
|
txs = append(txs, tx)
|
||||||
|
txset.Shift()
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, txi := range txs {
|
||||||
|
fromi, _ := txi.From()
|
||||||
|
|
||||||
|
// Make sure the nonce order is valid
|
||||||
|
for j, txj := range txs[i+1:] {
|
||||||
|
fromj, _ := txj.From()
|
||||||
|
if fromi == fromj && txi.Nonce() > txj.Nonce() {
|
||||||
|
t.Errorf("invalid nonce ordering: tx #%d (A=%x N=%v) < tx #%d (A=%x N=%v)", i, fromi[:4], txi.Nonce(), i+j, fromj[:4], txj.Nonce())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// first first non prioritised transaction
|
||||||
|
index := 0
|
||||||
|
for i, tx := range txs {
|
||||||
|
// search first non prioritized transaction
|
||||||
|
to := tx.To()
|
||||||
|
if to != nil && *to != votingContractAddr {
|
||||||
|
index = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure that all transaction after this point are non-prioritized
|
||||||
|
gotNonPrioritised := make(map[common.Address]bool)
|
||||||
|
for i, tx := range txs[index:] {
|
||||||
|
from, _ := tx.From()
|
||||||
|
|
||||||
|
if _, ok := gotNonPrioritised[from]; ok { // got an non-prioritised before this one which, this tx is always good
|
||||||
|
continue
|
||||||
|
} else { // didn't got a non-prioritised tx before this one, ensure this tx has no priority
|
||||||
|
to := tx.To()
|
||||||
|
if to != nil && *to == votingContractAddr {
|
||||||
|
for n, trans := range txs {
|
||||||
|
transFrom, _ := trans.From()
|
||||||
|
t.Logf("Tx[%d] nonce: %d, from: %x, to: %x", n, trans.Nonce(), transFrom, trans.To())
|
||||||
|
}
|
||||||
|
t.Fatalf("Found a priority tx on index %d that hasn't got no priority is should have", index+i)
|
||||||
|
}
|
||||||
|
gotNonPrioritised[from] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Tests that transactions can be correctly sorted according to their price in
|
// Tests that transactions can be correctly sorted according to their price in
|
||||||
// decreasing order, but at the same time with increasing nonces when issued by
|
// decreasing order, but at the same time with increasing nonces when issued by
|
||||||
// the same account.
|
// the same account.
|
||||||
|
@ -144,8 +232,9 @@ func TestTransactionPriceNonceSort(t *testing.T) {
|
||||||
if tx := txset.Peek(); tx != nil {
|
if tx := txset.Peek(); tx != nil {
|
||||||
txs = append(txs, tx)
|
txs = append(txs, tx)
|
||||||
txset.Shift()
|
txset.Shift()
|
||||||
|
} else {
|
||||||
|
break
|
||||||
}
|
}
|
||||||
break
|
|
||||||
}
|
}
|
||||||
for i, txi := range txs {
|
for i, txi := range txs {
|
||||||
fromi, _ := txi.From()
|
fromi, _ := txi.From()
|
||||||
|
|
Loading…
Reference in New Issue