forked from bitcoin/bitcoin
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtransaction.cpp
More file actions
111 lines (97 loc) · 3.77 KB
/
Copy pathtransaction.cpp
File metadata and controls
111 lines (97 loc) · 3.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// Copyright (c) 2021-present The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <wallet/transaction.h>
#include <consensus/validation.h>
#include <interfaces/chain.h>
using interfaces::FoundBlock;
namespace wallet {
bool CWalletTx::IsEquivalentTo(const CWalletTx& _tx) const
{
CMutableTransaction tx1 {*this->GetTx()};
CMutableTransaction tx2 {*_tx.GetTx()};
for (auto& txin : tx1.vin) {
txin.scriptSig = CScript();
txin.scriptWitness.SetNull();
}
for (auto& txin : tx2.vin) {
txin.scriptSig = CScript();
txin.scriptWitness.SetNull();
}
return CTransaction(tx1) == CTransaction(tx2);
}
bool CWalletTx::InMempool() const
{
return state<TxStateInMempool>();
}
int64_t CWalletTx::GetTxTime() const
{
int64_t n = nTimeSmart;
return n ? n : nTimeReceived;
}
void CWalletTx::updateState(interfaces::Chain& chain)
{
bool active;
auto lookup_block = [&](const uint256& hash, int& height, TxState& state) {
// If tx block (or conflicting block) was reorged out of chain
// while the wallet was shutdown, change tx status to UNCONFIRMED
// and reset block height, hash, and index. ABANDONED tx don't have
// associated blocks and don't need to be updated. The case where a
// transaction was reorged out while online and then reconfirmed
// while offline is covered by the rescan logic.
if (!chain.findBlock(hash, FoundBlock().inActiveChain(active).height(height)) || !active) {
state = TxStateInactive{};
}
};
if (auto* conf = state<TxStateConfirmed>()) {
lookup_block(conf->confirmed_block_hash, conf->confirmed_block_height, m_state);
} else if (auto* conf = state<TxStateBlockConflicted>()) {
lookup_block(conf->conflicting_block_hash, conf->conflicting_block_height, m_state);
}
// If the above downgraded a previously-confirmed witness variant back to unconfirmed,
// the canonical choice is no longer pinned by confirmation. Re-apply the least-weight rule.
if (!isConfirmed()) RecomputeCanonical();
}
bool CWalletTx::Update(CTransactionRef new_tx, const TxState& new_state)
{
Assert(new_tx);
if (!Assume(GetHash() == new_tx->GetHash())) {
return false;
}
bool ret = false;
const auto& [tx_pair, inserted] = m_txs.emplace(new_tx->GetWitnessHash(), std::move(new_tx));
if (inserted) {
ret = true;
}
const auto& [wtxid, tx] = *tx_pair;
if (new_state.index() != m_state.index()) {
m_state = new_state;
if (state<TxStateConfirmed>()) {
m_canonical_wtxid = wtxid;
}
ret = true;
} else {
assert(TxStateSerializedIndex(m_state) == TxStateSerializedIndex(new_state));
assert(TxStateSerializedBlockHash(m_state) == TxStateSerializedBlockHash(new_state));
}
// While unconfirmed, derive the canonical variant from all known variants
if (!isConfirmed()) {
const Wtxid prev_canonical = m_canonical_wtxid;
RecomputeCanonical();
if (m_canonical_wtxid != prev_canonical) {
ret = true;
}
}
return ret;
}
void CWalletTx::RecomputeCanonical()
{
// Recompute the canonical variant among the witness variants. They share
// the txid but differ in the wtxid. Prefer variant with witness data and
// the least weight.
Assert(!m_txs.empty());
m_canonical_wtxid = std::ranges::min_element(m_txs, std::less{}, [](const auto& entry) {
return std::make_pair(!entry.second->HasWitness(), GetTransactionWeight(*entry.second));
})->first;
}
} // namespace wallet