Bitcoin Core  27.1.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>
10 #include <primitives/transaction.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 
25 namespace interfaces {
26 class Chain;
27 } // namespace interfaces
28 
29 namespace 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 TxStateConflicted(const uint256& block_hash, int height) : conflicting_block_hash(block_hash), conflicting_block_height(height) {}
51  std::string toString() const { return strprintf("Conflicted (block=%s, height=%i)", conflicting_block_hash.ToString(), conflicting_block_height); }
52 };
53 
59  bool abandoned;
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 
78 using TxState = std::variant<TxStateConfirmed, TxStateInMempool, TxStateConflicted, TxStateInactive, TxStateUnrecognized>;
79 
81 using 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 TxStateConflicted{data.block_hash, /*height=*/-1};
94  }
95  return data;
96 }
97 
99 static 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 TxStateConflicted& conflicted) { return conflicted.conflicting_block_hash; },
106  [](const TxStateUnrecognized& unrecognized) { return unrecognized.block_hash; }
107  }, state);
108 }
109 
111 static 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 TxStateConflicted& conflicted) { return -1; },
118  [](const TxStateUnrecognized& unrecognized) { return unrecognized.index; }
119  }, state);
120 }
121 
123 template<typename T>
124 std::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 
149 typedef std::map<std::string, std::string> mapValue_t;
150 
151 
158 {
159 public:
160  template<typename Stream>
161  void Unserialize(Stream& s)
162  {
163  CTransactionRef tx;
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 {
178 public:
205  std::vector<std::pair<std::string, std::string> > vOrderForm;
206  unsigned int fTimeReceivedIsTxTime;
207  unsigned int nTimeReceived;
208 
217  unsigned int nTimeSmart;
223  bool fFromMe;
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  template<typename Stream>
262  void Serialize(Stream& s) const
263  {
264  mapValue_t mapValueCopy = mapValue;
265 
266  mapValueCopy["fromaccount"] = "";
267  if (nOrderPos != -1) {
268  mapValueCopy["n"] = ToString(nOrderPos);
269  }
270  if (nTimeSmart) {
271  mapValueCopy["timesmart"] = strprintf("%u", nTimeSmart);
272  }
273 
274  std::vector<uint8_t> dummy_vector1;
275  std::vector<uint8_t> dummy_vector2;
276  bool dummy_bool = false;
277  uint256 serializedHash = TxStateSerializedBlockHash(m_state);
278  int serializedIndex = TxStateSerializedIndex(m_state);
279  s << TX_WITH_WITNESS(tx) << serializedHash << dummy_vector1 << serializedIndex << dummy_vector2 << mapValueCopy << vOrderForm << fTimeReceivedIsTxTime << nTimeReceived << fFromMe << dummy_bool;
280  }
281 
282  template<typename Stream>
283  void Unserialize(Stream& s)
284  {
285  Init();
286 
287  std::vector<uint256> dummy_vector1;
288  std::vector<CMerkleTx> dummy_vector2;
289  bool dummy_bool;
290  uint256 serialized_block_hash;
291  int serializedIndex;
292  s >> TX_WITH_WITNESS(tx) >> serialized_block_hash >> dummy_vector1 >> serializedIndex >> dummy_vector2 >> mapValue >> vOrderForm >> fTimeReceivedIsTxTime >> nTimeReceived >> fFromMe >> dummy_bool;
293 
294  m_state = TxStateInterpretSerialized({serialized_block_hash, serializedIndex});
295 
296  const auto it_op = mapValue.find("n");
297  nOrderPos = (it_op != mapValue.end()) ? LocaleIndependentAtoi<int64_t>(it_op->second) : -1;
298  const auto it_ts = mapValue.find("timesmart");
299  nTimeSmart = (it_ts != mapValue.end()) ? static_cast<unsigned int>(LocaleIndependentAtoi<int64_t>(it_ts->second)) : 0;
300 
301  mapValue.erase("fromaccount");
302  mapValue.erase("spent");
303  mapValue.erase("n");
304  mapValue.erase("timesmart");
305  }
306 
308  {
309  tx = std::move(arg);
310  }
311 
313  void MarkDirty()
314  {
315  m_amounts[DEBIT].Reset();
319  fChangeCached = false;
320  m_is_cache_empty = true;
321  }
322 
324  bool IsEquivalentTo(const CWalletTx& tx) const;
325 
326  bool InMempool() const;
327 
328  int64_t GetTxTime() const;
329 
330  template<typename T> const T* state() const { return std::get_if<T>(&m_state); }
331  template<typename T> T* state() { return std::get_if<T>(&m_state); }
332 
335  void updateState(interfaces::Chain& chain);
336 
337  bool isAbandoned() const { return state<TxStateInactive>() && state<TxStateInactive>()->abandoned; }
338  bool isConflicted() const { return state<TxStateConflicted>(); }
339  bool isInactive() const { return state<TxStateInactive>(); }
340  bool isUnconfirmed() const { return !isAbandoned() && !isConflicted() && !isConfirmed(); }
341  bool isConfirmed() const { return state<TxStateConfirmed>(); }
342  const Txid& GetHash() const LIFETIMEBOUND { return tx->GetHash(); }
343  const Wtxid& GetWitnessHash() const LIFETIMEBOUND { return tx->GetWitnessHash(); }
344  bool IsCoinBase() const { return tx->IsCoinBase(); }
345 
346 private:
347  // Disable copying of CWalletTx objects to prevent bugs where instances get
348  // copied in and out of the mapWallet map, and fields are updated in the
349  // wrong copy.
350  CWalletTx(const CWalletTx&) = default;
351  CWalletTx& operator=(const CWalletTx&) = default;
352 public:
353  // Instead have an explicit copy function
354  void CopyFrom(const CWalletTx&);
355 };
356 
358  bool operator()(const CWalletTx* a, const CWalletTx* b) const
359  {
360  return a->nOrderPos < b->nOrderPos;
361  }
362 };
363 } // namespace wallet
364 
365 #endif // BITCOIN_WALLET_TRANSACTION_H
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:423
State of transaction added to mempool.
Definition: transaction.h:41
static const uint256 ONE
Definition: uint256.h:112
void Serialize(Stream &s) const
Definition: transaction.h:262
mapValue_t mapValue
Key/value map with information about the transaction.
Definition: transaction.h:204
void MarkDirty()
make sure balances are recalculated
Definition: transaction.h:313
const T * state() const
Definition: transaction.h:330
const Wtxid & GetWitnessHash() const LIFETIMEBOUND
Definition: transaction.h:343
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1162
std::map< std::string, std::string > mapValue_t
Definition: transaction.h:149
std::vector< std::pair< std::string, std::string > > vOrderForm
Definition: transaction.h:205
CWalletTx(CTransactionRef tx, const TxState &state)
Definition: transaction.h:240
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
bool m_is_cache_empty
This flag is true if all m_amounts caches are empty.
Definition: transaction.h:236
std::string TxStateString(const T &state)
Return TxState or SyncTxState as a string for logging or debugging.
Definition: transaction.h:124
State of transaction not confirmed or conflicting with a known block and not in the mempool...
Definition: transaction.h:58
TxStateConfirmed(const uint256 &block_hash, int height, int index)
Definition: transaction.h:36
std::string toString() const
Definition: transaction.h:42
std::variant< TxStateConfirmed, TxStateInMempool, TxStateInactive > SyncTxState
Subset of states transaction sync logic is implemented to handle.
Definition: transaction.h:81
TxStateConflicted(const uint256 &block_hash, int height)
Definition: transaction.h:50
bool isConflicted() const
Definition: transaction.h:338
State of transaction confirmed in a block.
Definition: transaction.h:31
bool IsEquivalentTo(const CWalletTx &tx) const
True if only scriptSigs are different.
Definition: transaction.cpp:12
std::string toString() const
Definition: transaction.h:62
CAmount m_value[ISMINE_ENUM_ELEMENTS]
Definition: transaction.h:136
bool isAbandoned() const
Definition: transaction.h:337
int64_t GetTxTime() const
Definition: transaction.cpp:26
State of transaction loaded in an unrecognized state with unexpected hash or index values...
Definition: transaction.h:69
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
A transaction with a bunch of additional info that only the owner cares about.
Definition: transaction.h:176
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:109
TxStateUnrecognized(const uint256 &block_hash, int index)
Definition: transaction.h:73
std::underlying_type< isminetype >::type isminefilter
used for bitflags of isminetype
Definition: wallet.h:43
std::bitset< ISMINE_ENUM_ELEMENTS > m_cached
Definition: transaction.h:135
#define LIFETIMEBOUND
Definition: attributes.h:16
std::multimap< int64_t, CWalletTx * >::const_iterator m_it_wtxOrdered
Definition: transaction.h:225
static TxState TxStateInterpretSerialized(TxStateUnrecognized data)
Try to interpret deserialized TxStateUnrecognized data as a recognized state.
Definition: transaction.h:84
static const uint256 ZERO
Definition: uint256.h:111
void Unserialize(Stream &s)
Definition: transaction.h:283
static int TxStateSerializedIndex(const TxState &state)
Get TxState serialized block index. Inverse of TxStateInterpretSerialized.
Definition: transaction.h:111
std::string toString() const
Definition: transaction.h:51
std::string toString() const
Definition: transaction.h:37
std::string ToString() const
Definition: uint256.cpp:55
void CopyFrom(const CWalletTx &)
Definition: transaction.cpp:53
static uint256 TxStateSerializedBlockHash(const TxState &state)
Get TxState serialized block hash. Inverse of TxStateInterpretSerialized.
Definition: transaction.h:99
Cachable amount subdivided into watchonly and spendable parts.
Definition: transaction.h:132
TxStateInactive(bool abandoned=false)
Definition: transaction.h:61
256-bit opaque blob.
Definition: uint256.h:106
const Txid & GetHash() const LIFETIMEBOUND
Definition: transaction.h:342
unsigned int fTimeReceivedIsTxTime
Definition: transaction.h:206
State of rejected transaction that conflicts with a confirmed block.
Definition: transaction.h:46
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
Definition: chain.h:123
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
bool InMempool() const
Definition: transaction.cpp:21
unsigned int nTimeSmart
Stable timestamp that never changes, and reflects the order a transaction was added to the wallet...
Definition: transaction.h:217
void Unserialize(Stream &s)
Definition: transaction.h:161
std::string toString() const
Definition: transaction.h:74
CachableAmount m_amounts[AMOUNTTYPE_ENUM_ELEMENTS]
Definition: transaction.h:229
bool IsCoinBase() const
Definition: transaction.h:344
unsigned int nTimeReceived
time received by this node
Definition: transaction.h:207
int64_t nOrderPos
position in ordered transaction list
Definition: transaction.h:224
void Set(isminefilter filter, CAmount value)
Definition: transaction.h:141
bool operator()(const CWalletTx *a, const CWalletTx *b) const
Definition: transaction.h:358
CAmount nChangeCached
Definition: transaction.h:238
CWalletTx & operator=(const CWalletTx &)=default
Overloaded helper for std::visit.
Definition: overloaded.h:16
bool isInactive() const
Definition: transaction.h:339
void SetTx(CTransactionRef arg)
Definition: transaction.h:307
#define T(expected, seed, data)
CTransactionRef tx
Definition: transaction.h:258
bool isConfirmed() const
Definition: transaction.h:341
std::variant< TxStateConfirmed, TxStateInMempool, TxStateConflicted, TxStateInactive, TxStateUnrecognized > TxState
All possible CWalletTx states.
Definition: transaction.h:78
static constexpr TransactionSerParams TX_WITH_WITNESS
Definition: transaction.h:195
bool isUnconfirmed() const
Definition: transaction.h:340
Legacy class used for deserializing vtxPrev for backwards compatibility.
Definition: transaction.h:157