From 51293f733e8d994c694c7b8b43f7585f7542545d Mon Sep 17 00:00:00 2001 From: saizsassin <39055732+saizsassin@users.noreply.github.com> Date: Thu, 10 May 2018 15:01:04 +0530 Subject: [PATCH] FIFO selection wallet.cpp This wallet.cpp is selects the UTXOs based on FIFO. Coin selection is done in selectCoins function --- src/wallet/wallet.cpp | 59 ++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 93dd40b7c..00abd0c6e 100755 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2458,12 +2458,16 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin bool CWallet::SelectCoins(const std::vector& vAvailableCoins, const CAmount& nTargetValue, std::set& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl) const { + /*This selectCoins function selects the coins (UTXOs) in FIFO order i.e, the coins that is received first will be sent to spending first*/ + + //get the received time of each coin and store in set time (using set because the content will be automatically stored in ascending order of the data) std::vector vCoinsTmp(vAvailableCoins); std::vector::iterator it; std::set time; for(it=vCoinsTmp.begin();it!=vCoinsTmp.end();it++) - time.insert(it->tx->nTimeReceived); + time.insert(it->tx->nTimeReceived); //nTimeReceived is the received time of the UTXO + //store UTXOs in vCoins in the ascending order of time std::vector vCoins; vCoins.clear(); for(std::set::iterator its = time.begin();its!=time.end();its++) @@ -2471,7 +2475,7 @@ bool CWallet::SelectCoins(const std::vector& vAvailableCoins, const CAm if(it->tx->nTimeReceived == *its) vCoins.push_back(*it); - // coin control -> return all selected outputs (we want all selected to go into the transaction for sure) + // coin control -> return all selected outputs (we want all selected to go into the transaction for sure) [manual selection] has no effect in default FIFO selection if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs) { for (const COutput& out : vCoins) @@ -2484,31 +2488,31 @@ bool CWallet::SelectCoins(const std::vector& vAvailableCoins, const CAm return (nValueRet >= nTargetValue); } - // calculate value from preset inputs and store them - std::vector setPresetCoins; - CAmount nValueFromPresetInputs = 0; + // calculate value from preset inputs and store them in PresetCoins set + std::vector setPresetCoins; + CAmount nValueFromPresetInputs = 0; setPresetCoins.clear(); - std::vector vPresetInputs; - if (coinControl) - coinControl->ListSelected(vPresetInputs); - for (const COutPoint& outpoint : vPresetInputs) - { - std::map::const_iterator it = mapWallet.find(outpoint.hash); - if (it != mapWallet.end()) - { - const CWalletTx* pcoin = &it->second; - // Clearly invalid input, fail - if (pcoin->tx->vout.size() <= outpoint.n) - return false; - nValueFromPresetInputs += pcoin->tx->vout[outpoint.n].nValue; - setPresetCoins.push_back(CInputCoin(pcoin, outpoint.n)); - } else - return false; // TODO: Allow non-wallet inputs + std::vector vPresetInputs; + if (coinControl) + coinControl->ListSelected(vPresetInputs); + for (const COutPoint& outpoint : vPresetInputs) + { + std::map::const_iterator it = mapWallet.find(outpoint.hash); + if (it != mapWallet.end()) + { + const CWalletTx* pcoin = &it->second; + // Clearly invalid input, fail + if (pcoin->tx->vout.size() <= outpoint.n) + return false; + nValueFromPresetInputs += pcoin->tx->vout[outpoint.n].nValue; + setPresetCoins.push_back(CInputCoin(pcoin, outpoint.n)); + } else + return false; // TODO: Allow non-wallet inputs } - // remove preset inputs from vCoins + // remove preset inputs from vCoins (utxo) for (std::vector::iterator it = vCoins.begin(); it != vCoins.end() && coinControl && coinControl->HasSelected();) { if (std::find(setPresetCoins.begin(), setPresetCoins.end(), CInputCoin(it->tx, it->i)) != setPresetCoins.end()) @@ -2516,14 +2520,17 @@ bool CWallet::SelectCoins(const std::vector& vAvailableCoins, const CAm else ++it; } - + + //insert all preset Inputs to the setCoinsRet (returning set of selected utxo) setCoinsRet.clear(); setCoinsRet.insert(setPresetCoins.begin(), setPresetCoins.end()); nValueRet = nValueFromPresetInputs; - if (nValueFromPresetInputs >= nTargetValue) + //return true if total preset input value is greater than required amount + if (nValueFromPresetInputs >= nTargetValue) return true; + //select UTXOs from vCoins and insert into setCoinsRet (returning set of selected utxo) until required amount is obtained CAmount nRemainReqValue = nTargetValue - nValueFromPresetInputs; for (const COutput &output : vCoins) { @@ -2537,13 +2544,13 @@ bool CWallet::SelectCoins(const std::vector& vAvailableCoins, const CAm nRemainReqValue -= coin.txout.nValue; nValueRet += coin.txout.nValue; - //return true if coins of required Value are selected + //return true if coins of required amount are selected if (nRemainReqValue <= 0) return true; } - //return false since coins of required Value are not selected + //return false since coins of required amount is not available return false; }