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 : : #include <future>
# 18 : :
# 19 : : namespace node {
# 20 : : static TransactionError HandleATMPError(const TxValidationState& state, std::string& err_string_out)
# 21 : 4308 : {
# 22 : 4308 : err_string_out = state.ToString();
# 23 [ + - ]: 4308 : if (state.IsInvalid()) {
# 24 [ + + ]: 4308 : if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
# 25 : 18 : return TransactionError::MISSING_INPUTS;
# 26 : 18 : }
# 27 : 4290 : return TransactionError::MEMPOOL_REJECTED;
# 28 : 4308 : } else {
# 29 : 0 : return TransactionError::MEMPOOL_ERROR;
# 30 : 0 : }
# 31 : 4308 : }
# 32 : :
# 33 : : TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback)
# 34 : 13661 : {
# 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 : 13661 : assert(node.chainman);
# 39 : 0 : assert(node.mempool);
# 40 : 0 : assert(node.peerman);
# 41 : :
# 42 : 0 : std::promise<void> promise;
# 43 : 13661 : uint256 txid = tx->GetHash();
# 44 : 13661 : uint256 wtxid = tx->GetWitnessHash();
# 45 : 13661 : bool callback_set = false;
# 46 : :
# 47 : 13661 : {
# 48 : 13661 : LOCK(cs_main);
# 49 : :
# 50 : : // If the transaction is already confirmed in the chain, don't do anything
# 51 : : // and return early.
# 52 : 13661 : CCoinsViewCache &view = node.chainman->ActiveChainstate().CoinsTip();
# 53 [ + + ]: 98786 : for (size_t o = 0; o < tx->vout.size(); o++) {
# 54 : 85133 : 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 [ + + ]: 85133 : if (!existingCoin.IsSpent()) return TransactionError::ALREADY_IN_CHAIN;
# 58 : 85133 : }
# 59 : :
# 60 [ + + ]: 13653 : 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 : 72 : wtxid = mempool_tx->GetWitnessHash();
# 69 : 13581 : } else {
# 70 : : // Transaction is not already in the mempool.
# 71 [ + + ]: 13581 : 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 : 4596 : const MempoolAcceptResult result = node.chainman->ProcessTransaction(tx, /*test_accept=*/ true);
# 75 [ + + ]: 4596 : if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
# 76 : 499 : return HandleATMPError(result.m_state, err_string);
# 77 [ + + ]: 4097 : } else if (result.m_base_fees.value() > max_tx_fee) {
# 78 : 4 : return TransactionError::MAX_FEE_EXCEEDED;
# 79 : 4 : }
# 80 : 4596 : }
# 81 : : // Try to submit the transaction to the mempool.
# 82 : 13078 : const MempoolAcceptResult result = node.chainman->ProcessTransaction(tx, /*test_accept=*/ false);
# 83 [ + + ]: 13078 : if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
# 84 : 3809 : return HandleATMPError(result.m_state, err_string);
# 85 : 3809 : }
# 86 : :
# 87 : : // Transaction was accepted to the mempool.
# 88 : :
# 89 [ + + ]: 9269 : if (relay) {
# 90 : : // the mempool tracks locally submitted transactions to make a
# 91 : : // best-effort of initial broadcast
# 92 : 9260 : node.mempool->AddUnbroadcastTx(txid);
# 93 : 9260 : }
# 94 : :
# 95 [ + + ]: 9269 : 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 : 6962 : CallFunctionInValidationInterfaceQueue([&promise] {
# 105 : 6962 : promise.set_value();
# 106 : 6962 : });
# 107 : 6962 : callback_set = true;
# 108 : 6962 : }
# 109 : 9269 : }
# 110 : 13653 : } // cs_main
# 111 : :
# 112 [ + + ]: 9341 : if (callback_set) {
# 113 : : // Wait until Validation Interface clients have been notified of the
# 114 : : // transaction entering the mempool.
# 115 : 6962 : promise.get_future().wait();
# 116 : 6962 : }
# 117 : :
# 118 [ + + ]: 9341 : if (relay) {
# 119 : 9265 : node.peerman->RelayTransaction(txid, wtxid);
# 120 : 9265 : }
# 121 : :
# 122 : 9341 : return TransactionError::OK;
# 123 : 13653 : }
# 124 : :
# 125 : : CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMemPool* const mempool, const uint256& hash, const Consensus::Params& consensusParams, uint256& hashBlock)
# 126 : 1074 : {
# 127 [ + + ][ + + ]: 1074 : if (mempool && !block_index) {
# 128 : 964 : CTransactionRef ptx = mempool->get(hash);
# 129 [ + + ]: 964 : if (ptx) return ptx;
# 130 : 964 : }
# 131 [ + + ]: 138 : if (g_txindex) {
# 132 : 22 : CTransactionRef tx;
# 133 : 22 : uint256 block_hash;
# 134 [ + - ]: 22 : if (g_txindex->FindTx(hash, block_hash, tx)) {
# 135 [ + + ][ + + ]: 22 : 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 : 20 : hashBlock = block_hash;
# 140 : 20 : return tx;
# 141 : 20 : }
# 142 : 22 : }
# 143 : 22 : }
# 144 [ + + ]: 118 : if (block_index) {
# 145 : 103 : CBlock block;
# 146 [ + - ]: 103 : if (ReadBlockFromDisk(block, block_index, consensusParams)) {
# 147 [ + + ]: 274 : for (const auto& tx : block.vtx) {
# 148 [ + + ]: 274 : if (tx->GetHash() == hash) {
# 149 : 99 : hashBlock = block_index->GetBlockHash();
# 150 : 99 : return tx;
# 151 : 99 : }
# 152 : 274 : }
# 153 : 103 : }
# 154 : 103 : }
# 155 : 19 : return nullptr;
# 156 : 118 : }
# 157 : : } // namespace node
|