Line data Source code
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 <coinjoin/options.h>
6 : #include <consensus/consensus.h>
7 : #include <wallet/coinjoin.h>
8 : #include <wallet/receive.h>
9 : #include <wallet/transaction.h>
10 : #include <wallet/wallet.h>
11 :
12 : namespace wallet {
13 1296 : isminetype InputIsMine(const CWallet& wallet, const CTxIn& txin)
14 : {
15 1296 : AssertLockHeld(wallet.cs_wallet);
16 1296 : const CWalletTx* prev = wallet.GetWalletTx(txin.prevout.hash);
17 1296 : if (prev && txin.prevout.n < prev->tx->vout.size()) {
18 68 : return wallet.IsMine(prev->tx->vout[txin.prevout.n]);
19 : }
20 1228 : return ISMINE_NO;
21 1296 : }
22 :
23 0 : bool AllInputsMine(const CWallet& wallet, const CTransaction& tx, const isminefilter& filter)
24 : {
25 0 : LOCK(wallet.cs_wallet);
26 0 : for (const CTxIn& txin : tx.vin) {
27 0 : if (!(InputIsMine(wallet, txin) & filter)) return false;
28 : }
29 0 : return true;
30 0 : }
31 :
32 97026 : CAmount OutputGetCredit(const CWallet& wallet, const CTxOut& txout, const isminefilter& filter)
33 : {
34 97026 : if (!MoneyRange(txout.nValue))
35 0 : throw std::runtime_error(std::string(__func__) + ": value out of range");
36 97026 : LOCK(wallet.cs_wallet);
37 97026 : return ((wallet.IsMine(txout) & filter) ? txout.nValue : 0);
38 97026 : }
39 :
40 55655 : CAmount TxGetCredit(const CWallet& wallet, const CTransaction& tx, const isminefilter& filter)
41 : {
42 55655 : CAmount nCredit = 0;
43 113437 : for (const CTxOut& txout : tx.vout)
44 : {
45 57782 : nCredit += OutputGetCredit(wallet, txout, filter);
46 57782 : if (!MoneyRange(nCredit))
47 0 : throw std::runtime_error(std::string(__func__) + ": value out of range");
48 : }
49 55655 : return nCredit;
50 0 : }
51 :
52 3983 : 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 3983 : AssertLockHeld(wallet.cs_wallet);
62 3983 : if (wallet.IsMine(script))
63 : {
64 2921 : CTxDestination address;
65 2921 : if (!ExtractDestination(script, address))
66 0 : return true;
67 2921 : if (!wallet.FindAddressBookEntry(address)) {
68 1148 : return true;
69 : }
70 1773 : }
71 2835 : return false;
72 3983 : }
73 :
74 2039 : bool OutputIsChange(const CWallet& wallet, const CTxOut& txout)
75 : {
76 2039 : return ScriptIsChange(wallet, txout.scriptPubKey);
77 : }
78 :
79 0 : CAmount OutputGetChange(const CWallet& wallet, const CTxOut& txout)
80 : {
81 0 : AssertLockHeld(wallet.cs_wallet);
82 0 : if (!MoneyRange(txout.nValue))
83 0 : throw std::runtime_error(std::string(__func__) + ": value out of range");
84 0 : return (OutputIsChange(wallet, txout) ? txout.nValue : 0);
85 0 : }
86 :
87 0 : CAmount TxGetChange(const CWallet& wallet, const CTransaction& tx)
88 : {
89 0 : LOCK(wallet.cs_wallet);
90 0 : CAmount nChange = 0;
91 0 : for (const CTxOut& txout : tx.vout)
92 : {
93 0 : nChange += OutputGetChange(wallet, txout);
94 0 : if (!MoneyRange(nChange))
95 0 : throw std::runtime_error(std::string(__func__) + ": value out of range");
96 : }
97 0 : return nChange;
98 0 : }
99 :
100 1128798 : static CAmount GetCachableAmount(const CWallet& wallet, const CWalletTx& wtx, CWalletTx::AmountType type, const isminefilter& filter)
101 : {
102 1128798 : auto& amount = wtx.m_amounts[type];
103 1128798 : if (!amount.m_cached[filter]) {
104 104298 : amount.Set(filter, type == CWalletTx::DEBIT ? wallet.GetDebit(*wtx.tx, filter) : TxGetCredit(wallet, *wtx.tx, filter));
105 104298 : wtx.m_is_cache_empty = false;
106 104298 : }
107 1128798 : return amount.m_value[filter];
108 : }
109 :
110 503 : CAmount CachedTxGetCredit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter)
111 : {
112 503 : AssertLockHeld(wallet.cs_wallet);
113 :
114 : // Must wait until coinbase is safely deep enough in the chain before valuing it
115 503 : if (wallet.IsTxImmatureCoinBase(wtx))
116 18 : return 0;
117 :
118 485 : CAmount credit = 0;
119 485 : const isminefilter get_amount_filter{filter & ISMINE_ALL};
120 485 : if (get_amount_filter) {
121 : // GetBalance can assume transactions in mapWallet won't change
122 485 : credit += GetCachableAmount(wallet, wtx, CWalletTx::CREDIT, get_amount_filter);
123 485 : }
124 485 : return credit;
125 503 : }
126 :
127 889715 : CAmount CachedTxGetDebit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter)
128 : {
129 889715 : if (wtx.tx->vin.empty())
130 158 : return 0;
131 :
132 889557 : CAmount debit = 0;
133 889557 : const isminefilter get_amount_filter{filter & ISMINE_ALL};
134 889557 : if (get_amount_filter) {
135 889557 : debit += GetCachableAmount(wallet, wtx, CWalletTx::DEBIT, get_amount_filter);
136 889557 : }
137 889557 : return debit;
138 889715 : }
139 :
140 0 : CAmount CachedTxGetChange(const CWallet& wallet, const CWalletTx& wtx)
141 : {
142 0 : if (wtx.fChangeCached)
143 0 : return wtx.nChangeCached;
144 0 : wtx.nChangeCached = TxGetChange(wallet, *wtx.tx);
145 0 : wtx.fChangeCached = true;
146 0 : return wtx.nChangeCached;
147 0 : }
148 :
149 341694 : CAmount CachedTxGetImmatureCredit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter)
150 : {
151 341694 : AssertLockHeld(wallet.cs_wallet);
152 :
153 341694 : if (wallet.IsTxImmatureCoinBase(wtx) && wallet.IsTxInMainChain(wtx)) {
154 238756 : return GetCachableAmount(wallet, wtx, CWalletTx::IMMATURE_CREDIT, filter);
155 : }
156 :
157 102938 : return 0;
158 341694 : }
159 :
160 341695 : CAmount CachedTxGetAvailableCredit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter)
161 : {
162 341695 : AssertLockHeld(wallet.cs_wallet);
163 :
164 : // Avoid caching ismine for NO or ALL cases (could remove this check and simplify in the future).
165 341695 : 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 341695 : if (wallet.IsTxImmatureCoinBase(wtx))
169 238822 : return 0;
170 :
171 102873 : if (allow_cache && wtx.m_amounts[CWalletTx::AVAILABLE_CREDIT].m_cached[filter]) {
172 68808 : return wtx.m_amounts[CWalletTx::AVAILABLE_CREDIT].m_value[filter];
173 : }
174 :
175 34065 : bool allow_used_addresses = (filter & ISMINE_USED) || !wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE);
176 34065 : CAmount nCredit = 0;
177 34065 : uint256 hashTx = wtx.GetHash();
178 75334 : for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) {
179 41269 : const CTxOut& txout = wtx.tx->vout[i];
180 80491 : if (!wallet.IsSpent(COutPoint(hashTx, i)) && (allow_used_addresses || !wallet.IsSpentKey(txout.scriptPubKey))) {
181 39202 : nCredit += OutputGetCredit(wallet, txout, filter);
182 39202 : if (!MoneyRange(nCredit))
183 0 : throw std::runtime_error(std::string(__func__) + ": value out of range");
184 39202 : }
185 41269 : }
186 :
187 34065 : if (allow_cache) {
188 34065 : wtx.m_amounts[CWalletTx::AVAILABLE_CREDIT].Set(filter, nCredit);
189 34065 : wtx.m_is_cache_empty = false;
190 34065 : }
191 :
192 34065 : return nCredit;
193 341695 : }
194 :
195 12673 : void CachedTxGetAmounts(const CWallet& wallet, const CWalletTx& wtx,
196 : std::list<COutputEntry>& listReceived,
197 : std::list<COutputEntry>& listSent, CAmount& nFee, const isminefilter& filter)
198 : {
199 12673 : nFee = 0;
200 12673 : listReceived.clear();
201 12673 : listSent.clear();
202 :
203 : // Compute fee:
204 12673 : CAmount nDebit = CachedTxGetDebit(wallet, wtx, filter);
205 12673 : if (nDebit > 0) // debit>0 means we signed/sent this transaction
206 : {
207 1015 : CAmount nValueOut = wtx.tx->GetValueOut();
208 1015 : nFee = nDebit - nValueOut;
209 1015 : }
210 :
211 12673 : LOCK(wallet.cs_wallet);
212 : // Sent/received.
213 30065 : for (unsigned int i = 0; i < wtx.tx->vout.size(); ++i)
214 : {
215 17392 : const CTxOut& txout = wtx.tx->vout[i];
216 17392 : isminetype fIsMine = wallet.IsMine(txout);
217 : // Only need to handle txouts if AT LEAST one of these is true:
218 : // 1) they debit from us (sent)
219 : // 2) the output is to us (received)
220 17392 : if (nDebit > 0)
221 : {
222 : // Don't report 'change' txouts
223 1986 : if (OutputIsChange(wallet, txout))
224 800 : continue;
225 1186 : }
226 15406 : else if (!(fIsMine & filter))
227 3728 : continue;
228 :
229 : // In either case, we need to get the destination address
230 12864 : CTxDestination address;
231 :
232 12864 : if (!ExtractDestination(txout.scriptPubKey, address) && !txout.scriptPubKey.IsUnspendable())
233 : {
234 0 : wallet.WalletLogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
235 0 : wtx.GetHash().ToString());
236 0 : address = CNoDestination();
237 0 : }
238 :
239 12864 : COutputEntry output = {address, txout.nValue, (int)i};
240 :
241 : // If we are debited by the transaction, add the output as a "sent" entry
242 12864 : if (nDebit > 0)
243 1186 : listSent.push_back(output);
244 :
245 : // If we are receiving the output, add it as a "received" entry
246 12864 : if (fIsMine & filter)
247 12089 : listReceived.push_back(output);
248 12864 : }
249 :
250 12673 : }
251 :
252 876539 : bool CachedTxIsFromMe(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter)
253 : {
254 876539 : return (CachedTxGetDebit(wallet, wtx, filter) > 0);
255 : }
256 :
257 1106773 : bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx, std::set<uint256>& trusted_parents)
258 : {
259 1106773 : AssertLockHeld(wallet.cs_wallet);
260 1106773 : int nDepth = wallet.GetTxDepthInMainChain(wtx);
261 1106773 : if (nDepth >= 1) return true;
262 284745 : if (nDepth < 0) return false;
263 282996 : if (wallet.IsTxLockedByInstantSend(wtx)) return true;
264 : // using wtx's cached debit
265 282742 : if (!wallet.m_spend_zero_conf_change || !CachedTxIsFromMe(wallet, wtx, ISMINE_ALL)) return false;
266 :
267 : // Don't trust unconfirmed transactions from us unless they are in the mempool.
268 271920 : if (!wtx.InMempool()) return false;
269 :
270 : // Trusted if all inputs are from us and are in the mempool:
271 565215 : for (const CTxIn& txin : wtx.tx->vin)
272 : {
273 : // Transactions not sent by us: not trusted
274 293704 : const CWalletTx* parent = wallet.GetWalletTx(txin.prevout.hash);
275 293704 : if (parent == nullptr) return false;
276 293668 : const CTxOut& parentOut = parent->tx->vout[txin.prevout.n];
277 : // Check that this specific input being spent is trusted
278 293668 : if (wallet.IsMine(parentOut) != ISMINE_SPENDABLE) return false;
279 : // If we've already trusted this parent, continue
280 293639 : if (trusted_parents.count(parent->GetHash())) continue;
281 : // Recurse to check that the parent is also trusted
282 291376 : if (!CachedTxIsTrusted(wallet, *parent, trusted_parents)) return false;
283 291300 : trusted_parents.insert(parent->GetHash());
284 : }
285 271511 : return true;
286 1106773 : }
287 :
288 53103 : bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx)
289 : {
290 53103 : std::set<uint256> trusted_parents;
291 53103 : LOCK(wallet.cs_wallet);
292 53103 : return CachedTxIsTrusted(wallet, wtx, trusted_parents);
293 53103 : }
294 :
295 5647 : Balance GetBalance(const CWallet& wallet, const int min_depth, bool avoid_reuse, bool fAddLocked)
296 : {
297 5647 : Balance ret;
298 5647 : isminefilter reuse_filter = avoid_reuse ? ISMINE_NO : ISMINE_USED;
299 5647 : const bool cj_enabled = CCoinJoinClientOptions::IsEnabled();
300 : {
301 5647 : LOCK(wallet.cs_wallet);
302 5647 : std::set<uint256> trusted_parents;
303 176493 : for (const auto* pcoin : wallet.GetSpendableTXs()) {
304 170846 : const auto& wtx{*pcoin};
305 :
306 170846 : const bool is_trusted{CachedTxIsTrusted(wallet, wtx, trusted_parents)};
307 170846 : const int tx_depth{wallet.GetTxDepthInMainChain(wtx)};
308 170846 : const CAmount tx_credit_mine{CachedTxGetAvailableCredit(wallet, wtx, ISMINE_SPENDABLE | reuse_filter)};
309 170846 : const CAmount tx_credit_watchonly{CachedTxGetAvailableCredit(wallet, wtx, ISMINE_WATCH_ONLY | reuse_filter)};
310 170846 : if (is_trusted && ((tx_depth >= min_depth) || (fAddLocked && wallet.IsTxLockedByInstantSend(wtx)))) {
311 169233 : ret.m_mine_trusted += tx_credit_mine;
312 169233 : ret.m_watchonly_trusted += tx_credit_watchonly;
313 169233 : }
314 170846 : if (!is_trusted && tx_depth == 0 && wtx.InMempool()) {
315 1461 : ret.m_mine_untrusted_pending += tx_credit_mine;
316 1461 : ret.m_watchonly_untrusted_pending += tx_credit_watchonly;
317 1461 : }
318 170846 : ret.m_mine_immature += CachedTxGetImmatureCredit(wallet, wtx, ISMINE_SPENDABLE);
319 170846 : ret.m_watchonly_immature += CachedTxGetImmatureCredit(wallet, wtx, ISMINE_WATCH_ONLY);
320 170846 : if (cj_enabled) {
321 170843 : const auto balance_anonymized = CachedTxGetAvailableCoinJoinCredits(wallet, wtx);
322 170843 : ret.m_anonymized += balance_anonymized.m_anonymized;
323 170843 : if (balance_anonymized.is_unconfirmed) {
324 3518 : ret.m_denominated_untrusted_pending += balance_anonymized.m_denominated;
325 3518 : } else {
326 167325 : ret.m_denominated_trusted += balance_anonymized.m_denominated;
327 : }
328 170843 : }
329 : }
330 5647 : }
331 5647 : return ret;
332 0 : }
333 :
334 28 : std::map<CTxDestination, CAmount> GetAddressBalances(const CWallet& wallet)
335 : {
336 28 : std::map<CTxDestination, CAmount> balances;
337 :
338 : {
339 28 : LOCK(wallet.cs_wallet);
340 28 : std::set<uint256> trusted_parents;
341 1936 : for (const auto& walletEntry : wallet.mapWallet)
342 : {
343 1908 : const CWalletTx& wtx = walletEntry.second;
344 :
345 1908 : if (!CachedTxIsTrusted(wallet, wtx, trusted_parents))
346 0 : continue;
347 :
348 1908 : if (wallet.IsTxImmatureCoinBase(wtx))
349 1800 : continue;
350 :
351 108 : int nDepth = wallet.GetTxDepthInMainChain(wtx);
352 108 : if (nDepth < (CachedTxIsFromMe(wallet, wtx, ISMINE_ALL) ? 0 : 1) && !wallet.IsTxLockedByInstantSend(wtx))
353 0 : continue;
354 :
355 276 : for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) {
356 168 : const auto& output = wtx.tx->vout[i];
357 168 : CTxDestination addr;
358 168 : if (!wallet.IsMine(output))
359 66 : continue;
360 102 : if(!ExtractDestination(output.scriptPubKey, addr))
361 0 : continue;
362 :
363 102 : CAmount n = wallet.IsSpent(COutPoint(walletEntry.first, i)) ? 0 : output.nValue;
364 102 : balances[addr] += n;
365 102 : }
366 : }
367 28 : }
368 :
369 28 : return balances;
370 28 : }
371 :
372 16 : std::set< std::set<CTxDestination> > GetAddressGroupings(const CWallet& wallet)
373 : {
374 16 : AssertLockHeld(wallet.cs_wallet);
375 16 : std::set< std::set<CTxDestination> > groupings;
376 16 : std::set<CTxDestination> grouping;
377 :
378 1306 : for (const auto& walletEntry : wallet.mapWallet)
379 : {
380 1290 : const CWalletTx& wtx = walletEntry.second;
381 :
382 1290 : if (wtx.tx->vin.size() > 0)
383 : {
384 1290 : bool any_mine = false;
385 : // group all input addresses with each other
386 2586 : for (const CTxIn& txin : wtx.tx->vin)
387 : {
388 1296 : CTxDestination address;
389 1296 : if(!InputIsMine(wallet, txin)) /* If this input isn't mine, ignore it */
390 1264 : continue;
391 32 : if(!ExtractDestination(wallet.mapWallet.at(txin.prevout.hash).tx->vout[txin.prevout.n].scriptPubKey, address))
392 0 : continue;
393 32 : grouping.insert(address);
394 32 : any_mine = true;
395 : }
396 :
397 : // group change with input addresses
398 1290 : if (any_mine)
399 : {
400 72 : for (const CTxOut& txout : wtx.tx->vout)
401 46 : if (OutputIsChange(wallet, txout))
402 : {
403 20 : CTxDestination txoutAddr;
404 20 : if(!ExtractDestination(txout.scriptPubKey, txoutAddr))
405 0 : continue;
406 20 : grouping.insert(txoutAddr);
407 20 : }
408 26 : }
409 1290 : if (grouping.size() > 0)
410 : {
411 26 : groupings.insert(grouping);
412 26 : grouping.clear();
413 26 : }
414 1290 : }
415 :
416 : // group lone addrs by themselves
417 2640 : for (const auto& txout : wtx.tx->vout)
418 1350 : if (wallet.IsMine(txout))
419 : {
420 1284 : CTxDestination address;
421 1284 : if(!ExtractDestination(txout.scriptPubKey, address))
422 0 : continue;
423 1284 : grouping.insert(address);
424 1284 : groupings.insert(grouping);
425 1284 : grouping.clear();
426 1284 : }
427 : }
428 :
429 16 : std::set< std::set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
430 16 : std::map< CTxDestination, std::set<CTxDestination>* > setmap; // map addresses to the unique group containing it
431 126 : for (const std::set<CTxDestination>& _grouping : groupings)
432 : {
433 : // make a set of all the groups hit by this new group
434 110 : std::set< std::set<CTxDestination>* > hits;
435 110 : std::map< CTxDestination, std::set<CTxDestination>* >::iterator it;
436 246 : for (const CTxDestination& address : _grouping)
437 136 : if ((it = setmap.find(address)) != setmap.end())
438 52 : hits.insert((*it).second);
439 :
440 : // merge all hit groups into a new single group and delete old groups
441 110 : std::set<CTxDestination>* merged = new std::set<CTxDestination>(_grouping);
442 162 : for (std::set<CTxDestination>* hit : hits)
443 : {
444 52 : merged->insert(hit->begin(), hit->end());
445 52 : uniqueGroupings.erase(hit);
446 52 : delete hit;
447 : }
448 110 : uniqueGroupings.insert(merged);
449 :
450 : // update setmap
451 272 : for (const CTxDestination& element : *merged)
452 162 : setmap[element] = merged;
453 110 : }
454 :
455 16 : std::set< std::set<CTxDestination> > ret;
456 74 : for (const std::set<CTxDestination>* uniqueGrouping : uniqueGroupings)
457 : {
458 58 : ret.insert(*uniqueGrouping);
459 58 : delete uniqueGrouping;
460 : }
461 :
462 16 : return ret;
463 16 : }
464 : } // namespace wallet
|