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