Motivation
Currently, freshly added transactions in private_broadcast are almost immediately flagged and logged as stale by the resend-stale job.
The Bug
m_transactions maps a transaction to a std::vector<SendStatus>. When try_emplace adds a new transaction, this vector is empty. When GetStale() runs, DerivePriority() evaluates the empty vector and returns a default Priority struct where last_confirmed evaluates to the Unix Epoch (Jan 1, 1970). The stale checker sees a 50-year-old timestamp and flags it on the next resend-stale cycle.
The Fix
Rather than modifying the transient Priority struct or creating a “Zombie Transaction” edge case by ignoring transactions with 0 picks, this PR modifies the state container:
- Wraps the
SendStatusvector in a newTxSendStatusstruct insideprivate_broadcast.h. TxSendStatusautomatically capturestime_addedupon emplace.GetStale()now checksp.num_confirmed == 0to measure age againsttime_addedusing a new 5-minuteINITIAL_STALE_DURATIONgrace period, falling back tolast_confirmedand the standard 1-minuteSTALE_DURATIONonce network interaction begins.
Additional Polish
- Exposed
time_addedvia thegetprivatebroadcastinfoRPC endpoint so users can see when a transaction entered the queue. - Added a dedicated
stale_unpicked_txtest case and updatedprivate_broadcast_tests.cppto properly mock the passage of time for the new grace period. Closes #34862