thread safe rand (#1157)
* thread safe InsecureRand class * remove GetInsecureRand, use GetRandInt for performance non-critical parts
This commit is contained in:
parent
e121829e40
commit
c2ec99ba8e
@ -664,7 +664,7 @@ void CDarksendPool::ChargeFees()
|
|||||||
if(!fMasterNode) return;
|
if(!fMasterNode) return;
|
||||||
|
|
||||||
//we don't need to charge collateral for every offence.
|
//we don't need to charge collateral for every offence.
|
||||||
if(GetInsecureRand(100) > 33) return;
|
if(GetRandInt(100) > 33) return;
|
||||||
|
|
||||||
std::vector<CTransaction> vecOffendersCollaterals;
|
std::vector<CTransaction> vecOffendersCollaterals;
|
||||||
|
|
||||||
@ -699,7 +699,7 @@ void CDarksendPool::ChargeFees()
|
|||||||
if(vecOffendersCollaterals.empty()) return;
|
if(vecOffendersCollaterals.empty()) return;
|
||||||
|
|
||||||
//mostly offending? Charge sometimes
|
//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
|
//everyone is an offender? That's not right
|
||||||
if((int)vecOffendersCollaterals.size() >= Params().PoolMaxTransactions()) return;
|
if((int)vecOffendersCollaterals.size() >= Params().PoolMaxTransactions()) return;
|
||||||
@ -740,7 +740,7 @@ void CDarksendPool::ChargeRandomFees()
|
|||||||
|
|
||||||
BOOST_FOREACH(const CTransaction& txCollateral, vecSessionCollaterals) {
|
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());
|
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);
|
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
|
// don't use the queues all of the time for mixing unless we are a liquidity provider
|
||||||
if(nLiquidityProvider || fUseQueue) {
|
if(nLiquidityProvider || fUseQueue) {
|
||||||
|
|
||||||
@ -2014,7 +2014,7 @@ bool CDarksendPool::CreateNewSession(int nDenom, CTransaction txCollateral, Pool
|
|||||||
|
|
||||||
// start new session
|
// start new session
|
||||||
nMessageIDRet = MSG_NOERR;
|
nMessageIDRet = MSG_NOERR;
|
||||||
nSessionID = GetInsecureRand(999999)+1;
|
nSessionID = GetRandInt(999999)+1;
|
||||||
nSessionDenom = nDenom;
|
nSessionDenom = nDenom;
|
||||||
|
|
||||||
SetState(POOL_STATE_QUEUE);
|
SetState(POOL_STATE_QUEUE);
|
||||||
@ -2145,7 +2145,7 @@ int CDarksendPool::GetDenominations(const std::vector<CTxOut>& vecTxOut, bool fS
|
|||||||
int c = 0;
|
int c = 0;
|
||||||
// if the denomination is used, shift the bit on
|
// if the denomination is used, shift the bit on
|
||||||
BOOST_FOREACH (PAIRTYPE(CAmount, int)& s, vecDenomUsed) {
|
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++;
|
nDenom |= bit << c++;
|
||||||
if(fSingleRandomDenom && bit) break; // use just one random denomination
|
if(fSingleRandomDenom && bit) break; // use just one random denomination
|
||||||
}
|
}
|
||||||
@ -2462,7 +2462,7 @@ void ThreadCheckDarkSendPool()
|
|||||||
|
|
||||||
if(nDoAutoNextRun == nTick) {
|
if(nDoAutoNextRun == nTick) {
|
||||||
darkSendPool.DoAutomaticDenominating();
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -543,8 +543,9 @@ CMasternode* CMasternodeMan::FindRandomNotInVec(const std::vector<CTxIn> &vecToE
|
|||||||
vpMasternodesShuffled.push_back(&mn);
|
vpMasternodesShuffled.push_back(&mn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InsecureRand insecureRand;
|
||||||
// shuffle pointers
|
// shuffle pointers
|
||||||
std::random_shuffle(vpMasternodesShuffled.begin(), vpMasternodesShuffled.end(), GetInsecureRand);
|
std::random_shuffle(vpMasternodesShuffled.begin(), vpMasternodesShuffled.end(), insecureRand);
|
||||||
bool fExclude;
|
bool fExclude;
|
||||||
|
|
||||||
// loop through
|
// loop through
|
||||||
@ -969,7 +970,7 @@ bool CMasternodeMan::SendVerifyRequest(const CAddress& addr, const std::vector<C
|
|||||||
if(pnode != NULL) {
|
if(pnode != NULL) {
|
||||||
netfulfilledman.AddFulfilledRequest(addr, strprintf("%s", NetMsgType::MNVERIFY)+"-request");
|
netfulfilledman.AddFulfilledRequest(addr, strprintf("%s", NetMsgType::MNVERIFY)+"-request");
|
||||||
// use random nonce, store it and require node to reply with correct one later
|
// 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;
|
mWeAskedForVerification[addr] = mnv;
|
||||||
LogPrintf("CMasternodeMan::SendVerifyRequest -- verifying using nonce %d addr=%s\n", mnv.nonce, addr.ToString());
|
LogPrintf("CMasternodeMan::SendVerifyRequest -- verifying using nonce %d addr=%s\n", mnv.nonce, addr.ToString());
|
||||||
pnode->PushMessage(NetMsgType::MNVERIFY, mnv);
|
pnode->PushMessage(NetMsgType::MNVERIFY, mnv);
|
||||||
|
@ -137,3 +137,21 @@ void seed_insecure_rand(bool fDeterministic)
|
|||||||
insecure_rand_Rw = tmp;
|
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;
|
||||||
|
}
|
||||||
|
29
src/random.h
29
src/random.h
@ -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){
|
class InsecureRand
|
||||||
return insecure_rand() % i;
|
{
|
||||||
}
|
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
|
#endif // BITCOIN_RANDOM_H
|
||||||
|
@ -2501,6 +2501,7 @@ bool CWallet::SelectCoinsByDenominations(int nDenom, CAmount nValueMin, CAmount
|
|||||||
|
|
||||||
int nDenomResult = 0;
|
int nDenomResult = 0;
|
||||||
|
|
||||||
|
InsecureRand insecureRand;
|
||||||
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
|
||||||
@ -2517,9 +2518,9 @@ bool CWallet::SelectCoinsByDenominations(int nDenom, CAmount nValueMin, CAmount
|
|||||||
if(out.tx->vout[out.i].nValue == vecPrivateSendDenominations[nBit]) {
|
if(out.tx->vout[out.i].nValue == vecPrivateSendDenominations[nBit]) {
|
||||||
if(nValueRet >= nValueMin) {
|
if(nValueRet >= nValueMin) {
|
||||||
//randomly reduce the max amount we'll submit (for anonymity)
|
//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
|
//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;
|
if((int)vecTxInRet.size() > r) return true;
|
||||||
}
|
}
|
||||||
txin.prevPubKey = out.tx->vout[out.i].scriptPubKey; // the inputs PubKey
|
txin.prevPubKey = out.tx->vout[out.i].scriptPubKey; // the inputs PubKey
|
||||||
|
Loading…
Reference in New Issue
Block a user