Coverage Report

Created: 2026-10-07 20:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/bitcoin/src/wallet/transaction.h
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
#ifndef BITCOIN_WALLET_TRANSACTION_H
6
#define BITCOIN_WALLET_TRANSACTION_H
7
8
#include <attributes.h>
9
#include <consensus/amount.h>
10
#include <primitives/transaction.h>
11
#include <tinyformat.h>
12
#include <uint256.h>
13
#include <util/check.h>
14
#include <util/overloaded.h>
15
#include <util/strencodings.h>
16
#include <util/string.h>
17
#include <wallet/types.h>
18
19
#include <bitset>
20
#include <cstdint>
21
#include <map>
22
#include <utility>
23
#include <variant>
24
#include <vector>
25
26
namespace interfaces {
27
class Chain;
28
} // namespace interfaces
29
30
namespace wallet {
31
class WalletBatch;
32
33
//! State of transaction confirmed in a block.
34
struct TxStateConfirmed {
35
    uint256 confirmed_block_hash;
36
    int confirmed_block_height;
37
    int position_in_block;
38
39
0
    explicit TxStateConfirmed(const uint256& block_hash, int height, int index) : confirmed_block_hash(block_hash), confirmed_block_height(height), position_in_block(index) {}
40
0
    std::string toString() const { return strprintf("Confirmed (block=%s, height=%i, index=%i)", confirmed_block_hash.ToString(), confirmed_block_height, position_in_block); }
41
};
42
43
//! State of transaction added to mempool.
44
struct TxStateInMempool {
45
0
    std::string toString() const { return strprintf("InMempool"); }
46
};
47
48
//! State of rejected transaction that conflicts with a confirmed block.
49
struct TxStateBlockConflicted {
50
    uint256 conflicting_block_hash;
51
    int conflicting_block_height;
52
53
0
    explicit TxStateBlockConflicted(const uint256& block_hash, int height) : conflicting_block_hash(block_hash), conflicting_block_height(height) {}
54
0
    std::string toString() const { return strprintf("BlockConflicted (block=%s, height=%i)", conflicting_block_hash.ToString(), conflicting_block_height); }
55
};
56
57
//! State of transaction not confirmed or conflicting with a known block and
58
//! not in the mempool. May conflict with the mempool, or with an unknown block,
59
//! or be abandoned, never broadcast, or rejected from the mempool for another
60
//! reason.
61
struct TxStateInactive {
62
    bool abandoned;
63
64
0
    explicit TxStateInactive(bool abandoned = false) : abandoned(abandoned) {}
65
0
    std::string toString() const { return strprintf("Inactive (abandoned=%i)", abandoned); }
66
};
67
68
//! State of transaction loaded in an unrecognized state with unexpected hash or
69
//! index values. Treated as inactive (with serialized hash and index values
70
//! preserved) by default, but may enter another state if transaction is added
71
//! to the mempool, or confirmed, or abandoned, or found conflicting.
72
struct TxStateUnrecognized {
73
    uint256 block_hash;
74
    int index;
75
76
0
    TxStateUnrecognized(const uint256& block_hash, int index) : block_hash(block_hash), index(index) {}
77
0
    std::string toString() const { return strprintf("Unrecognized (block=%s, index=%i)", block_hash.ToString(), index); }
78
};
79
80
//! All possible CWalletTx states
81
using TxState = std::variant<TxStateConfirmed, TxStateInMempool, TxStateBlockConflicted, TxStateInactive, TxStateUnrecognized>;
82
83
//! Subset of states transaction sync logic is implemented to handle.
84
using SyncTxState = std::variant<TxStateConfirmed, TxStateInMempool, TxStateInactive>;
85
86
//! Try to interpret deserialized TxStateUnrecognized data as a recognized state.
87
static inline TxState TxStateInterpretSerialized(TxStateUnrecognized data)
88
0
{
89
0
    if (data.block_hash == uint256::ZERO) {
  Branch (89:9): [True: 0, False: 0]
  Branch (89:9): [True: 0, False: 0]
  Branch (89:9): [True: 0, False: 0]
90
0
        if (data.index == 0) return TxStateInactive{};
  Branch (90:13): [True: 0, False: 0]
  Branch (90:13): [True: 0, False: 0]
  Branch (90:13): [True: 0, False: 0]
91
0
    } else if (data.block_hash == uint256::ONE) {
  Branch (91:16): [True: 0, False: 0]
  Branch (91:16): [True: 0, False: 0]
  Branch (91:16): [True: 0, False: 0]
92
0
        if (data.index == -1) return TxStateInactive{/*abandoned=*/true};
  Branch (92:13): [True: 0, False: 0]
  Branch (92:13): [True: 0, False: 0]
  Branch (92:13): [True: 0, False: 0]
93
0
    } else if (data.index >= 0) {
  Branch (93:16): [True: 0, False: 0]
  Branch (93:16): [True: 0, False: 0]
  Branch (93:16): [True: 0, False: 0]
94
0
        return TxStateConfirmed{data.block_hash, /*height=*/-1, data.index};
95
0
    } else if (data.index == -1) {
  Branch (95:16): [True: 0, False: 0]
  Branch (95:16): [True: 0, False: 0]
  Branch (95:16): [True: 0, False: 0]
96
0
        return TxStateBlockConflicted{data.block_hash, /*height=*/-1};
97
0
    }
98
0
    return data;
99
0
}
Unexecuted instantiation: fees.cpp:_ZN6walletL26TxStateInterpretSerializedENS_19TxStateUnrecognizedE
Unexecuted instantiation: scriptpubkeyman.cpp:_ZN6walletL26TxStateInterpretSerializedENS_19TxStateUnrecognizedE
Unexecuted instantiation: spend.cpp:_ZN6walletL26TxStateInterpretSerializedENS_19TxStateUnrecognizedE
Unexecuted instantiation: dump.cpp:_ZN6walletL26TxStateInterpretSerializedENS_19TxStateUnrecognizedE
Unexecuted instantiation: transaction.cpp:_ZN6walletL26TxStateInterpretSerializedENS_19TxStateUnrecognizedE
Unexecuted instantiation: wallet.cpp:_ZN6walletL26TxStateInterpretSerializedENS_19TxStateUnrecognizedE
Unexecuted instantiation: walletdb.cpp:_ZN6walletL26TxStateInterpretSerializedENS_19TxStateUnrecognizedE
Unexecuted instantiation: interfaces.cpp:_ZN6walletL26TxStateInterpretSerializedENS_19TxStateUnrecognizedE
Unexecuted instantiation: load.cpp:_ZN6walletL26TxStateInterpretSerializedENS_19TxStateUnrecognizedE
Unexecuted instantiation: receive.cpp:_ZN6walletL26TxStateInterpretSerializedENS_19TxStateUnrecognizedE
Unexecuted instantiation: scan.cpp:_ZN6walletL26TxStateInterpretSerializedENS_19TxStateUnrecognizedE
Unexecuted instantiation: export.cpp:_ZN6walletL26TxStateInterpretSerializedENS_19TxStateUnrecognizedE
Unexecuted instantiation: feebumper.cpp:_ZN6walletL26TxStateInterpretSerializedENS_19TxStateUnrecognizedE
Unexecuted instantiation: imports.cpp:_ZN6walletL26TxStateInterpretSerializedENS_19TxStateUnrecognizedE
Unexecuted instantiation: addresses.cpp:_ZN6walletL26TxStateInterpretSerializedENS_19TxStateUnrecognizedE
Unexecuted instantiation: backup.cpp:_ZN6walletL26TxStateInterpretSerializedENS_19TxStateUnrecognizedE
Unexecuted instantiation: coins.cpp:_ZN6walletL26TxStateInterpretSerializedENS_19TxStateUnrecognizedE
Unexecuted instantiation: encrypt.cpp:_ZN6walletL26TxStateInterpretSerializedENS_19TxStateUnrecognizedE
Unexecuted instantiation: signmessage.cpp:_ZN6walletL26TxStateInterpretSerializedENS_19TxStateUnrecognizedE
Unexecuted instantiation: transactions.cpp:_ZN6walletL26TxStateInterpretSerializedENS_19TxStateUnrecognizedE
Unexecuted instantiation: util.cpp:_ZN6walletL26TxStateInterpretSerializedENS_19TxStateUnrecognizedE
Unexecuted instantiation: init.cpp:_ZN6walletL26TxStateInterpretSerializedENS_19TxStateUnrecognizedE
100
101
//! Get TxState serialized block hash. Inverse of TxStateInterpretSerialized.
102
static inline uint256 TxStateSerializedBlockHash(const TxState& state)
103
0
{
104
0
    return std::visit(util::Overloaded{
105
0
        [](const TxStateInactive& inactive) { return inactive.abandoned ? uint256::ONE : uint256::ZERO; },
Unexecuted instantiation: transaction.cpp:_ZZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS4_E_clESA_
Unexecuted instantiation: wallet.cpp:_ZZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS4_E_clESA_
Unexecuted instantiation: walletdb.cpp:_ZZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS4_E_clESA_
Unexecuted instantiation: export.cpp:_ZZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS4_E_clESA_
  Branch (105:54): [True: 0, False: 0]
  Branch (105:54): [True: 0, False: 0]
  Branch (105:54): [True: 0, False: 0]
  Branch (105:54): [True: 0, False: 0]
106
0
        [](const TxStateInMempool& in_mempool) { return uint256::ZERO; },
Unexecuted instantiation: transaction.cpp:_ZZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS2_E_clESA_
Unexecuted instantiation: wallet.cpp:_ZZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS2_E_clESA_
Unexecuted instantiation: walletdb.cpp:_ZZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS2_E_clESA_
Unexecuted instantiation: export.cpp:_ZZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS2_E_clESA_
107
0
        [](const TxStateConfirmed& confirmed) { return confirmed.confirmed_block_hash; },
Unexecuted instantiation: transaction.cpp:_ZZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS1_E_clESA_
Unexecuted instantiation: wallet.cpp:_ZZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS1_E_clESA_
Unexecuted instantiation: walletdb.cpp:_ZZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS1_E_clESA_
Unexecuted instantiation: export.cpp:_ZZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS1_E_clESA_
108
0
        [](const TxStateBlockConflicted& conflicted) { return conflicted.conflicting_block_hash; },
Unexecuted instantiation: transaction.cpp:_ZZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS3_E_clESA_
Unexecuted instantiation: wallet.cpp:_ZZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS3_E_clESA_
Unexecuted instantiation: walletdb.cpp:_ZZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS3_E_clESA_
Unexecuted instantiation: export.cpp:_ZZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS3_E_clESA_
109
0
        [](const TxStateUnrecognized& unrecognized) { return unrecognized.block_hash; }
Unexecuted instantiation: transaction.cpp:_ZZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS5_E_clESA_
Unexecuted instantiation: wallet.cpp:_ZZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS5_E_clESA_
Unexecuted instantiation: walletdb.cpp:_ZZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS5_E_clESA_
Unexecuted instantiation: export.cpp:_ZZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS5_E_clESA_
110
0
    }, state);
111
0
}
Unexecuted instantiation: fees.cpp:_ZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: scriptpubkeyman.cpp:_ZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: spend.cpp:_ZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: dump.cpp:_ZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: transaction.cpp:_ZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: wallet.cpp:_ZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: walletdb.cpp:_ZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: interfaces.cpp:_ZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: load.cpp:_ZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: receive.cpp:_ZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: scan.cpp:_ZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: export.cpp:_ZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: feebumper.cpp:_ZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: imports.cpp:_ZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: addresses.cpp:_ZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: backup.cpp:_ZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: coins.cpp:_ZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: encrypt.cpp:_ZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: signmessage.cpp:_ZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: transactions.cpp:_ZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: util.cpp:_ZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: init.cpp:_ZN6walletL26TxStateSerializedBlockHashERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
112
113
//! Get TxState serialized block index. Inverse of TxStateInterpretSerialized.
114
static inline int TxStateSerializedIndex(const TxState& state)
115
0
{
116
0
    return std::visit(util::Overloaded{
117
0
        [](const TxStateInactive& inactive) { return inactive.abandoned ? -1 : 0; },
Unexecuted instantiation: transaction.cpp:_ZZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS4_E_clESA_
Unexecuted instantiation: wallet.cpp:_ZZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS4_E_clESA_
Unexecuted instantiation: walletdb.cpp:_ZZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS4_E_clESA_
Unexecuted instantiation: export.cpp:_ZZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS4_E_clESA_
  Branch (117:54): [True: 0, False: 0]
  Branch (117:54): [True: 0, False: 0]
  Branch (117:54): [True: 0, False: 0]
  Branch (117:54): [True: 0, False: 0]
118
0
        [](const TxStateInMempool& in_mempool) { return 0; },
Unexecuted instantiation: transaction.cpp:_ZZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS2_E_clESA_
Unexecuted instantiation: wallet.cpp:_ZZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS2_E_clESA_
Unexecuted instantiation: walletdb.cpp:_ZZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS2_E_clESA_
Unexecuted instantiation: export.cpp:_ZZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS2_E_clESA_
119
0
        [](const TxStateConfirmed& confirmed) { return confirmed.position_in_block; },
Unexecuted instantiation: transaction.cpp:_ZZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS1_E_clESA_
Unexecuted instantiation: wallet.cpp:_ZZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS1_E_clESA_
Unexecuted instantiation: walletdb.cpp:_ZZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS1_E_clESA_
Unexecuted instantiation: export.cpp:_ZZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS1_E_clESA_
120
0
        [](const TxStateBlockConflicted& conflicted) { return -1; },
Unexecuted instantiation: transaction.cpp:_ZZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS3_E_clESA_
Unexecuted instantiation: wallet.cpp:_ZZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS3_E_clESA_
Unexecuted instantiation: walletdb.cpp:_ZZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS3_E_clESA_
Unexecuted instantiation: export.cpp:_ZZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS3_E_clESA_
121
0
        [](const TxStateUnrecognized& unrecognized) { return unrecognized.index; }
Unexecuted instantiation: transaction.cpp:_ZZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS5_E_clESA_
Unexecuted instantiation: wallet.cpp:_ZZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS5_E_clESA_
Unexecuted instantiation: walletdb.cpp:_ZZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS5_E_clESA_
Unexecuted instantiation: export.cpp:_ZZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEENKUlRKS5_E_clESA_
122
0
    }, state);
123
0
}
Unexecuted instantiation: fees.cpp:_ZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: scriptpubkeyman.cpp:_ZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: spend.cpp:_ZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: dump.cpp:_ZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: transaction.cpp:_ZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: wallet.cpp:_ZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: walletdb.cpp:_ZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: interfaces.cpp:_ZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: load.cpp:_ZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: receive.cpp:_ZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: scan.cpp:_ZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: export.cpp:_ZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: feebumper.cpp:_ZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: imports.cpp:_ZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: addresses.cpp:_ZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: backup.cpp:_ZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: coins.cpp:_ZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: encrypt.cpp:_ZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: signmessage.cpp:_ZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: transactions.cpp:_ZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: util.cpp:_ZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
Unexecuted instantiation: init.cpp:_ZN6walletL22TxStateSerializedIndexERKSt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEE
124
125
//! Return TxState or SyncTxState as a string for logging or debugging.
126
template<typename T>
127
std::string TxStateString(const T& state)
128
0
{
129
0
    return std::visit([](const auto& s) { return s.toString(); }, state);
Unexecuted instantiation: _ZZN6wallet13TxStateStringISt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_ENKUlSG_E_clIS2_EEDaSG_
Unexecuted instantiation: _ZZN6wallet13TxStateStringISt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_ENKUlSG_E_clIS3_EEDaSG_
Unexecuted instantiation: _ZZN6wallet13TxStateStringISt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_ENKUlSG_E_clIS4_EEDaSG_
Unexecuted instantiation: _ZZN6wallet13TxStateStringISt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_ENKUlSG_E_clIS5_EEDaSG_
Unexecuted instantiation: _ZZN6wallet13TxStateStringISt7variantIJNS_16TxStateConfirmedENS_16TxStateInMempoolENS_22TxStateBlockConflictedENS_15TxStateInactiveENS_19TxStateUnrecognizedEEEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_ENKUlSG_E_clIS6_EEDaSG_
130
0
}
131
132
/**
133
 * Cachable amount subdivided into avoid reuse and all balances
134
 */
135
struct CachableAmount
136
{
137
    std::optional<CAmount> m_avoid_reuse_value;
138
    std::optional<CAmount> m_all_value;
139
    inline void Reset()
140
0
    {
141
0
        m_avoid_reuse_value.reset();
142
0
        m_all_value.reset();
143
0
    }
144
    void Set(bool avoid_reuse, CAmount value)
145
0
    {
146
0
        if (avoid_reuse) {
  Branch (146:13): [True: 0, False: 0]
147
0
            m_avoid_reuse_value = value;
148
0
        } else {
149
0
            m_all_value = value;
150
0
        }
151
0
    }
152
    CAmount Get(bool avoid_reuse)
153
0
    {
154
0
        if (avoid_reuse) {
  Branch (154:13): [True: 0, False: 0]
155
0
            Assert(m_avoid_reuse_value.has_value());
156
0
            return m_avoid_reuse_value.value();
157
0
        }
158
0
        Assert(m_all_value.has_value());
159
0
        return m_all_value.value();
160
0
    }
161
    bool IsCached(bool avoid_reuse)
162
0
    {
163
0
        if (avoid_reuse) return m_avoid_reuse_value.has_value();
  Branch (163:13): [True: 0, False: 0]
164
0
        return m_all_value.has_value();
165
0
    }
166
};
167
168
169
/** Legacy class used for deserializing vtxPrev for backwards compatibility.
170
 * vtxPrev was removed in commit 93a18a3650292afbb441a47d1fa1b94aeb0164e3,
171
 * but old wallet.dat files may still contain vtxPrev vectors of CMerkleTxs.
172
 * These need to get deserialized for field alignment when deserializing
173
 * a CWalletTx, but the deserialized values are discarded.**/
174
class CMerkleTx
175
{
176
public:
177
    template<typename Stream>
178
    void Unserialize(Stream& s)
179
0
    {
180
0
        CTransactionRef tx;
181
0
        uint256 hashBlock;
182
0
        std::vector<uint256> vMerkleBranch;
183
0
        int nIndex;
184
185
0
        s >> TX_WITH_WITNESS(tx) >> hashBlock >> vMerkleBranch >> nIndex;
186
0
    }
187
};
188
189
/**
190
 * A transaction with a bunch of additional info that only the owner cares about.
191
 * It includes any unrecorded transactions needed to link it back to the block chain.
192
 */
193
class CWalletTx
194
{
195
public:
196
    // "from" and "message" are obsolete fields that could be set in
197
    // the UI prior to 2011 (removed in commit 4d9b223)
198
    // These fields are kept to avoid losing metadata.
199
    std::optional<std::string> m_from;
200
    std::optional<std::string> m_message;
201
    // Comment strings provided by the user
202
    std::optional<std::string> m_comment;
203
    std::optional<std::string> m_comment_to;
204
    std::optional<Txid> m_replaces_txid;
205
    std::optional<Txid> m_replaced_by_txid;
206
    // BIP 21 URI Messages
207
    std::vector<std::string> m_messages;
208
    // BIP 70 Payment Request (deprecated, field kept to preserve metadata from old wallets)
209
    std::vector<std::string> m_payment_requests;
210
    unsigned int nTimeReceived; //!< time received by this node
211
    /**
212
     * Stable timestamp that never changes, and reflects the order a transaction
213
     * was added to the wallet. Timestamp is based on the block time for a
214
     * transaction added as part of a block, or else the time when the
215
     * transaction was received if it wasn't part of a block, with the timestamp
216
     * adjusted in both cases so timestamp order matches the order transactions
217
     * were added to the wallet. More details can be found in
218
     * CWallet::ComputeTimeSmart().
219
     */
220
    unsigned int nTimeSmart;
221
    // Cached value for whether the transaction spends any inputs known to the wallet
222
    mutable std::optional<bool> m_cached_from_me{std::nullopt};
223
    int64_t nOrderPos; //!< position in ordered transaction list
224
    std::multimap<int64_t, CWalletTx*>::const_iterator m_it_wtxOrdered;
225
226
    // memory only
227
    enum AmountType { DEBIT, CREDIT, AMOUNTTYPE_ENUM_ELEMENTS };
228
    mutable CachableAmount m_amounts[AMOUNTTYPE_ENUM_ELEMENTS];
229
    /**
230
     * This flag is true if all m_amounts caches are empty. This is particularly
231
     * useful in places where MarkDirty is conditionally called and the
232
     * condition can be expensive and thus can be skipped if the flag is true.
233
     * See MarkDestinationsDirty.
234
     */
235
    mutable bool m_is_cache_empty{true};
236
    mutable bool fChangeCached;
237
    mutable CAmount nChangeCached;
238
239
0
    CWalletTx(CTransactionRef tx, const TxState& state) : m_state(state)
240
0
    {
241
0
        Assert(tx);
242
0
        m_canonical_wtxid = tx->GetWitnessHash();
243
0
        m_txs.emplace(tx->GetWitnessHash(), std::move(tx));
244
0
        SetDefaults();
245
0
    }
246
247
    template <typename Stream>
248
0
    CWalletTx(deserialize_type, Stream& s, const std::map<Wtxid, CTransactionRef>& variants) : m_state(TxStateInactive{})
249
0
    {
250
0
        Unserialize(s);
251
0
        const Txid& canonical_txid = GetHash();
252
0
        for (const auto& [wtxid, tx] : variants) {
  Branch (252:38): [True: 0, False: 0]
253
0
            if (tx->GetHash() != canonical_txid) throw std::runtime_error("variant txid does not match wallet txid");
  Branch (253:17): [True: 0, False: 0]
254
0
        }
255
        // Merge witness variants
256
0
        m_txs.insert(variants.begin(), variants.end());
257
0
        Assert(m_txs.contains(GetWitnessHash()));
258
0
    }
259
260
    TxState m_state;
261
262
    // Set of mempool transactions that conflict
263
    // directly with the transaction, or that conflict
264
    // with an ancestor transaction. This set will be
265
    // empty if state is InMempool or Confirmed, but
266
    // can be nonempty if state is Inactive or
267
    // BlockConflicted.
268
    std::set<Txid> mempool_conflicts;
269
270
    // Track v3 mempool tx that spends from this tx
271
    // so that we don't try to create another unconfirmed child
272
    std::optional<Txid> truc_child_in_mempool;
273
274
    template<typename Stream>
275
    void Serialize(Stream& s) const
276
0
    {
277
0
        std::map<std::string, std::string> string_values;
278
0
        if (m_from) string_values["from"] = *m_from;
  Branch (278:13): [True: 0, False: 0]
279
0
        if (m_message) string_values["message"] = *m_message;
  Branch (279:13): [True: 0, False: 0]
280
0
        if (m_comment) string_values["comment"] = *m_comment;
  Branch (280:13): [True: 0, False: 0]
281
0
        if (m_comment_to) string_values["to"] = *m_comment_to;
  Branch (281:13): [True: 0, False: 0]
282
0
        if (m_replaces_txid) string_values["replaces_txid"] = m_replaces_txid->ToString();
  Branch (282:13): [True: 0, False: 0]
283
0
        if (m_replaced_by_txid) string_values["replaced_by_txid"] = m_replaced_by_txid->ToString();
  Branch (283:13): [True: 0, False: 0]
284
0
        string_values["fromaccount"] = "";
285
0
        if (nOrderPos != -1) string_values["n"] = util::ToString(nOrderPos);
  Branch (285:13): [True: 0, False: 0]
286
0
        if (nTimeSmart) string_values["timesmart"] = strprintf("%u", nTimeSmart);
  Branch (286:13): [True: 0, False: 0]
287
288
0
        std::vector<std::pair<std::string, std::string>> msgs_reqs;
289
0
        msgs_reqs.reserve(m_messages.size() + m_payment_requests.size());
290
0
        for (const std::string& msg : m_messages) {
  Branch (290:37): [True: 0, False: 0]
291
0
            msgs_reqs.emplace_back("Message", msg);
292
0
        }
293
0
        for (const std::string& req : m_payment_requests) {
  Branch (293:37): [True: 0, False: 0]
294
0
            msgs_reqs.emplace_back("PaymentRequest", req);
295
0
        }
296
297
0
        std::vector<uint8_t> dummy_vector1; // Used to be vMerkleBranch
298
0
        std::vector<uint8_t> dummy_vector2; // Used to be vtxPrev
299
0
        bool dummy_bool = false; // Used to be fFromMe, and fSpent
300
0
        uint32_t dummy_int = 0; // Used to be fTimeReceivedIsTxTime
301
0
        uint256 serializedHash = TxStateSerializedBlockHash(m_state);
302
0
        int serializedIndex = TxStateSerializedIndex(m_state);
303
0
        s << TX_WITH_WITNESS(GetTx()) << serializedHash << dummy_vector1 << serializedIndex << dummy_vector2 << string_values << msgs_reqs << dummy_int << nTimeReceived << dummy_bool << dummy_bool;
304
0
    }
305
306
    template<typename Stream>
307
    void Unserialize(Stream& s)
308
0
    {
309
0
        Init();
310
311
0
        std::vector<uint256> dummy_vector1; // Used to be vMerkleBranch
312
0
        std::vector<CMerkleTx> dummy_vector2; // Used to be vtxPrev
313
0
        bool dummy_bool; // Used to be fFromMe, and fSpent
314
0
        uint32_t dummy_int; // Used to be fTimeReceivedIsTxTime
315
0
        uint256 serialized_block_hash;
316
0
        int serializedIndex;
317
0
        std::map<std::string, std::string> string_values;
318
0
        std::vector<std::pair<std::string, std::string>> msgs_reqs;
319
0
        CTransactionRef canonical_tx;
320
0
        s >> TX_WITH_WITNESS(canonical_tx) >> serialized_block_hash >> dummy_vector1 >> serializedIndex >> dummy_vector2 >> string_values >> msgs_reqs >> dummy_int >> nTimeReceived >> dummy_bool >> dummy_bool;
321
0
        m_canonical_wtxid = canonical_tx->GetWitnessHash();
322
0
        m_txs.emplace(m_canonical_wtxid, std::move(canonical_tx));
323
324
0
        m_state = TxStateInterpretSerialized({serialized_block_hash, serializedIndex});
325
326
0
        string_values.erase("fromaccount");
327
0
        string_values.erase("spent");
328
0
        for (const auto& [key, value] : string_values) {
  Branch (328:39): [True: 0, False: 0]
329
0
            if (key == "n") nOrderPos = LocaleIndependentAtoi<int64_t>(value);
  Branch (329:17): [True: 0, False: 0]
330
0
            else if (key == "timesmart") nTimeSmart = LocaleIndependentAtoi<int64_t>(value);
  Branch (330:22): [True: 0, False: 0]
331
0
            else if (key == "from") m_from = value;
  Branch (331:22): [True: 0, False: 0]
332
0
            else if (key == "message") m_message = value;
  Branch (332:22): [True: 0, False: 0]
333
0
            else if (key == "comment") m_comment = value;
  Branch (333:22): [True: 0, False: 0]
334
0
            else if (key == "to") m_comment_to = value;
  Branch (334:22): [True: 0, False: 0]
335
0
            else if (key == "replaces_txid") m_replaces_txid = Txid::FromHex(value);
  Branch (335:22): [True: 0, False: 0]
336
0
            else if (key == "replaced_by_txid") m_replaced_by_txid = Txid::FromHex(value);
  Branch (336:22): [True: 0, False: 0]
337
0
            else {
338
0
                throw std::runtime_error("Unexpected value in CWalletTx strings value map");
339
0
            }
340
0
        }
341
342
0
        for (const auto& [type, data] : msgs_reqs) {
  Branch (342:39): [True: 0, False: 0]
343
0
            if (type == "Message") m_messages.emplace_back(data);
  Branch (343:17): [True: 0, False: 0]
344
0
            else if (type == "PaymentRequest") m_payment_requests.emplace_back(data);
  Branch (344:22): [True: 0, False: 0]
345
0
            else {
346
0
                throw std::runtime_error("Unknown type in CWalletTx messages and requests vector");
347
0
            }
348
0
        }
349
0
    }
350
351
0
    CTransactionRef GetTx() const { return m_txs.at(m_canonical_wtxid); }
352
353
    // Update the state of this wallet transaction along with a transaction that may have a different wtxid.
354
    // If the given transaction has a different wtxid, the transaction is stored if it has not been seen before.
355
    // The canonical wtxid is also updated. The tx that is confirmed becomes canonical. For unconfirmed txs,
356
    // those with witnesses are preferred, followed by least weight.
357
    bool Update(CTransactionRef tx, const TxState& new_state, WalletBatch& batch, bool metadata_changed);
358
359
    //! make sure balances are recalculated
360
    void MarkDirty()
361
0
    {
362
0
        m_amounts[DEBIT].Reset();
363
0
        m_amounts[CREDIT].Reset();
364
0
        fChangeCached = false;
365
0
        m_is_cache_empty = true;
366
0
        m_cached_from_me = std::nullopt;
367
0
    }
368
369
    /** True if tx is a malleation of this, i.e. it has the exact same version, locktime,
370
     * input order, input outpoints, input sequences, and outputs. Input scriptSigs and input scriptWitnesses may differ. */
371
    bool IsMalleation(const CWalletTx& tx) const;
372
373
    bool InMempool() const;
374
375
    int64_t GetTxTime() const;
376
377
0
    template<typename T> const T* state() const { return std::get_if<T>(&m_state); }
Unexecuted instantiation: _ZNK6wallet9CWalletTx5stateINS_15TxStateInactiveEEEPKT_v
Unexecuted instantiation: _ZNK6wallet9CWalletTx5stateINS_22TxStateBlockConflictedEEEPKT_v
Unexecuted instantiation: _ZNK6wallet9CWalletTx5stateINS_16TxStateConfirmedEEEPKT_v
Unexecuted instantiation: _ZNK6wallet9CWalletTx5stateINS_16TxStateInMempoolEEEPKT_v
378
0
    template<typename T> T* state() { return std::get_if<T>(&m_state); }
Unexecuted instantiation: _ZN6wallet9CWalletTx5stateINS_16TxStateConfirmedEEEPT_v
Unexecuted instantiation: _ZN6wallet9CWalletTx5stateINS_22TxStateBlockConflictedEEEPT_v
Unexecuted instantiation: _ZN6wallet9CWalletTx5stateINS_16TxStateInMempoolEEEPT_v
379
380
    //! Update transaction state when attaching to a chain, filling in heights
381
    //! of conflicted and confirmed blocks
382
    void updateState(interfaces::Chain& chain);
383
384
0
    bool isAbandoned() const { return state<TxStateInactive>() && state<TxStateInactive>()->abandoned; }
  Branch (384:39): [True: 0, False: 0]
  Branch (384:67): [True: 0, False: 0]
385
0
    bool isMempoolConflicted() const { return !mempool_conflicts.empty(); }
386
0
    bool isBlockConflicted() const { return state<TxStateBlockConflicted>(); }
387
0
    bool isInactive() const { return state<TxStateInactive>(); }
388
0
    bool isUnconfirmed() const { return !isAbandoned() && !isBlockConflicted() && !isMempoolConflicted() && !isConfirmed(); }
  Branch (388:41): [True: 0, False: 0]
  Branch (388:59): [True: 0, False: 0]
  Branch (388:83): [True: 0, False: 0]
  Branch (388:109): [True: 0, False: 0]
389
0
    bool isConfirmed() const { return state<TxStateConfirmed>(); }
390
0
    const Txid& GetHash() const LIFETIMEBOUND { return GetTx()->GetHash(); }
391
0
    const Wtxid& GetWitnessHash() const LIFETIMEBOUND { return GetTx()->GetWitnessHash(); }
392
0
    bool IsCoinBase() const { return GetTx()->IsCoinBase(); }
393
394
0
    const std::map<Wtxid, CTransactionRef>& GetTxs() const { return m_txs; }
395
396
    // Disable copying of CWalletTx objects to prevent bugs where instances get
397
    // copied in and out of the mapWallet map, and fields are updated in the
398
    // wrong copy.
399
    CWalletTx(const CWalletTx&) = delete;
400
    CWalletTx& operator=(const CWalletTx&) = delete;
401
402
    // Enable the default move constructor
403
0
    CWalletTx(CWalletTx&&) = default;
404
405
private:
406
    void SetDefaults()
407
0
    {
408
0
        nTimeReceived = 0;
409
0
        nTimeSmart = 0;
410
0
        fChangeCached = false;
411
0
        nChangeCached = 0;
412
0
        nOrderPos = -1;
413
0
    }
414
415
    void Init()
416
0
    {
417
0
        m_txs.clear();
418
0
        m_canonical_wtxid = Wtxid{};
419
0
        SetDefaults();
420
0
    }
421
422
    Wtxid m_canonical_wtxid;
423
    std::map<Wtxid, CTransactionRef> m_txs;
424
425
    //! Set m_canonical_wtxid to the best variant under the unconfirmed rule
426
    //! (witnessed preferred, then least weight). Ignores state.
427
    void RecomputeCanonical();
428
};
429
430
struct WalletTxOrderComparator {
431
    bool operator()(const CWalletTx* a, const CWalletTx* b) const
432
0
    {
433
0
        return a->nOrderPos < b->nOrderPos;
434
0
    }
435
};
436
437
class WalletTXO
438
{
439
private:
440
    const CWalletTx& m_wtx;
441
    const CTxOut& m_output;
442
443
public:
444
    WalletTXO(const CWalletTx& wtx, const CTxOut& output)
445
0
    : m_wtx(wtx),
446
0
    m_output(output)
447
0
    {
448
0
        Assume(std::ranges::find(wtx.GetTx()->vout, output) != wtx.GetTx()->vout.end());
449
0
    }
450
451
0
    const CWalletTx& GetWalletTx() const { return m_wtx; }
452
453
0
    const CTxOut& GetTxOut() const { return m_output; }
454
};
455
} // namespace wallet
456
457
#endif // BITCOIN_WALLET_TRANSACTION_H