Coverage Report

Created: 2025-06-10 13:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/bitcoin/src/wallet/transaction.h
Line
Count
Source
1
// Copyright (c) 2021-2022 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/overloaded.h>
14
#include <util/strencodings.h>
15
#include <util/string.h>
16
#include <wallet/types.h>
17
18
#include <bitset>
19
#include <cstdint>
20
#include <map>
21
#include <utility>
22
#include <variant>
23
#include <vector>
24
25
namespace interfaces {
26
class Chain;
27
} // namespace interfaces
28
29
namespace wallet {
30
//! State of transaction confirmed in a block.
31
struct TxStateConfirmed {
32
    uint256 confirmed_block_hash;
33
    int confirmed_block_height;
34
    int position_in_block;
35
36
12.0k
    explicit TxStateConfirmed(const uint256& block_hash, int height, int index) : confirmed_block_hash(block_hash), confirmed_block_height(height), position_in_block(index) {}
37
0
    std::string toString() const { return strprintf("Confirmed (block=%s, height=%i, index=%i)", confirmed_block_hash.ToString(), confirmed_block_height, position_in_block); }
38
};
39
40
//! State of transaction added to mempool.
41
struct TxStateInMempool {
42
0
    std::string toString() const { return strprintf("InMempool"); }
43
};
44
45
//! State of rejected transaction that conflicts with a confirmed block.
46
struct TxStateBlockConflicted {
47
    uint256 conflicting_block_hash;
48
    int conflicting_block_height;
49
50
0
    explicit TxStateBlockConflicted(const uint256& block_hash, int height) : conflicting_block_hash(block_hash), conflicting_block_height(height) {}
51
0
    std::string toString() const { return strprintf("BlockConflicted (block=%s, height=%i)", conflicting_block_hash.ToString(), conflicting_block_height); }
52
};
53
54
//! State of transaction not confirmed or conflicting with a known block and
55
//! not in the mempool. May conflict with the mempool, or with an unknown block,
56
//! or be abandoned, never broadcast, or rejected from the mempool for another
57
//! reason.
58
struct TxStateInactive {
59
    bool abandoned;
60
61
15.5k
    explicit TxStateInactive(bool abandoned = false) : abandoned(abandoned) {}
62
0
    std::string toString() const { return strprintf("Inactive (abandoned=%i)", abandoned); }
63
};
64
65
//! State of transaction loaded in an unrecognized state with unexpected hash or
66
//! index values. Treated as inactive (with serialized hash and index values
67
//! preserved) by default, but may enter another state if transaction is added
68
//! to the mempool, or confirmed, or abandoned, or found conflicting.
69
struct TxStateUnrecognized {
70
    uint256 block_hash;
71
    int index;
72
73
0
    TxStateUnrecognized(const uint256& block_hash, int index) : block_hash(block_hash), index(index) {}
74
0
    std::string toString() const { return strprintf("Unrecognized (block=%s, index=%i)", block_hash.ToString(), index); }
75
};
76
77
//! All possible CWalletTx states
78
using TxState = std::variant<TxStateConfirmed, TxStateInMempool, TxStateBlockConflicted, TxStateInactive, TxStateUnrecognized>;
79
80
//! Subset of states transaction sync logic is implemented to handle.
81
using SyncTxState = std::variant<TxStateConfirmed, TxStateInMempool, TxStateInactive>;
82
83
//! Try to interpret deserialized TxStateUnrecognized data as a recognized state.
84
static inline TxState TxStateInterpretSerialized(TxStateUnrecognized data)
85
0
{
86
0
    if (data.block_hash == uint256::ZERO) {
  Branch (86:9): [True: 0, False: 0]
87
0
        if (data.index == 0) return TxStateInactive{};
  Branch (87:13): [True: 0, False: 0]
88
0
    } else if (data.block_hash == uint256::ONE) {
  Branch (88:16): [True: 0, False: 0]
89
0
        if (data.index == -1) return TxStateInactive{/*abandoned=*/true};
  Branch (89:13): [True: 0, False: 0]
90
0
    } else if (data.index >= 0) {
  Branch (90:16): [True: 0, False: 0]
91
0
        return TxStateConfirmed{data.block_hash, /*height=*/-1, data.index};
92
0
    } else if (data.index == -1) {
  Branch (92:16): [True: 0, False: 0]
93
0
        return TxStateBlockConflicted{data.block_hash, /*height=*/-1};
94
0
    }
95
0
    return data;
96
0
}
Unexecuted instantiation: init.cpp:wallet::TxStateInterpretSerialized(wallet::TxStateUnrecognized)
Unexecuted instantiation: interfaces.cpp:wallet::TxStateInterpretSerialized(wallet::TxStateUnrecognized)
Unexecuted instantiation: load.cpp:wallet::TxStateInterpretSerialized(wallet::TxStateUnrecognized)
Unexecuted instantiation: receive.cpp:wallet::TxStateInterpretSerialized(wallet::TxStateUnrecognized)
Unexecuted instantiation: wallet.cpp:wallet::TxStateInterpretSerialized(wallet::TxStateUnrecognized)
Unexecuted instantiation: spend.cpp:wallet::TxStateInterpretSerialized(wallet::TxStateUnrecognized)
Unexecuted instantiation: transaction.cpp:wallet::TxStateInterpretSerialized(wallet::TxStateUnrecognized)
Unexecuted instantiation: walletdb.cpp:wallet::TxStateInterpretSerialized(wallet::TxStateUnrecognized)
Unexecuted instantiation: feebumper.cpp:wallet::TxStateInterpretSerialized(wallet::TxStateUnrecognized)
Unexecuted instantiation: fees.cpp:wallet::TxStateInterpretSerialized(wallet::TxStateUnrecognized)
Unexecuted instantiation: addresses.cpp:wallet::TxStateInterpretSerialized(wallet::TxStateUnrecognized)
Unexecuted instantiation: backup.cpp:wallet::TxStateInterpretSerialized(wallet::TxStateUnrecognized)
Unexecuted instantiation: coins.cpp:wallet::TxStateInterpretSerialized(wallet::TxStateUnrecognized)
Unexecuted instantiation: encrypt.cpp:wallet::TxStateInterpretSerialized(wallet::TxStateUnrecognized)
Unexecuted instantiation: signmessage.cpp:wallet::TxStateInterpretSerialized(wallet::TxStateUnrecognized)
Unexecuted instantiation: transactions.cpp:wallet::TxStateInterpretSerialized(wallet::TxStateUnrecognized)
Unexecuted instantiation: util.cpp:wallet::TxStateInterpretSerialized(wallet::TxStateUnrecognized)
97
98
//! Get TxState serialized block hash. Inverse of TxStateInterpretSerialized.
99
static inline uint256 TxStateSerializedBlockHash(const TxState& state)
100
0
{
101
0
    return std::visit(util::Overloaded{
102
0
        [](const TxStateInactive& inactive) { return inactive.abandoned ? uint256::ONE : uint256::ZERO; },
Unexecuted instantiation: wallet.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(wallet::TxStateInactive const&)#1}::operator()(wallet::TxStateInactive const&) const
Unexecuted instantiation: walletdb.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(wallet::TxStateInactive const&)#1}::operator()(wallet::TxStateInactive const&) const
  Branch (102:54): [True: 0, False: 0]
  Branch (102:54): [True: 0, False: 0]
103
0
        [](const TxStateInMempool& in_mempool) { return uint256::ZERO; },
Unexecuted instantiation: wallet.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(wallet::TxStateInMempool const&)#1}::operator()(wallet::TxStateInMempool const&) const
Unexecuted instantiation: walletdb.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(wallet::TxStateInMempool const&)#1}::operator()(wallet::TxStateInMempool const&) const
104
0
        [](const TxStateConfirmed& confirmed) { return confirmed.confirmed_block_hash; },
Unexecuted instantiation: wallet.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(wallet::TxStateConfirmed const&)#1}::operator()(wallet::TxStateConfirmed const&) const
Unexecuted instantiation: walletdb.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(wallet::TxStateConfirmed const&)#1}::operator()(wallet::TxStateConfirmed const&) const
105
0
        [](const TxStateBlockConflicted& conflicted) { return conflicted.conflicting_block_hash; },
Unexecuted instantiation: wallet.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(wallet::TxStateBlockConflicted const&)#1}::operator()(wallet::TxStateBlockConflicted const&) const
Unexecuted instantiation: walletdb.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(wallet::TxStateBlockConflicted const&)#1}::operator()(wallet::TxStateBlockConflicted const&) const
106
0
        [](const TxStateUnrecognized& unrecognized) { return unrecognized.block_hash; }
Unexecuted instantiation: wallet.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(wallet::TxStateUnrecognized const&)#1}::operator()(wallet::TxStateUnrecognized const&) const
Unexecuted instantiation: walletdb.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(wallet::TxStateUnrecognized const&)#1}::operator()(wallet::TxStateUnrecognized const&) const
107
0
    }, state);
108
0
}
Unexecuted instantiation: init.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: interfaces.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: load.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: receive.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: wallet.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: spend.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: transaction.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: walletdb.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: feebumper.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: fees.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: addresses.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: backup.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: coins.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: encrypt.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: signmessage.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: transactions.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: util.cpp:wallet::TxStateSerializedBlockHash(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
109
110
//! Get TxState serialized block index. Inverse of TxStateInterpretSerialized.
111
static inline int TxStateSerializedIndex(const TxState& state)
112
0
{
113
0
    return std::visit(util::Overloaded{
114
0
        [](const TxStateInactive& inactive) { return inactive.abandoned ? -1 : 0; },
Unexecuted instantiation: wallet.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(wallet::TxStateInactive const&)#1}::operator()(wallet::TxStateInactive const&) const
Unexecuted instantiation: walletdb.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(wallet::TxStateInactive const&)#1}::operator()(wallet::TxStateInactive const&) const
  Branch (114:54): [True: 0, False: 0]
  Branch (114:54): [True: 0, False: 0]
115
0
        [](const TxStateInMempool& in_mempool) { return 0; },
Unexecuted instantiation: wallet.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(wallet::TxStateInMempool const&)#1}::operator()(wallet::TxStateInMempool const&) const
Unexecuted instantiation: walletdb.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(wallet::TxStateInMempool const&)#1}::operator()(wallet::TxStateInMempool const&) const
116
0
        [](const TxStateConfirmed& confirmed) { return confirmed.position_in_block; },
Unexecuted instantiation: wallet.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(wallet::TxStateConfirmed const&)#1}::operator()(wallet::TxStateConfirmed const&) const
Unexecuted instantiation: walletdb.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(wallet::TxStateConfirmed const&)#1}::operator()(wallet::TxStateConfirmed const&) const
117
0
        [](const TxStateBlockConflicted& conflicted) { return -1; },
Unexecuted instantiation: wallet.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(wallet::TxStateBlockConflicted const&)#1}::operator()(wallet::TxStateBlockConflicted const&) const
Unexecuted instantiation: walletdb.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(wallet::TxStateBlockConflicted const&)#1}::operator()(wallet::TxStateBlockConflicted const&) const
118
0
        [](const TxStateUnrecognized& unrecognized) { return unrecognized.index; }
Unexecuted instantiation: wallet.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(wallet::TxStateUnrecognized const&)#1}::operator()(wallet::TxStateUnrecognized const&) const
Unexecuted instantiation: walletdb.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(wallet::TxStateUnrecognized const&)#1}::operator()(wallet::TxStateUnrecognized const&) const
119
0
    }, state);
120
0
}
Unexecuted instantiation: init.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: interfaces.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: load.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: receive.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: wallet.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: spend.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: transaction.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: walletdb.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: feebumper.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: fees.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: addresses.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: backup.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: coins.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: encrypt.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: signmessage.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: transactions.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
Unexecuted instantiation: util.cpp:wallet::TxStateSerializedIndex(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)
121
122
//! Return TxState or SyncTxState as a string for logging or debugging.
123
template<typename T>
124
std::string TxStateString(const T& state)
125
0
{
126
0
    return std::visit([](const auto& s) { return s.toString(); }, state);
Unexecuted instantiation: auto wallet::TxStateString<std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> >(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(auto:1 const&)#1}::operator()<wallet::TxStateConfirmed>(wallet::TxStateConfirmed const&) const
Unexecuted instantiation: auto wallet::TxStateString<std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> >(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(auto:1 const&)#1}::operator()<wallet::TxStateInMempool>(wallet::TxStateInMempool const&) const
Unexecuted instantiation: auto wallet::TxStateString<std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> >(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(auto:1 const&)#1}::operator()<wallet::TxStateBlockConflicted>(wallet::TxStateBlockConflicted const&) const
Unexecuted instantiation: auto wallet::TxStateString<std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> >(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(auto:1 const&)#1}::operator()<wallet::TxStateInactive>(wallet::TxStateInactive const&) const
Unexecuted instantiation: auto wallet::TxStateString<std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> >(std::variant<wallet::TxStateConfirmed, wallet::TxStateInMempool, wallet::TxStateBlockConflicted, wallet::TxStateInactive, wallet::TxStateUnrecognized> const&)::{lambda(auto:1 const&)#1}::operator()<wallet::TxStateUnrecognized>(wallet::TxStateUnrecognized const&) const
127
0
}
128
129
/**
130
 * Cachable amount subdivided into watchonly and spendable parts.
131
 */
132
struct CachableAmount
133
{
134
    // NO and ALL are never (supposed to be) cached
135
    std::bitset<ISMINE_ENUM_ELEMENTS> m_cached;
136
    CAmount m_value[ISMINE_ENUM_ELEMENTS];
137
    inline void Reset()
138
0
    {
139
0
        m_cached.reset();
140
0
    }
141
    void Set(isminefilter filter, CAmount value)
142
0
    {
143
0
        m_cached.set(filter);
144
0
        m_value[filter] = value;
145
0
    }
146
};
147
148
149
typedef std::map<std::string, std::string> mapValue_t;
150
151
152
/** Legacy class used for deserializing vtxPrev for backwards compatibility.
153
 * vtxPrev was removed in commit 93a18a3650292afbb441a47d1fa1b94aeb0164e3,
154
 * but old wallet.dat files may still contain vtxPrev vectors of CMerkleTxs.
155
 * These need to get deserialized for field alignment when deserializing
156
 * a CWalletTx, but the deserialized values are discarded.**/
157
class CMerkleTx
158
{
159
public:
160
    template<typename Stream>
161
    void Unserialize(Stream& s)
162
0
    {
163
0
        CTransactionRef tx;
164
0
        uint256 hashBlock;
165
0
        std::vector<uint256> vMerkleBranch;
166
0
        int nIndex;
167
168
0
        s >> TX_WITH_WITNESS(tx) >> hashBlock >> vMerkleBranch >> nIndex;
169
0
    }
170
};
171
172
/**
173
 * A transaction with a bunch of additional info that only the owner cares about.
174
 * It includes any unrecorded transactions needed to link it back to the block chain.
175
 */
176
class CWalletTx
177
{
178
public:
179
    /**
180
     * Key/value map with information about the transaction.
181
     *
182
     * The following keys can be read and written through the map and are
183
     * serialized in the wallet database:
184
     *
185
     *     "comment", "to"   - comment strings provided to sendtoaddress,
186
     *                         and sendmany wallet RPCs
187
     *     "replaces_txid"   - txid (as HexStr) of transaction replaced by
188
     *                         bumpfee on transaction created by bumpfee
189
     *     "replaced_by_txid" - txid (as HexStr) of transaction created by
190
     *                         bumpfee on transaction replaced by bumpfee
191
     *     "from", "message" - obsolete fields that could be set in UI prior to
192
     *                         2011 (removed in commit 4d9b223)
193
     *
194
     * The following keys are serialized in the wallet database, but shouldn't
195
     * be read or written through the map (they will be temporarily added and
196
     * removed from the map during serialization):
197
     *
198
     *     "fromaccount"     - serialized strFromAccount value
199
     *     "n"               - serialized nOrderPos value
200
     *     "timesmart"       - serialized nTimeSmart value
201
     *     "spent"           - serialized vfSpent value that existed prior to
202
     *                         2014 (removed in commit 93a18a3)
203
     */
204
    mapValue_t mapValue;
205
    std::vector<std::pair<std::string, std::string> > vOrderForm;
206
    unsigned int fTimeReceivedIsTxTime;
207
    unsigned int nTimeReceived; //!< time received by this node
208
    /**
209
     * Stable timestamp that never changes, and reflects the order a transaction
210
     * was added to the wallet. Timestamp is based on the block time for a
211
     * transaction added as part of a block, or else the time when the
212
     * transaction was received if it wasn't part of a block, with the timestamp
213
     * adjusted in both cases so timestamp order matches the order transactions
214
     * were added to the wallet. More details can be found in
215
     * CWallet::ComputeTimeSmart().
216
     */
217
    unsigned int nTimeSmart;
218
    int64_t nOrderPos; //!< position in ordered transaction list
219
    std::multimap<int64_t, CWalletTx*>::const_iterator m_it_wtxOrdered;
220
221
    // memory only
222
    enum AmountType { DEBIT, CREDIT, IMMATURE_CREDIT, AVAILABLE_CREDIT, AMOUNTTYPE_ENUM_ELEMENTS };
223
    mutable CachableAmount m_amounts[AMOUNTTYPE_ENUM_ELEMENTS];
224
    /**
225
     * This flag is true if all m_amounts caches are empty. This is particularly
226
     * useful in places where MarkDirty is conditionally called and the
227
     * condition can be expensive and thus can be skipped if the flag is true.
228
     * See MarkDestinationsDirty.
229
     */
230
    mutable bool m_is_cache_empty{true};
231
    mutable bool fChangeCached;
232
    mutable CAmount nChangeCached;
233
234
0
    CWalletTx(CTransactionRef tx, const TxState& state) : tx(std::move(tx)), m_state(state)
235
0
    {
236
0
        Init();
237
0
    }
238
239
    void Init()
240
0
    {
241
0
        mapValue.clear();
242
0
        vOrderForm.clear();
243
0
        fTimeReceivedIsTxTime = false;
244
0
        nTimeReceived = 0;
245
0
        nTimeSmart = 0;
246
0
        fChangeCached = false;
247
0
        nChangeCached = 0;
248
0
        nOrderPos = -1;
249
0
    }
250
251
    CTransactionRef tx;
252
    TxState m_state;
253
254
    // Set of mempool transactions that conflict
255
    // directly with the transaction, or that conflict
256
    // with an ancestor transaction. This set will be
257
    // empty if state is InMempool or Confirmed, but
258
    // can be nonempty if state is Inactive or
259
    // BlockConflicted.
260
    std::set<Txid> mempool_conflicts;
261
262
    template<typename Stream>
263
    void Serialize(Stream& s) const
264
0
    {
265
0
        mapValue_t mapValueCopy = mapValue;
266
267
0
        mapValueCopy["fromaccount"] = "";
268
0
        if (nOrderPos != -1) {
  Branch (268:13): [True: 0, False: 0]
269
0
            mapValueCopy["n"] = util::ToString(nOrderPos);
270
0
        }
271
0
        if (nTimeSmart) {
  Branch (271:13): [True: 0, False: 0]
272
0
            mapValueCopy["timesmart"] = strprintf("%u", nTimeSmart);
273
0
        }
274
275
0
        std::vector<uint8_t> dummy_vector1; //!< Used to be vMerkleBranch
276
0
        std::vector<uint8_t> dummy_vector2; //!< Used to be vtxPrev
277
0
        bool dummy_bool = false; //!< Used to be fFromMe and fSpent
278
0
        uint256 serializedHash = TxStateSerializedBlockHash(m_state);
279
0
        int serializedIndex = TxStateSerializedIndex(m_state);
280
0
        s << TX_WITH_WITNESS(tx) << serializedHash << dummy_vector1 << serializedIndex << dummy_vector2 << mapValueCopy << vOrderForm << fTimeReceivedIsTxTime << nTimeReceived << dummy_bool << dummy_bool;
281
0
    }
282
283
    template<typename Stream>
284
    void Unserialize(Stream& s)
285
0
    {
286
0
        Init();
287
288
0
        std::vector<uint256> dummy_vector1; //!< Used to be vMerkleBranch
289
0
        std::vector<CMerkleTx> dummy_vector2; //!< Used to be vtxPrev
290
0
        bool dummy_bool; //! Used to be fFromMe and fSpent
291
0
        uint256 serialized_block_hash;
292
0
        int serializedIndex;
293
0
        s >> TX_WITH_WITNESS(tx) >> serialized_block_hash >> dummy_vector1 >> serializedIndex >> dummy_vector2 >> mapValue >> vOrderForm >> fTimeReceivedIsTxTime >> nTimeReceived >> dummy_bool >> dummy_bool;
294
295
0
        m_state = TxStateInterpretSerialized({serialized_block_hash, serializedIndex});
296
297
0
        const auto it_op = mapValue.find("n");
298
0
        nOrderPos = (it_op != mapValue.end()) ? LocaleIndependentAtoi<int64_t>(it_op->second) : -1;
  Branch (298:21): [True: 0, False: 0]
299
0
        const auto it_ts = mapValue.find("timesmart");
300
0
        nTimeSmart = (it_ts != mapValue.end()) ? static_cast<unsigned int>(LocaleIndependentAtoi<int64_t>(it_ts->second)) : 0;
  Branch (300:22): [True: 0, False: 0]
301
302
0
        mapValue.erase("fromaccount");
303
0
        mapValue.erase("spent");
304
0
        mapValue.erase("n");
305
0
        mapValue.erase("timesmart");
306
0
    }
307
308
    void SetTx(CTransactionRef arg)
309
0
    {
310
0
        tx = std::move(arg);
311
0
    }
312
313
    //! make sure balances are recalculated
314
    void MarkDirty()
315
0
    {
316
0
        m_amounts[DEBIT].Reset();
317
0
        m_amounts[CREDIT].Reset();
318
0
        m_amounts[IMMATURE_CREDIT].Reset();
319
0
        m_amounts[AVAILABLE_CREDIT].Reset();
320
0
        fChangeCached = false;
321
0
        m_is_cache_empty = true;
322
0
    }
323
324
    /** True if only scriptSigs are different */
325
    bool IsEquivalentTo(const CWalletTx& tx) const;
326
327
    bool InMempool() const;
328
329
    int64_t GetTxTime() const;
330
331
0
    template<typename T> const T* state() const { return std::get_if<T>(&m_state); }
Unexecuted instantiation: wallet::TxStateInactive const* wallet::CWalletTx::state<wallet::TxStateInactive>() const
Unexecuted instantiation: wallet::TxStateBlockConflicted const* wallet::CWalletTx::state<wallet::TxStateBlockConflicted>() const
Unexecuted instantiation: wallet::TxStateConfirmed const* wallet::CWalletTx::state<wallet::TxStateConfirmed>() const
Unexecuted instantiation: wallet::TxStateInMempool const* wallet::CWalletTx::state<wallet::TxStateInMempool>() const
332
0
    template<typename T> T* state() { return std::get_if<T>(&m_state); }
Unexecuted instantiation: wallet::TxStateConfirmed* wallet::CWalletTx::state<wallet::TxStateConfirmed>()
Unexecuted instantiation: wallet::TxStateBlockConflicted* wallet::CWalletTx::state<wallet::TxStateBlockConflicted>()
Unexecuted instantiation: wallet::TxStateInMempool* wallet::CWalletTx::state<wallet::TxStateInMempool>()
333
334
    //! Update transaction state when attaching to a chain, filling in heights
335
    //! of conflicted and confirmed blocks
336
    void updateState(interfaces::Chain& chain);
337
338
0
    bool isAbandoned() const { return state<TxStateInactive>() && state<TxStateInactive>()->abandoned; }
  Branch (338:39): [True: 0, False: 0]
  Branch (338:67): [True: 0, False: 0]
339
0
    bool isMempoolConflicted() const { return !mempool_conflicts.empty(); }
340
0
    bool isBlockConflicted() const { return state<TxStateBlockConflicted>(); }
341
0
    bool isInactive() const { return state<TxStateInactive>(); }
342
0
    bool isUnconfirmed() const { return !isAbandoned() && !isBlockConflicted() && !isMempoolConflicted() && !isConfirmed(); }
  Branch (342:41): [True: 0, False: 0]
  Branch (342:59): [True: 0, False: 0]
  Branch (342:83): [True: 0, False: 0]
  Branch (342:109): [True: 0, False: 0]
343
0
    bool isConfirmed() const { return state<TxStateConfirmed>(); }
344
0
    const Txid& GetHash() const LIFETIMEBOUND { return tx->GetHash(); }
345
0
    const Wtxid& GetWitnessHash() const LIFETIMEBOUND { return tx->GetWitnessHash(); }
346
0
    bool IsCoinBase() const { return tx->IsCoinBase(); }
347
348
private:
349
    // Disable copying of CWalletTx objects to prevent bugs where instances get
350
    // copied in and out of the mapWallet map, and fields are updated in the
351
    // wrong copy.
352
    CWalletTx(const CWalletTx&) = default;
353
0
    CWalletTx& operator=(const CWalletTx&) = default;
354
public:
355
    // Instead have an explicit copy function
356
    void CopyFrom(const CWalletTx&);
357
};
358
359
struct WalletTxOrderComparator {
360
    bool operator()(const CWalletTx* a, const CWalletTx* b) const
361
0
    {
362
0
        return a->nOrderPos < b->nOrderPos;
363
0
    }
364
};
365
} // namespace wallet
366
367
#endif // BITCOIN_WALLET_TRANSACTION_H