@@ -63,18 +63,16 @@ type uint64RingBuffer struct {
63
63
// environment is the workers current environment and holds
64
64
// all of the current state information
65
65
type Work struct {
66
- config * core.ChainConfig
67
- state * state.StateDB // apply state changes here
68
- ancestors * set.Set // ancestor set (used for checking uncle parent validity)
69
- family * set.Set // family set (used for checking uncle invalidity)
70
- uncles * set.Set // uncle set
71
- tcount int // tx count in cycle
72
- ignoredTransactors * set.Set
73
- lowGasTransactors * set.Set
74
- ownedAccounts * set.Set
75
- lowGasTxs types.Transactions
76
- failedTxs types.Transactions
77
- localMinedBlocks * uint64RingBuffer // the most recent block numbers that were mined locally (used to check block inclusion)
66
+ config * core.ChainConfig
67
+ state * state.StateDB // apply state changes here
68
+ ancestors * set.Set // ancestor set (used for checking uncle parent validity)
69
+ family * set.Set // family set (used for checking uncle invalidity)
70
+ uncles * set.Set // uncle set
71
+ tcount int // tx count in cycle
72
+ ownedAccounts * set.Set
73
+ lowGasTxs types.Transactions
74
+ failedTxs types.Transactions
75
+ localMinedBlocks * uint64RingBuffer // the most recent block numbers that were mined locally (used to check block inclusion)
78
76
79
77
Block * types.Block // the new block
80
78
@@ -236,7 +234,12 @@ func (self *worker) update() {
236
234
// Apply transaction to the pending state if we're not mining
237
235
if atomic .LoadInt32 (& self .mining ) == 0 {
238
236
self .currentMu .Lock ()
239
- self .current .commitTransactions (self .mux , types.Transactions {ev .Tx }, self .gasPrice , self .chain )
237
+
238
+ acc , _ := ev .Tx .From ()
239
+ txs := map [common.Address ]types.Transactions {acc : types.Transactions {ev .Tx }}
240
+ txset := types .NewTransactionsByPriceAndNonce (txs )
241
+
242
+ self .current .commitTransactions (self .mux , txset , self .gasPrice , self .chain )
240
243
self .currentMu .Unlock ()
241
244
}
242
245
}
@@ -384,8 +387,6 @@ func (self *worker) makeCurrent(parent *types.Block, header *types.Header) error
384
387
385
388
// Keep track of transactions which return errors so they can be removed
386
389
work .tcount = 0
387
- work .ignoredTransactors = set .New ()
388
- work .lowGasTransactors = set .New ()
389
390
work .ownedAccounts = accountAddressesSet (accounts )
390
391
if self .current != nil {
391
392
work .localMinedBlocks = self .current .localMinedBlocks
@@ -494,43 +495,8 @@ func (self *worker) commitNewWork() {
494
495
if self .config .DAOForkSupport && self .config .DAOForkBlock != nil && self .config .DAOForkBlock .Cmp (header .Number ) == 0 {
495
496
core .ApplyDAOHardFork (work .state )
496
497
}
497
-
498
- /* //approach 1
499
- transactions := self.eth.TxPool().GetTransactions()
500
- sort.Sort(types.TxByNonce(transactions))
501
- */
502
-
503
- //approach 2
504
- transactions := types .SortByPriceAndNonce (self .eth .TxPool ().Pending ())
505
-
506
- /* // approach 3
507
- // commit transactions for this run.
508
- txPerOwner := make(map[common.Address]types.Transactions)
509
- // Sort transactions by owner
510
- for _, tx := range self.eth.TxPool().GetTransactions() {
511
- from, _ := tx.From() // we can ignore the sender error
512
- txPerOwner[from] = append(txPerOwner[from], tx)
513
- }
514
- var (
515
- singleTxOwner types.Transactions
516
- multiTxOwner types.Transactions
517
- )
518
- // Categorise transactions by
519
- // 1. 1 owner tx per block
520
- // 2. multi txs owner per block
521
- for _, txs := range txPerOwner {
522
- if len(txs) == 1 {
523
- singleTxOwner = append(singleTxOwner, txs[0])
524
- } else {
525
- multiTxOwner = append(multiTxOwner, txs...)
526
- }
527
- }
528
- sort.Sort(types.TxByPrice(singleTxOwner))
529
- sort.Sort(types.TxByNonce(multiTxOwner))
530
- transactions := append(singleTxOwner, multiTxOwner...)
531
- */
532
-
533
- work .commitTransactions (self .mux , transactions , self .gasPrice , self .chain )
498
+ txs := types .NewTransactionsByPriceAndNonce (self .eth .TxPool ().Pending ())
499
+ work .commitTransactions (self .mux , txs , self .gasPrice , self .chain )
534
500
535
501
self .eth .TxPool ().RemoveBatch (work .lowGasTxs )
536
502
self .eth .TxPool ().RemoveBatch (work .failedTxs )
@@ -591,64 +557,51 @@ func (self *worker) commitUncle(work *Work, uncle *types.Header) error {
591
557
return nil
592
558
}
593
559
594
- func (env * Work ) commitTransactions (mux * event.TypeMux , transactions types.Transactions , gasPrice * big.Int , bc * core.BlockChain ) {
560
+ func (env * Work ) commitTransactions (mux * event.TypeMux , txs * types.TransactionsByPriceAndNonce , gasPrice * big.Int , bc * core.BlockChain ) {
595
561
gp := new (core.GasPool ).AddGas (env .header .GasLimit )
596
562
597
563
var coalescedLogs vm.Logs
598
- for _ , tx := range transactions {
564
+ for {
565
+ // Retrieve the next transaction and abort if all done
566
+ tx := txs .Peek ()
567
+ if tx == nil {
568
+ break
569
+ }
599
570
// Error may be ignored here. The error has already been checked
600
571
// during transaction acceptance is the transaction pool.
601
572
from , _ := tx .From ()
602
573
603
- // Check if it falls within margin. Txs from owned accounts are always processed.
574
+ // Ignore any transactions (and accounts subsequently) with low gas limits
604
575
if tx .GasPrice ().Cmp (gasPrice ) < 0 && ! env .ownedAccounts .Has (from ) {
605
- // ignore the transaction and transactor. We ignore the transactor
606
- // because nonce will fail after ignoring this transaction so there's
607
- // no point
608
- env .lowGasTransactors .Add (from )
609
-
610
- glog .V (logger .Info ).Infof ("transaction(%x) below gas price (tx=%v ask=%v). All sequential txs from this address(%x) will be ignored\n " , tx .Hash ().Bytes ()[:4 ], common .CurrencyToString (tx .GasPrice ()), common .CurrencyToString (gasPrice ), from [:4 ])
611
- }
576
+ // Pop the current low-priced transaction without shifting in the next from the account
577
+ glog .V (logger .Info ).Infof ("Transaction (%x) below gas price (tx=%v ask=%v). All sequential txs from this address(%x) will be ignored\n " , tx .Hash ().Bytes ()[:4 ], common .CurrencyToString (tx .GasPrice ()), common .CurrencyToString (gasPrice ), from [:4 ])
612
578
613
- // Continue with the next transaction if the transaction sender is included in
614
- // the low gas tx set. This will also remove the tx and all sequential transaction
615
- // from this transactor
616
- if env .lowGasTransactors .Has (from ) {
617
- // add tx to the low gas set. This will be removed at the end of the run
618
- // owned accounts are ignored
619
- if ! env .ownedAccounts .Has (from ) {
620
- env .lowGasTxs = append (env .lowGasTxs , tx )
621
- }
622
- continue
623
- }
579
+ env .lowGasTxs = append (env .lowGasTxs , tx )
580
+ txs .Pop ()
624
581
625
- // Move on to the next transaction when the transactor is in ignored transactions set
626
- // This may occur when a transaction hits the gas limit. When a gas limit is hit and
627
- // the transaction is processed (that could potentially be included in the block) it
628
- // will throw a nonce error because the previous transaction hasn't been processed.
629
- // Therefor we need to ignore any transaction after the ignored one.
630
- if env .ignoredTransactors .Has (from ) {
631
582
continue
632
583
}
633
-
584
+ // Start executing the transaction
634
585
env .state .StartRecord (tx .Hash (), common.Hash {}, 0 )
635
586
636
587
err , logs := env .commitTransaction (tx , bc , gp )
637
588
switch {
638
589
case core .IsGasLimitErr (err ):
639
- // ignore the transactor so no nonce errors will be thrown for this account
640
- // next time the worker is run, they'll be picked up again.
641
- env .ignoredTransactors .Add (from )
590
+ // Pop the current out-of-gas transaction without shifting in the next from the account
642
591
glog .V (logger .Detail ).Infof ("Gas limit reached for (%x) in this block. Continue to try smaller txs\n " , from [:4 ])
592
+ txs .Pop ()
643
593
644
594
case err != nil :
595
+ // Pop the current failed transaction without shifting in the next from the account
596
+ glog .V (logger .Detail ).Infof ("Transaction (%x) failed, will be removed: %v\n " , tx .Hash ().Bytes ()[:4 ], err )
645
597
env .failedTxs = append (env .failedTxs , tx )
646
- if glog .V (logger .Detail ) {
647
- glog .Infof ("TX (%x) failed, will be removed: %v\n " , tx .Hash ().Bytes ()[:4 ], err )
648
- }
598
+ txs .Pop ()
599
+
649
600
default :
650
- env . tcount ++
601
+ // Everything ok, collect the logs and shift in the next transaction from the same account
651
602
coalescedLogs = append (coalescedLogs , logs ... )
603
+ env .tcount ++
604
+ txs .Shift ()
652
605
}
653
606
}
654
607
if len (coalescedLogs ) > 0 || env .tcount > 0 {
0 commit comments