Skip to content

Commit 8c8aa19

Browse files
author
Antoine Riard
committed
Add BroadcastTransaction utility usage in Chain interface
Access through a broadcastTransaction method. Add a wait_callback flag to turn off race protection when wallet already track its tx being in mempool Standardise highfee, absurdfee variable name to max_tx_fee We drop the P2P check in BroadcastTransaction as g_connman is only called by RPCs and the wallet scheduler, both of which are initialized after g_connman is assigned and stopped before g_connman is reset.
1 parent 7821821 commit 8c8aa19

File tree

5 files changed

+34
-19
lines changed

5 files changed

+34
-19
lines changed

src/interfaces/chain.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <net.h>
1212
#include <net_processing.h>
1313
#include <node/coin.h>
14+
#include <node/transaction.h>
1415
#include <policy/fees.h>
1516
#include <policy/policy.h>
1617
#include <policy/rbf.h>
@@ -295,6 +296,14 @@ class ChainImpl : public Chain
295296
{
296297
RelayTransaction(txid, *g_connman);
297298
}
299+
bool broadcastTransaction(const CTransactionRef& tx, std::string& err_string, const CAmount& max_tx_fee, bool relay) override
300+
{
301+
const TransactionError err = BroadcastTransaction(tx, err_string, max_tx_fee, relay, /*wait_callback*/ false);
302+
// Chain clients only care about failures to accept the tx to the mempool. Disregard non-mempool related failures.
303+
// Note: this will need to be updated if BroadcastTransactions() is updated to return other non-mempool failures
304+
// that Chain clients do not need to know about.
305+
return TransactionError::OK == err;
306+
}
298307
void getTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants) override
299308
{
300309
::mempool.GetTransactionAncestry(txid, ancestors, descendants);

src/interfaces/chain.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,11 @@ class Chain
167167
//! Relay transaction.
168168
virtual void relayTransaction(const uint256& txid) = 0;
169169

170+
//! Transaction is added to memory pool, if the transaction fee is below the
171+
//! amount specified by max_tx_fee, and broadcast to all peers if relay is set to true.
172+
//! Return false if the transaction could not be added due to the fee or for another reason.
173+
virtual bool broadcastTransaction(const CTransactionRef& tx, std::string& err_string, const CAmount& max_tx_fee, bool relay) = 0;
174+
170175
//! Calculate mempool ancestor and descendant counts for the given transaction.
171176
virtual void getTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants) = 0;
172177

src/node/transaction.cpp

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414

1515
#include <future>
1616

17-
TransactionError BroadcastTransaction(const CTransactionRef tx, uint256& hashTx, std::string& err_string, const CAmount& highfee)
17+
TransactionError BroadcastTransaction(const CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback)
1818
{
19+
assert(g_connman);
1920
std::promise<void> promise;
20-
hashTx = tx->GetHash();
21+
uint256 hashTx = tx->GetHash();
22+
bool callback_set = false;
2123

2224
{ // cs_main scope
2325
LOCK(cs_main);
@@ -33,7 +35,7 @@ TransactionError BroadcastTransaction(const CTransactionRef tx, uint256& hashTx,
3335
CValidationState state;
3436
bool fMissingInputs;
3537
if (!AcceptToMemoryPool(mempool, state, std::move(tx), &fMissingInputs,
36-
nullptr /* plTxnReplaced */, false /* bypass_limits */, highfee)) {
38+
nullptr /* plTxnReplaced */, false /* bypass_limits */, max_tx_fee)) {
3739
if (state.IsInvalid()) {
3840
err_string = FormatStateMessage(state);
3941
return TransactionError::MEMPOOL_REJECTED;
@@ -44,7 +46,7 @@ TransactionError BroadcastTransaction(const CTransactionRef tx, uint256& hashTx,
4446
err_string = FormatStateMessage(state);
4547
return TransactionError::MEMPOOL_ERROR;
4648
}
47-
} else {
49+
} else if (wait_callback) {
4850
// If wallet is enabled, ensure that the wallet has been made aware
4951
// of the new transaction prior to returning. This prevents a race
5052
// where a user might call sendrawtransaction with a transaction
@@ -53,24 +55,21 @@ TransactionError BroadcastTransaction(const CTransactionRef tx, uint256& hashTx,
5355
CallFunctionInValidationInterfaceQueue([&promise] {
5456
promise.set_value();
5557
});
58+
callback_set = true;
5659
}
5760
} else if (fHaveChain) {
5861
return TransactionError::ALREADY_IN_CHAIN;
59-
} else {
60-
// Make sure we don't block forever if re-sending
61-
// a transaction already in mempool.
62-
promise.set_value();
6362
}
6463

6564
} // cs_main
6665

67-
promise.get_future().wait();
68-
69-
if (!g_connman) {
70-
return TransactionError::P2P_DISABLED;
66+
if (callback_set) {
67+
promise.get_future().wait();
7168
}
7269

73-
RelayTransaction(hashTx, *g_connman);
70+
if (relay) {
71+
RelayTransaction(hashTx, *g_connman);
72+
}
7473

7574
return TransactionError::OK;
7675
}

src/node/transaction.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414
* Broadcast a transaction
1515
*
1616
* @param[in] tx the transaction to broadcast
17-
* @param[out] &txid the txid of the transaction, if successfully broadcast
1817
* @param[out] &err_string reference to std::string to fill with error string if available
19-
* @param[in] highfee Reject txs with fees higher than this (if 0, accept any fee)
18+
* @param[in] max_tx_fee reject txs with fees higher than this (if 0, accept any fee)
19+
* @param[in] relay flag if both mempool insertion and p2p relay are requested
20+
* @param[in] wait_callback, wait until callbacks have been processed to avoid stale result due to a sequentially RPC.
21+
* It MUST NOT be set while cs_main, cs_mempool or cs_wallet are held to avoid deadlock
2022
* return error
2123
*/
22-
NODISCARD TransactionError BroadcastTransaction(CTransactionRef tx, uint256& txid, std::string& err_string, const CAmount& highfee);
24+
NODISCARD TransactionError BroadcastTransaction(CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback);
2325

2426
#endif // BITCOIN_NODE_TRANSACTION_H

src/rpc/rawtransaction.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -810,14 +810,14 @@ static UniValue sendrawtransaction(const JSONRPCRequest& request)
810810
max_raw_tx_fee = fr.GetFee((weight+3)/4);
811811
}
812812

813-
uint256 txid;
814813
std::string err_string;
815-
const TransactionError err = BroadcastTransaction(tx, txid, err_string, max_raw_tx_fee);
814+
AssertLockNotHeld(cs_main);
815+
const TransactionError err = BroadcastTransaction(tx, err_string, max_raw_tx_fee, /*relay*/ true, /*wait_callback*/ true);
816816
if (TransactionError::OK != err) {
817817
throw JSONRPCTransactionError(err, err_string);
818818
}
819819

820-
return txid.GetHex();
820+
return tx->GetHash().GetHex();
821821
}
822822

823823
static UniValue testmempoolaccept(const JSONRPCRequest& request)

0 commit comments

Comments
 (0)