@@ -97,6 +97,8 @@ type blobTxMeta struct {
97
97
execTipCap * uint256.Int // Needed to prioritize inclusion order across accounts and validate replacement price bump
98
98
execFeeCap * uint256.Int // Needed to validate replacement price bump
99
99
blobFeeCap * uint256.Int // Needed to validate replacement price bump
100
+ execGas uint64 // Needed to check inclusion validity before reading the blob
101
+ blobGas uint64 // Needed to check inclusion validity before reading the blob
100
102
101
103
basefeeJumps float64 // Absolute number of 1559 fee adjustments needed to reach the tx's fee cap
102
104
blobfeeJumps float64 // Absolute number of 4844 fee adjustments needed to reach the tx's blob fee cap
@@ -118,6 +120,8 @@ func newBlobTxMeta(id uint64, size uint32, tx *types.Transaction) *blobTxMeta {
118
120
execTipCap : uint256 .MustFromBig (tx .GasTipCap ()),
119
121
execFeeCap : uint256 .MustFromBig (tx .GasFeeCap ()),
120
122
blobFeeCap : uint256 .MustFromBig (tx .BlobGasFeeCap ()),
123
+ execGas : tx .Gas (),
124
+ blobGas : tx .BlobGas (),
121
125
}
122
126
meta .basefeeJumps = dynamicFeeJumps (meta .execFeeCap )
123
127
meta .blobfeeJumps = dynamicFeeJumps (meta .blobFeeCap )
@@ -307,8 +311,8 @@ type BlobPool struct {
307
311
spent map [common.Address ]* uint256.Int // Expenditure tracking for individual accounts
308
312
evict * evictHeap // Heap of cheapest accounts for eviction when full
309
313
310
- eventFeed event.Feed // Event feed to send out new tx events on pool inclusion
311
- eventScope event.SubscriptionScope // Event scope to track and mass unsubscribe on termination
314
+ discoverFeed event.Feed // Event feed to send out new tx events on pool discovery (reorg excluded)
315
+ insertFeed event.Feed // Event feed to send out new tx events on pool inclusion (reorg included)
312
316
313
317
lock sync.RWMutex // Mutex protecting the pool during reorg handling
314
318
}
@@ -436,8 +440,6 @@ func (p *BlobPool) Close() error {
436
440
if err := p .store .Close (); err != nil {
437
441
errs = append (errs , err )
438
442
}
439
- p .eventScope .Close ()
440
-
441
443
switch {
442
444
case errs == nil :
443
445
return nil
@@ -758,15 +760,21 @@ func (p *BlobPool) Reset(oldHead, newHead *types.Header) {
758
760
// Run the reorg between the old and new head and figure out which accounts
759
761
// need to be rechecked and which transactions need to be readded
760
762
if reinject , inclusions := p .reorg (oldHead , newHead ); reinject != nil {
763
+ var adds []* types.Transaction
761
764
for addr , txs := range reinject {
762
765
// Blindly push all the lost transactions back into the pool
763
766
for _ , tx := range txs {
764
- p .reinject (addr , tx .Hash ())
767
+ if err := p .reinject (addr , tx .Hash ()); err == nil {
768
+ adds = append (adds , tx .WithoutBlobTxSidecar ())
769
+ }
765
770
}
766
771
// Recheck the account's pooled transactions to drop included and
767
772
// invalidated one
768
773
p .recheck (addr , inclusions )
769
774
}
775
+ if len (adds ) > 0 {
776
+ p .insertFeed .Send (core.NewTxsEvent {Txs : adds })
777
+ }
770
778
}
771
779
// Flush out any blobs from limbo that are older than the latest finality
772
780
if p .chain .Config ().IsCancun (p .head .Number , p .head .Time ) {
@@ -921,13 +929,13 @@ func (p *BlobPool) reorg(oldHead, newHead *types.Header) (map[common.Address][]*
921
929
// Note, the method will not initialize the eviction cache values as those will
922
930
// be done once for all transactions belonging to an account after all individual
923
931
// transactions are injected back into the pool.
924
- func (p * BlobPool ) reinject (addr common.Address , txhash common.Hash ) {
932
+ func (p * BlobPool ) reinject (addr common.Address , txhash common.Hash ) error {
925
933
// Retrieve the associated blob from the limbo. Without the blobs, we cannot
926
934
// add the transaction back into the pool as it is not mineable.
927
935
tx , err := p .limbo .pull (txhash )
928
936
if err != nil {
929
937
log .Error ("Blobs unavailable, dropping reorged tx" , "err" , err )
930
- return
938
+ return err
931
939
}
932
940
// TODO: seems like an easy optimization here would be getting the serialized tx
933
941
// from limbo instead of re-serializing it here.
@@ -936,20 +944,20 @@ func (p *BlobPool) reinject(addr common.Address, txhash common.Hash) {
936
944
blob , err := rlp .EncodeToBytes (tx )
937
945
if err != nil {
938
946
log .Error ("Failed to encode transaction for storage" , "hash" , tx .Hash (), "err" , err )
939
- return
947
+ return err
940
948
}
941
949
id , err := p .store .Put (blob )
942
950
if err != nil {
943
951
log .Error ("Failed to write transaction into storage" , "hash" , tx .Hash (), "err" , err )
944
- return
952
+ return err
945
953
}
946
954
947
955
// Update the indixes and metrics
948
956
meta := newBlobTxMeta (id , p .store .Size (id ), tx )
949
957
if _ , ok := p .index [addr ]; ! ok {
950
958
if err := p .reserve (addr , true ); err != nil {
951
959
log .Warn ("Failed to reserve account for blob pool" , "tx" , tx .Hash (), "from" , addr , "err" , err )
952
- return
960
+ return err
953
961
}
954
962
p .index [addr ] = []* blobTxMeta {meta }
955
963
p .spent [addr ] = meta .costCap
@@ -960,6 +968,7 @@ func (p *BlobPool) reinject(addr common.Address, txhash common.Hash) {
960
968
}
961
969
p .lookup [meta .hash ] = meta .id
962
970
p .stored += uint64 (meta .size )
971
+ return nil
963
972
}
964
973
965
974
// SetGasTip implements txpool.SubPool, allowing the blob pool's gas requirements
@@ -1154,9 +1163,19 @@ func (p *BlobPool) Get(hash common.Hash) *types.Transaction {
1154
1163
// Add inserts a set of blob transactions into the pool if they pass validation (both
1155
1164
// consensus validity and pool restictions).
1156
1165
func (p * BlobPool ) Add (txs []* types.Transaction , local bool , sync bool ) []error {
1157
- errs := make ([]error , len (txs ))
1166
+ var (
1167
+ adds = make ([]* types.Transaction , 0 , len (txs ))
1168
+ errs = make ([]error , len (txs ))
1169
+ )
1158
1170
for i , tx := range txs {
1159
1171
errs [i ] = p .add (tx )
1172
+ if errs [i ] == nil {
1173
+ adds = append (adds , tx .WithoutBlobTxSidecar ())
1174
+ }
1175
+ }
1176
+ if len (adds ) > 0 {
1177
+ p .discoverFeed .Send (core.NewTxsEvent {Txs : adds })
1178
+ p .insertFeed .Send (core.NewTxsEvent {Txs : adds })
1160
1179
}
1161
1180
return errs
1162
1181
}
@@ -1384,6 +1403,8 @@ func (p *BlobPool) Pending(enforceTips bool) map[common.Address][]*txpool.LazyTr
1384
1403
Time : time .Now (), // TODO(karalabe): Maybe save these and use that?
1385
1404
GasFeeCap : tx .execFeeCap .ToBig (),
1386
1405
GasTipCap : tx .execTipCap .ToBig (),
1406
+ Gas : tx .execGas ,
1407
+ BlobGas : tx .blobGas ,
1387
1408
})
1388
1409
}
1389
1410
if len (lazies ) > 0 {
@@ -1468,10 +1489,14 @@ func (p *BlobPool) updateLimboMetrics() {
1468
1489
limboSlotusedGauge .Update (int64 (slotused ))
1469
1490
}
1470
1491
1471
- // SubscribeTransactions registers a subscription of NewTxsEvent and
1472
- // starts sending event to the given channel.
1473
- func (p * BlobPool ) SubscribeTransactions (ch chan <- core.NewTxsEvent ) event.Subscription {
1474
- return p .eventScope .Track (p .eventFeed .Subscribe (ch ))
1492
+ // SubscribeTransactions registers a subscription for new transaction events,
1493
+ // supporting feeding only newly seen or also resurrected transactions.
1494
+ func (p * BlobPool ) SubscribeTransactions (ch chan <- core.NewTxsEvent , reorgs bool ) event.Subscription {
1495
+ if reorgs {
1496
+ return p .insertFeed .Subscribe (ch )
1497
+ } else {
1498
+ return p .discoverFeed .Subscribe (ch )
1499
+ }
1475
1500
}
1476
1501
1477
1502
// Nonce returns the next nonce of an account, with all transactions executable
0 commit comments