Branch data Line data Source code
1 : : // Copyright (c) 2010 Satoshi Nakamoto 2 : : // Copyright (c) 2009-2021 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 <txmempool.h> 13 : : #include <validation.h> 14 : : #include <validationinterface.h> 15 : : #include <node/transaction.h> 16 : : 17 [ + - ]: 2 : #include <future> 18 [ + - ]: 2 : 19 : : namespace node { 20 : 0 : static TransactionError HandleATMPError(const TxValidationState& state, std::string& err_string_out) 21 : : { 22 : 0 : err_string_out = state.ToString(); 23 [ # # ]: 0 : if (state.IsInvalid()) { 24 [ # # ]: 0 : if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) { 25 : 0 : return TransactionError::MISSING_INPUTS; 26 : : } 27 : 2 : return TransactionError::MEMPOOL_REJECTED; 28 : : } else { 29 : 0 : return TransactionError::MEMPOOL_ERROR; 30 : : } 31 : 0 : } 32 : : 33 : 0 : TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback) 34 : : { 35 : : // BroadcastTransaction can be called by either sendrawtransaction RPC or the wallet. 36 : : // chainman, mempool and peerman are initialized before the RPC server and wallet are started 37 : : // and reset after the RPC sever and wallet are stopped. 38 [ # # ]: 0 : assert(node.chainman); 39 [ # # ]: 0 : assert(node.mempool); 40 [ # # ]: 0 : assert(node.peerman); 41 : : 42 : 0 : std::promise<void> promise; 43 [ # # ][ # # ]: 0 : uint256 txid = tx->GetHash(); 44 [ # # ][ # # ]: 0 : uint256 wtxid = tx->GetWitnessHash(); 45 : 0 : bool callback_set = false; 46 : : 47 : : { 48 [ # # ][ # # ]: 0 : LOCK(cs_main); 49 : : 50 : : // If the transaction is already confirmed in the chain, don't do anything 51 : : // and return early. 52 [ # # ][ # # ]: 0 : CCoinsViewCache &view = node.chainman->ActiveChainstate().CoinsTip(); 53 [ # # ]: 0 : for (size_t o = 0; o < tx->vout.size(); o++) { 54 [ # # ][ # # ]: 0 : 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 [ # # ][ # # ]: 0 : if (!existingCoin.IsSpent()) return TransactionError::ALREADY_IN_CHAIN; 58 : 0 : } 59 : : 60 [ # # ][ # # ]: 0 : 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 relay=true. 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 [ # # ][ # # ]: 0 : wtxid = mempool_tx->GetWitnessHash(); 69 : 0 : } else { 70 : : // Transaction is not already in the mempool. 71 [ # # ]: 0 : if (max_tx_fee > 0) { 72 : : // First, call ATMP with test_accept and check the fee. If ATMP 73 : : // fails here, return error immediately. 74 [ # # ]: 0 : const MempoolAcceptResult result = node.chainman->ProcessTransaction(tx, /*test_accept=*/ true); 75 [ # # ]: 0 : if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) { 76 [ # # ]: 0 : return HandleATMPError(result.m_state, err_string); 77 [ # # ][ # # ]: 0 : } else if (result.m_base_fees.value() > max_tx_fee) { 78 : 0 : return TransactionError::MAX_FEE_EXCEEDED; 79 : : } 80 [ # # ]: 0 : } 81 : : // Try to submit the transaction to the mempool. 82 [ # # ]: 0 : const MempoolAcceptResult result = node.chainman->ProcessTransaction(tx, /*test_accept=*/ false); 83 [ + - ][ # # ]: 2 : if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) { 84 [ # # ]: 0 : return HandleATMPError(result.m_state, err_string); 85 : : } 86 : : 87 : : // Transaction was accepted to the mempool. 88 : : 89 [ # # ]: 0 : if (relay) { 90 : : // the mempool tracks locally submitted transactions to make a 91 : : // best-effort of initial broadcast 92 [ # # ]: 0 : node.mempool->AddUnbroadcastTx(txid); 93 : 0 : } 94 : : 95 [ # # ]: 0 : if (wait_callback) { 96 : : // For transactions broadcast from outside the wallet, make sure 97 : : // that the wallet has been notified of the transaction before 98 : : // continuing. 99 : : // 100 : : // This prevents a race where a user might call sendrawtransaction 101 : : // with a transaction to/from their wallet, immediately call some 102 : : // wallet RPC, and get a stale result because callbacks have not 103 : : // yet been processed. 104 [ # # ]: 0 : CallFunctionInValidationInterfaceQueue([&promise] { 105 : 0 : promise.set_value(); 106 : 0 : }); 107 : 0 : callback_set = true; 108 : 0 : } 109 [ # # ]: 0 : } 110 [ # # ]: 0 : } // cs_main 111 : : 112 [ # # ]: 0 : if (callback_set) { 113 : : // Wait until Validation Interface clients have been notified of the 114 : : // transaction entering the mempool. 115 [ # # ][ # # ]: 0 : promise.get_future().wait(); 116 : 0 : } 117 : : 118 [ # # ]: 0 : if (relay) { 119 [ # # ]: 0 : node.peerman->RelayTransaction(txid, wtxid); 120 : 0 : } 121 : : 122 : 0 : return TransactionError::OK; 123 : 0 : } 124 : : 125 : 0 : CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMemPool* const mempool, const uint256& hash, uint256& hashBlock, const BlockManager& blockman) 126 : : { 127 [ # # ][ # # ]: 0 : if (mempool && !block_index) { 128 : 0 : CTransactionRef ptx = mempool->get(hash); 129 [ # # ]: 0 : if (ptx) return ptx; 130 [ # # ]: 0 : } 131 [ # # ]: 0 : if (g_txindex) { 132 : 0 : CTransactionRef tx; 133 [ # # ]: 0 : uint256 block_hash; 134 [ # # ][ # # ]: 0 : if (g_txindex->FindTx(hash, block_hash, tx)) { 135 [ # # ][ # # ]: 0 : if (!block_index || block_index->GetBlockHash() == block_hash) { [ # # ][ # # ] 136 : : // Don't return the transaction if the provided block hash doesn't match. 137 : : // The case where a transaction appears in multiple blocks (e.g. reorgs or 138 : : // BIP30) is handled by the block lookup below. 139 : 0 : hashBlock = block_hash; 140 : 0 : return tx; 141 : : } 142 : 0 : } 143 [ # # ]: 0 : } 144 [ # # ]: 0 : if (block_index) { 145 : 0 : CBlock block; 146 [ # # ][ # # ]: 0 : if (blockman.ReadBlockFromDisk(block, *block_index)) { 147 [ # # ]: 0 : for (const auto& tx : block.vtx) { 148 [ # # ][ # # ]: 0 : if (tx->GetHash() == hash) { [ # # ] 149 [ # # ]: 0 : hashBlock = block_index->GetBlockHash(); 150 : 0 : return tx; 151 : : } 152 : : } 153 : 0 : } 154 [ # # ]: 0 : } 155 : 0 : return nullptr; 156 : 0 : } 157 : : } // namespace node