Branch data Line data Source code
1 : : // Copyright (c) 2010 Satoshi Nakamoto
2 : : // Copyright (c) 2009-present The Bitcoin Core developers
3 : : // Distributed under the MIT software license, see the accompanying
4 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 : :
6 : : #include <consensus/validation.h>
7 : : #include <index/txindex.h>
8 : : #include <net.h>
9 : : #include <net_processing.h>
10 : : #include <node/blockstorage.h>
11 : : #include <node/context.h>
12 : : #include <node/types.h>
13 : : #include <txmempool.h>
14 : : #include <validation.h>
15 : : #include <validationinterface.h>
16 : : #include <node/transaction.h>
17 : :
18 : : #include <future>
19 : :
20 : : namespace node {
21 : 4360 : static TransactionError HandleATMPError(const TxValidationState& state, std::string& err_string_out)
22 : : {
23 : 4360 : err_string_out = state.ToString();
24 [ + - ]: 4360 : if (state.IsInvalid()) {
25 [ + + ]: 4360 : if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
26 : : return TransactionError::MISSING_INPUTS;
27 : : }
28 : 4351 : return TransactionError::MEMPOOL_REJECTED;
29 : : } else {
30 : : return TransactionError::MEMPOOL_ERROR;
31 : : }
32 : : }
33 : :
34 : 24527 : TransactionError BroadcastTransaction(NodeContext& node,
35 : : const CTransactionRef tx,
36 : : std::string& err_string,
37 : : const CAmount& max_tx_fee,
38 : : TxBroadcast broadcast_method,
39 : : bool wait_callback)
40 : : {
41 : : // BroadcastTransaction can be called by RPC or by the wallet.
42 : : // chainman, mempool and peerman are initialized before the RPC server and wallet are started
43 : : // and reset after the RPC sever and wallet are stopped.
44 [ - + ]: 24527 : assert(node.chainman);
45 [ - + ]: 24527 : assert(node.mempool);
46 [ - + ]: 24527 : assert(node.peerman);
47 : :
48 : 24527 : std::promise<void> promise;
49 [ + - ]: 24527 : Txid txid = tx->GetHash();
50 : 24527 : Wtxid wtxid = tx->GetWitnessHash();
51 : 24527 : bool callback_set = false;
52 : :
53 : 24527 : {
54 [ + - ]: 24527 : LOCK(cs_main);
55 : :
56 : : // If the transaction is already confirmed in the chain, don't do anything
57 : : // and return early.
58 [ + - + - ]: 24527 : CCoinsViewCache &view = node.chainman->ActiveChainstate().CoinsTip();
59 [ - + + + ]: 92271 : for (size_t o = 0; o < tx->vout.size(); o++) {
60 [ + - ]: 67747 : const Coin& existingCoin = view.AccessCoin(COutPoint(txid, o));
61 : : // IsSpent doesn't mean the coin is spent, it means the output doesn't exist.
62 : : // So if the output does exist, then this transaction exists in the chain.
63 [ + + ]: 67747 : if (!existingCoin.IsSpent()) return TransactionError::ALREADY_IN_UTXO_SET;
64 : : }
65 : :
66 [ + - + + ]: 24524 : if (auto mempool_tx = node.mempool->get(txid); mempool_tx) {
67 : : // There's already a transaction in the mempool with this txid. Don't
68 : : // try to submit this transaction to the mempool (since it'll be
69 : : // rejected as a TX_CONFLICT), but do attempt to reannounce the mempool
70 : : // transaction if broadcast_method is not TxBroadcast::MEMPOOL_NO_BROADCAST.
71 : : //
72 : : // The mempool transaction may have the same or different witness (and
73 : : // wtxid) as this transaction. Use the mempool's wtxid for reannouncement.
74 : 9029 : wtxid = mempool_tx->GetWitnessHash();
75 : : } else {
76 : : // Transaction is not already in the mempool.
77 : 15495 : const bool check_max_fee{max_tx_fee > 0};
78 [ + + ]: 15495 : if (check_max_fee || broadcast_method == TxBroadcast::NO_MEMPOOL_PRIVATE_BROADCAST) {
79 : : // First, call ATMP with test_accept and check the fee. If ATMP
80 : : // fails here, return error immediately.
81 [ + - ]: 4012 : const MempoolAcceptResult result = node.chainman->ProcessTransaction(tx, /*test_accept=*/ true);
82 [ + + ]: 4012 : if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
83 [ + - ]: 135 : return HandleATMPError(result.m_state, err_string);
84 [ + + + + ]: 7753 : } else if (check_max_fee && result.m_base_fees.value() > max_tx_fee) {
85 : : return TransactionError::MAX_FEE_EXCEEDED;
86 : : }
87 : 4012 : }
88 : :
89 [ + + ]: 15358 : switch (broadcast_method) {
90 : 15353 : case TxBroadcast::MEMPOOL_NO_BROADCAST:
91 : 15353 : case TxBroadcast::MEMPOOL_AND_BROADCAST_TO_ALL:
92 : : // Try to submit the transaction to the mempool.
93 : 15353 : {
94 : 15353 : const MempoolAcceptResult result =
95 [ + - ]: 15353 : node.chainman->ProcessTransaction(tx, /*test_accept=*/false);
96 [ + + ]: 15353 : if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
97 [ + - ]: 4225 : return HandleATMPError(result.m_state, err_string);
98 : : }
99 : 15353 : }
100 : : // Transaction was accepted to the mempool.
101 : :
102 [ + + ]: 11128 : if (broadcast_method == TxBroadcast::MEMPOOL_AND_BROADCAST_TO_ALL) {
103 : : // the mempool tracks locally submitted transactions to make a
104 : : // best-effort of initial broadcast
105 [ + - ]: 11116 : node.mempool->AddUnbroadcastTx(txid);
106 : : }
107 : : break;
108 : : case TxBroadcast::NO_MEMPOOL_PRIVATE_BROADCAST:
109 : : break;
110 : : }
111 : :
112 [ + + + - ]: 11133 : if (wait_callback && node.validation_signals) {
113 : : // For transactions broadcast from outside the wallet, make sure
114 : : // that the wallet has been notified of the transaction before
115 : : // continuing.
116 : : //
117 : : // This prevents a race where a user might call sendrawtransaction
118 : : // with a transaction to/from their wallet, immediately call some
119 : : // wallet RPC, and get a stale result because callbacks have not
120 : : // yet been processed.
121 [ + - ]: 9610 : node.validation_signals->CallFunctionInValidationInterfaceQueue([&promise] {
122 : 9610 : promise.set_value();
123 : : });
124 : 9610 : callback_set = true;
125 : : }
126 [ + - ]: 24524 : }
127 : 4365 : } // cs_main
128 : :
129 [ + + ]: 20162 : if (callback_set) {
130 : : // Wait until Validation Interface clients have been notified of the
131 : : // transaction entering the mempool.
132 [ + - + - ]: 28830 : promise.get_future().wait();
133 : : }
134 : :
135 [ + + + ]: 20162 : switch (broadcast_method) {
136 : : case TxBroadcast::MEMPOOL_NO_BROADCAST:
137 : : break;
138 : 20045 : case TxBroadcast::MEMPOOL_AND_BROADCAST_TO_ALL:
139 [ + - ]: 20045 : node.peerman->InitiateTxBroadcastToAll(txid, wtxid);
140 : : break;
141 : 6 : case TxBroadcast::NO_MEMPOOL_PRIVATE_BROADCAST:
142 [ + - ]: 6 : node.peerman->InitiateTxBroadcastPrivate(tx);
143 : : break;
144 : : }
145 : :
146 : : return TransactionError::OK;
147 : 24527 : }
148 : :
149 : 3089 : CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMemPool* const mempool, const Txid& hash, const BlockManager& blockman, uint256& hashBlock)
150 : : {
151 [ + + ]: 3089 : if (mempool && !block_index) {
152 : 3054 : CTransactionRef ptx = mempool->get(hash);
153 [ + + ]: 3054 : if (ptx) return ptx;
154 : 70 : }
155 [ + + ]: 70 : if (g_txindex) {
156 : 34 : CTransactionRef tx;
157 : 34 : uint256 block_hash;
158 [ + - + - ]: 34 : if (g_txindex->FindTx(hash, block_hash, tx)) {
159 [ + + + + ]: 34 : if (!block_index || block_index->GetBlockHash() == block_hash) {
160 : : // Don't return the transaction if the provided block hash doesn't match.
161 : : // The case where a transaction appears in multiple blocks (e.g. reorgs or
162 : : // BIP30) is handled by the block lookup below.
163 : 33 : hashBlock = block_hash;
164 [ - + ]: 33 : return tx;
165 : : }
166 : : }
167 : 34 : }
168 [ + + ]: 37 : if (block_index) {
169 : 28 : CBlock block;
170 [ + - + - ]: 28 : if (blockman.ReadBlock(block, *block_index)) {
171 [ + + ]: 55 : for (const auto& tx : block.vtx) {
172 [ + + ]: 53 : if (tx->GetHash() == hash) {
173 : 26 : hashBlock = block_index->GetBlockHash();
174 [ + - ]: 52 : return tx;
175 : : }
176 : : }
177 : : }
178 : 28 : }
179 : 11 : return nullptr;
180 : : }
181 : : } // namespace node
|