-
Notifications
You must be signed in to change notification settings - Fork 1.2k
fix(coinjoin): push finalized DSTX directly to participants before DSCOMPLETE #7478
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -388,6 +388,14 @@ void CCoinJoinServer::CommitFinalTransaction() | |
|
|
||
| LogPrint(BCLog::COINJOIN, "CCoinJoinServer::CommitFinalTransaction -- TRANSMITTING DSTX\n"); | ||
|
|
||
| // Push the fully signed transaction directly to every mixing participant first: | ||
| // the inv-based relay below is subject to delayed trickling, so without this a | ||
| // participant could process DSCOMPLETE (which is sent directly) and release its | ||
| // inputs for reuse before ever seeing the transaction that spends them. | ||
| if (const auto dstx = m_dstxman.GetDSTX(hashTx); dstx) { | ||
| WITH_LOCK(cs_coinjoin, RelayDSTXToParticipants(dstx)); | ||
|
Comment on lines
+391
to
+396
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 Blocking: Direct DSTX ordering does not prevent wallet input reuse Processing DSTX first only adds the transaction to the mempool and enqueues source: ['codex']
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree; I'll work on another PR. I want this one just doing the send ordering fix |
||
| } | ||
|
|
||
| CInv inv(MSG_DSTX, hashTx); | ||
| m_peer_manager->PeerRelayInv(inv); | ||
|
|
||
|
|
@@ -852,6 +860,25 @@ void CCoinJoinServer::RelayFinalTransaction(const CTransaction& txFinal) | |
| } | ||
| } | ||
|
|
||
| void CCoinJoinServer::RelayDSTXToParticipants(const CCoinJoinBroadcastTx& dstx) | ||
| { | ||
| AssertLockHeld(cs_coinjoin); | ||
| // the fully signed mixing tx is pushed to mixing participants only, everyone else | ||
| // gets it via the regular inv-based relay | ||
| for (const auto& entry : vecEntries) { | ||
| bool fOk = connman.ForNode(entry.addr, [&dstx, this](CNode* pnode) { | ||
| CNetMsgMaker msgMaker(pnode->GetCommonVersion()); | ||
| connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSTX, dstx)); | ||
| return true; | ||
| }); | ||
| if (!fOk) { | ||
| // best-effort only: the participant will still get the tx via regular inv relay | ||
| LogPrint(BCLog::COINJOIN, "CCoinJoinServer::%s -- failed to push DSTX to participant %s\n", __func__, | ||
| entry.addr.ToStringAddrPort()); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void CCoinJoinServer::PushStatus(CNode& peer, PoolStatusUpdate nStatusUpdate, PoolMessage nMessageID) const | ||
| { | ||
| CCoinJoinStatusUpdate psssup(nSessionID, nState, 0, nStatusUpdate, nMessageID); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a participant receives this direct
DSTX,ProcessTransactiononly enqueues the wallet'sTransactionAddedToMempoolcallback; it does not synchronously mark the wallet input spent. The following directly queuedDSCOMPLETEis handled immediately andCompletedTransaction()callsUnlockCoins(), so if the validation callback queue has not drained (a normal scheduling race, or a backlog), a-coinjoinmultisession=1session can still select and sign the same input. Thus sending the messages in socket order does not establish the claimed wallet-observation ordering; retain the lock until the wallet-side callback/observed spend is processed.AGENTS.md reference: AGENTS.md:L164-L164
Useful? React with 👍 / 👎.