From a3faa6f944a672faccac5dd201c8d33a638d9091 Mon Sep 17 00:00:00 2001 From: Vasil Dimov Date: Tue, 7 Oct 2025 16:57:15 +0200 Subject: [PATCH] node: extend node::TxBroadcast with a 3rd option Extend `node::TxBroadcast` with a 3rd option to not add the transaction to the mempool and broadcast privately. This is a non-functional change - `BroadcastTransaction()` will not do anything if the 3rd options is passed and is not used by any of its callers. --- src/node/transaction.cpp | 9 +++++++-- src/node/types.h | 3 +++ src/wallet/wallet.cpp | 3 +++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/node/transaction.cpp b/src/node/transaction.cpp index 4f0ee6f7060..a5a3a9d9bed 100644 --- a/src/node/transaction.cpp +++ b/src/node/transaction.cpp @@ -74,13 +74,14 @@ TransactionError BroadcastTransaction(NodeContext& node, wtxid = mempool_tx->GetWitnessHash(); } else { // Transaction is not already in the mempool. - if (max_tx_fee > 0) { + const bool check_max_fee{max_tx_fee > 0}; + if (check_max_fee || broadcast_method == TxBroadcast::NO_MEMPOOL_PRIVATE_BROADCAST) { // First, call ATMP with test_accept and check the fee. If ATMP // fails here, return error immediately. const MempoolAcceptResult result = node.chainman->ProcessTransaction(tx, /*test_accept=*/ true); if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) { return HandleATMPError(result.m_state, err_string); - } else if (result.m_base_fees.value() > max_tx_fee) { + } else if (check_max_fee && result.m_base_fees.value() > max_tx_fee) { return TransactionError::MAX_FEE_EXCEEDED; } } @@ -104,6 +105,8 @@ TransactionError BroadcastTransaction(NodeContext& node, node.mempool->AddUnbroadcastTx(txid); } break; + case TxBroadcast::NO_MEMPOOL_PRIVATE_BROADCAST: + break; } if (wait_callback && node.validation_signals) { @@ -135,6 +138,8 @@ TransactionError BroadcastTransaction(NodeContext& node, case TxBroadcast::MEMPOOL_AND_BROADCAST_TO_ALL: node.peerman->InitiateTxBroadcastToAll(txid, wtxid); break; + case TxBroadcast::NO_MEMPOOL_PRIVATE_BROADCAST: + break; } return TransactionError::OK; diff --git a/src/node/types.h b/src/node/types.h index 6c2687626c9..bf11c2cba55 100644 --- a/src/node/types.h +++ b/src/node/types.h @@ -108,6 +108,9 @@ enum class TxBroadcast : uint8_t { MEMPOOL_AND_BROADCAST_TO_ALL, /// Add the transaction to the mempool, but don't broadcast to anybody. MEMPOOL_NO_BROADCAST, + /// Omit the mempool and directly send the transaction via a few dedicated connections to + /// peers on privacy networks. + NO_MEMPOOL_PRIVATE_BROADCAST, }; } // namespace node diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index d7b749bcaed..769ded68f3a 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1984,6 +1984,9 @@ bool CWallet::SubmitTxMemoryPoolAndRelay(CWalletTx& wtx, case node::TxBroadcast::MEMPOOL_NO_BROADCAST: what = "to mempool without broadcast"; break; + case node::TxBroadcast::NO_MEMPOOL_PRIVATE_BROADCAST: + what = "for private broadcast without adding to the mempool"; + break; } WalletLogPrintf("Submitting wtx %s %s\n", wtx.GetHash().ToString(), what); // We must set TxStateInMempool here. Even though it will also be set later by the