/tmp/bitcoin/src/wallet/transaction.cpp
Line | Count | Source |
1 | | // Copyright (c) 2021-present 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 | | #include <wallet/transaction.h> |
6 | | |
7 | | #include <consensus/validation.h> |
8 | | #include <interfaces/chain.h> |
9 | | |
10 | | using interfaces::FoundBlock; |
11 | | |
12 | | namespace wallet { |
13 | | bool CWalletTx::IsEquivalentTo(const CWalletTx& _tx) const |
14 | 4.47k | { |
15 | 4.47k | CMutableTransaction tx1 {*this->GetTx()}; |
16 | 4.47k | CMutableTransaction tx2 {*_tx.GetTx()}; |
17 | 4.51k | for (auto& txin : tx1.vin) { |
18 | 4.51k | txin.scriptSig = CScript(); |
19 | 4.51k | txin.scriptWitness.SetNull(); |
20 | 4.51k | } |
21 | 4.52k | for (auto& txin : tx2.vin) { |
22 | 4.52k | txin.scriptSig = CScript(); |
23 | 4.52k | txin.scriptWitness.SetNull(); |
24 | 4.52k | } |
25 | 4.47k | return CTransaction(tx1) == CTransaction(tx2); |
26 | 4.47k | } |
27 | | |
28 | | bool CWalletTx::InMempool() const |
29 | 149k | { |
30 | 149k | return state<TxStateInMempool>(); |
31 | 149k | } |
32 | | |
33 | | int64_t CWalletTx::GetTxTime() const |
34 | 296k | { |
35 | 296k | int64_t n = nTimeSmart; |
36 | 296k | return n ? n : nTimeReceived; |
37 | 296k | } |
38 | | |
39 | | void CWalletTx::updateState(interfaces::Chain& chain) |
40 | 8.02k | { |
41 | 8.02k | bool active; |
42 | 8.02k | auto lookup_block = [&](const uint256& hash, int& height, TxState& state) { |
43 | | // If tx block (or conflicting block) was reorged out of chain |
44 | | // while the wallet was shutdown, change tx status to UNCONFIRMED |
45 | | // and reset block height, hash, and index. ABANDONED tx don't have |
46 | | // associated blocks and don't need to be updated. The case where a |
47 | | // transaction was reorged out while online and then reconfirmed |
48 | | // while offline is covered by the rescan logic. |
49 | 7.83k | if (!chain.findBlock(hash, FoundBlock().inActiveChain(active).height(height)) || !active) { |
50 | 362 | state = TxStateInactive{}; |
51 | 362 | } |
52 | 7.83k | }; |
53 | 8.02k | if (auto* conf = state<TxStateConfirmed>()) { |
54 | 7.78k | lookup_block(conf->confirmed_block_hash, conf->confirmed_block_height, m_state); |
55 | 7.78k | } else if (auto* conf = state<TxStateBlockConflicted>()) { |
56 | 52 | lookup_block(conf->conflicting_block_hash, conf->conflicting_block_height, m_state); |
57 | 52 | } |
58 | | |
59 | | // If the above downgraded a previously-confirmed witness variant back to unconfirmed, |
60 | | // the canonical choice is no longer pinned by confirmation. Re-apply the least-weight rule. |
61 | 8.02k | if (!isConfirmed()) RecomputeCanonical(); |
62 | 8.02k | } |
63 | | |
64 | | bool CWalletTx::Update(CTransactionRef new_tx, const TxState& new_state) |
65 | 8.56k | { |
66 | 8.56k | Assert(new_tx); |
67 | 8.56k | if (!Assume(GetHash() == new_tx->GetHash())) { |
68 | 0 | return false; |
69 | 0 | } |
70 | 8.56k | bool ret = false; |
71 | 8.56k | const auto& [tx_pair, inserted] = m_txs.emplace(new_tx->GetWitnessHash(), std::move(new_tx)); |
72 | 8.56k | if (inserted) { |
73 | 3 | ret = true; |
74 | 3 | } |
75 | 8.56k | const auto& [wtxid, tx] = *tx_pair; |
76 | | |
77 | 8.56k | if (new_state.index() != m_state.index()) { |
78 | 4.41k | m_state = new_state; |
79 | 4.41k | if (state<TxStateConfirmed>()) { |
80 | 3.80k | m_canonical_wtxid = wtxid; |
81 | 3.80k | } |
82 | 4.41k | ret = true; |
83 | 4.41k | } else { |
84 | 4.14k | assert(TxStateSerializedIndex(m_state) == TxStateSerializedIndex(new_state)); |
85 | 4.14k | assert(TxStateSerializedBlockHash(m_state) == TxStateSerializedBlockHash(new_state)); |
86 | 4.14k | } |
87 | | |
88 | | // While unconfirmed, derive the canonical variant from all known variants |
89 | 8.56k | if (!isConfirmed()) { |
90 | 2.30k | const Wtxid prev_canonical = m_canonical_wtxid; |
91 | 2.30k | RecomputeCanonical(); |
92 | 2.30k | if (m_canonical_wtxid != prev_canonical) { |
93 | 2 | ret = true; |
94 | 2 | } |
95 | 2.30k | } |
96 | | |
97 | 8.56k | return ret; |
98 | 8.56k | } |
99 | | |
100 | | void CWalletTx::RecomputeCanonical() |
101 | 2.90k | { |
102 | | // Recompute the canonical variant among the witness variants. They share |
103 | | // the txid but differ in the wtxid. Prefer variant with witness data and |
104 | | // the least weight. |
105 | 2.90k | Assert(!m_txs.empty()); |
106 | | |
107 | | // Returns true if 'a' should be preferred over 'b' |
108 | 2.90k | auto is_better = [](const CTransactionRef& a, const CTransactionRef& b) { |
109 | | // A witnessed variant always beats a witnessless one |
110 | 12 | if (a->HasWitness() != b->HasWitness()) return a->HasWitness(); |
111 | | // Otherwise the lighter one wins |
112 | 12 | return GetTransactionWeight(*a) < GetTransactionWeight(*b); |
113 | 12 | }; |
114 | | |
115 | 2.90k | auto it = m_txs.begin(); |
116 | 2.90k | auto best_wtxid = it->first; |
117 | 2.90k | const CTransactionRef* best = &it->second; |
118 | 2.90k | it = std::next(it); |
119 | 2.91k | for (; it != m_txs.end(); it = std::next(it)) { |
120 | 12 | if (is_better(it->second, *best)) { |
121 | 0 | best = &it->second; |
122 | 0 | best_wtxid = it->first; |
123 | 0 | } |
124 | 12 | } |
125 | 2.90k | m_canonical_wtxid = best_wtxid; |
126 | 2.90k | } |
127 | | } // namespace wallet |