Refactor PS code to deal with denoms in a more generic way (#1071)
This commit is contained in:
parent
27c445a891
commit
bdcc9ab47c
138
src/darksend.cpp
138
src/darksend.cpp
@ -14,6 +14,7 @@
|
|||||||
#include "script/sign.h"
|
#include "script/sign.h"
|
||||||
#include "txmempool.h"
|
#include "txmempool.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "utilmoneystr.h"
|
||||||
|
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
@ -1686,7 +1687,7 @@ bool CDarksendPool::PrepareDenominate(int nMinRounds, int nMaxRounds, std::strin
|
|||||||
|
|
||||||
if nMinRounds >= 0 it means only denominated inputs are going in and coming out
|
if nMinRounds >= 0 it means only denominated inputs are going in and coming out
|
||||||
*/
|
*/
|
||||||
bool fSelected = pwalletMain->SelectCoinsByDenominations(nSessionDenom, 0.1*COIN, PRIVATESEND_POOL_MAX, vecTxIn, vCoins, nValueIn, nMinRounds, nMaxRounds);
|
bool fSelected = pwalletMain->SelectCoinsByDenominations(nSessionDenom, vecPrivateSendDenominations.back(), PRIVATESEND_POOL_MAX, vecTxIn, vCoins, nValueIn, nMinRounds, nMaxRounds);
|
||||||
if (nMinRounds >= 0 && !fSelected) {
|
if (nMinRounds >= 0 && !fSelected) {
|
||||||
strErrorRet = "Can't select current denominated inputs";
|
strErrorRet = "Can't select current denominated inputs";
|
||||||
return false;
|
return false;
|
||||||
@ -1703,65 +1704,57 @@ bool CDarksendPool::PrepareDenominate(int nMinRounds, int nMaxRounds, std::strin
|
|||||||
|
|
||||||
CAmount nValueLeft = nValueIn;
|
CAmount nValueLeft = nValueIn;
|
||||||
|
|
||||||
/*
|
// Try to add every needed denomination, repeat up to 5-9 times.
|
||||||
TODO: Front load with needed denominations (e.g. .1, 1 )
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Make outputs by looping through denominations: try to add every needed denomination, repeat up to 5-10 times.
|
|
||||||
// This way we can be pretty sure that it should have at least one of each needed denomination.
|
|
||||||
// NOTE: No need to randomize order of inputs because they were
|
// NOTE: No need to randomize order of inputs because they were
|
||||||
// initially shuffled in CWallet::SelectCoinsByDenominations already.
|
// initially shuffled in CWallet::SelectCoinsByDenominations already.
|
||||||
int nStep = 0;
|
int nStep = 0;
|
||||||
int nStepsMax = 5 + GetRandInt(5);
|
int nStepsMax = 5 + GetRandInt(5);
|
||||||
while(nStep < nStepsMax) {
|
std::vector<int> vecBits;
|
||||||
|
if (!GetDenominationsBits(nSessionDenom, vecBits)) {
|
||||||
|
strErrorRet = "Incorrect session denom";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_FOREACH(CAmount nValueDenom, vecPrivateSendDenominations) {
|
while (nStep < nStepsMax) {
|
||||||
// only use the ones that are approved
|
BOOST_FOREACH(int nBit, vecBits) {
|
||||||
if (!((nSessionDenom & (1 << 0)) && nValueDenom == 100*COIN +100000) &&
|
CAmount nValueDenom = vecPrivateSendDenominations[nBit];
|
||||||
!((nSessionDenom & (1 << 1)) && nValueDenom == 10*COIN + 10000) &&
|
if (nValueLeft - nValueDenom < 0) continue;
|
||||||
!((nSessionDenom & (1 << 2)) && nValueDenom == 1*COIN + 1000) &&
|
|
||||||
!((nSessionDenom & (1 << 3)) && nValueDenom == .1*COIN + 100))
|
|
||||||
{ continue; }
|
|
||||||
|
|
||||||
// try to add it
|
// Note: this relies on a fact that both vectors MUST have same size
|
||||||
if (nValueLeft - nValueDenom >= 0) {
|
std::vector<CTxIn>::iterator it = vecTxIn.begin();
|
||||||
// Note: this relies on a fact that both vectors MUST have same size
|
std::vector<COutput>::iterator it2 = vCoins.begin();
|
||||||
std::vector<CTxIn>::iterator it = vecTxIn.begin();
|
while (it2 != vCoins.end()) {
|
||||||
std::vector<COutput>::iterator it2 = vCoins.begin();
|
// we have matching inputs
|
||||||
while (it2 != vCoins.end()) {
|
if ((*it2).tx->vout[(*it2).i].nValue == nValueDenom) {
|
||||||
// we have matching inputs
|
// add new input in resulting vector
|
||||||
if ((*it2).tx->vout[(*it2).i].nValue == nValueDenom) {
|
vecTxInRet.push_back(*it);
|
||||||
// add new input in resulting vector
|
// remove corresponting items from initial vectors
|
||||||
vecTxInRet.push_back(*it);
|
vecTxIn.erase(it);
|
||||||
// remove corresponting items from initial vectors
|
vCoins.erase(it2);
|
||||||
vecTxIn.erase(it);
|
|
||||||
vCoins.erase(it2);
|
|
||||||
|
|
||||||
CScript scriptChange;
|
CScript scriptChange;
|
||||||
CPubKey vchPubKey;
|
CPubKey vchPubKey;
|
||||||
// use a unique change address
|
// use a unique change address
|
||||||
assert(reservekey.GetReservedKey(vchPubKey)); // should never fail, as we just unlocked
|
assert(reservekey.GetReservedKey(vchPubKey)); // should never fail, as we just unlocked
|
||||||
scriptChange = GetScriptForDestination(vchPubKey.GetID());
|
scriptChange = GetScriptForDestination(vchPubKey.GetID());
|
||||||
reservekey.KeepKey();
|
reservekey.KeepKey();
|
||||||
|
|
||||||
// add new output
|
// add new output
|
||||||
CTxOut txout(nValueDenom, scriptChange);
|
CTxOut txout(nValueDenom, scriptChange);
|
||||||
vecTxOutRet.push_back(txout);
|
vecTxOutRet.push_back(txout);
|
||||||
|
|
||||||
// subtract denomination amount
|
// subtract denomination amount
|
||||||
nValueLeft -= nValueDenom;
|
nValueLeft -= nValueDenom;
|
||||||
|
|
||||||
break;
|
// step is complete
|
||||||
}
|
break;
|
||||||
++it;
|
|
||||||
++it2;
|
|
||||||
}
|
}
|
||||||
|
++it;
|
||||||
|
++it2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nStep++;
|
|
||||||
|
|
||||||
if(nValueLeft == 0) break;
|
if(nValueLeft == 0) break;
|
||||||
|
nStep++;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -2071,38 +2064,34 @@ bool CDarksendPool::IsDenomCompatibleWithSession(int nDenom, CTransaction txColl
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Create a nice string to show the denominations
|
/* Create a nice string to show the denominations
|
||||||
Function returns as follows:
|
Function returns as follows (for 4 denominations):
|
||||||
( bit on if present )
|
( bit on if present )
|
||||||
bit 0 - 100
|
bit 0 - 100
|
||||||
bit 1 - 10
|
bit 1 - 10
|
||||||
bit 2 - 1
|
bit 2 - 1
|
||||||
bit 3 - .1
|
bit 3 - .1
|
||||||
|
bit 4 and so on - out-of-bounds
|
||||||
none of above - non-denom
|
none of above - non-denom
|
||||||
bit 4 and so on - non-denom
|
|
||||||
*/
|
*/
|
||||||
std::string CDarksendPool::GetDenominationsToString(int nDenom)
|
std::string CDarksendPool::GetDenominationsToString(int nDenom)
|
||||||
{
|
{
|
||||||
std::string strDenom;
|
std::string strDenom = "";
|
||||||
|
int nMaxDenoms = vecPrivateSendDenominations.size();
|
||||||
|
|
||||||
if(nDenom & (1 << 0)) strDenom += "100";
|
if(nDenom >= (1 << nMaxDenoms)) {
|
||||||
|
return "out-of-bounds";
|
||||||
if(nDenom & (1 << 1)) {
|
|
||||||
if(strDenom.size() > 0) strDenom += "+";
|
|
||||||
strDenom += "10";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(nDenom & (1 << 2)) {
|
for (int i = 0; i < nMaxDenoms; ++i) {
|
||||||
if(strDenom.size() > 0) strDenom += "+";
|
if(nDenom & (1 << i)) {
|
||||||
strDenom += "1";
|
strDenom += (strDenom.empty() ? "" : "+") + FormatMoney(vecPrivateSendDenominations[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(nDenom & (1 << 3)) {
|
if(strDenom.empty()) {
|
||||||
if(strDenom.size() > 0) strDenom += "+";
|
return "non-denom";
|
||||||
strDenom += "0.1";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(strDenom.size() == 0 && nDenom >= (1 << 4)) strDenom += "non-denom";
|
|
||||||
|
|
||||||
return strDenom;
|
return strDenom;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2117,7 +2106,7 @@ int CDarksendPool::GetDenominations(const std::vector<CTxDSOut>& vecTxDSOut)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Return a bitshifted integer representing the denominations in this list
|
/* Return a bitshifted integer representing the denominations in this list
|
||||||
Function returns as follows:
|
Function returns as follows (for 4 denominations):
|
||||||
( bit on if present )
|
( bit on if present )
|
||||||
100 - bit 0
|
100 - bit 0
|
||||||
10 - bit 1
|
10 - bit 1
|
||||||
@ -2157,6 +2146,29 @@ int CDarksendPool::GetDenominations(const std::vector<CTxOut>& vecTxOut, bool fS
|
|||||||
return nDenom;
|
return nDenom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CDarksendPool::GetDenominationsBits(int nDenom, std::vector<int> &vecBitsRet)
|
||||||
|
{
|
||||||
|
// ( bit on if present, 4 denominations example )
|
||||||
|
// bit 0 - 100DASH+1
|
||||||
|
// bit 1 - 10DASH+1
|
||||||
|
// bit 2 - 1DASH+1
|
||||||
|
// bit 3 - .1DASH+1
|
||||||
|
|
||||||
|
int nMaxDenoms = vecPrivateSendDenominations.size();
|
||||||
|
|
||||||
|
if(nDenom >= (1 << nMaxDenoms)) return false;
|
||||||
|
|
||||||
|
vecBitsRet.clear();
|
||||||
|
|
||||||
|
for (int i = 0; i < nMaxDenoms; ++i) {
|
||||||
|
if(nDenom & (1 << i)) {
|
||||||
|
vecBitsRet.push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return !vecBitsRet.empty();
|
||||||
|
}
|
||||||
|
|
||||||
int CDarksendPool::GetDenominationsByAmounts(const std::vector<CAmount>& vecAmount)
|
int CDarksendPool::GetDenominationsByAmounts(const std::vector<CAmount>& vecAmount)
|
||||||
{
|
{
|
||||||
CScript scriptTmp = CScript();
|
CScript scriptTmp = CScript();
|
||||||
|
@ -446,6 +446,7 @@ public:
|
|||||||
int GetDenominations(const std::vector<CTxOut>& vecTxOut, bool fSingleRandomDenom = false);
|
int GetDenominations(const std::vector<CTxOut>& vecTxOut, bool fSingleRandomDenom = false);
|
||||||
int GetDenominations(const std::vector<CTxDSOut>& vecTxDSOut);
|
int GetDenominations(const std::vector<CTxDSOut>& vecTxDSOut);
|
||||||
std::string GetDenominationsToString(int nDenom);
|
std::string GetDenominationsToString(int nDenom);
|
||||||
|
bool GetDenominationsBits(int nDenom, std::vector<int> &vecBitsRet);
|
||||||
|
|
||||||
void SetMinBlockSpacing(int nMinBlockSpacingIn) { nMinBlockSpacing = nMinBlockSpacingIn; }
|
void SetMinBlockSpacing(int nMinBlockSpacingIn) { nMinBlockSpacing = nMinBlockSpacingIn; }
|
||||||
|
|
||||||
|
@ -2331,12 +2331,12 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl, AvailableCoinsType coin_type, bool fUseInstantSend) const
|
bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl, AvailableCoinsType nCoinType, bool fUseInstantSend) const
|
||||||
{
|
{
|
||||||
// Note: this function should never be used for "always free" tx types like dstx
|
// Note: this function should never be used for "always free" tx types like dstx
|
||||||
|
|
||||||
vector<COutput> vCoins;
|
vector<COutput> vCoins;
|
||||||
AvailableCoins(vCoins, true, coinControl, false, coin_type, fUseInstantSend);
|
AvailableCoins(vCoins, true, coinControl, false, nCoinType, fUseInstantSend);
|
||||||
|
|
||||||
// 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)
|
||||||
if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs)
|
if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs)
|
||||||
@ -2346,11 +2346,11 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*
|
|||||||
if(!out.fSpendable)
|
if(!out.fSpendable)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(coin_type == ONLY_DENOMINATED) {
|
if(nCoinType == ONLY_DENOMINATED) {
|
||||||
CTxIn vin = CTxIn(out.tx->GetHash(),out.i);
|
CTxIn txin = CTxIn(out.tx->GetHash(),out.i);
|
||||||
int rounds = GetInputPrivateSendRounds(vin);
|
int nRounds = GetInputPrivateSendRounds(txin);
|
||||||
// make sure it's actually anonymized
|
// make sure it's actually anonymized
|
||||||
if(rounds < nPrivateSendRounds) continue;
|
if(nRounds < nPrivateSendRounds) continue;
|
||||||
}
|
}
|
||||||
nValueRet += out.tx->vout[out.i].nValue;
|
nValueRet += out.tx->vout[out.i].nValue;
|
||||||
setCoinsRet.insert(make_pair(out.tx, out.i));
|
setCoinsRet.insert(make_pair(out.tx, out.i));
|
||||||
@ -2358,21 +2358,21 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*
|
|||||||
return (nValueRet >= nTargetValue);
|
return (nValueRet >= nTargetValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
//if we're doing only denominated, we need to round up to the nearest .1DRK
|
//if we're doing only denominated, we need to round up to the nearest smallest denomination
|
||||||
if(coin_type == ONLY_DENOMINATED) {
|
if(nCoinType == ONLY_DENOMINATED) {
|
||||||
|
CAmount nSmallestDenom = vecPrivateSendDenominations.back();
|
||||||
// Make outputs by looping through denominations, from large to small
|
// Make outputs by looping through denominations, from large to small
|
||||||
BOOST_FOREACH(CAmount v, vecPrivateSendDenominations)
|
BOOST_FOREACH(CAmount nDenom, vecPrivateSendDenominations)
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(const COutput& out, vCoins)
|
BOOST_FOREACH(const COutput& out, vCoins)
|
||||||
{
|
{
|
||||||
if(out.tx->vout[out.i].nValue == v //make sure it's the denom we're looking for
|
//make sure it's the denom we're looking for, round the amount up to smallest denom
|
||||||
&& nValueRet + out.tx->vout[out.i].nValue < nTargetValue + (0.1*COIN)+100 //round the amount up to .1DRK over
|
if(out.tx->vout[out.i].nValue == nDenom && nValueRet + nDenom < nTargetValue + nSmallestDenom) {
|
||||||
){
|
CTxIn txin = CTxIn(out.tx->GetHash(),out.i);
|
||||||
CTxIn vin = CTxIn(out.tx->GetHash(),out.i);
|
int nRounds = GetInputPrivateSendRounds(txin);
|
||||||
int rounds = GetInputPrivateSendRounds(vin);
|
|
||||||
// make sure it's actually anonymized
|
// make sure it's actually anonymized
|
||||||
if(rounds < nPrivateSendRounds) continue;
|
if(nRounds < nPrivateSendRounds) continue;
|
||||||
nValueRet += out.tx->vout[out.i].nValue;
|
nValueRet += nDenom;
|
||||||
setCoinsRet.insert(make_pair(out.tx, out.i));
|
setCoinsRet.insert(make_pair(out.tx, out.i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2480,19 +2480,13 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nC
|
|||||||
bool CWallet::SelectCoinsByDenominations(int nDenom, CAmount nValueMin, CAmount nValueMax, std::vector<CTxIn>& vecTxInRet, std::vector<COutput>& vCoinsRet, CAmount& nValueRet, int nPrivateSendRoundsMin, int nPrivateSendRoundsMax)
|
bool CWallet::SelectCoinsByDenominations(int nDenom, CAmount nValueMin, CAmount nValueMax, std::vector<CTxIn>& vecTxInRet, std::vector<COutput>& vCoinsRet, CAmount& nValueRet, int nPrivateSendRoundsMin, int nPrivateSendRoundsMax)
|
||||||
{
|
{
|
||||||
vecTxInRet.clear();
|
vecTxInRet.clear();
|
||||||
|
vCoinsRet.clear();
|
||||||
nValueRet = 0;
|
nValueRet = 0;
|
||||||
|
|
||||||
vCoinsRet.clear();
|
|
||||||
vector<COutput> vCoins;
|
vector<COutput> vCoins;
|
||||||
AvailableCoins(vCoins, true, NULL, false, ONLY_DENOMINATED);
|
AvailableCoins(vCoins, true, NULL, false, ONLY_DENOMINATED);
|
||||||
|
|
||||||
std::random_shuffle(vCoins.rbegin(), vCoins.rend());
|
std::random_shuffle(vCoins.rbegin(), vCoins.rend(), GetRandInt);
|
||||||
|
|
||||||
//keep track of each denomination that we have
|
|
||||||
bool fFound100 = false;
|
|
||||||
bool fFound10 = false;
|
|
||||||
bool fFound1 = false;
|
|
||||||
bool fFoundDot1 = false;
|
|
||||||
|
|
||||||
// ( bit on if present )
|
// ( bit on if present )
|
||||||
// bit 0 - 100DASH+1
|
// bit 0 - 100DASH+1
|
||||||
@ -2500,56 +2494,45 @@ bool CWallet::SelectCoinsByDenominations(int nDenom, CAmount nValueMin, CAmount
|
|||||||
// bit 2 - 1DASH+1
|
// bit 2 - 1DASH+1
|
||||||
// bit 3 - .1DASH+1
|
// bit 3 - .1DASH+1
|
||||||
|
|
||||||
//Check to see if any of the denomination are off, in that case mark them as fulfilled
|
std::vector<int> vecBits;
|
||||||
if(!(nDenom & (1 << 0))) fFound100 = true;
|
if (!darkSendPool.GetDenominationsBits(nDenom, vecBits)) {
|
||||||
if(!(nDenom & (1 << 1))) fFound10 = true;
|
return false;
|
||||||
if(!(nDenom & (1 << 2))) fFound1 = true;
|
}
|
||||||
if(!(nDenom & (1 << 3))) fFoundDot1 = true;
|
|
||||||
|
int nDenomResult = 0;
|
||||||
|
|
||||||
BOOST_FOREACH(const COutput& out, vCoins)
|
BOOST_FOREACH(const COutput& out, vCoins)
|
||||||
{
|
{
|
||||||
// masternode-like input should not be selected by AvailableCoins now anyway
|
// masternode-like input should not be selected by AvailableCoins now anyway
|
||||||
//if(out.tx->vout[out.i].nValue == 1000*COIN) continue;
|
//if(out.tx->vout[out.i].nValue == 1000*COIN) continue;
|
||||||
if(nValueRet + out.tx->vout[out.i].nValue <= nValueMax){
|
if(nValueRet + out.tx->vout[out.i].nValue <= nValueMax){
|
||||||
bool fAccepted = false;
|
|
||||||
|
|
||||||
CTxIn txin = CTxIn(out.tx->GetHash(),out.i);
|
CTxIn txin = CTxIn(out.tx->GetHash(), out.i);
|
||||||
|
|
||||||
int nRounds = GetInputPrivateSendRounds(txin);
|
int nRounds = GetInputPrivateSendRounds(txin);
|
||||||
if(nRounds >= nPrivateSendRoundsMax) continue;
|
if(nRounds >= nPrivateSendRoundsMax) continue;
|
||||||
if(nRounds < nPrivateSendRoundsMin) continue;
|
if(nRounds < nPrivateSendRoundsMin) continue;
|
||||||
|
|
||||||
if(fFound100 && fFound10 && fFound1 && fFoundDot1){ //if fulfilled
|
BOOST_FOREACH(int nBit, vecBits) {
|
||||||
//we can return this for submission
|
if(out.tx->vout[out.i].nValue == vecPrivateSendDenominations[nBit]) {
|
||||||
if(nValueRet >= nValueMin){
|
if(nValueRet >= nValueMin) {
|
||||||
//random reduce the max amount we'll submit for anonymity
|
//randomly reduce the max amount we'll submit (for anonymity)
|
||||||
nValueMax -= (rand() % (nValueMax/5));
|
nValueMax -= (GetInsecureRand(nValueMax/5));
|
||||||
//on average use 50% of the inputs or less
|
//on average use 50% of the inputs or less
|
||||||
int r = (rand() % (int)vCoins.size());
|
int r = GetInsecureRand((int)vCoins.size());
|
||||||
if((int)vecTxInRet.size() > r) return true;
|
if((int)vecTxInRet.size() > r) return true;
|
||||||
|
}
|
||||||
|
txin.prevPubKey = out.tx->vout[out.i].scriptPubKey; // the inputs PubKey
|
||||||
|
nValueRet += out.tx->vout[out.i].nValue;
|
||||||
|
vecTxInRet.push_back(txin);
|
||||||
|
vCoinsRet.push_back(out);
|
||||||
|
nDenomResult |= 1 << nBit;
|
||||||
}
|
}
|
||||||
//Denomination criterion has been met, we can take any matching denominations
|
|
||||||
if((nDenom & (1 << 0)) && out.tx->vout[out.i].nValue == ((100*COIN) +100000)) {fAccepted = true;}
|
|
||||||
else if((nDenom & (1 << 1)) && out.tx->vout[out.i].nValue == ((10*COIN)+10000)) {fAccepted = true;}
|
|
||||||
else if((nDenom & (1 << 2)) && out.tx->vout[out.i].nValue == ((1*COIN) +1000)) {fAccepted = true;}
|
|
||||||
else if((nDenom & (1 << 3)) && out.tx->vout[out.i].nValue == ((.1*COIN)+100)) {fAccepted = true;}
|
|
||||||
} else {
|
|
||||||
//Criterion has not been satisfied, we will only take 1 of each until it is.
|
|
||||||
if((nDenom & (1 << 0)) && out.tx->vout[out.i].nValue == ((100*COIN) +100000)) {fAccepted = true; fFound100 = true;}
|
|
||||||
else if((nDenom & (1 << 1)) && out.tx->vout[out.i].nValue == ((10*COIN)+10000)) {fAccepted = true; fFound10 = true;}
|
|
||||||
else if((nDenom & (1 << 2)) && out.tx->vout[out.i].nValue == ((1*COIN) +1000)) {fAccepted = true; fFound1 = true;}
|
|
||||||
else if((nDenom & (1 << 3)) && out.tx->vout[out.i].nValue == ((.1*COIN)+100)) {fAccepted = true; fFoundDot1 = true;}
|
|
||||||
}
|
}
|
||||||
if(!fAccepted) continue;
|
|
||||||
|
|
||||||
txin.prevPubKey = out.tx->vout[out.i].scriptPubKey; // the inputs PubKey
|
|
||||||
nValueRet += out.tx->vout[out.i].nValue;
|
|
||||||
vecTxInRet.push_back(txin);
|
|
||||||
vCoinsRet.push_back(out);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (nValueRet >= nValueMin && fFound100 && fFound10 && fFound1 && fFoundDot1);
|
return nValueRet >= nValueMin && nDenom == nDenomResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CompareByAmount
|
struct CompareByAmount
|
||||||
|
@ -518,7 +518,7 @@ private:
|
|||||||
* all coins from coinControl are selected; Never select unconfirmed coins
|
* all coins from coinControl are selected; Never select unconfirmed coins
|
||||||
* if they are not ours
|
* if they are not ours
|
||||||
*/
|
*/
|
||||||
bool SelectCoins(const CAmount& nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl *coinControl = NULL, AvailableCoinsType coin_type=ALL_COINS, bool fUseInstantSend = true) const;
|
bool SelectCoins(const CAmount& nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl *coinControl = NULL, AvailableCoinsType nCoinType=ALL_COINS, bool fUseInstantSend = true) const;
|
||||||
|
|
||||||
CWalletDB *pwalletdbEncryption;
|
CWalletDB *pwalletdbEncryption;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user