diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index 34ab36313d5..2a52f08eed1 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -206,13 +207,19 @@ public: //! Check if transaction has descendants in mempool. virtual bool hasDescendantsInMempool(const Txid& txid) = 0; - //! Transaction is added to memory pool, if the transaction fee is below the - //! amount specified by max_tx_fee, and broadcast to all peers if relay is set to true. - //! Return false if the transaction could not be added due to the fee or for another reason. + //! Consume a local transaction, optionally adding it to the mempool and + //! optionally broadcasting it to the network. + //! @param[in] tx Transaction to process. + //! @param[in] max_tx_fee Don't add the transaction to the mempool or + //! broadcast it if its fee is higher than this. + //! @param[in] broadcast_method Whether to add the transaction to the + //! mempool and how/whether to broadcast it. + //! @param[out] err_string Set if an error occurs. + //! @return False if the transaction could not be added due to the fee or for another reason. virtual bool broadcastTransaction(const CTransactionRef& tx, - const CAmount& max_tx_fee, - bool relay, - std::string& err_string) = 0; + const CAmount& max_tx_fee, + node::TxBroadcastMethod broadcast_method, + std::string& err_string) = 0; //! Calculate mempool ancestor and descendant counts for the given transaction. virtual void getTransactionAncestry(const Txid& txid, size_t& ancestors, size_t& descendants, size_t* ancestorsize = nullptr, CAmount* ancestorfees = nullptr) = 0; diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index fd3fa226cae..056a5c5e20a 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -363,7 +363,12 @@ public: } TransactionError broadcastTransaction(CTransactionRef tx, CAmount max_tx_fee, std::string& err_string) override { - return BroadcastTransaction(*m_context, std::move(tx), err_string, max_tx_fee, /*relay=*/ true, /*wait_callback=*/ false); + return BroadcastTransaction(*m_context, + std::move(tx), + err_string, + max_tx_fee, + ADD_TO_MEMPOOL_AND_BROADCAST_TO_ALL, + /*wait_callback=*/false); } WalletLoader& walletLoader() override { @@ -672,10 +677,10 @@ public: } bool broadcastTransaction(const CTransactionRef& tx, const CAmount& max_tx_fee, - bool relay, + TxBroadcastMethod broadcast_method, std::string& err_string) override { - const TransactionError err = BroadcastTransaction(m_node, tx, err_string, max_tx_fee, relay, /*wait_callback=*/false); + const TransactionError err = BroadcastTransaction(m_node, tx, err_string, max_tx_fee, broadcast_method, /*wait_callback=*/false); // Chain clients only care about failures to accept the tx to the mempool. Disregard non-mempool related failures. // Note: this will need to be updated if BroadcastTransactions() is updated to return other non-mempool failures // that Chain clients do not need to know about. diff --git a/src/node/transaction.cpp b/src/node/transaction.cpp index 7bb92872914..5da4e878ab2 100644 --- a/src/node/transaction.cpp +++ b/src/node/transaction.cpp @@ -31,7 +31,12 @@ static TransactionError HandleATMPError(const TxValidationState& state, std::str } } -TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback) +TransactionError BroadcastTransaction(NodeContext& node, + const CTransactionRef tx, + std::string& err_string, + const CAmount& max_tx_fee, + TxBroadcastMethod broadcast_method, + bool wait_callback) { // BroadcastTransaction can be called by RPC or by the wallet. // chainman, mempool and peerman are initialized before the RPC server and wallet are started @@ -62,7 +67,7 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t // There's already a transaction in the mempool with this txid. Don't // try to submit this transaction to the mempool (since it'll be // rejected as a TX_CONFLICT), but do attempt to reannounce the mempool - // transaction if relay=true. + // transaction if broadcast_method is not ADD_TO_MEMPOOL_NO_BROADCAST. // // The mempool transaction may have the same or different witness (and // wtxid) as this transaction. Use the mempool's wtxid for reannouncement. @@ -79,18 +84,26 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t return TransactionError::MAX_FEE_EXCEEDED; } } - // Try to submit the transaction to the mempool. - const MempoolAcceptResult result = node.chainman->ProcessTransaction(tx, /*test_accept=*/ false); - if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) { - return HandleATMPError(result.m_state, err_string); - } - // Transaction was accepted to the mempool. + switch (broadcast_method) { + case ADD_TO_MEMPOOL_NO_BROADCAST: + case ADD_TO_MEMPOOL_AND_BROADCAST_TO_ALL: + // Try to submit the transaction to the mempool. + { + const MempoolAcceptResult result = + node.chainman->ProcessTransaction(tx, /*test_accept=*/false); + if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) { + return HandleATMPError(result.m_state, err_string); + } + } + // Transaction was accepted to the mempool. - if (relay) { - // the mempool tracks locally submitted transactions to make a - // best-effort of initial broadcast - node.mempool->AddUnbroadcastTx(txid); + if (broadcast_method == ADD_TO_MEMPOOL_AND_BROADCAST_TO_ALL) { + // the mempool tracks locally submitted transactions to make a + // best-effort of initial broadcast + node.mempool->AddUnbroadcastTx(txid); + } + break; } if (wait_callback && node.validation_signals) { @@ -116,8 +129,12 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t promise.get_future().wait(); } - if (relay) { + switch (broadcast_method) { + case ADD_TO_MEMPOOL_NO_BROADCAST: + break; + case ADD_TO_MEMPOOL_AND_BROADCAST_TO_ALL: node.peerman->RelayTransaction(txid, wtxid); + break; } return TransactionError::OK; diff --git a/src/node/transaction.h b/src/node/transaction.h index 2a4115817b9..d5718747821 100644 --- a/src/node/transaction.h +++ b/src/node/transaction.h @@ -6,6 +6,7 @@ #define BITCOIN_NODE_TRANSACTION_H #include +#include #include #include @@ -45,11 +46,16 @@ static const CAmount DEFAULT_MAX_BURN_AMOUNT{0}; * @param[in] tx the transaction to broadcast * @param[out] err_string reference to std::string to fill with error string if available * @param[in] max_tx_fee reject txs with fees higher than this (if 0, accept any fee) - * @param[in] relay flag if both mempool insertion and p2p relay are requested + * @param[in] broadcast_method whether to add the transaction to the mempool and/if how to broadcast it * @param[in] wait_callback wait until callbacks have been processed to avoid stale result due to a sequentially RPC. * return error */ -[[nodiscard]] TransactionError BroadcastTransaction(NodeContext& node, CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback); +[[nodiscard]] TransactionError BroadcastTransaction(NodeContext& node, + CTransactionRef tx, + std::string& err_string, + const CAmount& max_tx_fee, + TxBroadcastMethod broadcast_method, + bool wait_callback); /** * Return transaction with a given hash. diff --git a/src/node/types.h b/src/node/types.h index 547d644831c..14b64569ae7 100644 --- a/src/node/types.h +++ b/src/node/types.h @@ -15,6 +15,7 @@ #include #include +#include #include #include