This commit is contained in:
UdjinM6 2015-01-20 20:57:55 +03:00
commit 39c7deb49d
4 changed files with 46 additions and 87 deletions

View File

@ -18,6 +18,7 @@
using namespace std; using namespace std;
using namespace boost; using namespace boost;
CCriticalSection cs_darksend;
/** The main object for accessing darksend */ /** The main object for accessing darksend */
CDarkSendPool darkSendPool; CDarkSendPool darkSendPool;
@ -461,7 +462,6 @@ void CDarkSendPool::SetNull(bool clearEverything){
sessionUsers = 0; sessionUsers = 0;
sessionDenom = 0; sessionDenom = 0;
sessionFoundMasternode = false; sessionFoundMasternode = false;
sessionTries = 0;
vecSessionCollateral.clear(); vecSessionCollateral.clear();
txCollateral = CTransaction(); txCollateral = CTransaction();
@ -864,7 +864,6 @@ void CDarkSendPool::CheckTimeout(){
sessionUsers = 0; sessionUsers = 0;
sessionDenom = 0; sessionDenom = 0;
sessionFoundMasternode = false; sessionFoundMasternode = false;
sessionTries = 0;
vecSessionCollateral.clear(); vecSessionCollateral.clear();
UpdateState(POOL_STATUS_ACCEPTING_ENTRIES); UpdateState(POOL_STATUS_ACCEPTING_ENTRIES);
@ -1410,6 +1409,8 @@ void CDarkSendPool::ClearLastMessage()
// //
bool CDarkSendPool::DoAutomaticDenominating(bool fDryRun, bool ready) bool CDarkSendPool::DoAutomaticDenominating(bool fDryRun, bool ready)
{ {
LOCK(cs_darksend);
if(fMasterNode) return false; if(fMasterNode) return false;
if(state == POOL_STATUS_ERROR || state == POOL_STATUS_SUCCESS) return false; if(state == POOL_STATUS_ERROR || state == POOL_STATUS_SUCCESS) return false;
@ -1443,6 +1444,7 @@ bool CDarkSendPool::DoAutomaticDenominating(bool fDryRun, bool ready)
// ** find the coins we'll use // ** find the coins we'll use
std::vector<CTxIn> vCoins; std::vector<CTxIn> vCoins;
std::vector<COutput> vCoins2;
int64_t nValueMin = 0.01*COIN; int64_t nValueMin = 0.01*COIN;
int64_t nValueIn = 0; int64_t nValueIn = 0;
int64_t lowestDenom = COIN*0.1; int64_t lowestDenom = COIN*0.1;
@ -1456,8 +1458,7 @@ bool CDarkSendPool::DoAutomaticDenominating(bool fDryRun, bool ready)
int64_t nonanonymized = pwalletMain->GetBalance() - pwalletMain->GetAnonymizedBalance() - COIN; int64_t nonanonymized = pwalletMain->GetBalance() - pwalletMain->GetAnonymizedBalance() - COIN;
if(balanceNeedsAnonymized > nonanonymized) balanceNeedsAnonymized = nonanonymized; if(balanceNeedsAnonymized > nonanonymized) balanceNeedsAnonymized = nonanonymized;
if(balanceNeedsAnonymized < lowestDenom || if(balanceNeedsAnonymized < lowestDenom){
(vecDisabledDenominations.size() > 0 && balanceNeedsAnonymized < COIN*10)){
LogPrintf("DoAutomaticDenominating : No funds detected in need of denominating \n"); LogPrintf("DoAutomaticDenominating : No funds detected in need of denominating \n");
strAutoDenomResult = "No funds detected in need of denominating"; strAutoDenomResult = "No funds detected in need of denominating";
return false; return false;
@ -1489,15 +1490,6 @@ bool CDarkSendPool::DoAutomaticDenominating(bool fDryRun, bool ready)
if(fDryRun) return true; if(fDryRun) return true;
if(vecDisabledDenominations.size() == 0){
//if we have 20x 0.1DRk and 1DRK inputs, we can start just anonymizing 10DRK inputs.
if(pwalletMain->CountInputsWithAmount((1 * COIN)+1) >= 20 &&
pwalletMain->CountInputsWithAmount((.1 * COIN)+1) >= 20){
vecDisabledDenominations.push_back((1 * COIN)+1);
vecDisabledDenominations.push_back((.1 * COIN)+1);
}
}
// initial phase, find a masternode // initial phase, find a masternode
if(!sessionFoundMasternode){ if(!sessionFoundMasternode){
int nUseQueue = rand()%100; int nUseQueue = rand()%100;
@ -1542,11 +1534,9 @@ bool CDarkSendPool::DoAutomaticDenominating(bool fDryRun, bool ready)
} }
// Try to match their denominations if possible // Try to match their denominations if possible
if (!pwalletMain->SelectCoinsByDenominations(dsq.nDenom, nValueMin, balanceNeedsAnonymized, vCoins, nValueIn, 0, nDarksendRounds)){ if (!pwalletMain->SelectCoinsByDenominations(dsq.nDenom, nValueMin, balanceNeedsAnonymized, vCoins, vCoins2, nValueIn, 0, nDarksendRounds)){
// if (!pwalletMain->SelectCoinsByDenominations(dsq.nDenom, nValueMin, balanceNeedsAnonymized, vCoins, nValueIn, -2, 0)){
LogPrintf("DoAutomaticDenominating - Couldn't match denominations %d\n", dsq.nDenom); LogPrintf("DoAutomaticDenominating - Couldn't match denominations %d\n", dsq.nDenom);
continue; continue;
// }
} }
// connect to masternode and submit the queue request // connect to masternode and submit the queue request
@ -1584,30 +1574,33 @@ bool CDarkSendPool::DoAutomaticDenominating(bool fDryRun, bool ready)
} }
} }
// otherwise, try one randomly //shuffle masternodes around before we try to connect
if(sessionTries++ < 10){ std::random_shuffle ( vecMasternodes.begin(), vecMasternodes.end() );
//pick a random masternode to use int i = 0;
int max_value = vecMasternodes.size();
if(max_value <= 0) return false;
int i = (rand() % max_value);
// otherwise, try one randomly
while(i < 10)
{
//don't reuse masternodes //don't reuse masternodes
BOOST_FOREACH(CTxIn usedVin, vecMasternodesUsed) { BOOST_FOREACH(CTxIn usedVin, vecMasternodesUsed) {
if(vecMasternodes[i].vin == usedVin){ if(vecMasternodes[i].vin == usedVin){
return DoAutomaticDenominating(); i++;
continue;
} }
} }
if(vecMasternodes[i].protocolVersion < MIN_PEER_PROTO_VERSION) { if(vecMasternodes[i].protocolVersion < MIN_PEER_PROTO_VERSION) {
return DoAutomaticDenominating(); i++;
continue;
} }
if(vecMasternodes[i].nLastDsq != 0 && if(vecMasternodes[i].nLastDsq != 0 &&
vecMasternodes[i].nLastDsq + CountMasternodesAboveProtocol(darkSendPool.MIN_PEER_PROTO_VERSION)/5 > darkSendPool.nDsqCount){ vecMasternodes[i].nLastDsq + CountMasternodesAboveProtocol(darkSendPool.MIN_PEER_PROTO_VERSION)/5 > darkSendPool.nDsqCount){
return DoAutomaticDenominating(); i++;
continue;
} }
lastTimeChanged = GetTimeMillis(); lastTimeChanged = GetTimeMillis();
LogPrintf("DoAutomaticDenominating -- attempt %d connection to masternode %s\n", sessionTries, vecMasternodes[i].addr.ToString().c_str()); LogPrintf("DoAutomaticDenominating -- attempt %d connection to masternode %s\n", i, vecMasternodes[i].addr.ToString().c_str());
if(ConnectNode((CAddress)vecMasternodes[i].addr, NULL, true)){ if(ConnectNode((CAddress)vecMasternodes[i].addr, NULL, true)){
submittedToMasternode = vecMasternodes[i].addr; submittedToMasternode = vecMasternodes[i].addr;
@ -1619,7 +1612,7 @@ bool CDarkSendPool::DoAutomaticDenominating(bool fDryRun, bool ready)
std::string strReason; std::string strReason;
if(txCollateral == CTransaction()){ if(txCollateral == CTransaction()){
if(!pwalletMain->CreateCollateralTransaction(txCollateral, strReason)){ if(!pwalletMain->CreateCollateralTransaction(txCollateral, strReason)){
LogPrintf("DoAutomaticDenominating -- dsa error:%s\n", strReason.c_str()); LogPrintf("DoAutomaticDenominating -- create collateral error:%s\n", strReason.c_str());
return false; return false;
} }
} }
@ -1636,14 +1629,14 @@ bool CDarkSendPool::DoAutomaticDenominating(bool fDryRun, bool ready)
return true; return true;
} }
} else { } else {
LogPrintf("DoAutomaticDenominating --- error connecting \n"); i++;
return DoAutomaticDenominating(); continue;
} }
} else { }
strAutoDenomResult = "No compatible masternode found"; strAutoDenomResult = "No compatible masternode found";
return false; return false;
} }
}
strAutoDenomResult = ""; strAutoDenomResult = "";
if(!ready) return true; if(!ready) return true;
@ -1820,15 +1813,8 @@ bool CDarkSendPool::CreateDenominated(int64_t nTotalValue)
// ****** Add denoms ************ / // ****** Add denoms ************ /
BOOST_REVERSE_FOREACH(int64_t v, darkSendDenominations){ BOOST_REVERSE_FOREACH(int64_t v, darkSendDenominations){
int nOutputs = 0; int nOutputs = 0;
if(std::find(vecDisabledDenominations.begin(),
vecDisabledDenominations.end(), v) !=
vecDisabledDenominations.end()){
continue;
}
// add each output up to 10 times until it can't be added again // add each output up to 10 times until it can't be added again
while(nValueLeft - v >= 0 && nOutputs <= 10) { while(nValueLeft - v >= 0 && nOutputs <= 10) {
CScript scriptChange; CScript scriptChange;
@ -2055,9 +2041,6 @@ int CDarkSendPool::GetDenominationsByAmount(int64_t nAmount, int nDenomTarget){
int nOutputs = 0; int nOutputs = 0;
if(std::find(vecDisabledDenominations.begin(), vecDisabledDenominations.end(), v) != vecDisabledDenominations.end())
continue;
// add each output up to 10 times until it can't be added again // add each output up to 10 times until it can't be added again
while(nValueLeft - v >= 0 && nOutputs <= 10) { while(nValueLeft - v >= 0 && nOutputs <= 10) {
CTxOut o(v, e); CTxOut o(v, e);

View File

@ -256,7 +256,6 @@ public:
int sessionDenom; //Users must submit an denom matching this int sessionDenom; //Users must submit an denom matching this
int sessionUsers; //N Users have said they'll join int sessionUsers; //N Users have said they'll join
bool sessionFoundMasternode; //If we've found a compatible masternode bool sessionFoundMasternode; //If we've found a compatible masternode
int sessionTries;
int64_t sessionTotalValue; //used for autoDenom int64_t sessionTotalValue; //used for autoDenom
std::vector<CTransaction> vecSessionCollateral; std::vector<CTransaction> vecSessionCollateral;
@ -270,8 +269,6 @@ public:
//debugging data //debugging data
std::string strAutoDenomResult; std::string strAutoDenomResult;
std::vector<int64_t> vecDisabledDenominations;
//incremented whenever a DSQ comes through //incremented whenever a DSQ comes through
int64_t nDsqCount; int64_t nDsqCount;
@ -288,7 +285,6 @@ public:
txCollateral = CTransaction(); txCollateral = CTransaction();
minBlockSpacing = 1; minBlockSpacing = 1;
nDsqCount = 0; nDsqCount = 0;
vecDisabledDenominations.clear();
SetNull(); SetNull();
} }

View File

@ -1505,18 +1505,17 @@ struct CompareByPriority
} }
}; };
bool CWallet::SelectCoinsByDenominations(int nDenom, int64_t nValueMin, int64_t nValueMax, std::vector<CTxIn>& setCoinsRet, int64_t& nValueRet, int nDarksendRoundsMin, int nDarksendRoundsMax) bool CWallet::SelectCoinsByDenominations(int nDenom, int64_t nValueMin, int64_t nValueMax, std::vector<CTxIn>& setCoinsRet, vector<COutput>& setCoinsRet2, int64_t& nValueRet, int nDarksendRoundsMin, int nDarksendRoundsMax)
{ {
CCoinControl *coinControl=NULL; CCoinControl *coinControl=NULL;
setCoinsRet.clear(); setCoinsRet.clear();
nValueRet = 0; nValueRet = 0;
setCoinsRet2.clear();
vector<COutput> vCoins; vector<COutput> vCoins;
AvailableCoins(vCoins, false, coinControl, ALL_COINS); AvailableCoins(vCoins, false, coinControl, ALL_COINS);
set<pair<const CWalletTx*,unsigned int> > setCoinsRet2;
//order the array so fees are first, then denominated money, then the rest. //order the array so fees are first, then denominated money, then the rest.
std::random_shuffle(vCoins.rbegin(), vCoins.rend()); std::random_shuffle(vCoins.rbegin(), vCoins.rend());
@ -1579,7 +1578,7 @@ bool CWallet::SelectCoinsByDenominations(int nDenom, int64_t nValueMin, int64_t
vin.prevPubKey = out.tx->vout[out.i].scriptPubKey; // the inputs PubKey vin.prevPubKey = out.tx->vout[out.i].scriptPubKey; // the inputs PubKey
nValueRet += out.tx->vout[out.i].nValue; nValueRet += out.tx->vout[out.i].nValue;
setCoinsRet.push_back(vin); setCoinsRet.push_back(vin);
setCoinsRet2.insert(make_pair(out.tx, out.i)); setCoinsRet2.push_back(out);
} }
} }
@ -2112,6 +2111,7 @@ string CWallet::PrepareDarksendDenominate(int minRounds, int maxRounds)
// ** find the coins we'll use // ** find the coins we'll use
std::vector<CTxIn> vCoins; std::vector<CTxIn> vCoins;
std::vector<COutput> vCoins2;
int64_t nValueIn = 0; int64_t nValueIn = 0;
CReserveKey reservekey(this); CReserveKey reservekey(this);
@ -2121,7 +2121,7 @@ string CWallet::PrepareDarksendDenominate(int minRounds, int maxRounds)
if minRounds >= 0 it means only denominated inputs are going in and coming out if minRounds >= 0 it means only denominated inputs are going in and coming out
*/ */
if(minRounds >= 0){ if(minRounds >= 0){
if (!SelectCoinsByDenominations(darkSendPool.sessionDenom, 0.1*COIN, DARKSEND_POOL_MAX, vCoins, nValueIn, minRounds, maxRounds)) if (!SelectCoinsByDenominations(darkSendPool.sessionDenom, 0.1*COIN, DARKSEND_POOL_MAX, vCoins, vCoins2, nValueIn, minRounds, maxRounds))
return _("Insufficient funds"); return _("Insufficient funds");
} }
@ -2138,18 +2138,8 @@ string CWallet::PrepareDarksendDenominate(int minRounds, int maxRounds)
std::vector<CTxOut> vOut; std::vector<CTxOut> vOut;
// Make outputs by looping through denominations, from small to large // Make outputs by looping through denominations, from small to large
BOOST_REVERSE_FOREACH(int64_t v, darkSendDenominations){
bool fAccepted = false;
if((darkSendPool.sessionDenom & (1 << 0)) && v == ((100*COIN)+1)) {fAccepted = true;}
else if((darkSendPool.sessionDenom & (1 << 1)) && v == ((10*COIN)+1)) {fAccepted = true;}
else if((darkSendPool.sessionDenom & (1 << 2)) && v == ((1*COIN)+1)) {fAccepted = true;}
else if((darkSendPool.sessionDenom & (1 << 3)) && v == ((.1*COIN)+1)) {fAccepted = true;}
if(!fAccepted) continue;
int nOutputs = 0; BOOST_FOREACH(const COutput& out, vCoins2){
// add each output up to 10 times until it can't be added again
while(nValueLeft - v >= 0 && nOutputs <= 10) {
CScript scriptChange; CScript scriptChange;
CPubKey vchPubKey; CPubKey vchPubKey;
//use a unique change address //use a unique change address
@ -2157,29 +2147,19 @@ string CWallet::PrepareDarksendDenominate(int minRounds, int maxRounds)
scriptChange.SetDestination(vchPubKey.GetID()); scriptChange.SetDestination(vchPubKey.GetID());
reservekey.KeepKey(); reservekey.KeepKey();
CTxOut o(v, scriptChange); CTxOut o(out.tx->vout[out.i].nValue, scriptChange);
vOut.push_back(o); vOut.push_back(o);
//increment outputs and subtract denomination amount //increment outputs and subtract denomination amount
nOutputs++; nValueLeft -= out.tx->vout[out.i].nValue;
nValueLeft -= v;
}
if(nValueLeft == 0) break; if(nValueLeft == 0) break;
} }
// if we have anything left over, send it back as change // if we have anything left over, send it back as change
if(nValueLeft > 0){ if(nValueLeft != 0)
CScript scriptChange; return "Error: change left-over in pool. Must use denominations only";
CPubKey vchPubKey;
assert(reservekey.GetReservedKey(vchPubKey)); // should never fail, as we just unlocked
scriptChange.SetDestination(vchPubKey.GetID());
reservekey.KeepKey();
CTxOut o(nValueLeft, scriptChange);
vOut.push_back(o);
}
darkSendPool.SendDarksendDenominate(vCoins, vOut, nValueIn); darkSendPool.SendDarksendDenominate(vCoins, vOut, nValueIn);

