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.
This commit is contained in:
Antoine Riard
2019-04-11 14:37:30 +00:00
parent 7821821a23
commit 8c8aa19b4b
5 changed files with 34 additions and 19 deletions

View File

@@ -14,10 +14,12 @@
#include <future>
TransactionError BroadcastTransaction(const CTransactionRef tx, uint256& hashTx, std::string& err_string, const CAmount& highfee)
TransactionError BroadcastTransaction(const CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback)
{
assert(g_connman);
std::promise<void> promise;
hashTx = tx->GetHash();
uint256 hashTx = tx->GetHash();
bool callback_set = false;
{ // cs_main scope
LOCK(cs_main);
@@ -33,7 +35,7 @@ TransactionError BroadcastTransaction(const CTransactionRef tx, uint256& hashTx,
CValidationState state;
bool fMissingInputs;
if (!AcceptToMemoryPool(mempool, state, std::move(tx), &fMissingInputs,
nullptr /* plTxnReplaced */, false /* bypass_limits */, highfee)) {
nullptr /* plTxnReplaced */, false /* bypass_limits */, max_tx_fee)) {
if (state.IsInvalid()) {
err_string = FormatStateMessage(state);
return TransactionError::MEMPOOL_REJECTED;
@@ -44,7 +46,7 @@ TransactionError BroadcastTransaction(const CTransactionRef tx, uint256& hashTx,
err_string = FormatStateMessage(state);
return TransactionError::MEMPOOL_ERROR;
}
} else {
} else if (wait_callback) {
// If wallet is enabled, ensure that the wallet has been made aware
// of the new transaction prior to returning. This prevents a race
// where a user might call sendrawtransaction with a transaction
@@ -53,24 +55,21 @@ TransactionError BroadcastTransaction(const CTransactionRef tx, uint256& hashTx,
CallFunctionInValidationInterfaceQueue([&promise] {
promise.set_value();
});
callback_set = true;
}
} else if (fHaveChain) {
return TransactionError::ALREADY_IN_CHAIN;
} else {
// Make sure we don't block forever if re-sending
// a transaction already in mempool.
promise.set_value();
}
} // cs_main
promise.get_future().wait();
if (!g_connman) {
return TransactionError::P2P_DISABLED;
if (callback_set) {
promise.get_future().wait();
}
RelayTransaction(hashTx, *g_connman);
if (relay) {
RelayTransaction(hashTx, *g_connman);
}
return TransactionError::OK;
}

View File

@@ -14,11 +14,13 @@
* Broadcast a transaction
*
* @param[in] tx the transaction to broadcast
* @param[out] &txid the txid of the transaction, if successfully broadcast
* @param[out] &err_string reference to std::string to fill with error string if available
* @param[in] highfee Reject txs with fees higher than this (if 0, accept any fee)
* @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] wait_callback, wait until callbacks have been processed to avoid stale result due to a sequentially RPC.
* It MUST NOT be set while cs_main, cs_mempool or cs_wallet are held to avoid deadlock
* return error
*/
NODISCARD TransactionError BroadcastTransaction(CTransactionRef tx, uint256& txid, std::string& err_string, const CAmount& highfee);
NODISCARD TransactionError BroadcastTransaction(CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback);
#endif // BITCOIN_NODE_TRANSACTION_H