Bitcoin Core 29.99.0
P2P Digital Currency
transaction.h
Go to the documentation of this file.
1// Copyright (c) 2021-2022 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#ifndef BITCOIN_WALLET_TRANSACTION_H
6#define BITCOIN_WALLET_TRANSACTION_H
7
8#include <attributes.h>
9#include <consensus/amount.h>
11#include <tinyformat.h>
12#include <uint256.h>
13#include <util/check.h>
14#include <util/overloaded.h>
15#include <util/strencodings.h>
16#include <util/string.h>
17#include <wallet/types.h>
18
19#include <bitset>
20#include <cstdint>
21#include <map>
22#include <utility>
23#include <variant>
24#include <vector>
25
26namespace interfaces {
27class Chain;
28} // namespace interfaces
29
30namespace wallet {
36
37 explicit TxStateConfirmed(const uint256& block_hash, int height, int index) : confirmed_block_hash(block_hash), confirmed_block_height(height), position_in_block(index) {}
38 std::string toString() const { return strprintf("Confirmed (block=%s, height=%i, index=%i)", confirmed_block_hash.ToString(), confirmed_block_height, position_in_block); }
39};
40
43 std::string toString() const { return strprintf("InMempool"); }
44};
45
50
51 explicit TxStateBlockConflicted(const uint256& block_hash, int height) : conflicting_block_hash(block_hash), conflicting_block_height(height) {}
52 std::string toString() const { return strprintf("BlockConflicted (block=%s, height=%i)", conflicting_block_hash.ToString(), conflicting_block_height); }
53};
54
61
62 explicit TxStateInactive(bool abandoned = false) : abandoned(abandoned) {}
63 std::string toString() const { return strprintf("Inactive (abandoned=%i)", abandoned); }
64};
65
72 int index;
73
75 std::string toString() const { return strprintf("Unrecognized (block=%s, index=%i)", block_hash.ToString(), index); }
76};
77
79using TxState = std::variant<TxStateConfirmed, TxStateInMempool, TxStateBlockConflicted, TxStateInactive, TxStateUnrecognized>;
80
82using SyncTxState = std::variant<TxStateConfirmed, TxStateInMempool, TxStateInactive>;
83
86{
87 if (data.block_hash == uint256::ZERO) {
88 if (data.index == 0) return TxStateInactive{};
89 } else if (data.block_hash == uint256::ONE) {
90 if (data.index == -1) return TxStateInactive{/*abandoned=*/true};
91 } else if (data.index >= 0) {
92 return TxStateConfirmed{data.block_hash, /*height=*/-1, data.index};
93 } else if (data.index == -1) {
94 return TxStateBlockConflicted{data.block_hash, /*height=*/-1};
95 }
96 return data;
97}
98
100static inline uint256 TxStateSerializedBlockHash(const TxState& state)
101{
102 return std::visit(util::Overloaded{
103 [](const TxStateInactive& inactive) { return inactive.abandoned ? uint256::ONE : uint256::ZERO; },
104 [](const TxStateInMempool& in_mempool) { return uint256::ZERO; },
105 [](const TxStateConfirmed& confirmed) { return confirmed.confirmed_block_hash; },
106 [](const TxStateBlockConflicted& conflicted) { return conflicted.conflicting_block_hash; },
107 [](const TxStateUnrecognized& unrecognized) { return unrecognized.block_hash; }
108 }, state);
109}
110
112static inline int TxStateSerializedIndex(const TxState& state)
113{
114 return std::visit(util::Overloaded{
115 [](const TxStateInactive& inactive) { return inactive.abandoned ? -1 : 0; },
116 [](const TxStateInMempool& in_mempool) { return 0; },
117 [](const TxStateConfirmed& confirmed) { return confirmed.position_in_block; },
118 [](const TxStateBlockConflicted& conflicted) { return -1; },
119 [](const TxStateUnrecognized& unrecognized) { return unrecognized.index; }
120 }, state);
121}
122
124template<typename T>
125std::string TxStateString(const T& state)
126{
127 return std::visit([](const auto& s) { return s.toString(); }, state);
128}
129
134{
135 std::optional<CAmount> m_avoid_reuse_value;
136 std::optional<CAmount> m_all_value;
137 inline void Reset()
138 {
139 m_avoid_reuse_value.reset();
140 m_all_value.reset();
141 }
142 void Set(bool avoid_reuse, CAmount value)
143 {
144 if (avoid_reuse) {
145 m_avoid_reuse_value = value;
146 } else {
147 m_all_value = value;
148 }
149 }
150 CAmount Get(bool avoid_reuse)
151 {
152 if (avoid_reuse) {
153 Assert(m_avoid_reuse_value.has_value());
154 return m_avoid_reuse_value.value();
155 }
156 Assert(m_all_value.has_value());
157 return m_all_value.value();
158 }
159 bool IsCached(bool avoid_reuse)
160 {
161 if (avoid_reuse) return m_avoid_reuse_value.has_value();
162 return m_all_value.has_value();
163 }
164};
165
166
167typedef std::map<std::string, std::string> mapValue_t;
168
169
176{
177public:
178 template<typename Stream>
179 void Unserialize(Stream& s)
180 {
182 uint256 hashBlock;
183 std::vector<uint256> vMerkleBranch;
184 int nIndex;
185
186 s >> TX_WITH_WITNESS(tx) >> hashBlock >> vMerkleBranch >> nIndex;
187 }
188};
189
195{
196public:
223 std::vector<std::pair<std::string, std::string> > vOrderForm;
224 unsigned int nTimeReceived;
234 unsigned int nTimeSmart;
235 int64_t nOrderPos;
236 std::multimap<int64_t, CWalletTx*>::const_iterator m_it_wtxOrdered;
237
238 // memory only
247 mutable bool m_is_cache_empty{true};
248 mutable bool fChangeCached;
250
252 {
253 Init();
254 }
255
256 void Init()
257 {
258 mapValue.clear();
259 vOrderForm.clear();
260 nTimeReceived = 0;
261 nTimeSmart = 0;
262 fChangeCached = false;
263 nChangeCached = 0;
264 nOrderPos = -1;
265 }
266
269
270 // Set of mempool transactions that conflict
271 // directly with the transaction, or that conflict
272 // with an ancestor transaction. This set will be
273 // empty if state is InMempool or Confirmed, but
274 // can be nonempty if state is Inactive or
275 // BlockConflicted.
276 std::set<Txid> mempool_conflicts;
277
278 // Track v3 mempool tx that spends from this tx
279 // so that we don't try to create another unconfirmed child
280 std::optional<Txid> truc_child_in_mempool;
281
282 template<typename Stream>
283 void Serialize(Stream& s) const
284 {
285 mapValue_t mapValueCopy = mapValue;
286
287 mapValueCopy["fromaccount"] = "";
288 if (nOrderPos != -1) {
289 mapValueCopy["n"] = util::ToString(nOrderPos);
290 }
291 if (nTimeSmart) {
292 mapValueCopy["timesmart"] = strprintf("%u", nTimeSmart);
293 }
294
295 std::vector<uint8_t> dummy_vector1;
296 std::vector<uint8_t> dummy_vector2;
297 bool dummy_bool = false;
298 uint32_t dummy_int = 0; // Used to be fTimeReceivedIsTxTime
300 int serializedIndex = TxStateSerializedIndex(m_state);
301 s << TX_WITH_WITNESS(tx) << serializedHash << dummy_vector1 << serializedIndex << dummy_vector2 << mapValueCopy << vOrderForm << dummy_int << nTimeReceived << dummy_bool << dummy_bool;
302 }
303
304 template<typename Stream>
305 void Unserialize(Stream& s)
306 {
307 Init();
308
309 std::vector<uint256> dummy_vector1;
310 std::vector<CMerkleTx> dummy_vector2;
311 bool dummy_bool;
312 uint32_t dummy_int; // Used to be fTimeReceivedIsTxTime
313 uint256 serialized_block_hash;
314 int serializedIndex;
315 s >> TX_WITH_WITNESS(tx) >> serialized_block_hash >> dummy_vector1 >> serializedIndex >> dummy_vector2 >> mapValue >> vOrderForm >> dummy_int >> nTimeReceived >> dummy_bool >> dummy_bool;
316
317 m_state = TxStateInterpretSerialized({serialized_block_hash, serializedIndex});
318
319 const auto it_op = mapValue.find("n");
320 nOrderPos = (it_op != mapValue.end()) ? LocaleIndependentAtoi<int64_t>(it_op->second) : -1;
321 const auto it_ts = mapValue.find("timesmart");
322 nTimeSmart = (it_ts != mapValue.end()) ? static_cast<unsigned int>(LocaleIndependentAtoi<int64_t>(it_ts->second)) : 0;
323
324 mapValue.erase("fromaccount");
325 mapValue.erase("spent");
326 mapValue.erase("n");
327 mapValue.erase("timesmart");
328 }
329
331 {
332 tx = std::move(arg);
333 }
334
337 {
340 fChangeCached = false;
341 m_is_cache_empty = true;
342 }
343
345 bool IsEquivalentTo(const CWalletTx& tx) const;
346
347 bool InMempool() const;
348
349 int64_t GetTxTime() const;
350
351 template<typename T> const T* state() const { return std::get_if<T>(&m_state); }
352 template<typename T> T* state() { return std::get_if<T>(&m_state); }
353
356 void updateState(interfaces::Chain& chain);
357
358 bool isAbandoned() const { return state<TxStateInactive>() && state<TxStateInactive>()->abandoned; }
359 bool isMempoolConflicted() const { return !mempool_conflicts.empty(); }
360 bool isBlockConflicted() const { return state<TxStateBlockConflicted>(); }
361 bool isInactive() const { return state<TxStateInactive>(); }
362 bool isUnconfirmed() const { return !isAbandoned() && !isBlockConflicted() && !isMempoolConflicted() && !isConfirmed(); }
363 bool isConfirmed() const { return state<TxStateConfirmed>(); }
364 const Txid& GetHash() const LIFETIMEBOUND { return tx->GetHash(); }
365 const Wtxid& GetWitnessHash() const LIFETIMEBOUND { return tx->GetWitnessHash(); }
366 bool IsCoinBase() const { return tx->IsCoinBase(); }
367
368private:
369 // Disable copying of CWalletTx objects to prevent bugs where instances get
370 // copied in and out of the mapWallet map, and fields are updated in the
371 // wrong copy.
372 CWalletTx(const CWalletTx&) = default;
373 CWalletTx& operator=(const CWalletTx&) = default;
374public:
375 // Instead have an explicit copy function
376 void CopyFrom(const CWalletTx&);
377};
378
380 bool operator()(const CWalletTx* a, const CWalletTx* b) const
381 {
382 return a->nOrderPos < b->nOrderPos;
383 }
384};
385
387{
388private:
391
392public:
393 WalletTXO(const CWalletTx& wtx, const CTxOut& output)
394 : m_wtx(wtx),
395 m_output(output)
396 {
397 Assume(std::ranges::find(wtx.tx->vout, output) != wtx.tx->vout.end());
398 }
399
400 const CWalletTx& GetWalletTx() const { return m_wtx; }
401
402 const CTxOut& GetTxOut() const { return m_output; }
403};
404} // namespace wallet
405
406#endif // BITCOIN_WALLET_TRANSACTION_H
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
#define LIFETIMEBOUND
Definition: attributes.h:16
#define Assert(val)
Identity function.
Definition: check.h:106
#define Assume(val)
Assume is the identity function.
Definition: check.h:118
An output of a transaction.
Definition: transaction.h:150
std::string ToString() const
Definition: uint256.cpp:21
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
Definition: chain.h:130
256-bit opaque blob.
Definition: uint256.h:196
static const uint256 ONE
Definition: uint256.h:205
static const uint256 ZERO
Definition: uint256.h:204
Legacy class used for deserializing vtxPrev for backwards compatibility.
Definition: transaction.h:176
void Unserialize(Stream &s)
Definition: transaction.h:179
A transaction with a bunch of additional info that only the owner cares about.
Definition: transaction.h:195
bool isConfirmed() const
Definition: transaction.h:363
bool isBlockConflicted() const
Definition: transaction.h:360
const Txid & GetHash() const LIFETIMEBOUND
Definition: transaction.h:364
const T * state() const
Definition: transaction.h:351
bool IsEquivalentTo(const CWalletTx &tx) const
True if only scriptSigs are different.
Definition: transaction.cpp:12
std::vector< std::pair< std::string, std::string > > vOrderForm
Definition: transaction.h:223
std::set< Txid > mempool_conflicts
Definition: transaction.h:276
mapValue_t mapValue
Key/value map with information about the transaction.
Definition: transaction.h:222
void updateState(interfaces::Chain &chain)
Update transaction state when attaching to a chain, filling in heights of conflicted and confirmed bl...
Definition: transaction.cpp:38
CAmount nChangeCached
Definition: transaction.h:249
void Serialize(Stream &s) const
Definition: transaction.h:283
int64_t nOrderPos
position in ordered transaction list
Definition: transaction.h:235
bool isUnconfirmed() const
Definition: transaction.h:362
void CopyFrom(const CWalletTx &)
Definition: transaction.cpp:59
unsigned int nTimeReceived
time received by this node
Definition: transaction.h:224
CTransactionRef tx
Definition: transaction.h:267
void Unserialize(Stream &s)
Definition: transaction.h:305
void SetTx(CTransactionRef arg)
Definition: transaction.h:330
bool isMempoolConflicted() const
Definition: transaction.h:359
bool IsCoinBase() const
Definition: transaction.h:366
CachableAmount m_amounts[AMOUNTTYPE_ENUM_ELEMENTS]
Definition: transaction.h:240
CWalletTx & operator=(const CWalletTx &)=default
bool InMempool() const
Definition: transaction.cpp:27
bool isAbandoned() const
Definition: transaction.h:358
std::optional< Txid > truc_child_in_mempool
Definition: transaction.h:280
bool isInactive() const
Definition: transaction.h:361
int64_t GetTxTime() const
Definition: transaction.cpp:32
CWalletTx(CTransactionRef tx, const TxState &state)
Definition: transaction.h:251
bool m_is_cache_empty
This flag is true if all m_amounts caches are empty.
Definition: transaction.h:247
std::multimap< int64_t, CWalletTx * >::const_iterator m_it_wtxOrdered
Definition: transaction.h:236
CWalletTx(const CWalletTx &)=default
unsigned int nTimeSmart
Stable timestamp that never changes, and reflects the order a transaction was added to the wallet.
Definition: transaction.h:234
const Wtxid & GetWitnessHash() const LIFETIMEBOUND
Definition: transaction.h:365
void MarkDirty()
make sure balances are recalculated
Definition: transaction.h:336
WalletTXO(const CWalletTx &wtx, const CTxOut &output)
Definition: transaction.h:393
const CTxOut & m_output
Definition: transaction.h:390
const CWalletTx & m_wtx
Definition: transaction.h:389
const CWalletTx & GetWalletTx() const
Definition: transaction.h:400
const CTxOut & GetTxOut() const
Definition: transaction.h:402
#define T(expected, seed, data)
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:245
std::variant< TxStateConfirmed, TxStateInMempool, TxStateInactive > SyncTxState
Subset of states transaction sync logic is implemented to handle.
Definition: transaction.h:82
std::variant< TxStateConfirmed, TxStateInMempool, TxStateBlockConflicted, TxStateInactive, TxStateUnrecognized > TxState
All possible CWalletTx states.
Definition: transaction.h:79
std::map< std::string, std::string > mapValue_t
Definition: transaction.h:167
static int TxStateSerializedIndex(const TxState &state)
Get TxState serialized block index. Inverse of TxStateInterpretSerialized.
Definition: transaction.h:112
static TxState TxStateInterpretSerialized(TxStateUnrecognized data)
Try to interpret deserialized TxStateUnrecognized data as a recognized state.
Definition: transaction.h:85
static uint256 TxStateSerializedBlockHash(const TxState &state)
Get TxState serialized block hash. Inverse of TxStateInterpretSerialized.
Definition: transaction.h:100
std::string TxStateString(const T &state)
Return TxState or SyncTxState as a string for logging or debugging.
Definition: transaction.h:125
static constexpr TransactionSerParams TX_WITH_WITNESS
Definition: transaction.h:195
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:423
Overloaded helper for std::visit.
Definition: overloaded.h:16
Cachable amount subdivided into avoid reuse and all balances.
Definition: transaction.h:134
std::optional< CAmount > m_avoid_reuse_value
Definition: transaction.h:135
std::optional< CAmount > m_all_value
Definition: transaction.h:136
bool IsCached(bool avoid_reuse)
Definition: transaction.h:159
CAmount Get(bool avoid_reuse)
Definition: transaction.h:150
void Set(bool avoid_reuse, CAmount value)
Definition: transaction.h:142
State of rejected transaction that conflicts with a confirmed block.
Definition: transaction.h:47
std::string toString() const
Definition: transaction.h:52
TxStateBlockConflicted(const uint256 &block_hash, int height)
Definition: transaction.h:51
State of transaction confirmed in a block.
Definition: transaction.h:32
std::string toString() const
Definition: transaction.h:38
TxStateConfirmed(const uint256 &block_hash, int height, int index)
Definition: transaction.h:37
State of transaction added to mempool.
Definition: transaction.h:42
std::string toString() const
Definition: transaction.h:43
State of transaction not confirmed or conflicting with a known block and not in the mempool.
Definition: transaction.h:59
std::string toString() const
Definition: transaction.h:63
TxStateInactive(bool abandoned=false)
Definition: transaction.h:62
State of transaction loaded in an unrecognized state with unexpected hash or index values.
Definition: transaction.h:70
TxStateUnrecognized(const uint256 &block_hash, int index)
Definition: transaction.h:74
std::string toString() const
Definition: transaction.h:75
bool operator()(const CWalletTx *a, const CWalletTx *b) const
Definition: transaction.h:380
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1172
is a home for public enum and struct type definitions that are used by internally by wallet code,...