Bitcoin Core  24.99.0
P2P Digital Currency
transaction.h
Go to the documentation of this file.
1 // Copyright (c) 2021 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 <consensus/amount.h>
10 #include <serialize.h>
11 #include <wallet/ismine.h>
12 #include <threadsafety.h>
13 #include <tinyformat.h>
14 #include <util/overloaded.h>
15 #include <util/strencodings.h>
16 #include <util/string.h>
17 
18 #include <list>
19 #include <variant>
20 #include <vector>
21 
22 namespace wallet {
28 
29  explicit TxStateConfirmed(const uint256& block_hash, int height, int index) : confirmed_block_hash(block_hash), confirmed_block_height(height), position_in_block(index) {}
30 };
31 
34 };
35 
40 
41  explicit TxStateConflicted(const uint256& block_hash, int height) : conflicting_block_hash(block_hash), conflicting_block_height(height) {}
42 };
43 
49  bool abandoned;
50 
51  explicit TxStateInactive(bool abandoned = false) : abandoned(abandoned) {}
52 };
53 
60  int index;
61 
63 };
64 
66 using TxState = std::variant<TxStateConfirmed, TxStateInMempool, TxStateConflicted, TxStateInactive, TxStateUnrecognized>;
67 
69 using SyncTxState = std::variant<TxStateConfirmed, TxStateInMempool, TxStateInactive>;
70 
73 {
74  if (data.block_hash == uint256::ZERO) {
75  if (data.index == 0) return TxStateInactive{};
76  } else if (data.block_hash == uint256::ONE) {
77  if (data.index == -1) return TxStateInactive{/*abandoned=*/true};
78  } else if (data.index >= 0) {
79  return TxStateConfirmed{data.block_hash, /*height=*/-1, data.index};
80  } else if (data.index == -1) {
81  return TxStateConflicted{data.block_hash, /*height=*/-1};
82  }
83  return data;
84 }
85 
87 static inline uint256 TxStateSerializedBlockHash(const TxState& state)
88 {
89  return std::visit(util::Overloaded{
90  [](const TxStateInactive& inactive) { return inactive.abandoned ? uint256::ONE : uint256::ZERO; },
91  [](const TxStateInMempool& in_mempool) { return uint256::ZERO; },
92  [](const TxStateConfirmed& confirmed) { return confirmed.confirmed_block_hash; },
93  [](const TxStateConflicted& conflicted) { return conflicted.conflicting_block_hash; },
94  [](const TxStateUnrecognized& unrecognized) { return unrecognized.block_hash; }
95  }, state);
96 }
97 
99 static inline int TxStateSerializedIndex(const TxState& state)
100 {
101  return std::visit(util::Overloaded{
102  [](const TxStateInactive& inactive) { return inactive.abandoned ? -1 : 0; },
103  [](const TxStateInMempool& in_mempool) { return 0; },
104  [](const TxStateConfirmed& confirmed) { return confirmed.position_in_block; },
105  [](const TxStateConflicted& conflicted) { return -1; },
106  [](const TxStateUnrecognized& unrecognized) { return unrecognized.index; }
107  }, state);
108 }
109 
110 
111 typedef std::map<std::string, std::string> mapValue_t;
112 
119 {
120 public:
121  template<typename Stream>
122  void Unserialize(Stream& s)
123  {
124  CTransactionRef tx;
125  uint256 hashBlock;
126  std::vector<uint256> vMerkleBranch;
127  int nIndex;
128 
129  s >> tx >> hashBlock >> vMerkleBranch >> nIndex;
130  }
131 };
132 
138 {
139 public:
166  std::vector<std::pair<std::string, std::string> > vOrderForm;
167  unsigned int fTimeReceivedIsTxTime;
168  unsigned int nTimeReceived;
178  unsigned int nTimeSmart;
184  bool fFromMe;
185  int64_t nOrderPos;
186  std::multimap<int64_t, CWalletTx*>::const_iterator m_it_wtxOrdered;
187 
188  // memory only
197  mutable bool m_is_cache_empty{true};
198  mutable bool fChangeCached;
200 
202  {
203  Init();
204  }
205 
206  void Init()
207  {
208  mapValue.clear();
209  vOrderForm.clear();
210  fTimeReceivedIsTxTime = false;
211  nTimeReceived = 0;
212  nTimeSmart = 0;
213  fFromMe = false;
214  fChangeCached = false;
215  nChangeCached = 0;
216  nOrderPos = -1;
217  }
218 
221 
222  template<typename Stream>
223  void Serialize(Stream& s) const
224  {
225  mapValue_t mapValueCopy = mapValue;
226 
227  mapValueCopy["fromaccount"] = "";
228  if (nOrderPos != -1) {
229  mapValueCopy["n"] = ToString(nOrderPos);
230  }
231  if (nTimeSmart) {
232  mapValueCopy["timesmart"] = strprintf("%u", nTimeSmart);
233  }
234 
235  std::vector<uint8_t> dummy_vector1;
236  std::vector<uint8_t> dummy_vector2;
237  bool dummy_bool = false;
238  uint256 serializedHash = TxStateSerializedBlockHash(m_state);
239  int serializedIndex = TxStateSerializedIndex(m_state);
240  s << tx << serializedHash << dummy_vector1 << serializedIndex << dummy_vector2 << mapValueCopy << vOrderForm << fTimeReceivedIsTxTime << nTimeReceived << fFromMe << dummy_bool;
241  }
242 
243  template<typename Stream>
244  void Unserialize(Stream& s)
245  {
246  Init();
247 
248  std::vector<uint256> dummy_vector1;
249  std::vector<CMerkleTx> dummy_vector2;
250  bool dummy_bool;
251  uint256 serialized_block_hash;
252  int serializedIndex;
253  s >> tx >> serialized_block_hash >> dummy_vector1 >> serializedIndex >> dummy_vector2 >> mapValue >> vOrderForm >> fTimeReceivedIsTxTime >> nTimeReceived >> fFromMe >> dummy_bool;
254 
255  m_state = TxStateInterpretSerialized({serialized_block_hash, serializedIndex});
256 
257  const auto it_op = mapValue.find("n");
258  nOrderPos = (it_op != mapValue.end()) ? LocaleIndependentAtoi<int64_t>(it_op->second) : -1;
259  const auto it_ts = mapValue.find("timesmart");
260  nTimeSmart = (it_ts != mapValue.end()) ? static_cast<unsigned int>(LocaleIndependentAtoi<int64_t>(it_ts->second)) : 0;
261 
262  mapValue.erase("fromaccount");
263  mapValue.erase("spent");
264  mapValue.erase("n");
265  mapValue.erase("timesmart");
266  }
267 
269  {
270  tx = std::move(arg);
271  }
272 
274  void MarkDirty()
275  {
276  m_amounts[DEBIT].Reset();
280  fChangeCached = false;
281  m_is_cache_empty = true;
282  }
283 
285  bool IsEquivalentTo(const CWalletTx& tx) const;
286 
287  bool InMempool() const;
288 
289  int64_t GetTxTime() const;
290 
291  template<typename T> const T* state() const { return std::get_if<T>(&m_state); }
292  template<typename T> T* state() { return std::get_if<T>(&m_state); }
293 
294  bool isAbandoned() const { return state<TxStateInactive>() && state<TxStateInactive>()->abandoned; }
295  bool isConflicted() const { return state<TxStateConflicted>(); }
296  bool isUnconfirmed() const { return !isAbandoned() && !isConflicted() && !isConfirmed(); }
297  bool isConfirmed() const { return state<TxStateConfirmed>(); }
298  const uint256& GetHash() const { return tx->GetHash(); }
299  const uint256& GetWitnessHash() const { return tx->GetWitnessHash(); }
300  bool IsCoinBase() const { return tx->IsCoinBase(); }
301 
302  // Disable copying of CWalletTx objects to prevent bugs where instances get
303  // copied in and out of the mapWallet map, and fields are updated in the
304  // wrong copy.
305  CWalletTx(CWalletTx const &) = delete;
306  void operator=(CWalletTx const &x) = delete;
307 };
308 
310  bool operator()(const CWalletTx* a, const CWalletTx* b) const
311  {
312  return a->nOrderPos < b->nOrderPos;
313  }
314 };
315 } // namespace wallet
316 
317 #endif // BITCOIN_WALLET_TRANSACTION_H
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
256-bit opaque blob.
Definition: uint256.h:119
static const uint256 ONE
Definition: uint256.h:125
static const uint256 ZERO
Definition: uint256.h:124
Legacy class used for deserializing vtxPrev for backwards compatibility.
Definition: transaction.h:119
void Unserialize(Stream &s)
Definition: transaction.h:122
A transaction with a bunch of additional info that only the owner cares about.
Definition: transaction.h:138
bool isConfirmed() const
Definition: transaction.h:297
bool IsEquivalentTo(const CWalletTx &tx) const
True if only scriptSigs are different.
Definition: transaction.cpp:8
const T * state() const
Definition: transaction.h:291
std::vector< std::pair< std::string, std::string > > vOrderForm
Definition: transaction.h:166
mapValue_t mapValue
Key/value map with information about the transaction.
Definition: transaction.h:165
CAmount nChangeCached
Definition: transaction.h:199
void Serialize(Stream &s) const
Definition: transaction.h:223
int64_t nOrderPos
position in ordered transaction list
Definition: transaction.h:185
bool isUnconfirmed() const
Definition: transaction.h:296
bool fFromMe
From me flag is set to 1 for transactions that were created by the wallet on this bitcoin node,...
Definition: transaction.h:184
unsigned int nTimeReceived
time received by this node
Definition: transaction.h:168
CTransactionRef tx
Definition: transaction.h:219
bool isConflicted() const
Definition: transaction.h:295
void Unserialize(Stream &s)
Definition: transaction.h:244
void SetTx(CTransactionRef arg)
Definition: transaction.h:268
bool IsCoinBase() const
Definition: transaction.h:300
void operator=(CWalletTx const &x)=delete
unsigned int fTimeReceivedIsTxTime
Definition: transaction.h:167
CachableAmount m_amounts[AMOUNTTYPE_ENUM_ELEMENTS]
Definition: transaction.h:190
bool InMempool() const
Definition: transaction.cpp:17
bool isAbandoned() const
Definition: transaction.h:294
const uint256 & GetHash() const
Definition: transaction.h:298
const uint256 & GetWitnessHash() const
Definition: transaction.h:299
std::multimap< int64_t, CWalletTx * >::const_iterator m_it_wtxOrdered
Definition: transaction.h:186
int64_t GetTxTime() const
Definition: transaction.cpp:22
CWalletTx(CTransactionRef tx, const TxState &state)
Definition: transaction.h:201
CWalletTx(CWalletTx const &)=delete
bool m_is_cache_empty
This flag is true if all m_amounts caches are empty.
Definition: transaction.h:197
unsigned int nTimeSmart
Stable timestamp that never changes, and reflects the order a transaction was added to the wallet.
Definition: transaction.h:178
void MarkDirty()
make sure balances are recalculated
Definition: transaction.h:274
#define T(expected, seed, data)
Definition: node.h:39
std::variant< TxStateConfirmed, TxStateInMempool, TxStateInactive > SyncTxState
Subset of states transaction sync logic is implemented to handle.
Definition: transaction.h:69
std::map< std::string, std::string > mapValue_t
Definition: transaction.h:111
static int TxStateSerializedIndex(const TxState &state)
Get TxState serialized block index. Inverse of TxStateInterpretSerialized.
Definition: transaction.h:99
static TxState TxStateInterpretSerialized(TxStateUnrecognized data)
Try to interpret deserialized TxStateUnrecognized data as a recognized state.
Definition: transaction.h:72
static uint256 TxStateSerializedBlockHash(const TxState &state)
Get TxState serialized block hash. Inverse of TxStateInterpretSerialized.
Definition: transaction.h:87
std::variant< TxStateConfirmed, TxStateInMempool, TxStateConflicted, TxStateInactive, TxStateUnrecognized > TxState
All possible CWalletTx states.
Definition: transaction.h:66
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:414
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:109
Overloaded helper for std::visit.
Definition: overloaded.h:16
Cachable amount subdivided into watchonly and spendable parts.
Definition: ismine.h:57
State of transaction confirmed in a block.
Definition: transaction.h:24
TxStateConfirmed(const uint256 &block_hash, int height, int index)
Definition: transaction.h:29
State of rejected transaction that conflicts with a confirmed block.
Definition: transaction.h:37
TxStateConflicted(const uint256 &block_hash, int height)
Definition: transaction.h:41
State of transaction added to mempool.
Definition: transaction.h:33
State of transaction not confirmed or conflicting with a known block and not in the mempool.
Definition: transaction.h:48
TxStateInactive(bool abandoned=false)
Definition: transaction.h:51
State of transaction loaded in an unrecognized state with unexpected hash or index values.
Definition: transaction.h:58
TxStateUnrecognized(const uint256 &block_hash, int index)
Definition: transaction.h:62
bool operator()(const CWalletTx *a, const CWalletTx *b) const
Definition: transaction.h:310
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1164