@@ -386,6 +386,8 @@ func (p *BlobPool) Init(gasTip *big.Int, head *types.Header, reserve txpool.Addr
386386
387387 if len (fails ) > 0 {
388388 log .Warn ("Dropping invalidated blob transactions" , "ids" , fails )
389+ dropInvalidMeter .Mark (int64 (len (fails )))
390+
389391 for _ , id := range fails {
390392 if err := p .store .Delete (id ); err != nil {
391393 p .Close ()
@@ -467,7 +469,13 @@ func (p *BlobPool) parseTransaction(id uint64, size uint32, blob []byte) error {
467469 }
468470
469471 meta := newBlobTxMeta (id , size , tx )
470-
472+ if _ , exists := p .lookup [meta .hash ]; exists {
473+ // This path is only possible after a crash, where deleted items are not
474+ // removed via the normal shutdown-startup procedure and thus may get
475+ // partially resurrected.
476+ log .Error ("Rejecting duplicate blob pool entry" , "id" , id , "hash" , tx .Hash ())
477+ return errors .New ("duplicate blob entry" )
478+ }
471479 sender , err := p .signer .Sender (tx )
472480 if err != nil {
473481 // This path is impossible unless the signature validity changes across
@@ -537,8 +545,10 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
537545
538546 if gapped {
539547 log .Warn ("Dropping dangling blob transactions" , "from" , addr , "missing" , next , "drop" , nonces , "ids" , ids )
548+ dropDanglingMeter .Mark (int64 (len (ids )))
540549 } else {
541550 log .Trace ("Dropping filled blob transactions" , "from" , addr , "filled" , nonces , "ids" , ids )
551+ dropFilledMeter .Mark (int64 (len (ids )))
542552 }
543553 for _ , id := range ids {
544554 if err := p .store .Delete (id ); err != nil {
@@ -569,6 +579,8 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
569579 txs = txs [1 :]
570580 }
571581 log .Trace ("Dropping overlapped blob transactions" , "from" , addr , "overlapped" , nonces , "ids" , ids , "left" , len (txs ))
582+ dropOverlappedMeter .Mark (int64 (len (ids )))
583+
572584 for _ , id := range ids {
573585 if err := p .store .Delete (id ); err != nil {
574586 log .Error ("Failed to delete blob transaction" , "from" , addr , "id" , id , "err" , err )
@@ -600,10 +612,30 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
600612 }
601613 continue
602614 }
603- // Sanity check that there's no double nonce. This case would be a coding
604- // error, but better know about it
615+ // Sanity check that there's no double nonce. This case would generally
616+ // be a coding error, so better know about it.
617+ //
618+ // Also, Billy behind the blobpool does not journal deletes. A process
619+ // crash would result in previously deleted entities being resurrected.
620+ // That could potentially cause a duplicate nonce to appear.
605621 if txs [i ].nonce == txs [i - 1 ].nonce {
606- log .Error ("Duplicate nonce blob transaction" , "from" , addr , "nonce" , txs [i ].nonce )
622+ id := p .lookup [txs [i ].hash ]
623+
624+ log .Error ("Dropping repeat nonce blob transaction" , "from" , addr , "nonce" , txs [i ].nonce , "id" , id )
625+ dropRepeatedMeter .Mark (1 )
626+
627+ p .spent [addr ] = new (uint256.Int ).Sub (p .spent [addr ], txs [i ].costCap )
628+ p .stored -= uint64 (txs [i ].size )
629+ delete (p .lookup , txs [i ].hash )
630+
631+ if err := p .store .Delete (id ); err != nil {
632+ log .Error ("Failed to delete blob transaction" , "from" , addr , "id" , id , "err" , err )
633+ }
634+ txs = append (txs [:i ], txs [i + 1 :]... )
635+ p .index [addr ] = txs
636+
637+ i --
638+ continue
607639 }
608640 // Otherwise if there's a nonce gap evict all later transactions
609641 var (
@@ -621,6 +653,8 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
621653 txs = txs [:i ]
622654
623655 log .Error ("Dropping gapped blob transactions" , "from" , addr , "missing" , txs [i - 1 ].nonce + 1 , "drop" , nonces , "ids" , ids )
656+ dropGappedMeter .Mark (int64 (len (ids )))
657+
624658 for _ , id := range ids {
625659 if err := p .store .Delete (id ); err != nil {
626660 log .Error ("Failed to delete blob transaction" , "from" , addr , "id" , id , "err" , err )
@@ -665,6 +699,8 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
665699 p .index [addr ] = txs
666700 }
667701 log .Warn ("Dropping overdrafted blob transactions" , "from" , addr , "balance" , balance , "spent" , spent , "drop" , nonces , "ids" , ids )
702+ dropOverdraftedMeter .Mark (int64 (len (ids )))
703+
668704 for _ , id := range ids {
669705 if err := p .store .Delete (id ); err != nil {
670706 log .Error ("Failed to delete blob transaction" , "from" , addr , "id" , id , "err" , err )
@@ -695,6 +731,8 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
695731 p .index [addr ] = txs
696732
697733 log .Warn ("Dropping overcapped blob transactions" , "from" , addr , "kept" , len (txs ), "drop" , nonces , "ids" , ids )
734+ dropOvercappedMeter .Mark (int64 (len (ids )))
735+
698736 for _ , id := range ids {
699737 if err := p .store .Delete (id ); err != nil {
700738 log .Error ("Failed to delete blob transaction" , "from" , addr , "id" , id , "err" , err )
@@ -952,7 +990,7 @@ func (p *BlobPool) reinject(addr common.Address, txhash common.Hash) error {
952990 return err
953991 }
954992
955- // Update the indixes and metrics
993+ // Update the indices and metrics
956994 meta := newBlobTxMeta (id , p .store .Size (id ), tx )
957995 if _ , ok := p .index [addr ]; ! ok {
958996 if err := p .reserve (addr , true ); err != nil {
@@ -1019,6 +1057,8 @@ func (p *BlobPool) SetGasTip(tip *big.Int) {
10191057 }
10201058 // Clear out the transactions from the data store
10211059 log .Warn ("Dropping underpriced blob transaction" , "from" , addr , "rejected" , tx .nonce , "tip" , tx .execTipCap , "want" , tip , "drop" , nonces , "ids" , ids )
1060+ dropUnderpricedMeter .Mark (int64 (len (ids )))
1061+
10221062 for _ , id := range ids {
10231063 if err := p .store .Delete (id ); err != nil {
10241064 log .Error ("Failed to delete dropped transaction" , "id" , id , "err" , err )
@@ -1198,13 +1238,30 @@ func (p *BlobPool) add(tx *types.Transaction) (err error) {
11981238 // Ensure the transaction is valid from all perspectives
11991239 if err := p .validateTx (tx ); err != nil {
12001240 log .Trace ("Transaction validation failed" , "hash" , tx .Hash (), "err" , err )
1241+ switch {
1242+ case errors .Is (err , txpool .ErrUnderpriced ):
1243+ addUnderpricedMeter .Mark (1 )
1244+ case errors .Is (err , core .ErrNonceTooLow ):
1245+ addStaleMeter .Mark (1 )
1246+ case errors .Is (err , core .ErrNonceTooHigh ):
1247+ addGappedMeter .Mark (1 )
1248+ case errors .Is (err , core .ErrInsufficientFunds ):
1249+ addOverdraftedMeter .Mark (1 )
1250+ case errors .Is (err , txpool .ErrAccountLimitExceeded ):
1251+ addOvercappedMeter .Mark (1 )
1252+ case errors .Is (err , txpool .ErrReplaceUnderpriced ):
1253+ addNoreplaceMeter .Mark (1 )
1254+ default :
1255+ addInvalidMeter .Mark (1 )
1256+ }
12011257 return err
12021258 }
12031259 // If the address is not yet known, request exclusivity to track the account
12041260 // only by this subpool until all transactions are evicted
12051261 from , _ := types .Sender (p .signer , tx ) // already validated above
12061262 if _ , ok := p .index [from ]; ! ok {
12071263 if err := p .reserve (from , true ); err != nil {
1264+ addNonExclusiveMeter .Mark (1 )
12081265 return err
12091266 }
12101267 defer func () {
@@ -1244,6 +1301,8 @@ func (p *BlobPool) add(tx *types.Transaction) (err error) {
12441301 }
12451302 if len (p .index [from ]) > offset {
12461303 // Transaction replaces a previously queued one
1304+ dropReplacedMeter .Mark (1 )
1305+
12471306 prev := p.index [from ][offset ]
12481307 if err := p .store .Delete (prev .id ); err != nil {
12491308 // Shitty situation, but try to recover gracefully instead of going boom
@@ -1322,6 +1381,7 @@ func (p *BlobPool) add(tx *types.Transaction) (err error) {
13221381 }
13231382 p .updateStorageMetrics ()
13241383
1384+ addValidMeter .Mark (1 )
13251385 return nil
13261386}
13271387
@@ -1371,7 +1431,9 @@ func (p *BlobPool) drop() {
13711431 }
13721432 }
13731433 // Remove the transaction from the data store
1374- log .Warn ("Evicting overflown blob transaction" , "from" , from , "evicted" , drop .nonce , "id" , drop .id )
1434+ log .Debug ("Evicting overflown blob transaction" , "from" , from , "evicted" , drop .nonce , "id" , drop .id )
1435+ dropOverflownMeter .Mark (1 )
1436+
13751437 if err := p .store .Delete (drop .id ); err != nil {
13761438 log .Error ("Failed to drop evicted transaction" , "id" , drop .id , "err" , err )
13771439 }
0 commit comments