@@ -1741,6 +1741,13 @@ func (p *BlobPool) add(tx *types.Transaction) (err error) {
17411741 addtimeHist .Update (time .Since (start ).Nanoseconds ())
17421742 }(time .Now ())
17431743
1744+ return p .addLocked (tx , true )
1745+ }
1746+
1747+ // addLocked inserts a new blob transaction into the pool if it passes validation (both
1748+ // consensus validity and pool restrictions). It must be called with the pool lock held.
1749+ // Only for internal use.
1750+ func (p * BlobPool ) addLocked (tx * types.Transaction , checkGapped bool ) (err error ) {
17441751 // Ensure the transaction is valid from all perspectives
17451752 if err := p .validateTx (tx ); err != nil {
17461753 log .Trace ("Transaction validation failed" , "hash" , tx .Hash (), "err" , err )
@@ -1904,34 +1911,48 @@ func (p *BlobPool) add(tx *types.Transaction) (err error) {
19041911
19051912 addValidMeter .Mark (1 )
19061913
1914+ // Notify all listeners of the new arrival
1915+ p .discoverFeed .Send (core.NewTxsEvent {Txs : []* types.Transaction {tx .WithoutBlobTxSidecar ()}})
1916+ p .insertFeed .Send (core.NewTxsEvent {Txs : []* types.Transaction {tx .WithoutBlobTxSidecar ()}})
1917+
19071918 //check the gapped queue for this account and try to promote
1908- if gtxs , ok := p .gapped [from ]; ok && len (gtxs ) > 0 {
1919+ if gtxs , ok := p .gapped [from ]; checkGapped && ok && len (gtxs ) > 0 {
19091920 // We have to add in nonce order, but we want to stable sort to cater for situations
19101921 // where transactions are replaced, keeping the original receive order for same nonce
19111922 sort .SliceStable (gtxs , func (i , j int ) bool {
19121923 return gtxs [i ].tx .Nonce () < gtxs [j ].tx .Nonce ()
19131924 })
1914- firstgap := p .state .GetNonce (from ) + uint64 (len (p .index [from ]))
19151925 for len (gtxs ) > 0 {
1916- if gtxs [0 ].tx .Nonce () <= firstgap {
1917- // Drop any buffered transactions that became stale in themeantime (included in chain or replaced)
1918- // If we arrive to the tx at the first gap, we try to add it now (also dropping it from the gapped queue)
1919- tx := gtxs [0 ].tx
1920- gtxs [0 ] = nil
1921- gtxs = gtxs [1 :]
1922- delete (p .gappedSource , tx .Hash ())
1923- if tx .Nonce () == firstgap {
1924- // We are under lock. Add the first transaction in a goroutine to avoid blocking.
1925- // This might lead to a race between new calls to add and the revalidation here,
1926- // we should revisit if this is a potential issue.
1927- go func () {
1928- if err := p .add (tx ); err == nil {
1929- log .Trace ("Gapped blob transaction added to pool" , "hash" , tx .Hash (), "from" , from , "nonce" , tx .Nonce (), "qlen" , len (p .gapped [from ]))
1930- } else {
1931- log .Trace ("Gapped blob transaction not accepted" , "hash" , tx .Hash (), "from" , from , "nonce" , tx .Nonce (), "err" , err )
1932- }
1933- }()
1934- break
1926+ stateNonce := p .state .GetNonce (from )
1927+ firstgap := stateNonce + uint64 (len (p .index [from ]))
1928+
1929+ if gtxs [0 ].tx .Nonce () > firstgap {
1930+ // Anything beyond the first gap is not addable yet
1931+ break
1932+ }
1933+
1934+ // Drop any buffered transactions that became stale in the meantime (included in chain or replaced)
1935+ // If we arrive to the transaction in the pending range (between the state Nonce and first gap, we
1936+ // try to add them now while removing from here.
1937+ tx := gtxs [0 ].tx
1938+ gtxs [0 ] = nil
1939+ gtxs = gtxs [1 :]
1940+ delete (p .gappedSource , tx .Hash ())
1941+
1942+ if tx .Nonce () < stateNonce {
1943+ // Stale, drop it. Eventually we could add to limbo here if hash matches.
1944+ log .Trace ("Gapped blob transaction became stale" , "hash" , tx .Hash (), "from" , from , "nonce" , tx .Nonce (), "state" , stateNonce , "qlen" , len (p .gapped [from ]))
1945+ continue
1946+ }
1947+
1948+ if tx .Nonce () <= firstgap {
1949+ // If we hit the pending range, including the first gap, add it and continue to try to add more.
1950+ // We do not recurse here, but continue to loop instead.
1951+ // We are under lock, so we can add the transaction directly.
1952+ if err := p .addLocked (tx , false ); err == nil {
1953+ log .Trace ("Gapped blob transaction added to pool" , "hash" , tx .Hash (), "from" , from , "nonce" , tx .Nonce (), "qlen" , len (p .gapped [from ]))
1954+ } else {
1955+ log .Trace ("Gapped blob transaction not accepted" , "hash" , tx .Hash (), "from" , from , "nonce" , tx .Nonce (), "err" , err )
19351956 }
19361957 }
19371958 }
@@ -1941,9 +1962,6 @@ func (p *BlobPool) add(tx *types.Transaction) (err error) {
19411962 p .gapped [from ] = gtxs
19421963 }
19431964 }
1944- // Notify all listeners of the new arrival
1945- p .discoverFeed .Send (core.NewTxsEvent {Txs : []* types.Transaction {tx .WithoutBlobTxSidecar ()}})
1946- p .insertFeed .Send (core.NewTxsEvent {Txs : []* types.Transaction {tx .WithoutBlobTxSidecar ()}})
19471965 return nil
19481966}
19491967
0 commit comments