Bitcoin ABC  0.26.3
P2P Digital Currency
transaction.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2018 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 <node/transaction.h>
7 
8 #include <config.h>
9 #include <consensus/validation.h>
10 #include <index/txindex.h>
11 #include <net.h>
12 #include <net_processing.h>
13 #include <node/blockstorage.h>
14 #include <node/context.h>
15 #include <primitives/blockhash.h>
16 #include <primitives/txid.h>
17 #include <txmempool.h>
18 #include <validation.h>
19 #include <validationinterface.h>
20 
21 #include <future>
22 
23 namespace node {
25  std::string &err_string_out) {
26  err_string_out = state.ToString();
27  if (state.IsInvalid()) {
30  }
32  } else {
34  }
35 }
36 
38  const CTransactionRef tx,
39  std::string &err_string,
40  const Amount max_tx_fee, bool relay,
41  bool wait_callback) {
42  // BroadcastTransaction can be called by either sendrawtransaction RPC or
43  // the wallet. chainman, mempool and peerman are initialized before the RPC
44  // server and wallet are started and reset after the RPC server and wallet
45  // are stopped.
46  assert(node.chainman);
47  assert(node.mempool);
48  assert(node.peerman);
49 
50  std::promise<void> promise;
51  TxId txid = tx->GetId();
52  bool callback_set = false;
53 
54  {
55  LOCK(cs_main);
56 
57  // If the transaction is already confirmed in the chain, don't do
58  // anything and return early.
59  CCoinsViewCache &view = node.chainman->ActiveChainstate().CoinsTip();
60  for (size_t o = 0; o < tx->vout.size(); o++) {
61  const Coin &existingCoin = view.AccessCoin(COutPoint(txid, o));
62  // IsSpent doesn't mean the coin is spent, it means the output
63  // doesn't exist. So if the output does exist, then this transaction
64  // exists in the chain.
65  if (!existingCoin.IsSpent()) {
67  }
68  }
69 
70  if (!node.mempool->exists(txid)) {
71  // Transaction is not already in the mempool.
72  if (max_tx_fee > Amount::zero()) {
73  // First, call ATMP with test_accept and check the fee. If ATMP
74  // fails here, return error immediately.
75  const MempoolAcceptResult result =
76  node.chainman->ProcessTransaction(tx, /*test_accept=*/true);
77  if (result.m_result_type !=
79  return HandleATMPError(result.m_state, err_string);
80  } else if (result.m_base_fees.value() > max_tx_fee) {
82  }
83  }
84  // Try to submit the transaction to the mempool.
85  const MempoolAcceptResult result =
86  node.chainman->ProcessTransaction(tx, /*test_accept=*/false);
87  if (result.m_result_type !=
89  return HandleATMPError(result.m_state, err_string);
90  }
91 
92  // Transaction was accepted to the mempool.
93 
94  if (relay) {
95  // the mempool tracks locally submitted transactions to make a
96  // best-effort of initial broadcast
97  node.mempool->AddUnbroadcastTx(txid);
98  }
99 
100  if (wait_callback) {
101  // For transactions broadcast from outside the wallet, make sure
102  // that the wallet has been notified of the transaction before
103  // continuing.
104  //
105  // This prevents a race where a user might call
106  // sendrawtransaction with a transaction to/from their wallet,
107  // immediately call some wallet RPC, and get a stale result
108  // because callbacks have not yet been processed.
110  [&promise] { promise.set_value(); });
111  callback_set = true;
112  }
113  }
114  } // cs_main
115 
116  if (callback_set) {
117  // Wait until Validation Interface clients have been notified of the
118  // transaction entering the mempool.
119  promise.get_future().wait();
120  }
121 
122  if (relay) {
123  node.peerman->RelayTransaction(txid);
124  }
125 
126  return TransactionError::OK;
127 }
128 
129 CTransactionRef GetTransaction(const CBlockIndex *const block_index,
130  const CTxMemPool *const mempool,
131  const TxId &txid, BlockHash &hashBlock,
132  const BlockManager &blockman) {
133  if (mempool && !block_index) {
134  CTransactionRef ptx = mempool->get(txid);
135  if (ptx) {
136  return ptx;
137  }
138  }
139  if (g_txindex) {
140  CTransactionRef tx;
141  BlockHash block_hash;
142  if (g_txindex->FindTx(txid, block_hash, tx)) {
143  if (!block_index || block_index->GetBlockHash() == block_hash) {
144  // Don't return the transaction if the provided block hash
145  // doesn't match.
146  // The case where a transaction appears in multiple blocks
147  // (e.g. reorgs or BIP30) is handled by the block lookup below.
148  hashBlock = block_hash;
149  return tx;
150  }
151  }
152  }
153  if (block_index) {
154  CBlock block;
155  if (blockman.ReadBlockFromDisk(block, *block_index)) {
156  for (const auto &tx : block.vtx) {
157  if (tx->GetId() == txid) {
158  hashBlock = block_index->GetBlockHash();
159  return tx;
160  }
161  }
162  }
163  }
164  return nullptr;
165 }
166 } // namespace node
Definition: block.h:60
std::vector< CTransactionRef > vtx
Definition: block.h:63
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: blockindex.h:25
BlockHash GetBlockHash() const
Definition: blockindex.h:146
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Definition: coins.h:221
const Coin & AccessCoin(const COutPoint &output) const
Return a reference to Coin in the cache, or coinEmpty if not found.
Definition: coins.cpp:196
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:20
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition: txmempool.h:209
CTransactionRef get(const TxId &txid) const
Definition: txmempool.cpp:505
A UTXO entry.
Definition: coins.h:28
bool IsSpent() const
Definition: coins.h:47
Result GetResult() const
Definition: validation.h:120
std::string ToString() const
Definition: validation.h:123
bool IsInvalid() const
Definition: validation.h:118
Maintains a tree of blocks (stored in m_block_index) which is consulted to determine where the most-w...
Definition: blockstorage.h:74
bool ReadBlockFromDisk(CBlock &block, const FlatFilePos &pos) const
Functions for disk access for blocks.
@ TX_MISSING_INPUTS
transaction was missing some of its inputs
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition: cs_main.cpp:7
TransactionError
Definition: error.h:22
Definition: init.h:28
TransactionError BroadcastTransaction(const NodeContext &node, const CTransactionRef tx, std::string &err_string, const Amount max_tx_fee, bool relay, bool wait_callback)
Submit a transaction to the mempool and (optionally) relay it to all P2P peers.
Definition: transaction.cpp:37
CTransactionRef GetTransaction(const CBlockIndex *const block_index, const CTxMemPool *const mempool, const TxId &txid, BlockHash &hashBlock, const BlockManager &blockman)
Return transaction with a given txid.
static TransactionError HandleATMPError(const TxValidationState &state, std::string &err_string_out)
Definition: transaction.cpp:24
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:315
Definition: amount.h:19
static constexpr Amount zero() noexcept
Definition: amount.h:32
A BlockHash is a unqiue identifier for a block.
Definition: blockhash.h:13
Validation result for a transaction evaluated by MemPoolAccept (single or package).
Definition: validation.h:206
const ResultType m_result_type
Result type.
Definition: validation.h:217
const TxValidationState m_state
Contains information about why the transaction failed.
Definition: validation.h:220
@ VALID
Fully validated, valid.
const std::optional< Amount > m_base_fees
Raw base fees in satoshis.
Definition: validation.h:228
A TxId is the identifier of a transaction.
Definition: txid.h:14
NodeContext struct containing references to chain state and connection state.
Definition: context.h:43
#define LOCK(cs)
Definition: sync.h:306
std::unique_ptr< TxIndex > g_txindex
The global transaction index, used in GetTransaction. May be null.
Definition: txindex.cpp:16
assert(!tx.IsCoinBase())
void CallFunctionInValidationInterfaceQueue(std::function< void()> func)
Pushes a function to callback onto the notification queue, guaranteeing any callbacks generated prior...