Bitcoin Core 28.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/overloaded.h>
14#include <util/strencodings.h>
15#include <util/string.h>
16#include <wallet/types.h>
17
18#include <bitset>
19#include <cstdint>
20#include <map>
21#include <utility>
22#include <variant>
23#include <vector>
24
25namespace interfaces {
26class Chain;
27} // namespace interfaces
28
29namespace wallet {
35
36 explicit TxStateConfirmed(const uint256& block_hash, int height, int index) : confirmed_block_hash(block_hash), confirmed_block_height(height), position_in_block(index) {}
37 std::string toString() const { return strprintf("Confirmed (block=%s, height=%i, index=%i)", confirmed_block_hash.ToString(), confirmed_block_height, position_in_block); }
38};
39
42 std::string toString() const { return strprintf("InMempool"); }
43};
44
49
50 explicit TxStateBlockConflicted(const uint256& block_hash, int height) : conflicting_block_hash(block_hash), conflicting_block_height(height) {}
51 std::string toString() const { return strprintf("BlockConflicted (block=%s, height=%i)", conflicting_block_hash.ToString(), conflicting_block_height); }
52};
53
60
61 explicit TxStateInactive(bool abandoned = false) : abandoned(abandoned) {}
62 std::string toString() const { return strprintf("Inactive (abandoned=%i)", abandoned); }
63};
64
71 int index;
72
74 std::string toString() const { return strprintf("Unrecognized (block=%s, index=%i)", block_hash.ToString(), index); }
75};
76
78using TxState = std::variant<TxStateConfirmed, TxStateInMempool, TxStateBlockConflicted, TxStateInactive, TxStateUnrecognized>;
79
81using SyncTxState = std::variant<TxStateConfirmed, TxStateInMempool, TxStateInactive>;
82
85{
86 if (data.block_hash == uint256::ZERO) {
87 if (data.index == 0) return TxStateInactive{};
88 } else if (data.block_hash == uint256::ONE) {
89 if (data.index == -1) return TxStateInactive{/*abandoned=*/true};
90 } else if (data.index >= 0) {
91 return TxStateConfirmed{data.block_hash, /*height=*/-1, data.index};
92 } else if (data.index == -1) {
93 return TxStateBlockConflicted{data.block_hash, /*height=*/-1};
94 }
95 return data;
96}
97
99static inline uint256 TxStateSerializedBlockHash(const TxState& state)
100{
101 return std::visit(util::Overloaded{
102 [](const TxStateInactive& inactive) { return inactive.abandoned ? uint256::ONE : uint256::ZERO; },
103 [](const TxStateInMempool& in_mempool) { return uint256::ZERO; },
104 [](const TxStateConfirmed& confirmed) { return confirmed.confirmed_block_hash; },
105 [](const TxStateBlockConflicted& conflicted) { return conflicted.conflicting_block_hash; },
106 [](const TxStateUnrecognized& unrecognized) { return unrecognized.block_hash; }
107 }, state);
108}
109
111static inline int TxStateSerializedIndex(const TxState& state)
112{
113 return std::visit(util::Overloaded{
114 [](const TxStateInactive& inactive) { return inactive.abandoned ? -1 : 0; },
115 [](const TxStateInMempool& in_mempool) { return 0; },
116 [](const TxStateConfirmed& confirmed) { return confirmed.position_in_block; },
117 [](const TxStateBlockConflicted& conflicted) { return -1; },
118 [](const TxStateUnrecognized& unrecognized) { return unrecognized.index; }
119 }, state);
120}
121
123template<typename T>
124std::string TxStateString(const T& state)
125{
126 return std::visit([](const auto& s) { return s.toString(); }, state);
127}
128
133{
134 // NO and ALL are never (supposed to be) cached
135 std::bitset<ISMINE_ENUM_ELEMENTS> m_cached;
137 inline void Reset()
138 {
139 m_cached.reset();
140 }
141 void Set(isminefilter filter, CAmount value)
142 {
143 m_cached.set(filter);
144 m_value[filter] = value;
145 }
146};
147
148
149typedef std::map<std::string, std::string> mapValue_t;
150
151
158{
159public:
160 template<typename Stream>
161 void Unserialize(Stream& s)
162 {
164 uint256 hashBlock;
165 std::vector<uint256> vMerkleBranch;
166 int nIndex;
167
168 s >> TX_WITH_WITNESS(tx) >> hashBlock >> vMerkleBranch >> nIndex;
169 }
170};
171
177{
178public:
205 std::vector<std::pair<std::string, std::string> > vOrderForm;
207 unsigned int nTimeReceived;
217 unsigned int nTimeSmart;
224 int64_t nOrderPos;
225 std::multimap<int64_t, CWalletTx*>::const_iterator m_it_wtxOrdered;
226
227 // memory only
236 mutable bool m_is_cache_empty{true};
237 mutable bool fChangeCached;
239
241 {
242 Init();
243 }
244
245 void Init()
246 {
247 mapValue.clear();
248 vOrderForm.clear();
249 fTimeReceivedIsTxTime = false;
250 nTimeReceived = 0;
251 nTimeSmart = 0;
252 fFromMe = false;
253 fChangeCached = false;
254 nChangeCached = 0;
255 nOrderPos = -1;
256 }
257
260
261 // Set of mempool transactions that conflict
262 // directly with the transaction, or that conflict
263 // with an ancestor transaction. This set will be
264 // empty if state is InMempool or Confirmed, but
265 // can be nonempty if state is Inactive or
266 // BlockConflicted.
267 std::set<Txid> mempool_conflicts;
268
269 template<typename Stream>
270 void Serialize(Stream& s) const
271 {
272 mapValue_t mapValueCopy = mapValue;
273
274 mapValueCopy["fromaccount"] = "";
275 if (nOrderPos != -1) {
276 mapValueCopy["n"] = util::ToString(nOrderPos);
277 }
278 if (nTimeSmart) {
279 mapValueCopy["timesmart"] = strprintf("%u", nTimeSmart);
280 }
281
282 std::vector<uint8_t> dummy_vector1;
283 std::vector<uint8_t> dummy_vector2;
284 bool dummy_bool = false;
286 int serializedIndex = TxStateSerializedIndex(m_state);
287 s << TX_WITH_WITNESS(tx) << serializedHash << dummy_vector1 << serializedIndex << dummy_vector2 << mapValueCopy << vOrderForm << fTimeReceivedIsTxTime << nTimeReceived << fFromMe << dummy_bool;
288 }
289
290 template<typename Stream>
291 void Unserialize(Stream& s)
292 {
293 Init();
294
295 std::vector<uint256> dummy_vector1;
296 std::vector<CMerkleTx> dummy_vector2;
297 bool dummy_bool;
298 uint256 serialized_block_hash;
299 int serializedIndex;
300 s >> TX_WITH_WITNESS(tx) >> serialized_block_hash >> dummy_vector1 >> serializedIndex >> dummy_vector2 >> mapValue >> vOrderForm >> fTimeReceivedIsTxTime >> nTimeReceived >> fFromMe >> dummy_bool;
301
302 m_state = TxStateInterpretSerialized({serialized_block_hash, serializedIndex});
303
304 const auto it_op = mapValue.find("n");
305 nOrderPos = (it_op != mapValue.end()) ? LocaleIndependentAtoi<int64_t>(it_op->second) : -1;
306 const auto it_ts = mapValue.find("timesmart");
307 nTimeSmart = (it_ts != mapValue.end()) ? static_cast<unsigned int>(LocaleIndependentAtoi<int64_t>(it_ts->second)) : 0;
308
309 mapValue.erase("fromaccount");
310 mapValue.erase("spent");
311 mapValue.erase("n");
312 mapValue.erase("timesmart");
313 }
314
316 {
317 tx = std::move(arg);
318 }
319
322 {
327 fChangeCached = false;
328 m_is_cache_empty = true;
329 }
330
332 bool IsEquivalentTo(const CWalletTx& tx) const;
333
334 bool InMempool() const;
335
336 int64_t GetTxTime() const;
337
338 template<typename T> const T* state() const { return std::get_if<T>(&m_state); }
339 template<typename T> T* state() { return std::get_if<T>(&m_state); }
340
343 void updateState(interfaces::Chain& chain);
344
345 bool isAbandoned() const { return state<TxStateInactive>() && state<TxStateInactive>()->abandoned; }
346 bool isMempoolConflicted() const { return !mempool_conflicts.empty(); }
347 bool isBlockConflicted() const { return state<TxStateBlockConflicted>(); }
348 bool isInactive() const { return state<TxStateInactive>(); }
349 bool isUnconfirmed() const { return !isAbandoned() && !isBlockConflicted() && !isMempoolConflicted() && !isConfirmed(); }
350 bool isConfirmed() const { return state<TxStateConfirmed>(); }
351 const Txid& GetHash() const LIFETIMEBOUND { return tx->GetHash(); }
352 const Wtxid& GetWitnessHash() const LIFETIMEBOUND { return tx->GetWitnessHash(); }
353 bool IsCoinBase() const { return tx->IsCoinBase(); }
354
355private:
356 // Disable copying of CWalletTx objects to prevent bugs where instances get
357 // copied in and out of the mapWallet map, and fields are updated in the
358 // wrong copy.
359 CWalletTx(const CWalletTx&) = default;
360 CWalletTx& operator=(const CWalletTx&) = default;
361public:
362 // Instead have an explicit copy function
363 void CopyFrom(const CWalletTx&);
364};
365
367 bool operator()(const CWalletTx* a, const CWalletTx* b) const
368 {
369 return a->nOrderPos < b->nOrderPos;
370 }
371};
372} // namespace wallet
373
374#endif // BITCOIN_WALLET_TRANSACTION_H
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
#define LIFETIMEBOUND
Definition: attributes.h:16
std::string ToString() const
Definition: uint256.cpp:47
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
Definition: chain.h:129
256-bit opaque blob.
Definition: uint256.h:190
static const uint256 ONE
Definition: uint256.h:199
static const uint256 ZERO
Definition: uint256.h:198
Legacy class used for deserializing vtxPrev for backwards compatibility.
Definition: transaction.h:158
void Unserialize(Stream &s)
Definition: transaction.h:161
A transaction with a bunch of additional info that only the owner cares about.
Definition: transaction.h:177
bool isConfirmed() const
Definition: transaction.h:350
bool isBlockConflicted() const
Definition: transaction.h:347
const Txid & GetHash() const LIFETIMEBOUND
Definition: transaction.h:351
const T * state() const
Definition: transaction.h:338
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:205
std::set< Txid > mempool_conflicts
Definition: transaction.h:267
mapValue_t mapValue
Key/value map with information about the transaction.
Definition: transaction.h:204
void updateState(interfaces::Chain &chain)
Update transaction state when attaching to a chain, filling in heights of conflicted and confirmed bl...
Definition: transaction.cpp:32
CAmount nChangeCached
Definition: transaction.h:238
void Serialize(Stream &s) const
Definition: transaction.h:270
int64_t nOrderPos
position in ordered transaction list
Definition: transaction.h:224
bool isUnconfirmed() const
Definition: transaction.h:349
void CopyFrom(const CWalletTx &)
Definition: transaction.cpp:53
bool fFromMe
From me flag is set to 1 for transactions that were created by the wallet on this bitcoin node,...
Definition: transaction.h:223
unsigned int nTimeReceived
time received by this node
Definition: transaction.h:207
CTransactionRef tx
Definition: transaction.h:258
void Unserialize(Stream &s)
Definition: transaction.h:291
void SetTx(CTransactionRef arg)
Definition: transaction.h:315
bool isMempoolConflicted() const
Definition: transaction.h:346
bool IsCoinBase() const
Definition: transaction.h:353
unsigned int fTimeReceivedIsTxTime
Definition: transaction.h:206
CachableAmount m_amounts[AMOUNTTYPE_ENUM_ELEMENTS]
Definition: transaction.h:229
CWalletTx & operator=(const CWalletTx &)=default
bool InMempool() const
Definition: transaction.cpp:21
bool isAbandoned() const
Definition: transaction.h:345
bool isInactive() const
Definition: transaction.h:348
int64_t GetTxTime() const
Definition: transaction.cpp:26
CWalletTx(CTransactionRef tx, const TxState &state)
Definition: transaction.h:240
bool m_is_cache_empty
This flag is true if all m_amounts caches are empty.
Definition: transaction.h:236
std::multimap< int64_t, CWalletTx * >::const_iterator m_it_wtxOrdered
Definition: transaction.h:225
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:217
const Wtxid & GetWitnessHash() const LIFETIMEBOUND
Definition: transaction.h:352
void MarkDirty()
make sure balances are recalculated
Definition: transaction.h:321
#define T(expected, seed, data)
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:233
std::variant< TxStateConfirmed, TxStateInMempool, TxStateInactive > SyncTxState
Subset of states transaction sync logic is implemented to handle.
Definition: transaction.h:81
std::variant< TxStateConfirmed, TxStateInMempool, TxStateBlockConflicted, TxStateInactive, TxStateUnrecognized > TxState
All possible CWalletTx states.
Definition: transaction.h:78
std::map< std::string, std::string > mapValue_t
Definition: transaction.h:149
static int TxStateSerializedIndex(const TxState &state)
Get TxState serialized block index. Inverse of TxStateInterpretSerialized.
Definition: transaction.h:111
std::underlying_type< isminetype >::type isminefilter
used for bitflags of isminetype
Definition: wallet.h:48
static TxState TxStateInterpretSerialized(TxStateUnrecognized data)
Try to interpret deserialized TxStateUnrecognized data as a recognized state.
Definition: transaction.h:84
@ ISMINE_ENUM_ELEMENTS
Definition: types.h:48
static uint256 TxStateSerializedBlockHash(const TxState &state)
Get TxState serialized block hash. Inverse of TxStateInterpretSerialized.
Definition: transaction.h:99
std::string TxStateString(const T &state)
Return TxState or SyncTxState as a string for logging or debugging.
Definition: transaction.h:124
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 watchonly and spendable parts.
Definition: transaction.h:133
void Set(isminefilter filter, CAmount value)
Definition: transaction.h:141
CAmount m_value[ISMINE_ENUM_ELEMENTS]
Definition: transaction.h:136
std::bitset< ISMINE_ENUM_ELEMENTS > m_cached
Definition: transaction.h:135
State of rejected transaction that conflicts with a confirmed block.
Definition: transaction.h:46
std::string toString() const
Definition: transaction.h:51
TxStateBlockConflicted(const uint256 &block_hash, int height)
Definition: transaction.h:50
State of transaction confirmed in a block.
Definition: transaction.h:31
std::string toString() const
Definition: transaction.h:37
TxStateConfirmed(const uint256 &block_hash, int height, int index)
Definition: transaction.h:36
State of transaction added to mempool.
Definition: transaction.h:41
std::string toString() const
Definition: transaction.h:42
State of transaction not confirmed or conflicting with a known block and not in the mempool.
Definition: transaction.h:58
std::string toString() const
Definition: transaction.h:62
TxStateInactive(bool abandoned=false)
Definition: transaction.h:61
State of transaction loaded in an unrecognized state with unexpected hash or index values.
Definition: transaction.h:69
TxStateUnrecognized(const uint256 &block_hash, int index)
Definition: transaction.h:73
std::string toString() const
Definition: transaction.h:74
bool operator()(const CWalletTx *a, const CWalletTx *b) const
Definition: transaction.h:367
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1165
is a home for public enum and struct type definitions that are used by internally by wallet code,...