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