Bitcoin ABC 0.33.1
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>
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 <node/types.h>
17#include <primitives/txid.h>
18#include <txmempool.h>
19#include <validation.h>
20#include <validationinterface.h>
21
22#include <future>
23
24namespace node {
26 std::string &err_string_out) {
27 err_string_out = state.ToString();
28 if (state.IsInvalid()) {
31 }
33 } else {
35 }
36}
37
39 const CTransactionRef tx,
40 std::string &err_string,
41 const Amount max_tx_fee, bool relay,
42 bool wait_callback) {
43 // BroadcastTransaction can be called by either sendrawtransaction RPC or
44 // the wallet. chainman, mempool and peerman are initialized before the RPC
45 // server and wallet are started and reset after the RPC server and wallet
46 // are stopped.
47 assert(node.chainman);
48 assert(node.mempool);
49 assert(node.peerman);
50
51 std::promise<void> promise;
52 TxId txid = tx->GetId();
53 bool callback_set = false;
54
55 {
57
58 // If the transaction is already confirmed in the chain, don't do
59 // anything and return early.
60 CCoinsViewCache &view = node.chainman->ActiveChainstate().CoinsTip();
61 for (size_t o = 0; o < tx->vout.size(); o++) {
62 const Coin &existingCoin = view.AccessCoin(COutPoint(txid, o));
63 // IsSpent doesn't mean the coin is spent, it means the output
64 // doesn't exist. So if the output does exist, then this transaction
65 // exists in the chain.
66 if (!existingCoin.IsSpent()) {
68 }
69 }
70
71 if (!node.mempool->exists(txid)) {
72 // Transaction is not already in the mempool.
73 if (max_tx_fee > Amount::zero()) {
74 // First, call ATMP with test_accept and check the fee. If ATMP
75 // fails here, return error immediately.
76 const MempoolAcceptResult result =
77 node.chainman->ProcessTransaction(tx, /*test_accept=*/true);
78 if (result.m_result_type !=
80 return HandleATMPError(result.m_state, err_string);
81 } else if (result.m_base_fees.value() > max_tx_fee) {
83 }
84 }
85 // Try to submit the transaction to the mempool.
86 const MempoolAcceptResult result =
87 node.chainman->ProcessTransaction(tx, /*test_accept=*/false);
88 if (result.m_result_type !=
90 return HandleATMPError(result.m_state, err_string);
91 }
92
93 // Transaction was accepted to the mempool.
94
95 if (relay) {
96 // the mempool tracks locally submitted transactions to make a
97 // best-effort of initial broadcast
98 node.mempool->AddUnbroadcastTx(txid);
99 }
100
101 if (wait_callback) {
102 // For transactions broadcast from outside the wallet, make sure
103 // that the wallet has been notified of the transaction before
104 // continuing.
105 //
106 // This prevents a race where a user might call
107 // sendrawtransaction with a transaction to/from their wallet,
108 // immediately call some wallet RPC, and get a stale result
109 // because callbacks have not yet been processed.
111 [&promise] { promise.set_value(); });
112 callback_set = true;
113 }
114 }
115 } // cs_main
116
117 if (callback_set) {
118 // Wait until Validation Interface clients have been notified of the
119 // transaction entering the mempool.
120 promise.get_future().wait();
121 }
122
123 if (relay) {
124 node.peerman->RelayTransaction(txid);
125 }
126
128}
129
131 const CTxMemPool *const mempool,
132 const TxId &txid, BlockHash &hashBlock,
133 const BlockManager &blockman) {
134 if (mempool && !block_index) {
135 CTransactionRef ptx = mempool->get(txid);
136 if (ptx) {
137 return ptx;
138 }
139 }
140 if (g_txindex) {
142 BlockHash block_hash;
143 if (g_txindex->FindTx(txid, block_hash, tx)) {
144 if (!block_index || block_index->GetBlockHash() == block_hash) {
145 // Don't return the transaction if the provided block hash
146 // doesn't match.
147 // The case where a transaction appears in multiple blocks
148 // (e.g. reorgs or BIP30) is handled by the block lookup below.
149 hashBlock = block_hash;
150 return tx;
151 }
152 }
153 }
154 if (block_index) {
155 CBlock block;
156 if (blockman.ReadBlock(block, *block_index)) {
157 for (const auto &tx : block.vtx) {
158 if (tx->GetId() == txid) {
159 hashBlock = block_index->GetBlockHash();
160 return tx;
161 }
162 }
163 }
164 }
165 return nullptr;
166}
167} // 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:130
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Definition: coins.h:363
const Coin & AccessCoin(const COutPoint &output) const
Return a reference to Coin in the cache, or coinEmpty if not found.
Definition: coins.cpp:195
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition: txmempool.h:221
CTransactionRef get(const TxId &txid) const
Definition: txmempool.cpp:676
A UTXO entry.
Definition: coins.h:29
bool IsSpent() const
Definition: coins.h:48
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...
Definition: blockstorage.h:116
bool ReadBlock(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
Definition: messages.h:12
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:38
TransactionError
Definition: types.h:17
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:25
is a home for public enum and struct type definitions that are used by internally by node code,...
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:315
Definition: amount.h:21
static constexpr Amount zero() noexcept
Definition: amount.h:34
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:212
const ResultType m_result_type
Result type.
Definition: validation.h:223
const TxValidationState m_state
Contains information about why the transaction failed.
Definition: validation.h:226
@ VALID
Fully validated, valid.
const std::optional< Amount > m_base_fees
Raw base fees in satoshis.
Definition: validation.h:234
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:48
#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:17
assert(!tx.IsCoinBase())
void CallFunctionInValidationInterfaceQueue(std::function< void()> func)
Pushes a function to callback onto the notification queue, guaranteeing any callbacks generated prior...