Merge bitcoin/bitcoin#33567: node: change a tx-relay on/off flag to enum
07a926474bnode: change a tx-relay on/off flag to enum (Vasil Dimov) Pull request description: Previously the `bool relay` argument to `BroadcastTransaction()` designated: ``` relay=true: add to the mempool and broadcast to all peers relay=false: add to the mempool ``` Change this to an `enum`, so it is more readable and easier to extend with a 3rd option. Consider these example call sites: ```cpp Paint(true); // Or Paint(/*is_red=*/true); ``` vs ```cpp Paint(RED); ``` The idea for putting `TxBroadcastMethod` into `node/types.h` by Ryan. --- This is part of [#29415 Broadcast own transactions only via short-lived Tor or I2P connections](https://github.com/bitcoin/bitcoin/pull/29415). Putting it in its own PR to reduce the size of #29415 and because it does not logically depend on the other commits from there. ACKs for top commit: optout21: ACK07a926474bkevkevinpal: ACK [07a9264](https://github.com/bitcoin/bitcoin/pull/33567/commits/07a926474b5a6fa1d3d4656362a0117611f6da2f) laanwj: Concept and code review ACK07a926474b. Agree with the general reasoning and the change in #29415 is a valid motivation to change this interface. glozow: utACK07a926474bTree-SHA512: ec8f6fa56a6d2422a0fbd5941ff2792685e8d8e7b9dd50bba9f3e21ed9b4a4a26c89b0d7e4895d48f30b7a635f2eddd894af26b5266410952cbdaf5c40b42966
This commit is contained in:
10 files changed
+116
-44
No files matched your search
@@ -9,6 +9,7 @@
|
||||
#include <interfaces/chain.h>
|
||||
#include <key_io.h>
|
||||
#include <merkleblock.h>
|
||||
#include <node/types.h>
|
||||
#include <rpc/util.h>
|
||||
#include <script/descriptor.h>
|
||||
#include <script/script.h>
|
||||
@@ -402,7 +403,7 @@ RPCHelpMan importdescriptors()
|
||||
// Rescan the blockchain using the lowest timestamp
|
||||
if (rescan) {
|
||||
int64_t scanned_time = pwallet->RescanFromTime(lowest_timestamp, reserver, /*update=*/true);
|
||||
pwallet->ResubmitWalletTransactions(/*relay=*/false, /*force=*/true);
|
||||
pwallet->ResubmitWalletTransactions(node::TxBroadcast::MEMPOOL_NO_BROADCAST, /*force=*/true);
|
||||
|
||||
if (pwallet->IsAbortingRescan()) {
|
||||
throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted by user.");
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <interfaces/chain.h>
|
||||
#include <key_io.h>
|
||||
#include <node/blockstorage.h>
|
||||
#include <node/types.h>
|
||||
#include <policy/policy.h>
|
||||
#include <rpc/server.h>
|
||||
#include <script/solver.h>
|
||||
@@ -618,7 +619,7 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
|
||||
auto block_tx = TestSimpleSpend(*m_coinbase_txns[0], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
|
||||
m_coinbase_txns.push_back(CreateAndProcessBlock({block_tx}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
|
||||
auto mempool_tx = TestSimpleSpend(*m_coinbase_txns[1], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
|
||||
BOOST_CHECK(m_node.chain->broadcastTransaction(MakeTransactionRef(mempool_tx), DEFAULT_TRANSACTION_MAXFEE, false, error));
|
||||
BOOST_CHECK(m_node.chain->broadcastTransaction(MakeTransactionRef(mempool_tx), DEFAULT_TRANSACTION_MAXFEE, node::TxBroadcast::MEMPOOL_NO_BROADCAST, error));
|
||||
|
||||
|
||||
// Reload wallet and make sure new transactions are detected despite events
|
||||
@@ -660,7 +661,7 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
|
||||
block_tx = TestSimpleSpend(*m_coinbase_txns[2], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
|
||||
m_coinbase_txns.push_back(CreateAndProcessBlock({block_tx}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
|
||||
mempool_tx = TestSimpleSpend(*m_coinbase_txns[3], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
|
||||
BOOST_CHECK(m_node.chain->broadcastTransaction(MakeTransactionRef(mempool_tx), DEFAULT_TRANSACTION_MAXFEE, false, error));
|
||||
BOOST_CHECK(m_node.chain->broadcastTransaction(MakeTransactionRef(mempool_tx), DEFAULT_TRANSACTION_MAXFEE, node::TxBroadcast::MEMPOOL_NO_BROADCAST, error));
|
||||
m_node.validation_signals->SyncWithValidationInterfaceQueue();
|
||||
});
|
||||
wallet = TestLoadWallet(context);
|
||||
|
||||
+23
-12
@@ -1959,7 +1959,9 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CWallet::SubmitTxMemoryPoolAndRelay(CWalletTx& wtx, std::string& err_string, bool relay) const
|
||||
bool CWallet::SubmitTxMemoryPoolAndRelay(CWalletTx& wtx,
|
||||
std::string& err_string,
|
||||
node::TxBroadcast broadcast_method) const
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
|
||||
@@ -1973,8 +1975,16 @@ bool CWallet::SubmitTxMemoryPoolAndRelay(CWalletTx& wtx, std::string& err_string
|
||||
// Don't try to submit conflicted or confirmed transactions.
|
||||
if (GetTxDepthInMainChain(wtx) != 0) return false;
|
||||
|
||||
// Submit transaction to mempool for relay
|
||||
WalletLogPrintf("Submitting wtx %s to mempool for relay\n", wtx.GetHash().ToString());
|
||||
const char* what{""};
|
||||
switch (broadcast_method) {
|
||||
case node::TxBroadcast::MEMPOOL_AND_BROADCAST_TO_ALL:
|
||||
what = "to mempool and for broadcast to peers";
|
||||
break;
|
||||
case node::TxBroadcast::MEMPOOL_NO_BROADCAST:
|
||||
what = "to mempool without broadcast";
|
||||
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
|
||||
// entered-mempool callback, if we did not there would be a race where a
|
||||
// user could call sendmoney in a loop and hit spurious out of funds errors
|
||||
@@ -1984,7 +1994,7 @@ bool CWallet::SubmitTxMemoryPoolAndRelay(CWalletTx& wtx, std::string& err_string
|
||||
// If broadcast fails for any reason, trying to set wtx.m_state here would be incorrect.
|
||||
// If transaction was previously in the mempool, it should be updated when
|
||||
// TransactionRemovedFromMempool fires.
|
||||
bool ret = chain().broadcastTransaction(wtx.tx, m_default_max_tx_fee, relay, err_string);
|
||||
bool ret = chain().broadcastTransaction(wtx.tx, m_default_max_tx_fee, broadcast_method, err_string);
|
||||
if (ret) wtx.m_state = TxStateInMempool{};
|
||||
return ret;
|
||||
}
|
||||
@@ -2039,10 +2049,11 @@ NodeClock::time_point CWallet::GetDefaultNextResend() { return FastRandomContext
|
||||
//
|
||||
// The `force` option results in all unconfirmed transactions being submitted to
|
||||
// the mempool. This does not necessarily result in those transactions being relayed,
|
||||
// that depends on the `relay` option. Periodic rebroadcast uses the pattern
|
||||
// relay=true force=false, while loading into the mempool
|
||||
// (on start, or after import) uses relay=false force=true.
|
||||
void CWallet::ResubmitWalletTransactions(bool relay, bool force)
|
||||
// that depends on the `broadcast_method` option. Periodic rebroadcast uses the pattern
|
||||
// broadcast_method=TxBroadcast::MEMPOOL_AND_BROADCAST_TO_ALL force=false, while loading into
|
||||
// the mempool (on start, or after import) uses
|
||||
// broadcast_method=TxBroadcast::MEMPOOL_NO_BROADCAST force=true.
|
||||
void CWallet::ResubmitWalletTransactions(node::TxBroadcast broadcast_method, bool force)
|
||||
{
|
||||
// Don't attempt to resubmit if the wallet is configured to not broadcast,
|
||||
// even if forcing.
|
||||
@@ -2068,7 +2079,7 @@ void CWallet::ResubmitWalletTransactions(bool relay, bool force)
|
||||
// Now try submitting the transactions to the memory pool and (optionally) relay them.
|
||||
for (auto wtx : to_submit) {
|
||||
std::string unused_err_string;
|
||||
if (SubmitTxMemoryPoolAndRelay(*wtx, unused_err_string, relay)) ++submitted_tx_count;
|
||||
if (SubmitTxMemoryPoolAndRelay(*wtx, unused_err_string, broadcast_method)) ++submitted_tx_count;
|
||||
}
|
||||
} // cs_wallet
|
||||
|
||||
@@ -2083,7 +2094,7 @@ void MaybeResendWalletTxs(WalletContext& context)
|
||||
{
|
||||
for (const std::shared_ptr<CWallet>& pwallet : GetWallets(context)) {
|
||||
if (!pwallet->ShouldResend()) continue;
|
||||
pwallet->ResubmitWalletTransactions(/*relay=*/true, /*force=*/false);
|
||||
pwallet->ResubmitWalletTransactions(node::TxBroadcast::MEMPOOL_AND_BROADCAST_TO_ALL, /*force=*/false);
|
||||
pwallet->SetNextResend();
|
||||
}
|
||||
}
|
||||
@@ -2284,7 +2295,7 @@ void CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::ve
|
||||
}
|
||||
|
||||
std::string err_string;
|
||||
if (!SubmitTxMemoryPoolAndRelay(*wtx, err_string, true)) {
|
||||
if (!SubmitTxMemoryPoolAndRelay(*wtx, err_string, node::TxBroadcast::MEMPOOL_AND_BROADCAST_TO_ALL)) {
|
||||
WalletLogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
|
||||
// TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure.
|
||||
}
|
||||
@@ -3233,7 +3244,7 @@ void CWallet::postInitProcess()
|
||||
{
|
||||
// Add wallet transactions that aren't already in a block to mempool
|
||||
// Do this here as mempool requires genesis block to be loaded
|
||||
ResubmitWalletTransactions(/*relay=*/false, /*force=*/true);
|
||||
ResubmitWalletTransactions(node::TxBroadcast::MEMPOOL_NO_BROADCAST, /*force=*/true);
|
||||
|
||||
// Update wallet transactions with current mempool transactions.
|
||||
WITH_LOCK(cs_wallet, chain().requestMempoolTransactions(*this));
|
||||
|
||||
+4
-3
@@ -12,6 +12,7 @@
|
||||
#include <interfaces/handler.h>
|
||||
#include <kernel/cs_main.h>
|
||||
#include <logging.h>
|
||||
#include <node/types.h>
|
||||
#include <outputtype.h>
|
||||
#include <policy/feerate.h>
|
||||
#include <primitives/transaction.h>
|
||||
@@ -654,7 +655,7 @@ public:
|
||||
void SetNextResend() { m_next_resend = GetDefaultNextResend(); }
|
||||
/** Return true if all conditions for periodically resending transactions are met. */
|
||||
bool ShouldResend() const;
|
||||
void ResubmitWalletTransactions(bool relay, bool force);
|
||||
void ResubmitWalletTransactions(node::TxBroadcast broadcast_method, bool force);
|
||||
|
||||
OutputType TransactionChangeType(const std::optional<OutputType>& change_type, const std::vector<CRecipient>& vecSend) const;
|
||||
|
||||
@@ -698,8 +699,8 @@ public:
|
||||
*/
|
||||
void CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm);
|
||||
|
||||
/** Pass this transaction to node for mempool insertion and relay to peers if flag set to true */
|
||||
bool SubmitTxMemoryPoolAndRelay(CWalletTx& wtx, std::string& err_string, bool relay) const
|
||||
/** Pass this transaction to node for optional mempool insertion and relay to peers. */
|
||||
bool SubmitTxMemoryPoolAndRelay(CWalletTx& wtx, std::string& err_string, node::TxBroadcast broadcast_method) const
|
||||
EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
/** Updates wallet birth time if 'time' is below it */
|
||||
|
||||
Reference in new issue
Block a user