thread safe rand (#1157)

* thread safe InsecureRand class

* remove GetInsecureRand, use GetRandInt for performance non-critical parts
This commit is contained in:
UdjinM6 2016-11-20 10:52:45 +04:00 committed by GitHub
parent e121829e40
commit c2ec99ba8e
5 changed files with 56 additions and 15 deletions

View File

@ -664,7 +664,7 @@ void CDarksendPool::ChargeFees()
if(!fMasterNode) return;
//we don't need to charge collateral for every offence.
if(GetInsecureRand(100) > 33) return;
if(GetRandInt(100) > 33) return;
std::vector<CTransaction> vecOffendersCollaterals;
@ -699,7 +699,7 @@ void CDarksendPool::ChargeFees()
if(vecOffendersCollaterals.empty()) return;
//mostly offending? Charge sometimes
if((int)vecOffendersCollaterals.size() >= Params().PoolMaxTransactions() - 1 && GetInsecureRand(100) > 33) return;
if((int)vecOffendersCollaterals.size() >= Params().PoolMaxTransactions() - 1 && GetRandInt(100) > 33) return;
//everyone is an offender? That's not right
if((int)vecOffendersCollaterals.size() >= Params().PoolMaxTransactions()) return;
@ -740,7 +740,7 @@ void CDarksendPool::ChargeRandomFees()
BOOST_FOREACH(const CTransaction& txCollateral, vecSessionCollaterals) {
if(GetInsecureRand(100) > 10) return;
if(GetRandInt(100) > 10) return;
LogPrintf("CDarksendPool::ChargeRandomFees -- charging random fees, txCollateral=%s", txCollateral.ToString());
@ -1480,7 +1480,7 @@ bool CDarksendPool::DoAutomaticDenominating(bool fDryRun)
LogPrint("privatesend", " vecMasternodesUsed: new size: %d, threshold: %d\n", (int)vecMasternodesUsed.size(), nThreshold_high);
}
bool fUseQueue = insecure_rand()%100 > 33;
bool fUseQueue = GetRandInt(100) > 33;
// don't use the queues all of the time for mixing unless we are a liquidity provider
if(nLiquidityProvider || fUseQueue) {
@ -2014,7 +2014,7 @@ bool CDarksendPool::CreateNewSession(int nDenom, CTransaction txCollateral, Pool
// start new session
nMessageIDRet = MSG_NOERR;
nSessionID = GetInsecureRand(999999)+1;
nSessionID = GetRandInt(999999)+1;
nSessionDenom = nDenom;
SetState(POOL_STATE_QUEUE);
@ -2145,7 +2145,7 @@ int CDarksendPool::GetDenominations(const std::vector<CTxOut>& vecTxOut, bool fS
int c = 0;
// if the denomination is used, shift the bit on
BOOST_FOREACH (PAIRTYPE(CAmount, int)& s, vecDenomUsed) {
int bit = (fSingleRandomDenom ? insecure_rand()%2 : 1) & s.second;
int bit = (fSingleRandomDenom ? GetRandInt(2) : 1) & s.second;
nDenom |= bit << c++;
if(fSingleRandomDenom && bit) break; // use just one random denomination
}
@ -2462,7 +2462,7 @@ void ThreadCheckDarkSendPool()
if(nDoAutoNextRun == nTick) {
darkSendPool.DoAutomaticDenominating();
nDoAutoNextRun = nTick + PRIVATESEND_AUTO_TIMEOUT_MIN + GetInsecureRand(PRIVATESEND_AUTO_TIMEOUT_MAX - PRIVATESEND_AUTO_TIMEOUT_MIN);
nDoAutoNextRun = nTick + PRIVATESEND_AUTO_TIMEOUT_MIN + GetRandInt(PRIVATESEND_AUTO_TIMEOUT_MAX - PRIVATESEND_AUTO_TIMEOUT_MIN);
}
}
}

View File

@ -543,8 +543,9 @@ CMasternode* CMasternodeMan::FindRandomNotInVec(const std::vector<CTxIn> &vecToE
vpMasternodesShuffled.push_back(&mn);
}
InsecureRand insecureRand;
// shuffle pointers
std::random_shuffle(vpMasternodesShuffled.begin(), vpMasternodesShuffled.end(), GetInsecureRand);
std::random_shuffle(vpMasternodesShuffled.begin(), vpMasternodesShuffled.end(), insecureRand);
bool fExclude;
// loop through
@ -969,7 +970,7 @@ bool CMasternodeMan::SendVerifyRequest(const CAddress& addr, const std::vector<C
if(pnode != NULL) {
netfulfilledman.AddFulfilledRequest(addr, strprintf("%s", NetMsgType::MNVERIFY)+"-request");
// use random nonce, store it and require node to reply with correct one later
CMasternodeVerification mnv(addr, GetInsecureRand(999999), pCurrentBlockIndex->nHeight - 1);
CMasternodeVerification mnv(addr, GetRandInt(999999), pCurrentBlockIndex->nHeight - 1);
mWeAskedForVerification[addr] = mnv;
LogPrintf("CMasternodeMan::SendVerifyRequest -- verifying using nonce %d addr=%s\n", mnv.nonce, addr.ToString());
pnode->PushMessage(NetMsgType::MNVERIFY, mnv);

View File

@ -137,3 +137,21 @@ void seed_insecure_rand(bool fDeterministic)
insecure_rand_Rw = tmp;
}
}
InsecureRand::InsecureRand(bool _fDeterministic)
: nRz(11),
nRw(11),
fDeterministic(_fDeterministic)
{
// The seed values have some unlikely fixed points which we avoid.
if(fDeterministic) return;
uint32_t nTmp;
do {
GetRandBytes((unsigned char*)&nTmp, 4);
} while (nTmp == 0 || nTmp == 0x9068ffffU);
nRz = nTmp;
do {
GetRandBytes((unsigned char*)&nTmp, 4);
} while (nTmp == 0 || nTmp == 0x464fffffU);
nRw = nTmp;
}

View File

@ -47,10 +47,31 @@ static inline uint32_t insecure_rand(void)
}
/**
* Function for std::random_shuffle
* PRNG initialized from secure entropy based RNG
*/
static inline uint32_t GetInsecureRand(uint32_t i){
return insecure_rand() % i;
class InsecureRand
{
private:
uint32_t nRz;
uint32_t nRw;
bool fDeterministic;
public:
InsecureRand(bool _fDeterministic = false);
/**
* MWC RNG of George Marsaglia
* This is intended to be fast. It has a period of 2^59.3, though the
* least significant 16 bits only have a period of about 2^30.1.
*
* @return random value < nMax
*/
int64_t operator()(int64_t nMax)
{
nRz = 36969 * (nRz & 65535) + (nRz >> 16);
nRw = 18000 * (nRw & 65535) + (nRw >> 16);
return ((nRw << 16) + nRz) % nMax;
}
};
#endif // BITCOIN_RANDOM_H

View File

@ -2501,6 +2501,7 @@ bool CWallet::SelectCoinsByDenominations(int nDenom, CAmount nValueMin, CAmount
int nDenomResult = 0;
InsecureRand insecureRand;
BOOST_FOREACH(const COutput& out, vCoins)
{
// masternode-like input should not be selected by AvailableCoins now anyway
@ -2517,9 +2518,9 @@ bool CWallet::SelectCoinsByDenominations(int nDenom, CAmount nValueMin, CAmount
if(out.tx->vout[out.i].nValue == vecPrivateSendDenominations[nBit]) {
if(nValueRet >= nValueMin) {
//randomly reduce the max amount we'll submit (for anonymity)
nValueMax -= (GetInsecureRand(nValueMax/5));
nValueMax -= insecureRand(nValueMax/5);
//on average use 50% of the inputs or less
int r = GetInsecureRand((int)vCoins.size());
int r = insecureRand(vCoins.size());
if((int)vecTxInRet.size() > r) return true;
}
txin.prevPubKey = out.tx->vout[out.i].scriptPubKey; // the inputs PubKey