Branch data Line data Source code
# 1 : : // Copyright (c) 2010 Satoshi Nakamoto
# 2 : : // Copyright (c) 2009-2020 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 <net.h>
# 8 : : #include <net_processing.h>
# 9 : : #include <node/context.h>
# 10 : : #include <validation.h>
# 11 : : #include <validationinterface.h>
# 12 : : #include <node/transaction.h>
# 13 : :
# 14 : : #include <future>
# 15 : :
# 16 : : static TransactionError HandleATMPError(const TxValidationState& state, std::string& err_string_out)
# 17 : 4291 : {
# 18 : 4291 : err_string_out = state.ToString();
# 19 [ + - ]: 4291 : if (state.IsInvalid()) {
# 20 [ + + ]: 4291 : if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
# 21 : 18 : return TransactionError::MISSING_INPUTS;
# 22 : 18 : }
# 23 : 4273 : return TransactionError::MEMPOOL_REJECTED;
# 24 : 4273 : } else {
# 25 : 0 : return TransactionError::MEMPOOL_ERROR;
# 26 : 0 : }
# 27 : 4291 : }
# 28 : :
# 29 : : TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback)
# 30 : 14309 : {
# 31 : : // BroadcastTransaction can be called by either sendrawtransaction RPC or wallet RPCs.
# 32 : : // node.peerman is assigned both before chain clients and before RPC server is accepting calls,
# 33 : : // and reset after chain clients and RPC sever are stopped. node.peerman should never be null here.
# 34 : 14309 : assert(node.peerman);
# 35 : 14309 : assert(node.mempool);
# 36 : 14309 : std::promise<void> promise;
# 37 : 14309 : uint256 hashTx = tx->GetHash();
# 38 : 14309 : bool callback_set = false;
# 39 : :
# 40 : 14309 : { // cs_main scope
# 41 : 14309 : assert(node.chainman);
# 42 : 14309 : LOCK(cs_main);
# 43 : 14309 : assert(std::addressof(::ChainstateActive()) == std::addressof(node.chainman->ActiveChainstate()));
# 44 : : // If the transaction is already confirmed in the chain, don't do anything
# 45 : : // and return early.
# 46 : 14309 : CCoinsViewCache &view = node.chainman->ActiveChainstate().CoinsTip();
# 47 [ + + ]: 101658 : for (size_t o = 0; o < tx->vout.size(); o++) {
# 48 : 87349 : const Coin& existingCoin = view.AccessCoin(COutPoint(hashTx, o));
# 49 : : // IsSpent doesn't mean the coin is spent, it means the output doesn't exist.
# 50 : : // So if the output does exist, then this transaction exists in the chain.
# 51 [ - + ]: 87349 : if (!existingCoin.IsSpent()) return TransactionError::ALREADY_IN_CHAIN;
# 52 : 87349 : }
# 53 [ + + ]: 14309 : if (!node.mempool->exists(hashTx)) {
# 54 : : // Transaction is not already in the mempool.
# 55 [ + + ]: 14240 : if (max_tx_fee > 0) {
# 56 : : // First, call ATMP with test_accept and check the fee. If ATMP
# 57 : : // fails here, return error immediately.
# 58 : 3474 : const MempoolAcceptResult result = AcceptToMemoryPool(node.chainman->ActiveChainstate(), *node.mempool, tx, false /* bypass_limits */,
# 59 : 3474 : true /* test_accept */);
# 60 [ + + ]: 3474 : if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
# 61 : 490 : return HandleATMPError(result.m_state, err_string);
# 62 [ + + ]: 2984 : } else if (result.m_base_fees.value() > max_tx_fee) {
# 63 : 4 : return TransactionError::MAX_FEE_EXCEEDED;
# 64 : 4 : }
# 65 : 13746 : }
# 66 : : // Try to submit the transaction to the mempool.
# 67 : 13746 : const MempoolAcceptResult result = AcceptToMemoryPool(node.chainman->ActiveChainstate(), *node.mempool, tx, false /* bypass_limits */,
# 68 : 13746 : false /* test_accept */);
# 69 [ + + ]: 13746 : if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
# 70 : 3801 : return HandleATMPError(result.m_state, err_string);
# 71 : 3801 : }
# 72 : :
# 73 : : // Transaction was accepted to the mempool.
# 74 : :
# 75 [ + + ]: 9945 : if (wait_callback) {
# 76 : : // For transactions broadcast from outside the wallet, make sure
# 77 : : // that the wallet has been notified of the transaction before
# 78 : : // continuing.
# 79 : : //
# 80 : : // This prevents a race where a user might call sendrawtransaction
# 81 : : // with a transaction to/from their wallet, immediately call some
# 82 : : // wallet RPC, and get a stale result because callbacks have not
# 83 : : // yet been processed.
# 84 : 7750 : CallFunctionInValidationInterfaceQueue([&promise] {
# 85 : 7750 : promise.set_value();
# 86 : 7750 : });
# 87 : 7750 : callback_set = true;
# 88 : 7750 : }
# 89 : 9945 : }
# 90 : :
# 91 : 14309 : } // cs_main
# 92 : :
# 93 [ + + ]: 14309 : if (callback_set) {
# 94 : : // Wait until Validation Interface clients have been notified of the
# 95 : : // transaction entering the mempool.
# 96 : 7750 : promise.get_future().wait();
# 97 : 7750 : }
# 98 : :
# 99 [ + + ]: 10014 : if (relay) {
# 100 : : // the mempool tracks locally submitted transactions to make a
# 101 : : // best-effort of initial broadcast
# 102 : 9936 : node.mempool->AddUnbroadcastTx(hashTx);
# 103 : 9936 : node.peerman->RelayTransaction(hashTx, tx->GetWitnessHash());
# 104 : 9936 : }
# 105 : :
# 106 : 10014 : return TransactionError::OK;
# 107 : 14309 : }
|