@@ -18,7 +18,6 @@ package txpool
18
18
19
19
import (
20
20
"errors"
21
- "fmt"
22
21
"math"
23
22
"math/big"
24
23
"sort"
91
90
// ErrFutureReplacePending is returned if a future transaction replaces a pending
92
91
// transaction. Future transactions should only be able to replace other future transactions.
93
92
ErrFutureReplacePending = errors .New ("future transaction tries to replace pending" )
94
-
95
- // ErrOverdraft is returned if a transaction would cause the senders balance to go negative
96
- // thus invalidating a potential large number of transactions.
97
- ErrOverdraft = errors .New ("transaction would cause overdraft" )
98
93
)
99
94
100
95
var (
@@ -178,8 +173,7 @@ type Config struct {
178
173
Lifetime time.Duration // Maximum amount of time non-executable transaction are queued
179
174
}
180
175
181
- // DefaultConfig contains the default configurations for the transaction
182
- // pool.
176
+ // DefaultConfig contains the default configurations for the transaction pool.
183
177
var DefaultConfig = Config {
184
178
Journal : "transactions.rlp" ,
185
179
Rejournal : time .Hour ,
@@ -245,20 +239,15 @@ type TxPool struct {
245
239
config Config
246
240
chainconfig * params.ChainConfig
247
241
chain blockChain
248
- gasPrice * big.Int
242
+ gasTip atomic. Pointer [ big.Int ]
249
243
txFeed event.Feed
250
244
scope event.SubscriptionScope
251
245
signer types.Signer
252
246
mu sync.RWMutex
253
247
254
- istanbul atomic.Bool // Fork indicator whether we are in the istanbul stage.
255
- eip2718 atomic.Bool // Fork indicator whether we are using EIP-2718 type transactions.
256
- eip1559 atomic.Bool // Fork indicator whether we are using EIP-1559 type transactions.
257
- shanghai atomic.Bool // Fork indicator whether we are in the Shanghai stage.
258
-
259
- currentState * state.StateDB // Current state in the blockchain head
260
- pendingNonces * noncer // Pending state tracking virtual nonces
261
- currentMaxGas atomic.Uint64 // Current gas limit for transaction caps
248
+ currentHead atomic.Pointer [types.Header ] // Current head of the blockchain
249
+ currentState * state.StateDB // Current state in the blockchain head
250
+ pendingNonces * noncer // Pending state tracking virtual nonces
262
251
263
252
locals * accountSet // Set of local transaction to exempt from eviction rules
264
253
journal * journal // Journal of local transaction to back up to disk
@@ -286,9 +275,9 @@ type txpoolResetRequest struct {
286
275
oldHead , newHead * types.Header
287
276
}
288
277
289
- // NewTxPool creates a new transaction pool to gather, sort and filter inbound
278
+ // New creates a new transaction pool to gather, sort and filter inbound
290
279
// transactions from the network.
291
- func NewTxPool (config Config , chainconfig * params.ChainConfig , chain blockChain ) * TxPool {
280
+ func New (config Config , chainconfig * params.ChainConfig , chain blockChain ) * TxPool {
292
281
// Sanitize the input to ensure no vulnerable gas prices are set
293
282
config = (& config ).sanitize ()
294
283
@@ -309,8 +298,8 @@ func NewTxPool(config Config, chainconfig *params.ChainConfig, chain blockChain)
309
298
reorgDoneCh : make (chan chan struct {}),
310
299
reorgShutdownCh : make (chan struct {}),
311
300
initDoneCh : make (chan struct {}),
312
- gasPrice : new (big.Int ).SetUint64 (config .PriceLimit ),
313
301
}
302
+ pool .gasTip .Store (new (big.Int ).SetUint64 (config .PriceLimit ))
314
303
pool .locals = newAccountSet (pool .signer )
315
304
for _ , addr := range config .Locals {
316
305
log .Info ("Setting new local account" , "address" , addr )
@@ -443,33 +432,25 @@ func (pool *TxPool) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subsc
443
432
return pool .scope .Track (pool .txFeed .Subscribe (ch ))
444
433
}
445
434
446
- // GasPrice returns the current gas price enforced by the transaction pool.
447
- func (pool * TxPool ) GasPrice () * big.Int {
448
- pool .mu .RLock ()
449
- defer pool .mu .RUnlock ()
450
-
451
- return new (big.Int ).Set (pool .gasPrice )
452
- }
453
-
454
- // SetGasPrice updates the minimum price required by the transaction pool for a
435
+ // SetGasTip updates the minimum gas tip required by the transaction pool for a
455
436
// new transaction, and drops all transactions below this threshold.
456
- func (pool * TxPool ) SetGasPrice ( price * big.Int ) {
437
+ func (pool * TxPool ) SetGasTip ( tip * big.Int ) {
457
438
pool .mu .Lock ()
458
439
defer pool .mu .Unlock ()
459
440
460
- old := pool .gasPrice
461
- pool .gasPrice = price
462
- // if the min miner fee increased, remove transactions below the new threshold
463
- if price .Cmp (old ) > 0 {
441
+ old := pool .gasTip .Load ()
442
+ pool .gasTip .Store (new (big.Int ).Set (tip ))
443
+
444
+ // If the min miner fee increased, remove transactions below the new threshold
445
+ if tip .Cmp (old ) > 0 {
464
446
// pool.priced is sorted by GasFeeCap, so we have to iterate through pool.all instead
465
- drop := pool .all .RemotesBelowTip (price )
447
+ drop := pool .all .RemotesBelowTip (tip )
466
448
for _ , tx := range drop {
467
449
pool .removeTx (tx .Hash (), false )
468
450
}
469
451
pool .priced .Removed (len (drop ))
470
452
}
471
-
472
- log .Info ("Transaction pool price threshold updated" , "price" , price )
453
+ log .Info ("Transaction pool tip threshold updated" , "tip" , tip )
473
454
}
474
455
475
456
// Nonce returns the next nonce of an account, with all transactions executable
@@ -556,7 +537,7 @@ func (pool *TxPool) Pending(enforceTips bool) map[common.Address]types.Transacti
556
537
// If the miner requests tip enforcement, cap the lists now
557
538
if enforceTips && ! pool .locals .contains (addr ) {
558
539
for i , tx := range txs {
559
- if tx .EffectiveGasTipIntCmp (pool .gasPrice , pool .priced .urgent .baseFee ) < 0 {
540
+ if tx .EffectiveGasTipIntCmp (pool .gasTip . Load () , pool .priced .urgent .baseFee ) < 0 {
560
541
txs = txs [:i ]
561
542
break
562
543
}
@@ -598,93 +579,48 @@ func (pool *TxPool) local() map[common.Address]types.Transactions {
598
579
// This check is meant as an early check which only needs to be performed once,
599
580
// and does not require the pool mutex to be held.
600
581
func (pool * TxPool ) validateTxBasics (tx * types.Transaction , local bool ) error {
601
- // Accept only legacy transactions until EIP-2718/2930 activates.
602
- if ! pool .eip2718 .Load () && tx .Type () != types .LegacyTxType {
603
- return core .ErrTxTypeNotSupported
604
- }
605
- // Reject dynamic fee transactions until EIP-1559 activates.
606
- if ! pool .eip1559 .Load () && tx .Type () == types .DynamicFeeTxType {
607
- return core .ErrTxTypeNotSupported
608
- }
609
- // Reject blob transactions forever, those will have their own pool.
610
- if tx .Type () == types .BlobTxType {
611
- return core .ErrTxTypeNotSupported
612
- }
613
- // Reject transactions over defined size to prevent DOS attacks
614
- if tx .Size () > txMaxSize {
615
- return ErrOversizedData
616
- }
617
- // Check whether the init code size has been exceeded.
618
- if pool .shanghai .Load () && tx .To () == nil && len (tx .Data ()) > params .MaxInitCodeSize {
619
- return fmt .Errorf ("%w: code size %v limit %v" , core .ErrMaxInitCodeSizeExceeded , len (tx .Data ()), params .MaxInitCodeSize )
620
- }
621
- // Transactions can't be negative. This may never happen using RLP decoded
622
- // transactions but may occur if you create a transaction using the RPC.
623
- if tx .Value ().Sign () < 0 {
624
- return ErrNegativeValue
625
- }
626
- // Ensure the transaction doesn't exceed the current block limit gas.
627
- if pool .currentMaxGas .Load () < tx .Gas () {
628
- return ErrGasLimit
629
- }
630
- // Sanity check for extremely large numbers
631
- if tx .GasFeeCap ().BitLen () > 256 {
632
- return core .ErrFeeCapVeryHigh
633
- }
634
- if tx .GasTipCap ().BitLen () > 256 {
635
- return core .ErrTipVeryHigh
582
+ opts := & ValidationOptions {
583
+ Config : pool .chainconfig ,
584
+ Accept : 0 |
585
+ 1 << types .LegacyTxType |
586
+ 1 << types .AccessListTxType |
587
+ 1 << types .DynamicFeeTxType ,
588
+ MaxSize : txMaxSize ,
589
+ MinTip : pool .gasTip .Load (),
636
590
}
637
- // Ensure gasFeeCap is greater than or equal to gasTipCap.
638
- if tx .GasFeeCapIntCmp (tx .GasTipCap ()) < 0 {
639
- return core .ErrTipAboveFeeCap
640
- }
641
- // Make sure the transaction is signed properly.
642
- if _ , err := types .Sender (pool .signer , tx ); err != nil {
643
- return ErrInvalidSender
644
- }
645
- // Drop non-local transactions under our own minimal accepted gas price or tip
646
- if ! local && tx .GasTipCapIntCmp (pool .gasPrice ) < 0 {
647
- return ErrUnderpriced
591
+ if local {
592
+ opts .MinTip = new (big.Int )
648
593
}
649
- // Ensure the transaction has more gas than the basic tx fee.
650
- intrGas , err := core .IntrinsicGas (tx .Data (), tx .AccessList (), tx .To () == nil , true , pool .istanbul .Load (), pool .shanghai .Load ())
651
- if err != nil {
594
+ if err := ValidateTransaction (tx , nil , nil , nil , pool .currentHead .Load (), pool .signer , opts ); err != nil {
652
595
return err
653
596
}
654
- if tx .Gas () < intrGas {
655
- return core .ErrIntrinsicGas
656
- }
657
597
return nil
658
598
}
659
599
660
600
// validateTx checks whether a transaction is valid according to the consensus
661
601
// rules and adheres to some heuristic limits of the local node (price and size).
662
602
func (pool * TxPool ) validateTx (tx * types.Transaction , local bool ) error {
663
- // Signature has been checked already, this cannot error.
664
- from , _ := types .Sender (pool .signer , tx )
665
- // Ensure the transaction adheres to nonce ordering
666
- if pool .currentState .GetNonce (from ) > tx .Nonce () {
667
- return core .ErrNonceTooLow
668
- }
669
- // Transactor should have enough funds to cover the costs
670
- // cost == V + GP * GL
671
- balance := pool .currentState .GetBalance (from )
672
- if balance .Cmp (tx .Cost ()) < 0 {
673
- return core .ErrInsufficientFunds
674
- }
675
-
676
- // Verify that replacing transactions will not result in overdraft
677
- list := pool .pending [from ]
678
- if list != nil { // Sender already has pending txs
679
- sum := new (big.Int ).Add (tx .Cost (), list .totalcost )
680
- if repl := list .txs .Get (tx .Nonce ()); repl != nil {
681
- // Deduct the cost of a transaction replaced by this
682
- sum .Sub (sum , repl .Cost ())
683
- }
684
- if balance .Cmp (sum ) < 0 {
685
- log .Trace ("Replacing transactions would overdraft" , "sender" , from , "balance" , pool .currentState .GetBalance (from ), "required" , sum )
686
- return ErrOverdraft
687
- }
603
+ opts := & ValidationOptionsWithState {
604
+ State : pool .currentState ,
605
+
606
+ FirstNonceGap : nil , // Pool allows arbitrary arrival order, don't invalidate nonce gaps
607
+ ExistingExpenditure : func (addr common.Address ) * big.Int {
608
+ if list := pool .pending [addr ]; list != nil {
609
+ return list .totalcost
610
+ }
611
+ return new (big.Int )
612
+ },
613
+ ExistingCost : func (addr common.Address , nonce uint64 ) * big.Int {
614
+ if list := pool .pending [addr ]; list != nil {
615
+ if tx := list .txs .Get (nonce ); tx != nil {
616
+ return tx .Cost ()
617
+ }
618
+ }
619
+ return nil
620
+ },
621
+ }
622
+ if err := ValidateTransactionWithState (tx , pool .signer , opts ); err != nil {
623
+ return err
688
624
}
689
625
return nil
690
626
}
@@ -995,7 +931,6 @@ func (pool *TxPool) addTxs(txs []*types.Transaction, local, sync bool) []error {
995
931
// Exclude transactions with basic errors, e.g invalid signatures and
996
932
// insufficient intrinsic gas as soon as possible and cache senders
997
933
// in transactions before obtaining lock
998
-
999
934
if err := pool .validateTxBasics (tx , local ); err != nil {
1000
935
errs [i ] = err
1001
936
invalidTxMeter .Mark (1 )
@@ -1385,21 +1320,14 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) {
1385
1320
log .Error ("Failed to reset txpool state" , "err" , err )
1386
1321
return
1387
1322
}
1323
+ pool .currentHead .Store (newHead )
1388
1324
pool .currentState = statedb
1389
1325
pool .pendingNonces = newNoncer (statedb )
1390
- pool .currentMaxGas .Store (newHead .GasLimit )
1391
1326
1392
1327
// Inject any transactions discarded due to reorgs
1393
1328
log .Debug ("Reinjecting stale transactions" , "count" , len (reinject ))
1394
1329
core .SenderCacher .Recover (pool .signer , reinject )
1395
1330
pool .addTxsLocked (reinject , false )
1396
-
1397
- // Update all fork indicator by next pending block number.
1398
- next := new (big.Int ).Add (newHead .Number , big .NewInt (1 ))
1399
- pool .istanbul .Store (pool .chainconfig .IsIstanbul (next ))
1400
- pool .eip2718 .Store (pool .chainconfig .IsBerlin (next ))
1401
- pool .eip1559 .Store (pool .chainconfig .IsLondon (next ))
1402
- pool .shanghai .Store (pool .chainconfig .IsShanghai (next , uint64 (time .Now ().Unix ())))
1403
1331
}
1404
1332
1405
1333
// promoteExecutables moves transactions that have become processable from the
@@ -1410,6 +1338,7 @@ func (pool *TxPool) promoteExecutables(accounts []common.Address) []*types.Trans
1410
1338
var promoted []* types.Transaction
1411
1339
1412
1340
// Iterate over all accounts and promote any executable transactions
1341
+ gasLimit := pool .currentHead .Load ().GasLimit
1413
1342
for _ , addr := range accounts {
1414
1343
list := pool .queue [addr ]
1415
1344
if list == nil {
@@ -1423,7 +1352,7 @@ func (pool *TxPool) promoteExecutables(accounts []common.Address) []*types.Trans
1423
1352
}
1424
1353
log .Trace ("Removed old queued transactions" , "count" , len (forwards ))
1425
1354
// Drop all transactions that are too costly (low balance or out of gas)
1426
- drops , _ := list .Filter (pool .currentState .GetBalance (addr ), pool . currentMaxGas . Load () )
1355
+ drops , _ := list .Filter (pool .currentState .GetBalance (addr ), gasLimit )
1427
1356
for _ , tx := range drops {
1428
1357
hash := tx .Hash ()
1429
1358
pool .all .Remove (hash )
@@ -1609,6 +1538,7 @@ func (pool *TxPool) truncateQueue() {
1609
1538
// to trigger a re-heap is this function
1610
1539
func (pool * TxPool ) demoteUnexecutables () {
1611
1540
// Iterate over all accounts and demote any non-executable transactions
1541
+ gasLimit := pool .currentHead .Load ().GasLimit
1612
1542
for addr , list := range pool .pending {
1613
1543
nonce := pool .currentState .GetNonce (addr )
1614
1544
@@ -1620,7 +1550,7 @@ func (pool *TxPool) demoteUnexecutables() {
1620
1550
log .Trace ("Removed old pending transaction" , "hash" , hash )
1621
1551
}
1622
1552
// Drop all transactions that are too costly (low balance or out of gas), and queue any invalids back for later
1623
- drops , invalids := list .Filter (pool .currentState .GetBalance (addr ), pool . currentMaxGas . Load () )
1553
+ drops , invalids := list .Filter (pool .currentState .GetBalance (addr ), gasLimit )
1624
1554
for _ , tx := range drops {
1625
1555
hash := tx .Hash ()
1626
1556
log .Trace ("Removed unpayable pending transaction" , "hash" , hash )
0 commit comments