/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.17k | { |
15 | 4.17k | CMutableTransaction tx1 {*this->GetTx()}; |
16 | 4.17k | CMutableTransaction tx2 {*_tx.GetTx()}; |
17 | 4.21k | for (auto& txin : tx1.vin) { |
18 | 4.21k | txin.scriptSig = CScript(); |
19 | 4.21k | txin.scriptWitness.SetNull(); |
20 | 4.21k | } |
21 | 4.22k | for (auto& txin : tx2.vin) { |
22 | 4.22k | txin.scriptSig = CScript(); |
23 | 4.22k | txin.scriptWitness.SetNull(); |
24 | 4.22k | } |
25 | 4.17k | return CTransaction(tx1) == CTransaction(tx2); |
26 | 4.17k | } |
27 | | |
28 | | bool CWalletTx::InMempool() const |
29 | 149k | { |
30 | 149k | return state<TxStateInMempool>(); |
31 | 149k | } |
32 | | |
33 | | int64_t CWalletTx::GetTxTime() const |
34 | 300k | { |
35 | 300k | int64_t n = nTimeSmart; |
36 | 300k | return n ? n : nTimeReceived; |
37 | 300k | } |
38 | | |
39 | | void CWalletTx::updateState(interfaces::Chain& chain) |
40 | 8.40k | { |
41 | 8.40k | bool active; |
42 | 8.40k | 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 | 8.21k | if (!chain.findBlock(hash, FoundBlock().inActiveChain(active).height(height)) || !active) { |
50 | 362 | state = TxStateInactive{}; |
51 | 362 | } |
52 | 8.21k | }; |
53 | 8.40k | if (auto* conf = state<TxStateConfirmed>()) { |
54 | 8.16k | lookup_block(conf->confirmed_block_hash, conf->confirmed_block_height, m_state); |
55 | 8.16k | } 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.40k | if (!isConfirmed()) RecomputeCanonical(); |
62 | 8.40k | } |
63 | | |
64 | | bool CWalletTx::Update(CTransactionRef new_tx, const TxState& new_state) |
65 | 8.60k | { |
66 | 8.60k | Assert(new_tx); |
67 | 8.60k | if (!Assume(GetHash() == new_tx->GetHash())) { |
68 | 0 | return false; |
69 | 0 | } |
70 | 8.60k | bool ret = false; |
71 | 8.60k | const auto& [tx_pair, inserted] = m_txs.emplace(new_tx->GetWitnessHash(), std::move(new_tx)); |
72 | 8.60k | if (inserted) { |
73 | 3 | ret = true; |
74 | 3 | } |
75 | 8.60k | const auto& [wtxid, tx] = *tx_pair; |
76 | | |
77 | 8.60k | if (new_state.index() != m_state.index()) { |
78 | 4.42k | m_state = new_state; |
79 | 4.42k | if (state<TxStateConfirmed>()) { |
80 | 3.81k | m_canonical_wtxid = wtxid; |
81 | 3.81k | } |
82 | 4.42k | ret = true; |
83 | 4.42k | } else { |
84 | 4.18k | assert(TxStateSerializedIndex(m_state) == TxStateSerializedIndex(new_state)); |
85 | 4.18k | assert(TxStateSerializedBlockHash(m_state) == TxStateSerializedBlockHash(new_state)); |
86 | 4.18k | } |
87 | | |
88 | | // While unconfirmed, derive the canonical variant from all known variants |
89 | 8.60k | if (!isConfirmed()) { |
90 | 2.35k | const Wtxid prev_canonical = m_canonical_wtxid; |
91 | 2.35k | RecomputeCanonical(); |
92 | 2.35k | if (m_canonical_wtxid != prev_canonical) { |
93 | 2 | ret = true; |
94 | 2 | } |
95 | 2.35k | } |
96 | | |
97 | 8.60k | return ret; |
98 | 8.60k | } |
99 | | |
100 | | void CWalletTx::RecomputeCanonical() |
101 | 2.95k | { |
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.95k | Assert(!m_txs.empty()); |
106 | | |
107 | 2.95k | m_canonical_wtxid = std::ranges::min_element(m_txs, std::less{}, [](const auto& entry) { |
108 | 24 | return std::make_pair(!entry.second->HasWitness(), GetTransactionWeight(*entry.second)); |
109 | 24 | })->first; |
110 | 2.95k | } |
111 | | } // namespace wallet |