Branch data Line data Source code
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 : 0 : bool CWalletTx::IsMalleation(const CWalletTx& _tx) const
15 : : {
16 [ # # # # : 0 : return GetTx()->Equals(*_tx.GetTx(), {.include_script_sig = false, .include_witness_data = false});
# # ]
17 : : }
18 : :
19 : 0 : bool CWalletTx::InMempool() const
20 : : {
21 [ # # ]: 0 : return state<TxStateInMempool>();
22 : : }
23 : :
24 : 117126 : int64_t CWalletTx::GetTxTime() const
25 : : {
26 : 117126 : int64_t n = nTimeSmart;
27 [ + + ]: 117126 : return n ? n : nTimeReceived;
28 : : }
29 : :
30 : 2 : void CWalletTx::updateState(interfaces::Chain& chain)
31 : : {
32 : 2 : bool active;
33 : 3 : 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 [ + - - + ]: 1 : if (!chain.findBlock(hash, FoundBlock().inActiveChain(active).height(height)) || !active) {
41 [ # # ]: 0 : state = TxStateInactive{};
42 : : }
43 : 3 : };
44 [ + + ]: 2 : if (auto* conf = state<TxStateConfirmed>()) {
45 : 1 : lookup_block(conf->confirmed_block_hash, conf->confirmed_block_height, m_state);
46 [ - + ]: 1 : } else if (auto* conf = state<TxStateBlockConflicted>()) {
47 : 0 : lookup_block(conf->conflicting_block_hash, conf->conflicting_block_height, m_state);
48 : : }
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 [ + + ]: 2 : if (!isConfirmed()) RecomputeCanonical();
53 : 2 : }
54 : :
55 : 6 : bool CWalletTx::Update(CTransactionRef new_tx, const TxState& new_state, WalletBatch& batch, bool metadata_changed)
56 : : {
57 [ - + ]: 6 : Assert(new_tx);
58 [ - + + - ]: 6 : if (!Assume(GetHash() == new_tx->GetHash())) {
59 : : return false;
60 : : }
61 [ - + ]: 6 : const auto& [tx_pair, new_variant] = m_txs.emplace(new_tx->GetWitnessHash(), std::move(new_tx));
62 [ - + ]: 6 : if (new_variant) {
63 [ # # ]: 0 : if (!batch.WriteWtxVariant(GetHash(), tx_pair->second)) {
64 [ # # ]: 0 : throw std::ios_base::failure("Unable to write wtxvariant record");
65 : : }
66 : : }
67 [ - + ]: 6 : const auto& [wtxid, tx] = *tx_pair;
68 : :
69 [ - + ]: 6 : if (new_state.index() != m_state.index()) {
70 : 0 : m_state = new_state;
71 [ # # ]: 0 : if (state<TxStateConfirmed>()) {
72 : 0 : m_canonical_wtxid = wtxid;
73 : : }
74 : : metadata_changed = true;
75 : : } else {
76 [ - + ]: 6 : assert(TxStateSerializedIndex(m_state) == TxStateSerializedIndex(new_state));
77 [ - + ]: 6 : assert(TxStateSerializedBlockHash(m_state) == TxStateSerializedBlockHash(new_state));
78 : : }
79 : :
80 : : // While unconfirmed, derive the canonical variant from all known variants
81 [ + + ]: 6 : if (!isConfirmed()) {
82 : 4 : const Wtxid prev_canonical = m_canonical_wtxid;
83 : 4 : RecomputeCanonical();
84 [ + - ]: 4 : if (m_canonical_wtxid != prev_canonical) {
85 : : metadata_changed = true;
86 : : }
87 : : }
88 : :
89 [ + + ]: 6 : if (metadata_changed) {
90 [ - + ]: 1 : if (!batch.WriteTxMetadata(*this)) {
91 [ # # ]: 0 : throw std::ios_base::failure("Unable to write tx record");
92 : : }
93 : : }
94 : :
95 [ + - + + ]: 6 : return new_variant || metadata_changed;
96 : : }
97 : :
98 : 5 : void CWalletTx::RecomputeCanonical()
99 : : {
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 [ - + ]: 5 : Assert(!m_txs.empty());
104 : :
105 : 5 : m_canonical_wtxid = std::ranges::min_element(m_txs, std::less{}, [](const auto& entry) {
106 : 0 : return std::make_pair(!entry.second->HasWitness(), GetTransactionWeight(*entry.second));
107 : 5 : })->first;
108 : 5 : }
109 : : } // namespace wallet
|