/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 | | #include <wallet/walletdb.h> |
7 | | |
8 | | #include <consensus/validation.h> |
9 | | #include <interfaces/chain.h> |
10 | | |
11 | | using interfaces::FoundBlock; |
12 | | |
13 | | namespace wallet { |
14 | | bool CWalletTx::IsMalleation(const CWalletTx& _tx) const |
15 | 54 | { |
16 | 54 | return GetTx()->Equals(*_tx.GetTx(), {.include_script_sig = false, .include_witness_data = false}); |
17 | 54 | } |
18 | | |
19 | | bool CWalletTx::InMempool() const |
20 | 149k | { |
21 | 149k | return state<TxStateInMempool>(); |
22 | 149k | } |
23 | | |
24 | | int64_t CWalletTx::GetTxTime() const |
25 | 296k | { |
26 | 296k | int64_t n = nTimeSmart; |
27 | 296k | return n ? n : nTimeReceived; |
28 | 296k | } |
29 | | |
30 | | void CWalletTx::updateState(interfaces::Chain& chain) |
31 | 9.27k | { |
32 | 9.27k | bool active; |
33 | 9.27k | auto lookup_block = [&](const uint256& hash, int& height, TxState& state) { |
34 | | // If tx block (or conflicting block) was reorged out of chain |
35 | | // while the wallet was shutdown, change tx status to UNCONFIRMED |
36 | | // and reset block height, hash, and index. ABANDONED tx don't have |
37 | | // associated blocks and don't need to be updated. The case where a |
38 | | // transaction was reorged out while online and then reconfirmed |
39 | | // while offline is covered by the rescan logic. |
40 | 9.06k | if (!chain.findBlock(hash, FoundBlock().inActiveChain(active).height(height)) || !active) { |
41 | 362 | state = TxStateInactive{}; |
42 | 362 | } |
43 | 9.06k | }; |
44 | 9.27k | if (auto* conf = state<TxStateConfirmed>()) { |
45 | 8.81k | lookup_block(conf->confirmed_block_hash, conf->confirmed_block_height, m_state); |
46 | 8.81k | } else if (auto* conf = state<TxStateBlockConflicted>()) { |
47 | 242 | lookup_block(conf->conflicting_block_hash, conf->conflicting_block_height, m_state); |
48 | 242 | } |
49 | | |
50 | | // If the above downgraded a previously-confirmed witness variant back to unconfirmed, |
51 | | // the canonical choice is no longer pinned by confirmation. Re-apply the least-weight rule. |
52 | 9.27k | if (!isConfirmed()) RecomputeCanonical(); |
53 | 9.27k | } |
54 | | |
55 | | bool CWalletTx::Update(CTransactionRef new_tx, const TxState& new_state, WalletBatch& batch, bool metadata_changed) |
56 | 8.80k | { |
57 | 8.80k | Assert(new_tx); |
58 | 8.80k | if (!Assume(GetHash() == new_tx->GetHash())) { |
59 | 0 | return false; |
60 | 0 | } |
61 | 8.80k | const auto& [tx_pair, new_variant] = m_txs.emplace(new_tx->GetWitnessHash(), std::move(new_tx)); |
62 | 8.80k | if (new_variant) { |
63 | 3 | if (!batch.WriteWtxVariant(GetHash(), tx_pair->second)) { |
64 | 0 | throw std::ios_base::failure("Unable to write wtxvariant record"); |
65 | 0 | } |
66 | 3 | } |
67 | 8.80k | const auto& [wtxid, tx] = *tx_pair; |
68 | | |
69 | 8.80k | if (new_state.index() != m_state.index()) { |
70 | 4.52k | m_state = new_state; |
71 | 4.52k | if (state<TxStateConfirmed>()) { |
72 | 3.90k | m_canonical_wtxid = wtxid; |
73 | 3.90k | } |
74 | 4.52k | metadata_changed = true; |
75 | 4.52k | } else { |
76 | 4.27k | assert(TxStateSerializedIndex(m_state) == TxStateSerializedIndex(new_state)); |
77 | 4.27k | assert(TxStateSerializedBlockHash(m_state) == TxStateSerializedBlockHash(new_state)); |
78 | 4.27k | } |
79 | | |
80 | | // While unconfirmed, derive the canonical variant from all known variants |
81 | 8.80k | if (!isConfirmed()) { |
82 | 2.45k | const Wtxid prev_canonical = m_canonical_wtxid; |
83 | 2.45k | RecomputeCanonical(); |
84 | 2.45k | if (m_canonical_wtxid != prev_canonical) { |
85 | 2 | metadata_changed = true; |
86 | 2 | } |
87 | 2.45k | } |
88 | | |
89 | 8.80k | if (metadata_changed) { |
90 | 4.52k | if (!batch.WriteTxMetadata(*this)) { |
91 | 0 | throw std::ios_base::failure("Unable to write tx record"); |
92 | 0 | } |
93 | 4.52k | } |
94 | | |
95 | 8.80k | return new_variant || metadata_changed; |
96 | 8.80k | } |
97 | | |
98 | | void CWalletTx::RecomputeCanonical() |
99 | 3.27k | { |
100 | | // Recompute the canonical variant among the witness variants. They share |
101 | | // the txid but differ in the wtxid. Prefer variant with witness data and |
102 | | // the least weight. |
103 | 3.27k | Assert(!m_txs.empty()); |
104 | | |
105 | 3.27k | m_canonical_wtxid = std::ranges::min_element(m_txs, std::less{}, [](const auto& entry) { |
106 | 24 | return std::make_pair(!entry.second->HasWitness(), GetTransactionWeight(*entry.second)); |
107 | 24 | })->first; |
108 | 3.27k | } |
109 | | } // namespace wallet |