Bitcoin Core 22.99.0
P2P Digital Currency
receive.cpp
Go to the documentation of this file.
1// Copyright (c) 2021 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 <consensus/amount.h>
7#include <wallet/receive.h>
9#include <wallet/wallet.h>
10
12{
13 AssertLockHeld(wallet.cs_wallet);
14 std::map<uint256, CWalletTx>::const_iterator mi = wallet.mapWallet.find(txin.prevout.hash);
15 if (mi != wallet.mapWallet.end())
16 {
17 const CWalletTx& prev = (*mi).second;
18 if (txin.prevout.n < prev.tx->vout.size())
19 return wallet.IsMine(prev.tx->vout[txin.prevout.n]);
20 }
21 return ISMINE_NO;
22}
23
24bool AllInputsMine(const CWallet& wallet, const CTransaction& tx, const isminefilter& filter)
25{
26 LOCK(wallet.cs_wallet);
27
28 for (const CTxIn& txin : tx.vin)
29 {
30 auto mi = wallet.mapWallet.find(txin.prevout.hash);
31 if (mi == wallet.mapWallet.end())
32 return false; // any unknown inputs can't be from us
33
34 const CWalletTx& prev = (*mi).second;
35
36 if (txin.prevout.n >= prev.tx->vout.size())
37 return false; // invalid input!
38
39 if (!(wallet.IsMine(prev.tx->vout[txin.prevout.n]) & filter))
40 return false;
41 }
42 return true;
43}
44
45CAmount OutputGetCredit(const CWallet& wallet, const CTxOut& txout, const isminefilter& filter)
46{
47 if (!MoneyRange(txout.nValue))
48 throw std::runtime_error(std::string(__func__) + ": value out of range");
49 LOCK(wallet.cs_wallet);
50 return ((wallet.IsMine(txout) & filter) ? txout.nValue : 0);
51}
52
53CAmount TxGetCredit(const CWallet& wallet, const CTransaction& tx, const isminefilter& filter)
54{
55 CAmount nCredit = 0;
56 for (const CTxOut& txout : tx.vout)
57 {
58 nCredit += OutputGetCredit(wallet, txout, filter);
59 if (!MoneyRange(nCredit))
60 throw std::runtime_error(std::string(__func__) + ": value out of range");
61 }
62 return nCredit;
63}
64
65bool ScriptIsChange(const CWallet& wallet, const CScript& script)
66{
67 // TODO: fix handling of 'change' outputs. The assumption is that any
68 // payment to a script that is ours, but is not in the address book
69 // is change. That assumption is likely to break when we implement multisignature
70 // wallets that return change back into a multi-signature-protected address;
71 // a better way of identifying which outputs are 'the send' and which are
72 // 'the change' will need to be implemented (maybe extend CWalletTx to remember
73 // which output, if any, was change).
74 AssertLockHeld(wallet.cs_wallet);
75 if (wallet.IsMine(script))
76 {
77 CTxDestination address;
78 if (!ExtractDestination(script, address))
79 return true;
80 if (!wallet.FindAddressBookEntry(address)) {
81 return true;
82 }
83 }
84 return false;
85}
86
87bool OutputIsChange(const CWallet& wallet, const CTxOut& txout)
88{
89 return ScriptIsChange(wallet, txout.scriptPubKey);
90}
91
93{
94 AssertLockHeld(wallet.cs_wallet);
95 if (!MoneyRange(txout.nValue))
96 throw std::runtime_error(std::string(__func__) + ": value out of range");
97 return (OutputIsChange(wallet, txout) ? txout.nValue : 0);
98}
99
101{
102 LOCK(wallet.cs_wallet);
103 CAmount nChange = 0;
104 for (const CTxOut& txout : tx.vout)
105 {
106 nChange += OutputGetChange(wallet, txout);
107 if (!MoneyRange(nChange))
108 throw std::runtime_error(std::string(__func__) + ": value out of range");
109 }
110 return nChange;
111}
112
113static CAmount GetCachableAmount(const CWallet& wallet, const CWalletTx& wtx, CWalletTx::AmountType type, const isminefilter& filter, bool recalculate = false)
114{
115 auto& amount = wtx.m_amounts[type];
116 if (recalculate || !amount.m_cached[filter]) {
117 amount.Set(filter, type == CWalletTx::DEBIT ? wallet.GetDebit(*wtx.tx, filter) : TxGetCredit(wallet, *wtx.tx, filter));
118 wtx.m_is_cache_empty = false;
119 }
120 return amount.m_value[filter];
121}
122
124{
125 // Must wait until coinbase is safely deep enough in the chain before valuing it
126 if (wallet.IsTxImmatureCoinBase(wtx))
127 return 0;
128
129 CAmount credit = 0;
130 if (filter & ISMINE_SPENDABLE) {
131 // GetBalance can assume transactions in mapWallet won't change
133 }
134 if (filter & ISMINE_WATCH_ONLY) {
136 }
137 return credit;
138}
139
141{
142 if (wtx.tx->vin.empty())
143 return 0;
144
145 CAmount debit = 0;
146 if (filter & ISMINE_SPENDABLE) {
148 }
149 if (filter & ISMINE_WATCH_ONLY) {
151 }
152 return debit;
153}
154
156{
157 if (wtx.fChangeCached)
158 return wtx.nChangeCached;
159 wtx.nChangeCached = TxGetChange(wallet, *wtx.tx);
160 wtx.fChangeCached = true;
161 return wtx.nChangeCached;
162}
163
164CAmount CachedTxGetImmatureCredit(const CWallet& wallet, const CWalletTx& wtx, bool fUseCache)
165{
166 if (wallet.IsTxImmatureCoinBase(wtx) && wallet.IsTxInMainChain(wtx)) {
168 }
169
170 return 0;
171}
172
173CAmount CachedTxGetImmatureWatchOnlyCredit(const CWallet& wallet, const CWalletTx& wtx, const bool fUseCache)
174{
175 if (wallet.IsTxImmatureCoinBase(wtx) && wallet.IsTxInMainChain(wtx)) {
177 }
178
179 return 0;
180}
181
182CAmount CachedTxGetAvailableCredit(const CWallet& wallet, const CWalletTx& wtx, bool fUseCache, const isminefilter& filter)
183{
184 // Avoid caching ismine for NO or ALL cases (could remove this check and simplify in the future).
185 bool allow_cache = (filter & ISMINE_ALL) && (filter & ISMINE_ALL) != ISMINE_ALL;
186
187 // Must wait until coinbase is safely deep enough in the chain before valuing it
188 if (wallet.IsTxImmatureCoinBase(wtx))
189 return 0;
190
191 if (fUseCache && allow_cache && wtx.m_amounts[CWalletTx::AVAILABLE_CREDIT].m_cached[filter]) {
193 }
194
195 bool allow_used_addresses = (filter & ISMINE_USED) || !wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE);
196 CAmount nCredit = 0;
197 uint256 hashTx = wtx.GetHash();
198 for (unsigned int i = 0; i < wtx.tx->vout.size(); i++)
199 {
200 if (!wallet.IsSpent(hashTx, i) && (allow_used_addresses || !wallet.IsSpentKey(hashTx, i))) {
201 const CTxOut &txout = wtx.tx->vout[i];
202 nCredit += OutputGetCredit(wallet, txout, filter);
203 if (!MoneyRange(nCredit))
204 throw std::runtime_error(std::string(__func__) + " : value out of range");
205 }
206 }
207
208 if (allow_cache) {
209 wtx.m_amounts[CWalletTx::AVAILABLE_CREDIT].Set(filter, nCredit);
210 wtx.m_is_cache_empty = false;
211 }
212
213 return nCredit;
214}
215
217 std::list<COutputEntry>& listReceived,
218 std::list<COutputEntry>& listSent, CAmount& nFee, const isminefilter& filter)
219{
220 nFee = 0;
221 listReceived.clear();
222 listSent.clear();
223
224 // Compute fee:
225 CAmount nDebit = CachedTxGetDebit(wallet, wtx, filter);
226 if (nDebit > 0) // debit>0 means we signed/sent this transaction
227 {
228 CAmount nValueOut = wtx.tx->GetValueOut();
229 nFee = nDebit - nValueOut;
230 }
231
232 LOCK(wallet.cs_wallet);
233 // Sent/received.
234 for (unsigned int i = 0; i < wtx.tx->vout.size(); ++i)
235 {
236 const CTxOut& txout = wtx.tx->vout[i];
237 isminetype fIsMine = wallet.IsMine(txout);
238 // Only need to handle txouts if AT LEAST one of these is true:
239 // 1) they debit from us (sent)
240 // 2) the output is to us (received)
241 if (nDebit > 0)
242 {
243 // Don't report 'change' txouts
244 if (OutputIsChange(wallet, txout))
245 continue;
246 }
247 else if (!(fIsMine & filter))
248 continue;
249
250 // In either case, we need to get the destination address
251 CTxDestination address;
252
253 if (!ExtractDestination(txout.scriptPubKey, address) && !txout.scriptPubKey.IsUnspendable())
254 {
255 wallet.WalletLogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
256 wtx.GetHash().ToString());
257 address = CNoDestination();
258 }
259
260 COutputEntry output = {address, txout.nValue, (int)i};
261
262 // If we are debited by the transaction, add the output as a "sent" entry
263 if (nDebit > 0)
264 listSent.push_back(output);
265
266 // If we are receiving the output, add it as a "received" entry
267 if (fIsMine & filter)
268 listReceived.push_back(output);
269 }
270
271}
272
273bool CachedTxIsFromMe(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter)
274{
275 return (CachedTxGetDebit(wallet, wtx, filter) > 0);
276}
277
278bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx, std::set<uint256>& trusted_parents)
279{
280 AssertLockHeld(wallet.cs_wallet);
281 // Quick answer in most cases
282 if (!wallet.chain().checkFinalTx(*wtx.tx)) return false;
283 int nDepth = wallet.GetTxDepthInMainChain(wtx);
284 if (nDepth >= 1) return true;
285 if (nDepth < 0) return false;
286 // using wtx's cached debit
287 if (!wallet.m_spend_zero_conf_change || !CachedTxIsFromMe(wallet, wtx, ISMINE_ALL)) return false;
288
289 // Don't trust unconfirmed transactions from us unless they are in the mempool.
290 if (!wtx.InMempool()) return false;
291
292 // Trusted if all inputs are from us and are in the mempool:
293 for (const CTxIn& txin : wtx.tx->vin)
294 {
295 // Transactions not sent by us: not trusted
296 const CWalletTx* parent = wallet.GetWalletTx(txin.prevout.hash);
297 if (parent == nullptr) return false;
298 const CTxOut& parentOut = parent->tx->vout[txin.prevout.n];
299 // Check that this specific input being spent is trusted
300 if (wallet.IsMine(parentOut) != ISMINE_SPENDABLE) return false;
301 // If we've already trusted this parent, continue
302 if (trusted_parents.count(parent->GetHash())) continue;
303 // Recurse to check that the parent is also trusted
304 if (!CachedTxIsTrusted(wallet, *parent, trusted_parents)) return false;
305 trusted_parents.insert(parent->GetHash());
306 }
307 return true;
308}
309
311{
312 std::set<uint256> trusted_parents;
313 LOCK(wallet.cs_wallet);
314 return CachedTxIsTrusted(wallet, wtx, trusted_parents);
315}
316
317Balance GetBalance(const CWallet& wallet, const int min_depth, bool avoid_reuse)
318{
319 Balance ret;
320 isminefilter reuse_filter = avoid_reuse ? ISMINE_NO : ISMINE_USED;
321 {
322 LOCK(wallet.cs_wallet);
323 std::set<uint256> trusted_parents;
324 for (const auto& entry : wallet.mapWallet)
325 {
326 const CWalletTx& wtx = entry.second;
327 const bool is_trusted{CachedTxIsTrusted(wallet, wtx, trusted_parents)};
328 const int tx_depth{wallet.GetTxDepthInMainChain(wtx)};
329 const CAmount tx_credit_mine{CachedTxGetAvailableCredit(wallet, wtx, /* fUseCache */ true, ISMINE_SPENDABLE | reuse_filter)};
330 const CAmount tx_credit_watchonly{CachedTxGetAvailableCredit(wallet, wtx, /* fUseCache */ true, ISMINE_WATCH_ONLY | reuse_filter)};
331 if (is_trusted && tx_depth >= min_depth) {
332 ret.m_mine_trusted += tx_credit_mine;
333 ret.m_watchonly_trusted += tx_credit_watchonly;
334 }
335 if (!is_trusted && tx_depth == 0 && wtx.InMempool()) {
336 ret.m_mine_untrusted_pending += tx_credit_mine;
337 ret.m_watchonly_untrusted_pending += tx_credit_watchonly;
338 }
341 }
342 }
343 return ret;
344}
345
346std::map<CTxDestination, CAmount> GetAddressBalances(const CWallet& wallet)
347{
348 std::map<CTxDestination, CAmount> balances;
349
350 {
351 LOCK(wallet.cs_wallet);
352 std::set<uint256> trusted_parents;
353 for (const auto& walletEntry : wallet.mapWallet)
354 {
355 const CWalletTx& wtx = walletEntry.second;
356
357 if (!CachedTxIsTrusted(wallet, wtx, trusted_parents))
358 continue;
359
360 if (wallet.IsTxImmatureCoinBase(wtx))
361 continue;
362
363 int nDepth = wallet.GetTxDepthInMainChain(wtx);
364 if (nDepth < (CachedTxIsFromMe(wallet, wtx, ISMINE_ALL) ? 0 : 1))
365 continue;
366
367 for (unsigned int i = 0; i < wtx.tx->vout.size(); i++)
368 {
369 CTxDestination addr;
370 if (!wallet.IsMine(wtx.tx->vout[i]))
371 continue;
372 if(!ExtractDestination(wtx.tx->vout[i].scriptPubKey, addr))
373 continue;
374
375 CAmount n = wallet.IsSpent(walletEntry.first, i) ? 0 : wtx.tx->vout[i].nValue;
376 balances[addr] += n;
377 }
378 }
379 }
380
381 return balances;
382}
383
384std::set< std::set<CTxDestination> > GetAddressGroupings(const CWallet& wallet)
385{
386 AssertLockHeld(wallet.cs_wallet);
387 std::set< std::set<CTxDestination> > groupings;
388 std::set<CTxDestination> grouping;
389
390 for (const auto& walletEntry : wallet.mapWallet)
391 {
392 const CWalletTx& wtx = walletEntry.second;
393
394 if (wtx.tx->vin.size() > 0)
395 {
396 bool any_mine = false;
397 // group all input addresses with each other
398 for (const CTxIn& txin : wtx.tx->vin)
399 {
400 CTxDestination address;
401 if(!InputIsMine(wallet, txin)) /* If this input isn't mine, ignore it */
402 continue;
403 if(!ExtractDestination(wallet.mapWallet.at(txin.prevout.hash).tx->vout[txin.prevout.n].scriptPubKey, address))
404 continue;
405 grouping.insert(address);
406 any_mine = true;
407 }
408
409 // group change with input addresses
410 if (any_mine)
411 {
412 for (const CTxOut& txout : wtx.tx->vout)
413 if (OutputIsChange(wallet, txout))
414 {
415 CTxDestination txoutAddr;
416 if(!ExtractDestination(txout.scriptPubKey, txoutAddr))
417 continue;
418 grouping.insert(txoutAddr);
419 }
420 }
421 if (grouping.size() > 0)
422 {
423 groupings.insert(grouping);
424 grouping.clear();
425 }
426 }
427
428 // group lone addrs by themselves
429 for (const auto& txout : wtx.tx->vout)
430 if (wallet.IsMine(txout))
431 {
432 CTxDestination address;
433 if(!ExtractDestination(txout.scriptPubKey, address))
434 continue;
435 grouping.insert(address);
436 groupings.insert(grouping);
437 grouping.clear();
438 }
439 }
440
441 std::set< std::set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
442 std::map< CTxDestination, std::set<CTxDestination>* > setmap; // map addresses to the unique group containing it
443 for (std::set<CTxDestination> _grouping : groupings)
444 {
445 // make a set of all the groups hit by this new group
446 std::set< std::set<CTxDestination>* > hits;
447 std::map< CTxDestination, std::set<CTxDestination>* >::iterator it;
448 for (const CTxDestination& address : _grouping)
449 if ((it = setmap.find(address)) != setmap.end())
450 hits.insert((*it).second);
451
452 // merge all hit groups into a new single group and delete old groups
453 std::set<CTxDestination>* merged = new std::set<CTxDestination>(_grouping);
454 for (std::set<CTxDestination>* hit : hits)
455 {
456 merged->insert(hit->begin(), hit->end());
457 uniqueGroupings.erase(hit);
458 delete hit;
459 }
460 uniqueGroupings.insert(merged);
461
462 // update setmap
463 for (const CTxDestination& element : *merged)
464 setmap[element] = merged;
465 }
466
467 std::set< std::set<CTxDestination> > ret;
468 for (const std::set<CTxDestination>* uniqueGrouping : uniqueGroupings)
469 {
470 ret.insert(*uniqueGrouping);
471 delete uniqueGrouping;
472 }
473
474 return ret;
475}
bool MoneyRange(const CAmount &nValue)
Definition: amount.h:27
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
uint32_t n
Definition: transaction.h:30
uint256 hash
Definition: transaction.h:29
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:406
bool IsUnspendable() const
Returns whether the script is guaranteed to fail at execution, regardless of the initial stack.
Definition: script.h:544
The basic transaction that is broadcasted on the network and contained in blocks.
Definition: transaction.h:260
const std::vector< CTxOut > vout
Definition: transaction.h:271
const std::vector< CTxIn > vin
Definition: transaction.h:270
An input of a transaction.
Definition: transaction.h:66
COutPoint prevout
Definition: transaction.h:68
An output of a transaction.
Definition: transaction.h:129
CScript scriptPubKey
Definition: transaction.h:132
CAmount nValue
Definition: transaction.h:131
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:229
A transaction with a bunch of additional info that only the owner cares about.
Definition: transaction.h:47
CTransactionRef tx
Definition: transaction.h:138
@ AVAILABLE_CREDIT
Definition: transaction.h:104
@ IMMATURE_CREDIT
Definition: transaction.h:104
const uint256 & GetHash() const
Definition: transaction.h:267
bool fChangeCached
Definition: transaction.h:113
CachableAmount m_amounts[AMOUNTTYPE_ENUM_ELEMENTS]
Definition: transaction.h:105
bool m_is_cache_empty
This flag is true if all m_amounts caches are empty.
Definition: transaction.h:112
bool InMempool() const
Definition: transaction.cpp:16
CAmount nChangeCached
Definition: transaction.h:115
std::string ToString() const
Definition: uint256.cpp:64
256-bit opaque blob.
Definition: uint256.h:124
uint8_t isminefilter
Definition: wallet.h:36
isminetype
IsMine() return codes, which depend on ScriptPubKeyMan implementation.
Definition: ismine.h:39
@ ISMINE_ALL
Definition: ismine.h:44
@ ISMINE_SPENDABLE
Definition: ismine.h:42
@ ISMINE_NO
Definition: ismine.h:40
@ ISMINE_WATCH_ONLY
Definition: ismine.h:41
@ ISMINE_USED
Definition: ismine.h:43
bool CachedTxIsFromMe(const CWallet &wallet, const CWalletTx &wtx, const isminefilter &filter)
Definition: receive.cpp:273
std::set< std::set< CTxDestination > > GetAddressGroupings(const CWallet &wallet)
Definition: receive.cpp:384
CAmount OutputGetCredit(const CWallet &wallet, const CTxOut &txout, const isminefilter &filter)
Definition: receive.cpp:45
CAmount TxGetCredit(const CWallet &wallet, const CTransaction &tx, const isminefilter &filter)
Definition: receive.cpp:53
CAmount TxGetChange(const CWallet &wallet, const CTransaction &tx)
Definition: receive.cpp:100
std::map< CTxDestination, CAmount > GetAddressBalances(const CWallet &wallet)
Definition: receive.cpp:346
bool ScriptIsChange(const CWallet &wallet, const CScript &script)
Definition: receive.cpp:65
CAmount CachedTxGetAvailableCredit(const CWallet &wallet, const CWalletTx &wtx, bool fUseCache, const isminefilter &filter)
Definition: receive.cpp:182
void CachedTxGetAmounts(const CWallet &wallet, const CWalletTx &wtx, std::list< COutputEntry > &listReceived, std::list< COutputEntry > &listSent, CAmount &nFee, const isminefilter &filter)
Definition: receive.cpp:216
CAmount CachedTxGetImmatureWatchOnlyCredit(const CWallet &wallet, const CWalletTx &wtx, const bool fUseCache)
Definition: receive.cpp:173
CAmount CachedTxGetImmatureCredit(const CWallet &wallet, const CWalletTx &wtx, bool fUseCache)
Definition: receive.cpp:164
static CAmount GetCachableAmount(const CWallet &wallet, const CWalletTx &wtx, CWalletTx::AmountType type, const isminefilter &filter, bool recalculate=false)
Definition: receive.cpp:113
bool AllInputsMine(const CWallet &wallet, const CTransaction &tx, const isminefilter &filter)
Returns whether all of the inputs match the filter.
Definition: receive.cpp:24
bool OutputIsChange(const CWallet &wallet, const CTxOut &txout)
Definition: receive.cpp:87
CAmount OutputGetChange(const CWallet &wallet, const CTxOut &txout)
Definition: receive.cpp:92
CAmount CachedTxGetDebit(const CWallet &wallet, const CWalletTx &wtx, const isminefilter &filter)
filter decides which addresses will count towards the debit
Definition: receive.cpp:140
CAmount CachedTxGetChange(const CWallet &wallet, const CWalletTx &wtx)
Definition: receive.cpp:155
CAmount CachedTxGetCredit(const CWallet &wallet, const CWalletTx &wtx, const isminefilter &filter)
Definition: receive.cpp:123
Balance GetBalance(const CWallet &wallet, const int min_depth, bool avoid_reuse)
Definition: receive.cpp:317
bool CachedTxIsTrusted(const CWallet &wallet, const CWalletTx &wtx, std::set< uint256 > &trusted_parents)
Definition: receive.cpp:278
isminetype InputIsMine(const CWallet &wallet, const CTxIn &txin)
Definition: receive.cpp:11
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:213
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:157
CAmount m_mine_immature
Immature coinbases in the main chain.
Definition: receive.h:54
CAmount m_watchonly_untrusted_pending
Definition: receive.h:56
CAmount m_mine_trusted
Trusted, at depth=GetBalance.min_depth or more.
Definition: receive.h:52
CAmount m_watchonly_immature
Definition: receive.h:57
CAmount m_watchonly_trusted
Definition: receive.h:55
CAmount m_mine_untrusted_pending
Untrusted, but in mempool (pending)
Definition: receive.h:53
Definition: receive.h:38
void Set(isminefilter filter, CAmount value)
Definition: ismine.h:63
CAmount m_value[ISMINE_ENUM_ELEMENTS]
Definition: ismine.h:58
std::bitset< ISMINE_ENUM_ELEMENTS > m_cached
Definition: ismine.h:57
#define LOCK(cs)
Definition: sync.h:226
AssertLockHeld(pool.cs)
@ WALLET_FLAG_AVOID_REUSE
Definition: walletutil.h:41