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 <node/transaction.h>
7 : :
8 : : #include <consensus/validation.h>
9 : : #include <index/txindex.h>
10 : : #include <net.h>
11 : : #include <net_processing.h>
12 : : #include <node/blockstorage.h>
13 : : #include <node/context.h>
14 : : #include <node/types.h>
15 : : #include <policy/feerate.h>
16 : : #include <txmempool.h>
17 : : #include <validation.h>
18 : : #include <validationinterface.h>
19 : :
20 : : namespace node {
21 : 4487 : static TransactionError HandleATMPError(const TxValidationState& state, std::string& err_string_out)
22 : : {
23 : 4487 : err_string_out = state.ToString();
24 [ + - ]: 4487 : if (state.IsInvalid()) {
25 [ + + ]: 4487 : if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
26 : : return TransactionError::MISSING_INPUTS;
27 : : }
28 : 4478 : return TransactionError::MEMPOOL_REJECTED;
29 : : } else {
30 : : return TransactionError::MEMPOOL_ERROR;
31 : : }
32 : : }
33 : :
34 : 39458 : TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, const CFeeRate& max_tx_fee_rate, TxBroadcast broadcast_method, bool wait_callback)
35 : : {
36 : : // BroadcastTransaction can be called by RPC or by the wallet.
37 : : // chainman, mempool and peerman are initialized before the RPC server and wallet are started
38 : : // and reset after the RPC sever and wallet are stopped.
39 [ - + ]: 39458 : assert(node.chainman);
40 [ - + ]: 39458 : assert(node.mempool);
41 [ - + ]: 39458 : assert(node.peerman);
42 : :
43 : 39458 : Txid txid = tx->GetHash();
44 : 39458 : Wtxid wtxid = tx->GetWitnessHash();
45 : 39458 : bool callback_set = false;
46 : :
47 : 39458 : {
48 : 39458 : LOCK(cs_main);
49 : :
50 : : // If the transaction is already confirmed in the chain, don't do anything
51 : : // and return early.
52 [ + - + - ]: 39458 : CCoinsViewCache &view = node.chainman->ActiveChainstate().CoinsTip();
53 [ - + + + ]: 123328 : for (size_t o = 0; o < tx->vout.size(); o++) {
54 [ + - ]: 83873 : const Coin& existingCoin = view.AccessCoin(COutPoint(txid, o));
55 : : // IsSpent doesn't mean the coin is spent, it means the output doesn't exist.
56 : : // So if the output does exist, then this transaction exists in the chain.
57 [ + + ]: 83873 : if (!existingCoin.IsSpent()) return TransactionError::ALREADY_IN_UTXO_SET;
58 : : }
59 : :
60 [ + - + + ]: 39455 : if (auto mempool_tx = node.mempool->get(txid); mempool_tx) {
61 : : // There's already a transaction in the mempool with this txid. Don't
62 : : // try to submit this transaction to the mempool (since it'll be
63 : : // rejected as a TX_CONFLICT), but do attempt to reannounce the mempool
64 : : // transaction if broadcast_method is not TxBroadcast::MEMPOOL_NO_BROADCAST.
65 : : //
66 : : // The mempool transaction may have the same or different witness (and
67 : : // wtxid) as this transaction. Use the mempool's wtxid for reannouncement.
68 : 8951 : wtxid = mempool_tx->GetWitnessHash();
69 : : } else {
70 : : // Transaction is not already in the mempool.
71 : 30504 : const bool check_max_fee{max_tx_fee > 0};
72 [ + + ]: 30504 : const bool check_max_feerate{max_tx_fee_rate > CFeeRate(0)};
73 [ + + + + ]: 30504 : if (check_max_fee || check_max_feerate || broadcast_method == TxBroadcast::NO_MEMPOOL_PRIVATE_BROADCAST) {
74 : : // First, call ATMP with test_accept and check the fee. If ATMP
75 : : // fails here, return error immediately.
76 [ + - ]: 16446 : const MempoolAcceptResult result = node.chainman->ProcessTransaction(tx, /*test_accept=*/ true);
77 [ + + ]: 16446 : if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
78 [ + - ]: 143 : return HandleATMPError(result.m_state, err_string);
79 [ + + + - ]: 18003 : } else if (check_max_fee && result.m_base_fees.value() > max_tx_fee) {
80 : : return TransactionError::MAX_FEE_EXCEEDED;
81 [ + + + - : 32605 : } else if (check_max_feerate && result.m_base_fees.value() > max_tx_fee_rate.GetFee(result.m_vsize.value())) {
+ - + + ]
82 : : return TransactionError::MAX_FEE_RATE_EXCEEDED;
83 : : }
84 : 16446 : }
85 : :
86 [ + + ]: 30357 : switch (broadcast_method) {
87 : 20340 : case TxBroadcast::MEMPOOL_NO_BROADCAST:
88 : 20340 : case TxBroadcast::MEMPOOL_AND_BROADCAST_TO_ALL:
89 : : // Try to submit the transaction to the mempool.
90 : 20340 : {
91 : 20340 : const MempoolAcceptResult result =
92 [ + - ]: 20340 : node.chainman->ProcessTransaction(tx, /*test_accept=*/false);
93 [ + + ]: 20340 : if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
94 [ + - ]: 4344 : return HandleATMPError(result.m_state, err_string);
95 : : }
96 : 20340 : }
97 : : // Transaction was accepted to the mempool.
98 : :
99 [ + + ]: 15996 : if (broadcast_method == TxBroadcast::MEMPOOL_AND_BROADCAST_TO_ALL) {
100 : : // the mempool tracks locally submitted transactions to make a
101 : : // best-effort of initial broadcast
102 [ + - ]: 15970 : node.mempool->AddUnbroadcastTx(txid);
103 : : }
104 : : break;
105 : : case TxBroadcast::NO_MEMPOOL_PRIVATE_BROADCAST:
106 : : break;
107 : : }
108 : :
109 [ + + - + ]: 26013 : if (wait_callback && node.validation_signals) {
110 : : // For transactions broadcast from outside the wallet, make sure
111 : : // that the wallet has been notified of the transaction before
112 : : // continuing.
113 : : //
114 : : // This prevents a race where a user might call sendrawtransaction
115 : : // with a transaction to/from their wallet, immediately call some
116 : : // wallet RPC, and get a stale result because callbacks have not
117 : : // yet been processed.
118 : : callback_set = true;
119 : : }
120 [ + - ]: 39455 : }
121 : 4494 : } // cs_main
122 : :
123 [ + + ]: 34964 : if (callback_set) {
124 : : // Wait until Validation Interface clients have been notified of the
125 : : // transaction entering the mempool.
126 : 24315 : node.validation_signals->SyncWithValidationInterfaceQueue();
127 : : }
128 : :
129 [ + + + ]: 34964 : switch (broadcast_method) {
130 : : case TxBroadcast::MEMPOOL_NO_BROADCAST:
131 : : break;
132 : 24813 : case TxBroadcast::MEMPOOL_AND_BROADCAST_TO_ALL:
133 : 24813 : node.peerman->InitiateTxBroadcastToAll(wtxid);
134 : 24813 : break;
135 : 10018 : case TxBroadcast::NO_MEMPOOL_PRIVATE_BROADCAST:
136 : 10018 : return node.peerman->InitiateTxBroadcastPrivate(tx);
137 : : }
138 : :
139 : : return TransactionError::OK;
140 : : }
141 : :
142 : 4107 : CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMemPool* const mempool, const Txid& hash, const BlockManager& blockman, uint256& hashBlock)
143 : : {
144 [ + + ]: 4107 : if (mempool && !block_index) {
145 : 4070 : CTransactionRef ptx = mempool->get(hash);
146 [ + + ]: 4070 : if (ptx) return ptx;
147 : 81 : }
148 [ + + ]: 81 : if (g_txindex) {
149 [ + + ]: 42 : if (auto result{g_txindex->FindTx(hash)}) {
150 [ + + + + ]: 42 : if (!block_index || block_index->GetBlockHash() == result->block_hash) {
151 : : // Don't return the transaction if the provided block hash doesn't match.
152 : : // The case where a transaction appears in multiple blocks (e.g. reorgs or
153 : : // BIP30) is handled by the block lookup below.
154 [ + - ]: 39 : hashBlock = result->block_hash;
155 [ + - ]: 78 : return result->tx;
156 : : }
157 : 42 : }
158 : : }
159 [ + + ]: 42 : if (block_index) {
160 : 30 : CBlock block;
161 [ + - + - ]: 30 : if (blockman.ReadBlock(block, *block_index)) {
162 [ + + ]: 60 : for (const auto& tx : block.vtx) {
163 [ + + ]: 58 : if (tx->GetHash() == hash) {
164 : 28 : hashBlock = block_index->GetBlockHash();
165 [ + - ]: 56 : return tx;
166 : : }
167 : : }
168 : : }
169 : 30 : }
170 : 14 : return nullptr;
171 : : }
172 : : } // namespace node
|