| 2387 | return true; |
| 2388 | } |
| 2389 | bool CWallet::SelectCoins(const std::string &account, const CAmount& nTargetValue, set<pair<const CWalletTx*, unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl, AvailableCoinsType coin_type, bool useIX) const |
| 2390 | { |
| 2391 | // Note: this function should never be used for "always free" tx types like dstx |
| 2392 | |
| 2393 | vector<COutput> vCoins; |
| 2394 | AvailableCoins(vCoins, true, coinControl, false, coin_type, useIX); |
| 2395 | |
| 2396 | // coin control -> return all selected outputs (we want all selected to go into the transaction for sure) |
| 2397 | if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs) { |
| 2398 | for (const COutput& out : vCoins) { |
| 2399 | if (!out.fSpendable) continue; |
| 2400 | |
| 2401 | if (coin_type == ONLY_DENOMINATED) { |
| 2402 | CTxIn vin = CTxIn(out.tx->GetHash(), out.i); |
| 2403 | int rounds = GetInputDarkSendRounds(vin); |
| 2404 | // make sure it's actually anonymized |
| 2405 | if (rounds < nDarksendRounds) continue; |
| 2406 | } |
| 2407 | nValueRet += out.tx->vout[out.i].nValue; |
| 2408 | setCoinsRet.insert(make_pair(out.tx, out.i)); |
| 2409 | } |
| 2410 | return (nValueRet >= nTargetValue); |
| 2411 | } |
| 2412 | |
| 2413 | // calculate value from preset inputs and store them |
| 2414 | set<pair<const CWalletTx*, uint32_t> > setPresetCoins; |
| 2415 | CAmount nValueFromPresetInputs = 0; |
| 2416 | |
| 2417 | std::vector<COutPoint> vPresetInputs; |
| 2418 | if (coinControl) |
| 2419 | coinControl->ListSelected(vPresetInputs); |
| 2420 | for (const COutPoint& outpoint : vPresetInputs) { |
| 2421 | map<uint256, CWalletTx>::const_iterator it = mapWallet.find(outpoint.hash); |
| 2422 | if (it != mapWallet.end()) { |
| 2423 | const CWalletTx* pcoin = &it->second; |
| 2424 | // Clearly invalid input, fail |
| 2425 | if (pcoin->vout.size() <= outpoint.n) |
| 2426 | return false; |
| 2427 | nValueFromPresetInputs += pcoin->vout[outpoint.n].nValue; |
| 2428 | setPresetCoins.insert(make_pair(pcoin, outpoint.n)); |
| 2429 | } else |
| 2430 | return false; |
| 2431 | } |
| 2432 | |
| 2433 | // remove preset inputs from vCoins |
| 2434 | for (vector<COutput>::iterator it = vCoins.begin(); it != vCoins.end() && coinControl && coinControl->HasSelected();) { |
| 2435 | if (setPresetCoins.count(make_pair(it->tx, it->i))) |
| 2436 | it = vCoins.erase(it); |
| 2437 | else |
| 2438 | ++it; |
| 2439 | } |
| 2440 | |
| 2441 | bool res = nTargetValue <= nValueFromPresetInputs || |
| 2442 | SelectCoinsMinConf(account, nTargetValue - nValueFromPresetInputs, 1, 6, vCoins, setCoinsRet, nValueRet) || |
| 2443 | SelectCoinsMinConf(account, nTargetValue - nValueFromPresetInputs, 1, 1, vCoins, setCoinsRet, nValueRet) || |
| 2444 | (bSpendZeroConfChange && SelectCoinsMinConf(account, nTargetValue - nValueFromPresetInputs, 0, 1, vCoins, setCoinsRet, nValueRet)); |
| 2445 | |
| 2446 | // because SelectCoinsMinConf clears the setCoinsRet, we now add the possible inputs to the coinset |