#36566 private broadcast: wait synchronously for mempool acceptance
| Reviewability | Reviews | Agreement | Size | |||||||
|---|---|---|---|---|---|---|---|---|---|---|
| #36566 private broadcast: wait synchronously for mempool acceptance | Waiting on author | 0 | Blocked | 107 + 152 tests | ||||||
|
|
|
|
| ||||||
Reviewability: ReadyStalePaused Agreement: StrongPositivePositive w/ caveatsNeutralMildDisputedBlockedCrickets Reviews: current code-review ACKs, then (+stale ACKs) and -NACKs; greener = more ACKs. Size: lines added or modified outside tests, then in tests; greener = smaller. | ||||||||||
Goal
Adds synchronous mempool acceptance waiting to BroadcastTransaction for private broadcasts, exposed via an optional timeout argument (defaulting to 10 minutes) on sendrawtransaction. It introduces a synchronous TransactionAddedToMempoolSync callback to CValidationInterface that fires immediately upon mempool insertion instead of routing through the background validation queue. Setting timeout to 0 allows callers to bypass waiting and preserve the previous non-blocking behavior.
Problem: Private transaction broadcast skips local mempool insertion, returning immediately once queued for external broadcast. External software and third-party wallets calling sendrawtransaction expect a successful return to guarantee the transaction is already in the mempool. Furthermore, future wallet integration cannot wait on the asynchronous validation interface queue while holding cs_wallet without risking deadlocks or timeouts from blocked queue processing.
Evidence of importance:
- PR description: "Calling BroadcastTransaction with the NO_MEMPOOL_PRIVATE_BROADCAST method skips inserting the transaction into the mempool and returns immediately. This causes problems with software that expects the transaction to be in the mempool after the function returns. For example many third-party wallets or services call sendrawtransaction and expect the transaction to be in the mempool after it returns a successful response."
- PR description: "Synchronously waiting for mempool acceptance is also a prerequisite for adding private broadcast support to the wallet. The TransactionAddedToMempoolSync method is added specifically for future wallet broadcasting, so a broadcast caller holding cs_wallet will not timeout waiting on another background event that is also trying to acquire cs_wallet."
Scope: Adds a synchronous callback to CValidationInterface alongside the asynchronous queue, and introduces a timeout loop with periodic shutdown checks in BroadcastTransaction.
Risk of a mistake: medium (validation, rpc_api). A synchronization or lock-order bug in the synchronous validation interface notification could hang RPC worker threads or disrupt transaction submission.
Reviewability
Paused · Waiting on author
Open objections from instagibbs with no author reply for 11 days; review would repeat what has been asked.
Waiting on (from the thread read):
- author: address instagibbs's question regarding affected software and objection regarding wallet UX and double-spend risks 2026-10-21
- author: response to instagibbs' question, suggestion for end-to-end integration, and UX safety concerns 2026-10-21
Agreement
Blocked
objection that needs a change, nobody has replied (instagibbs)
Thread notes: Initial record. instagibbs raised a question about which software requires synchronous mempool acceptance and objected that synchronous waiting can cause wallet hangs leading to double payments. / Initial review by instagibbs questioning the motivation for third-party software and raising safety concerns regarding wallet integration UX.
Objections, suggestions, and questions:
| Reviewer | Type | Harm, request, or question | Status | Must be | Author replied | Quote |
|---|---|---|---|---|---|---|
| instagibbs (member) | question, usefulness | Can we gather a list of third-party software and services that expect transactions to be in the mempool after sendrawtransaction returns? | open | answered | no | 2026-10-21: 'Can we gather a list of these?' |
| instagibbs (member) | objection, safety | Waiting synchronously for mempool acceptance can cause wallet operations to hang for up to 10 minutes, leading users to cancel and retry, which risks paying twice and losing funds. | open | changed | no | 2026-10-21: 'Naively done, it could end up with some dangerous behavior for users, such as: ... broadens the scope of possible loss through unclear UX.' |
| instagibbs (member) | objection, safety | Synchronously waiting for mempool acceptance risks users accidentally paying twice if they abort a hanging broadcast and retry | open | answered | no | 2026-10-21: 'I just think this broadens the scope of possible loss through unclear UX.' |
Participants:
- instagibbs (member, objection, 1 statements 2026-10-21 to 2026-10-21): asks which software needs this and objects that synchronous waiting could cause wallet hangs and duplicate payments
Dependencies
Enables:
- Private broadcast support in the wallet
Files
166 lines under test/bench/ci.
- src/node/transaction.cpp +63/-24
- src/test/validationinterface_tests.cpp +79/-1
- test/functional/p2p_private_broadcast_wait.py +59/-0
- test/functional/p2p_private_broadcast.py +7/-7
- src/node/transaction.h +11/-1
- src/rpc/mempool.cpp +8/-3
- doc/release-notes-private-broadcast-wait.md +10/-0
- test/functional/p2p_private_broadcast_cap.py +3/-3
- src/validationinterface.h +5/-0
- src/common/messages.cpp +4/-0
- test/functional/p2p_private_broadcast_completion.py +2/-2
- src/node/types.h +2/-0
- src/rpc/util.cpp +2/-0
- test/functional/p2p_private_broadcast_retry_v1.py +1/-1
- src/rpc/client.cpp +1/-0
- src/validationinterface.cpp +1/-0
- test/functional/test_runner.py +1/-0
Card
The short text the ranking pass compares across PRs.
Private transaction broadcasts bypass local mempool insertion and return immediately upon queueing, breaking downstream software and wallets that expect sendrawtransaction to guarantee mempool presence. This pull request adds a synchronous TransactionAddedToMempoolSync callback to CValidationInterface and makes BroadcastTransaction block until the transaction is accepted into the mempool or times out, defaulting to 10 minutes. By bypassing the asynchronous validation queue, the synchronous notification allows callers holding the wallet mutex to wait without risk of deadlocks from blocked background events. Setting the new timeout RPC parameter to zero preserves immediate return. This synchronous wait is a stated prerequisite for supporting private broadcast in the Bitcoin Core wallet.
Data
thread read through 2026-10-21 (1 statements), head bccae01515
labels: Private Broadcast
Categories
P2P
P2 · unblocks #N
Provides the synchronization needed for external clients and unblocks private broadcast integration in the wallet. The PR description notes that waiting synchronously for mempool acceptance resolves issues where software expects transactions in the mempool post-broadcast, and is a prerequisite for adding private broadcast support to the wallet.
Membership: Carries the Private Broadcast label and alters the node's private transaction broadcast synchronization behavior.
Factors: security/stability 1, bug 1, performance 0, user value 2, leverage 2
RPC / REST / ZMQ
P2 · user request (assessed alone as P3; Raised to P2 and moved up 17: it repairs a silent semantic break of sendrawtransaction for existing third-party callers and is a stated prerequisite for wallet private broadcast.)
Fixes caller assumptions around sendrawtransaction by allowing callers to wait for mempool inclusion. The PR description notes that third-party wallets and services call sendrawtransaction and expect the transaction to be in the mempool after a successful response.
Membership: Touches src/rpc/mempool.cpp and src/rpc/client.cpp, adding an optional timeout parameter to sendrawtransaction.
Factors: security/stability 1, bug 1, performance 0, user value 2, leverage 2