Bitcoin Core  22.99.0
P2P Digital Currency
transaction.cpp
Go to the documentation of this file.
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()) {
26  }
28  } else {
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 either sendrawtransaction RPC or 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  uint256 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);
76  return HandleATMPError(result.m_state, err_string);
77  } else if (result.m_base_fees.value() > max_tx_fee) {
79  }
80  }
81  // Try to submit the transaction to the mempool.
82  const MempoolAcceptResult result = node.chainman->ProcessTransaction(tx, /*test_accept=*/ false);
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) {
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.
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, const Consensus::Params& consensusParams, uint256& hashBlock)
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 (ReadBlockFromDisk(block, block_index, consensusParams)) {
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
assert
assert(!tx.IsCoinBase())
g_txindex
std::unique_ptr< TxIndex > g_txindex
The global transaction index, used in GetTransaction. May be null.
Definition: txindex.cpp:16
TransactionError::MEMPOOL_REJECTED
@ MEMPOOL_REJECTED
MempoolAcceptResult::m_state
const TxValidationState m_state
Contains information about why the transaction failed.
Definition: validation.h:172
MempoolAcceptResult::m_result_type
const ResultType m_result_type
Result type.
Definition: validation.h:169
CTxMemPool
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition: txmempool.h:429
node::NodeContext
NodeContext struct containing references to chain state and connection state.
Definition: context.h:40
validationinterface.h
validation.h
node::HandleATMPError
static TransactionError HandleATMPError(const TxValidationState &state, std::string &err_string_out)
Definition: transaction.cpp:20
TransactionError::MEMPOOL_ERROR
@ MEMPOOL_ERROR
CCoinsViewCache::AccessCoin
const Coin & AccessCoin(const COutPoint &output) const
Return a reference to Coin in the cache, or coinEmpty if not found.
Definition: coins.cpp:150
CTransactionRef
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:406
node::ReadBlockFromDisk
bool ReadBlockFromDisk(CBlock &block, const FlatFilePos &pos, const Consensus::Params &consensusParams)
Functions for disk access for blocks.
Definition: blockstorage.cpp:745
context.h
MempoolAcceptResult::m_base_fees
const std::optional< CAmount > m_base_fees
Raw base fees in satoshis.
Definition: validation.h:180
ValidationState::ToString
std::string ToString() const
Definition: validation.h:126
txmempool.h
txindex.h
transaction.h
TxValidationState
Definition: validation.h:140
Consensus::Params
Parameters that influence chain consensus.
Definition: params.h:70
TransactionError
TransactionError
Definition: error.h:22
CTxMemPool::get
CTransactionRef get(const uint256 &hash) const
Definition: txmempool.cpp:908
Coin
A UTXO entry.
Definition: coins.h:30
CAmount
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
uint256
256-bit opaque blob.
Definition: uint256.h:126
net_processing.h
CBlockIndex::GetBlockHash
uint256 GetBlockHash() const
Definition: chain.h:264
ValidationState::GetResult
Result GetResult() const
Definition: validation.h:123
MempoolAcceptResult::ResultType::VALID
@ VALID
CBlock
Definition: block.h:62
CBlock::vtx
std::vector< CTransactionRef > vtx
Definition: block.h:66
CCoinsViewCache
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Definition: coins.h:213
TxValidationResult::TX_MISSING_INPUTS
@ TX_MISSING_INPUTS
transaction was missing some of its inputs
LOCK
#define LOCK(cs)
Definition: sync.h:226
blockstorage.h
TransactionError::OK
@ OK
No error.
MempoolAcceptResult
Validation result for a single transaction mempool acceptance.
Definition: validation.h:160
node
Definition: init.h:22
COutPoint
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:26
node::GetTransaction
CTransactionRef GetTransaction(const CBlockIndex *const block_index, const CTxMemPool *const mempool, const uint256 &hash, const Consensus::Params &consensusParams, uint256 &hashBlock)
Return transaction with a given hash.
Definition: transaction.cpp:125
Coin::IsSpent
bool IsSpent() const
Either this coin never existed (see e.g.
Definition: coins.h:79
node::BroadcastTransaction
TransactionError BroadcastTransaction(NodeContext &node, const CTransactionRef tx, std::string &err_string, const CAmount &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:33
cs_main
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition: validation.cpp:138
CBlockIndex
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:151
CallFunctionInValidationInterfaceQueue
void CallFunctionInValidationInterfaceQueue(std::function< void()> func)
Pushes a function to callback onto the notification queue, guaranteeing any callbacks generated prior...
Definition: validationinterface.cpp:155
TransactionError::MISSING_INPUTS
@ MISSING_INPUTS
TransactionError::MAX_FEE_EXCEEDED
@ MAX_FEE_EXCEEDED
ValidationState::IsInvalid
bool IsInvalid() const
Definition: validation.h:121
TransactionError::ALREADY_IN_CHAIN
@ ALREADY_IN_CHAIN