diff --git a/zk/stages/stage_sequence_execute.go b/zk/stages/stage_sequence_execute.go index 3710ed6025d..9595cd04b85 100644 --- a/zk/stages/stage_sequence_execute.go +++ b/zk/stages/stage_sequence_execute.go @@ -2,6 +2,7 @@ package stages import ( "context" + "errors" "fmt" "time" @@ -432,12 +433,21 @@ func sequencingBatchStep( continue } - // if we have an error at this point something has gone wrong, either in the pool or otherwise - // to stop the pool growing and hampering further processing of good transactions here - // we mark it for being discarded - log.Warn(fmt.Sprintf("[%s] error adding transaction to batch, discarding from pool", logPrefix), "hash", txHash, "err", err) - badTxHashes = append(badTxHashes, txHash) - batchState.blockState.transactionsToDiscard = append(batchState.blockState.transactionsToDiscard, batchState.blockState.transactionHashesToSlots[txHash]) + if isOkKnownError(err) { + // if this is a known error that could be caused by some edge case coming from the pool we want to warn + // about it and continue on as normal but ensure we don't continue to keep trying to add this transaction + // to the block + log.Warn(fmt.Sprintf("[%s] known error adding transaction to block, skipping for now: %v", logPrefix, err), + "hash", txHash) + badTxHashes = append(badTxHashes, txHash) + } else { + // if we have an error at this point something has gone wrong, either in the pool or otherwise + // to stop the pool growing and hampering further processing of good transactions here + // we mark it for being discarded + log.Warn(fmt.Sprintf("[%s] error adding transaction to batch, discarding from pool", logPrefix), "hash", txHash, "err", err) + badTxHashes = append(badTxHashes, txHash) + batchState.blockState.transactionsToDiscard = append(batchState.blockState.transactionsToDiscard, batchState.blockState.transactionHashesToSlots[txHash]) + } } switch anyOverflow { @@ -575,8 +585,12 @@ func sequencingBatchStep( return err } - cfg.txPool.RemoveMinedTransactions(batchState.blockState.builtBlockElements.txSlots) - cfg.txPool.RemoveMinedTransactions(batchState.blockState.transactionsToDiscard) + if err := cfg.txPool.RemoveMinedTransactions(ctx, sdb.tx, header.GasLimit, batchState.blockState.builtBlockElements.txSlots); err != nil { + return err + } + if err := cfg.txPool.RemoveMinedTransactions(ctx, sdb.tx, header.GasLimit, batchState.blockState.transactionsToDiscard); err != nil { + return err + } if batchState.isLimboRecovery() { stateRoot := block.Root() @@ -660,3 +674,8 @@ func removeInclusionTransaction(orig []types.Transaction, index int) []types.Tra } return append(orig[:index], orig[index+1:]...) } + +func isOkKnownError(err error) bool { + return err == nil || + errors.Is(err, core.ErrNonceTooHigh) +} diff --git a/zk/txpool/pool_zk.go b/zk/txpool/pool_zk.go index c7a939abc71..05409049022 100644 --- a/zk/txpool/pool_zk.go +++ b/zk/txpool/pool_zk.go @@ -279,7 +279,9 @@ func (p *TxPool) MarkForDiscardFromPendingBest(txHash common.Hash) { } } -func (p *TxPool) RemoveMinedTransactions(ids []common.Hash) { +func (p *TxPool) RemoveMinedTransactions(ctx context.Context, tx kv.Tx, blockGasLimit uint64, ids []common.Hash) error { + cache := p.cache() + p.lock.Lock() defer p.lock.Unlock() @@ -304,9 +306,28 @@ func (p *TxPool) RemoveMinedTransactions(ids []common.Hash) { return true }) + sendersWithChangedState := make(map[uint64]struct{}) for _, mt := range toDelete { p.discardLocked(mt, Mined) + sendersWithChangedState[mt.Tx.SenderID] = struct{}{} + } + + baseFee := p.pendingBaseFee.Load() + + cacheView, err := cache.View(ctx, tx) + if err != nil { + return err } + for senderID := range sendersWithChangedState { + nonce, balance, err := p.senders.info(cacheView, senderID) + if err != nil { + return err + } + p.onSenderStateChange(senderID, nonce, balance, p.all, + baseFee, blockGasLimit, p.pending, p.baseFee, p.queued, p.discardLocked) + + } + return nil } // discards the transactions that are in overflowZkCoutners from pending