@@ -745,11 +745,11 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err e
745
745
}
746
746
747
747
// If the new transaction is a future transaction it should never churn pending transactions
748
- if ! isLocal && pool .isFuture (from , tx ) {
748
+ if ! isLocal && pool .isGapped (from , tx ) {
749
749
var replacesPending bool
750
750
for _ , dropTx := range drop {
751
751
dropSender , _ := types .Sender (pool .signer , dropTx )
752
- if list := pool .pending [dropSender ]; list != nil && list .Overlaps (dropTx ) {
752
+ if list := pool .pending [dropSender ]; list != nil && list .Contains (dropTx . Nonce () ) {
753
753
replacesPending = true
754
754
break
755
755
}
@@ -774,7 +774,7 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err e
774
774
}
775
775
776
776
// Try to replace an existing transaction in the pending pool
777
- if list := pool .pending [from ]; list != nil && list .Overlaps (tx ) {
777
+ if list := pool .pending [from ]; list != nil && list .Contains (tx . Nonce () ) {
778
778
// Nonce already pending, check if required price bump is met
779
779
inserted , old := list .Add (tx , pool .config .PriceBump )
780
780
if ! inserted {
@@ -817,18 +817,26 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err e
817
817
return replaced , nil
818
818
}
819
819
820
- // isFuture reports whether the given transaction is immediately executable.
821
- func (pool * TxPool ) isFuture (from common.Address , tx * types.Transaction ) bool {
822
- list := pool .pending [from ]
823
- if list == nil {
824
- return pool .pendingNonces .get (from ) != tx .Nonce ()
820
+ // isGapped reports whether the given transaction is immediately executable.
821
+ func (pool * TxPool ) isGapped (from common.Address , tx * types.Transaction ) bool {
822
+ // Short circuit if transaction matches pending nonce and can be promoted
823
+ // to pending list as an executable transaction.
824
+ next := pool .pendingNonces .get (from )
825
+ if tx .Nonce () == next {
826
+ return false
825
827
}
826
- // Sender has pending transactions.
827
- if old := list .txs .Get (tx .Nonce ()); old != nil {
828
- return false // It replaces a pending transaction.
828
+ // The transaction has a nonce gap with pending list, it's only considered
829
+ // as executable if transactions in queue can fill up the nonce gap.
830
+ queue , ok := pool .queue [from ]
831
+ if ! ok {
832
+ return true
829
833
}
830
- // Not replacing, check if parent nonce exists in pending.
831
- return list .txs .Get (tx .Nonce ()- 1 ) == nil
834
+ for nonce := next ; nonce < tx .Nonce (); nonce ++ {
835
+ if ! queue .Contains (nonce ) {
836
+ return true // txs in queue can't fill up the nonce gap
837
+ }
838
+ }
839
+ return false
832
840
}
833
841
834
842
// enqueueTx inserts a new transaction into the non-executable transaction queue.
0 commit comments