View File

@ -133,7 +133,7 @@ private:
public: public:
bool SelectCoins(int64_t nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet, const CCoinControl *coinControl = NULL, AvailableCoinsType coin_type=ALL_COINS) const; bool SelectCoins(int64_t nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet, const CCoinControl *coinControl = NULL, AvailableCoinsType coin_type=ALL_COINS) const;
bool SelectCoinsDark(int64_t nValueMin, int64_t nValueMax, std::vector<CTxIn>& setCoinsRet, int64_t& nValueRet, int nDarksendRoundsMin, int nDarksendRoundsMax) const; bool SelectCoinsDark(int64_t nValueMin, int64_t nValueMax, std::vector<CTxIn>& setCoinsRet, int64_t& nValueRet, int nDarksendRoundsMin, int nDarksendRoundsMax) const;
bool SelectCoinsByDenominations(int nDenom, int64_t nValueMin, int64_t nValueMax, std::vector<CTxIn>& setCoinsRet, int64_t& nValueRet, int nDarksendRoundsMin, int nDarksendRoundsMax); bool SelectCoinsByDenominations(int nDenom, int64_t nValueMin, int64_t nValueMax, std::vector<CTxIn>& setCoinsRet, vector<COutput>& vCoins, int64_t& nValueRet, int nDarksendRoundsMin, int nDarksendRoundsMax);
bool SelectCoinsDarkDenominated(int64_t nTargetValue, std::vector<CTxIn>& setCoinsRet, int64_t& nValueRet) const; bool SelectCoinsDarkDenominated(int64_t nTargetValue, std::vector<CTxIn>& setCoinsRet, int64_t& nValueRet) const;
bool SelectCoinsMasternode(CTxIn& vin, int64_t& nValueRet, CScript& pubScript) const; bool SelectCoinsMasternode(CTxIn& vin, int64_t& nValueRet, CScript& pubScript) const;
bool HasDarksendFeeInputs() const; bool HasDarksendFeeInputs() const;