receive.cpp raw
1 // Copyright (c) 2021-2022 The Limenka 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>
6 #include <consensus/consensus.h>
7 #include <util/check.h>
8 #include <wallet/receive.h>
9 #include <wallet/transaction.h>
10 #include <wallet/wallet.h>
11
12 namespace wallet {
13 isminetype InputIsMine(const CWallet& wallet, const CTxIn& txin)
14 {
15 AssertLockHeld(wallet.cs_wallet);
16 const CWalletTx* prev = wallet.GetWalletTx(txin.prevout.hash);
17 if (prev && txin.prevout.n < prev->tx->vout.size()) {
18 return wallet.IsMine(prev->tx->vout[txin.prevout.n]);
19 }
20 return ISMINE_NO;
21 }
22
23 bool AllInputsMine(const CWallet& wallet, const CTransaction& tx, const isminefilter& filter)
24 {
25 LOCK(wallet.cs_wallet);
26 for (const CTxIn& txin : tx.vin) {
27 if (!(InputIsMine(wallet, txin) & filter)) return false;
28 }
29 return true;
30 }
31
32 CAmount OutputGetCredit(const CWallet& wallet, const CTxOut& txout, const isminefilter& filter)
33 {
34 if (!MoneyRange(txout.nValue))
35 throw std::runtime_error(std::string(__func__) + ": value out of range");
36 LOCK(wallet.cs_wallet);
37 return ((wallet.IsMine(txout) & filter) ? txout.nValue : 0);
38 }
39
40 CAmount TxGetCredit(const CWallet& wallet, const CTransaction& tx, const isminefilter& filter)
41 {
42 CAmount nCredit = 0;
43 for (const CTxOut& txout : tx.vout)
44 {
45 nCredit += OutputGetCredit(wallet, txout, filter);
46 if (!MoneyRange(nCredit))
47 throw std::runtime_error(std::string(__func__) + ": value out of range");
48 }
49 return nCredit;
50 }
51
52 bool ScriptIsChange(const CWallet& wallet, const CScript& script)
53 {
54 // TODO: fix handling of 'change' outputs. The assumption is that any
55 // payment to a script that is ours, but is not in the address book
56 // is change. That assumption is likely to break when we implement multisignature
57 // wallets that return change back into a multi-signature-protected address;
58 // a better way of identifying which outputs are 'the send' and which are
59 // 'the change' will need to be implemented (maybe extend CWalletTx to remember
60 // which output, if any, was change).
61 AssertLockHeld(wallet.cs_wallet);
62 if (wallet.IsMine(script))
63 {
64 CTxDestination address;
65 if (!ExtractDestination(script, address))
66 return true;
67 if (!wallet.FindAddressBookEntry(address)) {
68 return true;
69 }
70 }
71 return false;
72 }
73
74 bool OutputIsChange(const CWallet& wallet, const CTxOut& txout)
75 {
76 return ScriptIsChange(wallet, txout.scriptPubKey);
77 }
78
79 CAmount OutputGetChange(const CWallet& wallet, const CTxOut& txout)
80 {
81 AssertLockHeld(wallet.cs_wallet);
82 if (!MoneyRange(txout.nValue))
83 throw std::runtime_error(std::string(__func__) + ": value out of range");
84 return (OutputIsChange(wallet, txout) ? txout.nValue : 0);
85 }
86
87 CAmount TxGetChange(const CWallet& wallet, const CTransaction& tx)
88 {
89 LOCK(wallet.cs_wallet);
90 CAmount nChange = 0;
91 for (const CTxOut& txout : tx.vout)
92 {
93 nChange += OutputGetChange(wallet, txout);
94 if (!MoneyRange(nChange))
95 throw std::runtime_error(std::string(__func__) + ": value out of range");
96 }
97 return nChange;
98 }
99
100 static CAmount GetCachableAmount(const CWallet& wallet, const CWalletTx& wtx, CWalletTx::AmountType type, const isminefilter& filter)
101 {
102 auto& amount = wtx.m_amounts[type];
103 if (!amount.m_cached[filter]) {
104 amount.Set(filter, type == CWalletTx::DEBIT ? wallet.GetDebit(*wtx.tx, filter) : TxGetCredit(wallet, *wtx.tx, filter));
105 wtx.m_is_cache_empty = false;
106 }
107 return amount.m_value[filter];
108 }
109
110 CAmount CachedTxGetCredit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter)
111 {
112 AssertLockHeld(wallet.cs_wallet);
113
114 // Must wait until coinbase is safely deep enough in the chain before valuing it
115 if (wallet.IsTxImmatureCoinBase(wtx))
116 return 0;
117
118 CAmount credit = 0;
119 const isminefilter get_amount_filter{filter & ISMINE_ALL};
120 if (get_amount_filter) {
121 // GetBalance can assume transactions in mapWallet won't change
122 credit += GetCachableAmount(wallet, wtx, CWalletTx::CREDIT, get_amount_filter);
123 }
124 return credit;
125 }
126
127 CAmount CachedTxGetDebit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter)
128 {
129 if (wtx.tx->vin.empty())
130 return 0;
131
132 CAmount debit = 0;
133 const isminefilter get_amount_filter{filter & ISMINE_ALL};
134 if (get_amount_filter) {
135 debit += GetCachableAmount(wallet, wtx, CWalletTx::DEBIT, get_amount_filter);
136 }
137 return debit;
138 }
139
140 CAmount CachedTxGetChange(const CWallet& wallet, const CWalletTx& wtx)
141 {
142 if (wtx.fChangeCached)
143 return wtx.nChangeCached;
144 wtx.nChangeCached = TxGetChange(wallet, *wtx.tx);
145 wtx.fChangeCached = true;
146 return wtx.nChangeCached;
147 }
148
149 CAmount CachedTxGetImmatureCredit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter)
150 {
151 AssertLockHeld(wallet.cs_wallet);
152
153 if (wallet.IsTxImmatureCoinBase(wtx) && wtx.isConfirmed()) {
154 return GetCachableAmount(wallet, wtx, CWalletTx::IMMATURE_CREDIT, filter);
155 }
156
157 return 0;
158 }
159
160 CAmount CachedTxGetAvailableCredit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter)
161 {
162 AssertLockHeld(wallet.cs_wallet);
163
164 // Avoid caching ismine for NO or ALL cases (could remove this check and simplify in the future).
165 bool allow_cache = (filter & ISMINE_ALL) && (filter & ISMINE_ALL) != ISMINE_ALL;
166
167 // Must wait until coinbase is safely deep enough in the chain before valuing it
168 if (wallet.IsTxImmatureCoinBase(wtx))
169 return 0;
170
171 if (allow_cache && wtx.m_amounts[CWalletTx::AVAILABLE_CREDIT].m_cached[filter]) {
172 return wtx.m_amounts[CWalletTx::AVAILABLE_CREDIT].m_value[filter];
173 }
174
175 bool allow_used_addresses = (filter & ISMINE_USED) || !wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE);
176 CAmount nCredit = 0;
177 Txid hashTx = wtx.GetHash();
178 for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) {
179 const CTxOut& txout = wtx.tx->vout[i];
180 if (!wallet.IsSpent(COutPoint(hashTx, i)) && (allow_used_addresses || !wallet.IsSpentKey(txout.scriptPubKey))) {
181 nCredit += OutputGetCredit(wallet, txout, filter);
182 if (!MoneyRange(nCredit))
183 throw std::runtime_error(std::string(__func__) + " : value out of range");
184 }
185 }
186
187 if (allow_cache) {
188 wtx.m_amounts[CWalletTx::AVAILABLE_CREDIT].Set(filter, nCredit);
189 wtx.m_is_cache_empty = false;
190 }
191
192 return nCredit;
193 }
194
195 void CachedTxGetAmounts(const CWallet& wallet, const CWalletTx& wtx,
196 std::list<COutputEntry>& listReceived,
197 std::list<COutputEntry>& listSent, CAmount& nFee, const isminefilter& filter,
198 bool include_change)
199 {
200 nFee = 0;
201 listReceived.clear();
202 listSent.clear();
203
204 // Compute fee:
205 CAmount nDebit = CachedTxGetDebit(wallet, wtx, filter);
206 if (nDebit > 0) // debit>0 means we signed/sent this transaction
207 {
208 CAmount nValueOut = wtx.tx->GetValueOut();
209 nFee = nDebit - nValueOut;
210 }
211
212 LOCK(wallet.cs_wallet);
213 // Sent/received.
214 for (unsigned int i = 0; i < wtx.tx->vout.size(); ++i)
215 {
216 const CTxOut& txout = wtx.tx->vout[i];
217 isminetype fIsMine = wallet.IsMine(txout);
218 // Only need to handle txouts if AT LEAST one of these is true:
219 // 1) they debit from us (sent)
220 // 2) the output is to us (received)
221 if (nDebit > 0)
222 {
223 if (!include_change && OutputIsChange(wallet, txout))
224 continue;
225 }
226 else if (!(fIsMine & filter))
227 continue;
228
229 // In either case, we need to get the destination address
230 CTxDestination address;
231
232 if (!ExtractDestination(txout.scriptPubKey, address) && !txout.scriptPubKey.IsUnspendable())
233 {
234 wallet.WalletLogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
235 wtx.GetHash().ToString());
236 address = CNoDestination();
237 }
238
239 COutputEntry output = {address, txout.nValue, (int)i};
240
241 // If we are debited by the transaction, add the output as a "sent" entry
242 if (nDebit > 0)
243 listSent.push_back(output);
244
245 // If we are receiving the output, add it as a "received" entry
246 if (fIsMine & filter)
247 listReceived.push_back(output);
248 }
249
250 }
251
252 bool CachedTxIsFromMe(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter)
253 {
254 return (CachedTxGetDebit(wallet, wtx, filter) > 0);
255 }
256
257 // NOLINTNEXTLINE(misc-no-recursion)
258 bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx, std::set<uint256>& trusted_parents)
259 {
260 AssertLockHeld(wallet.cs_wallet);
261 if (wtx.isConfirmed()) return true;
262 if (wtx.isBlockConflicted()) return false;
263 // using wtx's cached debit
264 if (!wallet.m_spend_zero_conf_change || !CachedTxIsFromMe(wallet, wtx, ISMINE_ALL)) return false;
265
266 // Don't trust unconfirmed transactions from us unless they are in the mempool.
267 if (!wtx.InMempool()) return false;
268
269 // Trusted if all inputs are from us and are in the mempool:
270 for (const CTxIn& txin : wtx.tx->vin)
271 {
272 // Transactions not sent by us: not trusted
273 const CWalletTx* parent = wallet.GetWalletTx(txin.prevout.hash);
274 if (parent == nullptr) return false;
275 const CTxOut& parentOut = parent->tx->vout[txin.prevout.n];
276 // Check that this specific input being spent is trusted
277 if (wallet.IsMine(parentOut) != ISMINE_SPENDABLE) return false;
278 // If we've already trusted this parent, continue
279 if (trusted_parents.count(parent->GetHash())) continue;
280 // Recurse to check that the parent is also trusted
281 if (!CachedTxIsTrusted(wallet, *parent, trusted_parents)) return false;
282 trusted_parents.insert(parent->GetHash());
283 }
284 return true;
285 }
286
287 bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx)
288 {
289 std::set<uint256> trusted_parents;
290 LOCK(wallet.cs_wallet);
291 return CachedTxIsTrusted(wallet, wtx, trusted_parents);
292 }
293
294 Balance GetBalance(const CWallet& wallet, const int min_depth, bool avoid_reuse)
295 {
296 Balance ret;
297 isminefilter reuse_filter = avoid_reuse ? ISMINE_NO : ISMINE_USED;
298 {
299 LOCK(wallet.cs_wallet);
300 std::set<uint256> trusted_parents;
301 for (const auto& entry : wallet.mapWallet)
302 {
303 const CWalletTx& wtx = entry.second;
304 const bool is_trusted{CachedTxIsTrusted(wallet, wtx, trusted_parents)};
305 const int tx_depth{wallet.GetTxDepthInMainChain(wtx)};
306 const CAmount tx_credit_mine{CachedTxGetAvailableCredit(wallet, wtx, ISMINE_SPENDABLE | reuse_filter)};
307 const CAmount tx_credit_watchonly{CachedTxGetAvailableCredit(wallet, wtx, ISMINE_WATCH_ONLY | reuse_filter)};
308 if (is_trusted && tx_depth >= min_depth) {
309 ret.m_mine_trusted += tx_credit_mine;
310 ret.m_watchonly_trusted += tx_credit_watchonly;
311 }
312 if (!is_trusted && tx_depth == 0 && wtx.InMempool()) {
313 ret.m_mine_untrusted_pending += tx_credit_mine;
314 ret.m_watchonly_untrusted_pending += tx_credit_watchonly;
315 }
316 ret.m_mine_immature += CachedTxGetImmatureCredit(wallet, wtx, ISMINE_SPENDABLE);
317 ret.m_watchonly_immature += CachedTxGetImmatureCredit(wallet, wtx, ISMINE_WATCH_ONLY);
318 }
319 }
320 return ret;
321 }
322
323 // Calculate total balance in a different way from GetBalance. The biggest
324 // difference is that GetBalance sums up all unspent TxOuts paying to the
325 // wallet, while this sums up both spent and unspent TxOuts paying to the
326 // wallet, and then subtracts the values of TxIns spending from the wallet. This
327 // also has fewer restrictions on which unconfirmed transactions are considered
328 // trusted.
329 CAmount CWallet::GetLegacyBalance(const isminefilter& filter, int minDepth) const
330 {
331 LOCK(cs_wallet);
332
333 const auto tip_height = GetLastBlockHeight();
334 const auto tip_blockhash = m_last_block_processed;
335 int64_t tip_mtp = -1;
336 const auto checkFinalTx = [&](const CTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
337 // cloned from tx_verify:IsFinalTx, but optimised a bit
338 // NOTE: LOCKTIME_THRESHOLD would need to be checked before AD ~11500
339 // NOTE: <= rather than < because we care about the *next* block
340 if ((int64_t)tx.nLockTime <= tip_height) {
341 return true;
342 }
343 for (const auto& txin : tx.vin) {
344 if (!(txin.nSequence == CTxIn::SEQUENCE_FINAL)) {
345 if (tx.nLockTime >= LOCKTIME_THRESHOLD) {
346 if (tip_mtp == -1) {
347 CHECK_NONFATAL(this->chain().findBlock(tip_blockhash, interfaces::FoundBlock().mtpTime(tip_mtp)));
348 }
349 if (tx.nLockTime < tip_mtp) {
350 return true;
351 }
352 }
353
354 return false;
355 }
356 }
357 return true;
358 };
359
360 CAmount balance = 0;
361 for (const auto& entry : mapWallet) {
362 const CWalletTx& wtx = entry.second;
363 const int depth = GetTxDepthInMainChain(wtx);
364 if (depth < 0 || IsTxImmatureCoinBase(wtx)) {
365 continue;
366 }
367
368 if (depth == 0) {
369 bool have_conflicts = false;
370 for (const CTxIn& txin : wtx.tx->vin) {
371 if (mapTxSpends.count(txin.prevout) > 1) {
372 have_conflicts = true;
373 break;
374 }
375 }
376 if (have_conflicts && !wtx.InMempool()) {
377 // Rather than include two conflicting unconfirmed transactions in the same balance, only include ones in our mempool (which cannot contain conflicts)
378 continue;
379 }
380
381 if (!checkFinalTx(*wtx.tx)) {
382 continue;
383 }
384 }
385
386 // Loop through tx outputs and add incoming payments. For outgoing txs,
387 // treat change outputs specially, as part of the amount debited.
388 CAmount debit = GetDebit(*wtx.tx, filter);
389 const bool outgoing = debit > 0;
390 for (const CTxOut& out : wtx.tx->vout) {
391 if (outgoing && OutputIsChange(*this, out)) {
392 debit -= out.nValue;
393 } else if (IsMine(out) & filter && depth >= minDepth) {
394 balance += out.nValue;
395 }
396 }
397
398 // For outgoing txs, subtract amount debited.
399 if (outgoing) {
400 balance -= debit;
401 }
402 }
403
404 return balance;
405 }
406
407 std::map<CTxDestination, CAmount> GetAddressBalances(const CWallet& wallet)
408 {
409 std::map<CTxDestination, CAmount> balances;
410
411 {
412 LOCK(wallet.cs_wallet);
413 std::set<uint256> trusted_parents;
414 for (const auto& walletEntry : wallet.mapWallet)
415 {
416 const CWalletTx& wtx = walletEntry.second;
417
418 if (!CachedTxIsTrusted(wallet, wtx, trusted_parents))
419 continue;
420
421 if (wallet.IsTxImmatureCoinBase(wtx))
422 continue;
423
424 int nDepth = wallet.GetTxDepthInMainChain(wtx);
425 if (nDepth < (CachedTxIsFromMe(wallet, wtx, ISMINE_ALL) ? 0 : 1))
426 continue;
427
428 for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) {
429 const auto& output = wtx.tx->vout[i];
430 CTxDestination addr;
431 if (!wallet.IsMine(output))
432 continue;
433 if(!ExtractDestination(output.scriptPubKey, addr))
434 continue;
435
436 CAmount n = wallet.IsSpent(COutPoint(Txid::FromUint256(walletEntry.first), i)) ? 0 : output.nValue;
437 balances[addr] += n;
438 }
439 }
440 }
441
442 return balances;
443 }
444
445 std::set< std::set<CTxDestination> > GetAddressGroupings(const CWallet& wallet)
446 {
447 AssertLockHeld(wallet.cs_wallet);
448 std::set< std::set<CTxDestination> > groupings;
449 std::set<CTxDestination> grouping;
450
451 for (const auto& walletEntry : wallet.mapWallet)
452 {
453 const CWalletTx& wtx = walletEntry.second;
454
455 if (wtx.tx->vin.size() > 0)
456 {
457 bool any_mine = false;
458 // group all input addresses with each other
459 for (const CTxIn& txin : wtx.tx->vin)
460 {
461 CTxDestination address;
462 if(!InputIsMine(wallet, txin)) /* If this input isn't mine, ignore it */
463 continue;
464 if(!ExtractDestination(wallet.mapWallet.at(txin.prevout.hash).tx->vout[txin.prevout.n].scriptPubKey, address))
465 continue;
466 grouping.insert(address);
467 any_mine = true;
468 }
469
470 // group change with input addresses
471 if (any_mine)
472 {
473 for (const CTxOut& txout : wtx.tx->vout)
474 if (OutputIsChange(wallet, txout))
475 {
476 CTxDestination txoutAddr;
477 if(!ExtractDestination(txout.scriptPubKey, txoutAddr))
478 continue;
479 grouping.insert(txoutAddr);
480 }
481 }
482 if (grouping.size() > 0)
483 {
484 groupings.insert(grouping);
485 grouping.clear();
486 }
487 }
488
489 // group lone addrs by themselves
490 for (const auto& txout : wtx.tx->vout)
491 if (wallet.IsMine(txout))
492 {
493 CTxDestination address;
494 if(!ExtractDestination(txout.scriptPubKey, address))
495 continue;
496 grouping.insert(address);
497 groupings.insert(grouping);
498 grouping.clear();
499 }
500 }
501
502 std::set< std::set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
503 std::map< CTxDestination, std::set<CTxDestination>* > setmap; // map addresses to the unique group containing it
504 for (const std::set<CTxDestination>& _grouping : groupings)
505 {
506 // make a set of all the groups hit by this new group
507 std::set< std::set<CTxDestination>* > hits;
508 std::map< CTxDestination, std::set<CTxDestination>* >::iterator it;
509 for (const CTxDestination& address : _grouping)
510 if ((it = setmap.find(address)) != setmap.end())
511 hits.insert((*it).second);
512
513 // merge all hit groups into a new single group and delete old groups
514 std::set<CTxDestination>* merged = new std::set<CTxDestination>(_grouping);
515 for (std::set<CTxDestination>* hit : hits)
516 {
517 merged->insert(hit->begin(), hit->end());
518 uniqueGroupings.erase(hit);
519 delete hit;
520 }
521 uniqueGroupings.insert(merged);
522
523 // update setmap
524 for (const CTxDestination& element : *merged)
525 setmap[element] = merged;
526 }
527
528 std::set< std::set<CTxDestination> > ret;
529 for (const std::set<CTxDestination>* uniqueGrouping : uniqueGroupings)
530 {
531 ret.insert(*uniqueGrouping);
532 delete uniqueGrouping;
533 }
534
535 return ret;
536 }
537 } // namespace wallet
538