LCOV - code coverage report
Current view: top level - src/node - transaction.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 56 58 96.6 %
Date: 2021-06-29 14:35:33 Functions: 3 3 100.0 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 22 24 91.7 %

           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 : }

Generated by: LCOV version 1.14