From 43b005c479fc9ddd996f05b2e58b6b4ce1c44559 Mon Sep 17 00:00:00 2001 From: Daniel Liu <139250065@qq.com> Date: Mon, 26 Jan 2026 13:50:33 +0800 Subject: [PATCH] txpool: make unreserve idempotent to avoid false non-reserved errors, fix #1975 (#1976) --- core/txpool/legacypool/legacypool.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go index c9a1ffe3df..bc093d6124 100644 --- a/core/txpool/legacypool/legacypool.go +++ b/core/txpool/legacypool/legacypool.go @@ -808,10 +808,6 @@ func (pool *LegacyPool) add(tx *types.Transaction, local bool) (replaced bool, e // already validated by this point from, _ := types.Sender(pool.signer, tx) - if tx.IsSpecialTransaction() && pool.IsSigner(from) && pool.pendingNonces.get(from) == tx.Nonce() { - return pool.promoteSpecialTx(from, tx, isLocal) - } - // If the address is not yet known, request exclusivity to track the account // only by this subpool until all transactions are evicted var ( @@ -834,6 +830,13 @@ func (pool *LegacyPool) add(tx *types.Transaction, local bool) (replaced bool, e } }() } + + // Special transactions must also honor the reservation semantics to keep + // the coordinator's ownership accounting balanced. + if tx.IsSpecialTransaction() && pool.IsSigner(from) && pool.pendingNonces.get(from) == tx.Nonce() { + return pool.promoteSpecialTx(from, tx, isLocal) + } + // If the transaction pool is full, discard underpriced transactions if uint64(pool.all.Slots()+numSlots(tx)) > pool.config.GlobalSlots+pool.config.GlobalQueue { // If the new transaction is underpriced, don't accept it