/ src / node / transaction.cpp
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