Summary
In update_mempool_jobs (main_loop.rs), each update job is processed unconditionally — the code fetches a mutator set update and recomputes the witness even if the mempool entry has already been updated to the latest block tip by another path (e.g., the proof_upgrader loop).
Proposed fix
Before processing a job, check whether the transaction's kernel.mutator_set_hash already matches the tip's mutator set accumulator hash in the mempool. If it does, the job is stale and can be skipped.
The check is:
let gs = global_state_lock.lock_guard().await;
let tip_ms_hash = gs
.chain
.light_state()
.tip()
.mutator_set_accumulator_after()
.ok()
.map(|msa| msa.hash());
if let (Some(current_tx), Some(tip_hash)) =
(gs.mempool.get(txid), tip_ms_hash)
{
if current_tx.kernel.mutator_set_hash == tip_hash {
// skip — already synced
}
}
Logic explanation
- Acquire a read-only lock (not a write lock, since we are only checking — the write lock is still taken later for the actual update).
- Get the tip block's mutator set accumulator hash from the chain's light state.
- Look up the transaction in the mempool by its
txid.
- If both exist and their MS hashes match, the transaction is already at the tip and no update is needed.
- The scoped block ensures the read lock is dropped before the match block, avoiding any deadlock with the later
lock_guard_mut() call.
Why this matters
Without this check, the function re-derives the mutator set update and re-witnesses the transaction even when the mempool already has the fresh version. This wastes CPU cycles on redundant computation and delays processing of other update jobs.
Summary
In
update_mempool_jobs(main_loop.rs), each update job is processed unconditionally — the code fetches a mutator set update and recomputes the witness even if the mempool entry has already been updated to the latest block tip by another path (e.g., theproof_upgraderloop).Proposed fix
Before processing a job, check whether the transaction's
kernel.mutator_set_hashalready matches the tip's mutator set accumulator hash in the mempool. If it does, the job is stale and can be skipped.The check is:
Logic explanation
txid.lock_guard_mut()call.Why this matters
Without this check, the function re-derives the mutator set update and re-witnesses the transaction even when the mempool already has the fresh version. This wastes CPU cycles on redundant computation and delays processing of other update jobs.