Bitcoin ABC 0.26.3
P2P Digital Currency
Loading...
Searching...
No Matches
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>
10#include <index/txindex.h>
11#include <net.h>
12#include <net_processing.h>
13#include <node/blockstorage.h>
14#include <node/context.h>
16#include <primitives/txid.h>
17#include <txmempool.h>
18#include <validation.h>
19#include <validationinterface.h>
20
21#include <future>
22
23namespace 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 {
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
127}
128
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) {
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
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Definition coins.h:221
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition txmempool.h:212
CTransactionRef get(const TxId &txid) const
A UTXO entry.
Definition coins.h:28
Result GetResult() const
Definition validation.h:122
std::string ToString() const
Definition validation.h:125
bool IsInvalid() const
Definition validation.h:120
Maintains a tree of blocks (stored in m_block_index) which is consulted to determine where the most-w...
@ 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.
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)
std::shared_ptr< const CTransaction > CTransactionRef
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
Definition random.h:85
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...