Merge remote-tracking branch 'upstream/master'
commit
c535367514
|
@ -212,8 +212,8 @@ static const CRPCCommand vRPCCommands[] =
|
|||
{ "setgenerate", &setgenerate, true, false },
|
||||
{ "getsievepercentage", &getsievepercentage, true, false },
|
||||
{ "setsievepercentage", &setsievepercentage, true, false },
|
||||
{ "getroundsievepercentage",&getroundsievepercentage,true,false },
|
||||
{ "setroundsievepercentage",&setroundsievepercentage,true,false },
|
||||
{ "getsieveextensions", &getsieveextensions, true, false },
|
||||
{ "setsieveextensions", &setsieveextensions, true, false },
|
||||
{ "getprimespersec", &getprimespersec, true, false },
|
||||
{ "getchainspermin", &getchainspermin, true, false },
|
||||
{ "getinfo", &getinfo, true, false },
|
||||
|
@ -273,6 +273,7 @@ static const CRPCCommand vRPCCommands[] =
|
|||
{ "lockunspent", &lockunspent, false, false },
|
||||
{ "listlockunspent", &listlockunspent, false, false },
|
||||
{ "listprimerecords", &listprimerecords, false, false },
|
||||
{ "listtopprimes", &listtopprimes, false, false },
|
||||
};
|
||||
|
||||
CRPCTable::CRPCTable()
|
||||
|
@ -1221,7 +1222,7 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
|
|||
if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
|
||||
if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
|
||||
if (strMethod == "setsievepercentage" && n > 0) ConvertTo<boost::int64_t>(params[0]);
|
||||
if (strMethod == "setroundsievepercentage" && n > 0) ConvertTo<boost::int64_t>(params[0]);
|
||||
if (strMethod == "setsieveextensions" && n > 0) ConvertTo<boost::int64_t>(params[0]);
|
||||
if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
|
||||
if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
|
||||
if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
|
||||
|
@ -1268,6 +1269,7 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
|
|||
if (strMethod == "lockunspent" && n > 1) ConvertTo<Array>(params[1]);
|
||||
if (strMethod == "importprivkey" && n > 2) ConvertTo<bool>(params[2]);
|
||||
if (strMethod == "listprimerecords" && n > 0) ConvertTo<boost::int64_t>(params[0]);
|
||||
if (strMethod == "listtopprimes" && n > 0) ConvertTo<boost::int64_t>(params[0]);
|
||||
|
||||
return params;
|
||||
}
|
||||
|
|
|
@ -151,8 +151,8 @@ extern json_spirit::Value getgenerate(const json_spirit::Array& params, bool fHe
|
|||
extern json_spirit::Value setgenerate(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value getsievepercentage(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value setsievepercentage(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value getroundsievepercentage(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value setroundsievepercentage(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value getsieveextensions(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value setsieveextensions(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value getprimespersec(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value getchainspermin(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value getmininginfo(const json_spirit::Array& params, bool fHelp);
|
||||
|
@ -210,5 +210,6 @@ extern json_spirit::Value getblock(const json_spirit::Array& params, bool fHelp)
|
|||
extern json_spirit::Value gettxoutsetinfo(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value gettxout(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value listprimerecords(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value listtopprimes(const json_spirit::Array& params, bool fHelp);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -158,6 +158,11 @@ bool WriteSyncCheckpoint(const uint256& hashCheckpoint)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool IsSyncCheckpointEnforced()
|
||||
{
|
||||
return (GetBoolArg("-checkpointenforce", false) || mapArgs.count("-checkpointkey")); // checkpoint master node is always enforced
|
||||
}
|
||||
|
||||
bool AcceptPendingSyncCheckpoint()
|
||||
{
|
||||
LOCK(cs_hashSyncCheckpoint);
|
||||
|
@ -171,7 +176,7 @@ bool AcceptPendingSyncCheckpoint()
|
|||
}
|
||||
|
||||
CBlockIndex* pindexCheckpoint = mapBlockIndex[hashPendingCheckpoint];
|
||||
if (!pindexCheckpoint->IsInMainChain())
|
||||
if (IsSyncCheckpointEnforced() && !pindexCheckpoint->IsInMainChain())
|
||||
{
|
||||
CValidationState state;
|
||||
if (!SetBestChain(state, pindexCheckpoint))
|
||||
|
@ -434,7 +439,7 @@ bool CSyncCheckpoint::ProcessSyncCheckpoint(CNode* pfrom)
|
|||
return false;
|
||||
|
||||
CBlockIndex* pindexCheckpoint = mapBlockIndex[hashCheckpoint];
|
||||
if (!pindexCheckpoint->IsInMainChain())
|
||||
if (IsSyncCheckpointEnforced() && !pindexCheckpoint->IsInMainChain())
|
||||
{
|
||||
// checkpoint chain received but not yet main chain
|
||||
CValidationState state;
|
||||
|
@ -474,7 +479,7 @@ Value getcheckpoint(const Array& params, bool fHelp)
|
|||
result.push_back(Pair("height", pindexCheckpoint->nHeight));
|
||||
result.push_back(Pair("timestamp", (boost::int64_t) pindexCheckpoint->GetBlockTime()));
|
||||
}
|
||||
result.push_back(Pair("subscribemode", (GetBoolArg("-checkpointenforce", false) || mapArgs.count("-checkpointkey")? "enforce" : "advisory")));
|
||||
result.push_back(Pair("subscribemode", IsSyncCheckpointEnforced()? "enforce" : "advisory"));
|
||||
if (mapArgs.count("-checkpointkey"))
|
||||
result.push_back(Pair("checkpointmaster", true));
|
||||
|
||||
|
@ -507,7 +512,7 @@ Value sendcheckpoint(const Array& params, bool fHelp)
|
|||
result.push_back(Pair("height", pindexCheckpoint->nHeight));
|
||||
result.push_back(Pair("timestamp", (boost::int64_t) pindexCheckpoint->GetBlockTime()));
|
||||
}
|
||||
result.push_back(Pair("subscribemode", (GetBoolArg("-checkpointenforce", false) || mapArgs.count("-checkpointkey")? "enforce" : "advisory")));
|
||||
result.push_back(Pair("subscribemode", IsSyncCheckpointEnforced()? "enforce" : "advisory"));
|
||||
if (mapArgs.count("-checkpointkey"))
|
||||
result.push_back(Pair("checkpointmaster", true));
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ extern std::string strCheckpointWarning;
|
|||
|
||||
CBlockIndex* GetLastSyncCheckpoint();
|
||||
bool WriteSyncCheckpoint(const uint256& hashCheckpoint);
|
||||
bool IsSyncCheckpointEnforced();
|
||||
bool AcceptPendingSyncCheckpoint();
|
||||
uint256 AutoSelectSyncCheckpoint();
|
||||
bool CheckSyncCheckpoint(const uint256& hashBlock, const CBlockIndex* pindexPrev);
|
||||
|
|
20
src/main.cpp
20
src/main.cpp
|
@ -1868,7 +1868,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
|
|||
strMiscWarning = _("Warning: This version is obsolete, upgrade required!");
|
||||
}
|
||||
|
||||
if (!(GetBoolArg("-checkpointenforce", false) || mapArgs.count("-checkpointkey"))) // checkpoint advisory mode
|
||||
if (!IsSyncCheckpointEnforced()) // checkpoint advisory mode
|
||||
{
|
||||
if (pindexBest->pprev && !CheckSyncCheckpoint(pindexBest->GetBlockHash(), pindexBest->pprev))
|
||||
strCheckpointWarning = _("Warning: checkpoint on different blockchain fork, contact developers to resolve the issue");
|
||||
|
@ -2146,7 +2146,7 @@ bool CBlock::AcceptBlock(CValidationState &state, CDiskBlockPos *dbp)
|
|||
return state.DoS(100, error("AcceptBlock() : rejected by checkpoint lock-in at %d", nHeight));
|
||||
|
||||
// ppcoin: check that the block satisfies synchronized checkpoint
|
||||
if ((GetBoolArg("-checkpointenforce", false) || mapArgs.count("-checkpointkey")) // checkpoint enforce mode
|
||||
if (IsSyncCheckpointEnforced() // checkpoint enforce mode
|
||||
&& !CheckSyncCheckpoint(hash, pindexPrev))
|
||||
return error("AcceptBlock() : rejected by synchronized checkpoint");
|
||||
|
||||
|
@ -4585,7 +4585,7 @@ void BitcoinMiner(CWallet *pwallet, CBlockProvider *block_provider)
|
|||
unsigned int nExtraNonce = 0; //^
|
||||
|
||||
unsigned int nPrimorialMultiplier = nPrimorialHashFactor;
|
||||
double nTimeExpected = 0; // time expected to prime chain (micro-second)
|
||||
double dTimeExpected = 0; // time expected to prime chain (micro-second)
|
||||
int64 nSieveGenTime = 0; // how many milliseconds sieve generation took
|
||||
bool fIncrementPrimorial = true; // increase or decrease primorial factor
|
||||
|
||||
|
@ -4790,17 +4790,18 @@ void BitcoinMiner(CWallet *pwallet, CBlockProvider *block_provider)
|
|||
{
|
||||
// Primecoin: a sieve+primality round completes
|
||||
// Primecoin: estimate time to block
|
||||
const double dTimeExpectedPrev = dTimeExpected;
|
||||
unsigned int nCalcRoundTests = max(1u, nRoundTests);
|
||||
// Make sure the estimated time is very high if only 0 primes were found
|
||||
if (nRoundPrimesHit == 0)
|
||||
nCalcRoundTests *= 1000;
|
||||
int64 nRoundTime = (GetTimeMicros() - nPrimeTimerStart);
|
||||
nTimeExpected = (double) nRoundTime / nCalcRoundTests;
|
||||
dTimeExpected = (double) nRoundTime / nCalcRoundTests;
|
||||
double dRoundChainExpected = (double) nRoundTests;
|
||||
for (unsigned int n = 0, nTargetLength = TargetGetLength(pblock->nBits); n < nTargetLength; n++)
|
||||
{
|
||||
double dPrimeProbability = EstimateCandidatePrimeProbability(nPrimorialMultiplier, n);
|
||||
nTimeExpected = nTimeExpected / max(0.01, dPrimeProbability);
|
||||
dTimeExpected = dTimeExpected / max(0.01, dPrimeProbability);
|
||||
dRoundChainExpected *= dPrimeProbability;
|
||||
}
|
||||
dChainExpected += dRoundChainExpected;
|
||||
|
@ -4809,7 +4810,7 @@ void BitcoinMiner(CWallet *pwallet, CBlockProvider *block_provider)
|
|||
double dPrimeProbabilityBegin = EstimateCandidatePrimeProbability(nPrimorialMultiplier, 0);
|
||||
unsigned int nTargetLength = TargetGetLength(pblock->nBits);
|
||||
double dPrimeProbabilityEnd = EstimateCandidatePrimeProbability(nPrimorialMultiplier, nTargetLength - 1);
|
||||
printf("PrimecoinMiner() : Round primorial=%u tests=%u primes=%u time=%uus pprob=%1.6f pprob2=%1.6f tochain=%6.3fd expect=%3.9f\n", nPrimorialMultiplier, nRoundTests, nRoundPrimesHit, (unsigned int) nRoundTime, dPrimeProbabilityBegin, dPrimeProbabilityEnd, ((nTimeExpected/1000000.0))/86400.0, dRoundChainExpected);
|
||||
printf("PrimecoinMiner() : Round primorial=%u tests=%u primes=%u time=%uus pprob=%1.6f pprob2=%1.6f tochain=%6.3fd expect=%3.9f\n", nPrimorialMultiplier, nRoundTests, nRoundPrimesHit, (unsigned int) nRoundTime, dPrimeProbabilityBegin, dPrimeProbabilityEnd, ((dTimeExpected/1000000.0))/86400.0, dRoundChainExpected);
|
||||
}
|
||||
|
||||
// Primecoin: update time and nonce
|
||||
|
@ -4842,11 +4843,8 @@ void BitcoinMiner(CWallet *pwallet, CBlockProvider *block_provider)
|
|||
|
||||
// Primecoin: reset sieve+primality round timer
|
||||
nPrimeTimerStart = GetTimeMicros();
|
||||
// Adjust primorial so that sieve generation takes a set percentage of round time
|
||||
if (nSieveGenTime >= nRoundSievePercentage * nRoundTime / 100)
|
||||
fIncrementPrimorial = true;
|
||||
else
|
||||
fIncrementPrimorial = false;
|
||||
if (dTimeExpected > dTimeExpectedPrev)
|
||||
fIncrementPrimorial = !fIncrementPrimorial;
|
||||
|
||||
// Primecoin: primorial always needs to be incremented if only 0 primes were found
|
||||
if (nRoundPrimesHit == 0)
|
||||
|
|
407
src/prime.cpp
407
src/prime.cpp
|
@ -13,20 +13,20 @@
|
|||
std::vector<unsigned int> vPrimes;
|
||||
unsigned int nSieveSize = nDefaultSieveSize;
|
||||
unsigned int nSievePercentage = nDefaultSievePercentage;
|
||||
unsigned int nRoundSievePercentage = nDefaultRoundSievePercentage;
|
||||
unsigned int nSieveExtensions = nDefaultSieveExtensions;
|
||||
|
||||
static unsigned int int_invert(unsigned int a, unsigned int nPrime);
|
||||
|
||||
void GeneratePrimeTable()
|
||||
{
|
||||
unsigned int nDefaultRSPercentage = (fTestNet) ? nDefaultRoundSievePercentageTestnet : nDefaultRoundSievePercentage;
|
||||
nRoundSievePercentage = (unsigned int)GetArg("-roundsievepercentage", nDefaultRSPercentage);
|
||||
nRoundSievePercentage = std::max(std::min(nRoundSievePercentage, nMaxRoundSievePercentage), nMinRoundSievePercentage);
|
||||
const unsigned int nDefaultSieveExt = (fTestNet) ? nDefaultSieveExtensionsTestnet : nDefaultSieveExtensions;
|
||||
nSieveExtensions = (unsigned int)GetArg("-sieveextensions", nDefaultSieveExt);
|
||||
nSieveExtensions = std::max(std::min(nSieveExtensions, nMaxSieveExtensions), nMinSieveExtensions);
|
||||
nSievePercentage = (unsigned int)GetArg("-sievepercentage", nDefaultSievePercentage);
|
||||
nSievePercentage = std::max(std::min(nSievePercentage, nMaxSievePercentage), nMinSievePercentage);
|
||||
nSieveSize = (unsigned int)GetArg("-sievesize", nDefaultSieveSize);
|
||||
nSieveSize = std::max(std::min(nSieveSize, nMaxSieveSize), nMinSieveSize);
|
||||
printf("GeneratePrimeTable() : setting nRoundSievePercentage = %u, nSievePercentage = %u, nSieveSize = %u\n", nRoundSievePercentage, nSievePercentage, nSieveSize);
|
||||
printf("GeneratePrimeTable() : setting nSieveExtensions = %u, nSievePercentage = %u, nSieveSize = %u\n", nSieveExtensions, nSievePercentage, nSieveSize);
|
||||
const unsigned nPrimeTableLimit = nSieveSize;
|
||||
vPrimes.clear();
|
||||
// Generate prime table using sieve of Eratosthenes
|
||||
|
@ -510,9 +510,6 @@ unsigned int EstimateWorkTransition(unsigned int nPrevWorkTransition, unsigned i
|
|||
/* PRIMECOIN MINING */
|
||||
/********************/
|
||||
|
||||
// Number of primes to test with fast divisibility testing
|
||||
static const unsigned int nFastDivPrimes = 60;
|
||||
|
||||
class CPrimalityTestParams
|
||||
{
|
||||
public:
|
||||
|
@ -526,11 +523,6 @@ public:
|
|||
mpz_class mpzOriginPlusOne;
|
||||
mpz_class N;
|
||||
|
||||
// Big divisors for fast div test
|
||||
std::vector<unsigned long> vFastDivisors;
|
||||
std::vector<unsigned int> vFastDivSeq;
|
||||
unsigned int nFastDivisorsSize;
|
||||
|
||||
// Values specific to a round
|
||||
unsigned int nBits;
|
||||
unsigned int nPrimorialSeq;
|
||||
|
@ -560,31 +552,12 @@ public:
|
|||
// Check Fermat probable primality test (2-PRP): 2 ** (n-1) = 1 (mod n)
|
||||
// true: n is probable prime
|
||||
// false: n is composite; set fractional length in the nLength output
|
||||
static bool FermatProbablePrimalityTestFast(const mpz_class& n, unsigned int& nLength, CPrimalityTestParams& testParams, bool fFastDiv = false, bool fFastFail = false)
|
||||
static bool FermatProbablePrimalityTestFast(const mpz_class& n, unsigned int& nLength, CPrimalityTestParams& testParams, bool fFastFail = false)
|
||||
{
|
||||
// Faster GMP version
|
||||
mpz_t& mpzE = testParams.mpzE;
|
||||
mpz_t& mpzR = testParams.mpzR;
|
||||
|
||||
if (fFastDiv)
|
||||
{
|
||||
// Fast divisibility tests
|
||||
// Divide n by a large divisor
|
||||
// Use the remainder to test divisibility by small primes
|
||||
const unsigned int nDivSize = testParams.nFastDivisorsSize;
|
||||
for (unsigned int i = 0; i < nDivSize; i++)
|
||||
{
|
||||
unsigned long lRemainder = mpz_tdiv_ui(n.get_mpz_t(), testParams.vFastDivisors[i]);
|
||||
unsigned int nPrimeSeq = testParams.vFastDivSeq[i];
|
||||
const unsigned int nPrimeSeqEnd = testParams.vFastDivSeq[i + 1];
|
||||
for (; nPrimeSeq < nPrimeSeqEnd; nPrimeSeq++)
|
||||
{
|
||||
if (lRemainder % vPrimes[nPrimeSeq] == 0)
|
||||
return false; // returning here skips the fractional length calculation!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mpz_sub_ui(mpzE, n.get_mpz_t(), 1);
|
||||
mpz_powm(mpzR, mpzTwo.get_mpz_t(), mpzE, n.get_mpz_t());
|
||||
if (mpz_cmp_ui(mpzR, 1) == 0)
|
||||
|
@ -670,7 +643,7 @@ static bool ProbableCunninghamChainTestFast(const mpz_class& n, bool fSophieGerm
|
|||
nProbableChainLength = 0;
|
||||
|
||||
// Fermat test for n first
|
||||
if (!FermatProbablePrimalityTestFast(n, nProbableChainLength, testParams, true, true))
|
||||
if (!FermatProbablePrimalityTestFast(n, nProbableChainLength, testParams, true))
|
||||
return false;
|
||||
|
||||
// Euler-Lagrange-Lifchitz test for the following numbers in chain
|
||||
|
@ -767,7 +740,7 @@ bool MineProbablePrimeChain(CBlock& block, mpz_class& mpzFixedMultiplier, bool&
|
|||
{
|
||||
// Build sieve
|
||||
nStart = GetTimeMicros();
|
||||
lpsieve = new CSieveOfEratosthenes(nSieveSize, nBits, mpzHash, mpzFixedMultiplier, pindexPrev);
|
||||
lpsieve = new CSieveOfEratosthenes(nSieveSize, nSievePercentage, nSieveExtensions, nBits, mpzHash, mpzFixedMultiplier, pindexPrev);
|
||||
while (lpsieve->Weave() && pindexPrev == pindexBest);
|
||||
nSieveGenTime = GetTimeMicros() - nStart;
|
||||
if (fDebug && GetBoolArg("-printmining"))
|
||||
|
@ -787,35 +760,6 @@ bool MineProbablePrimeChain(CBlock& block, mpz_class& mpzFixedMultiplier, bool&
|
|||
// Allocate GMP variables for primality tests
|
||||
CPrimalityTestParams testParams(nBits, nPrimorialSeq);
|
||||
|
||||
// Compute parameters for fast div test
|
||||
{
|
||||
unsigned long lDivisor = 1;
|
||||
unsigned int i;
|
||||
testParams.vFastDivSeq.push_back(nPrimorialSeq);
|
||||
for (i = 1; i <= nFastDivPrimes; i++)
|
||||
{
|
||||
// Multiply primes together until the result won't fit an unsigned long
|
||||
if (lDivisor < ULONG_MAX / vPrimes[nPrimorialSeq + i])
|
||||
lDivisor *= vPrimes[nPrimorialSeq + i];
|
||||
else
|
||||
{
|
||||
testParams.vFastDivisors.push_back(lDivisor);
|
||||
testParams.vFastDivSeq.push_back(nPrimorialSeq + i);
|
||||
lDivisor = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Finish off by multiplying as many primes as possible
|
||||
while (lDivisor < ULONG_MAX / vPrimes[nPrimorialSeq + i])
|
||||
{
|
||||
lDivisor *= vPrimes[nPrimorialSeq + i];
|
||||
i++;
|
||||
}
|
||||
testParams.vFastDivisors.push_back(lDivisor);
|
||||
testParams.vFastDivSeq.push_back(nPrimorialSeq + i);
|
||||
testParams.nFastDivisorsSize = testParams.vFastDivisors.size();
|
||||
}
|
||||
|
||||
nStart = GetTimeMicros();
|
||||
|
||||
// References to test parameters
|
||||
|
@ -846,6 +790,7 @@ bool MineProbablePrimeChain(CBlock& block, mpz_class& mpzFixedMultiplier, bool&
|
|||
CBigNum bnPrimeChainMultiplier;
|
||||
bnPrimeChainMultiplier.SetHex(mpzPrimeChainMultiplier.get_str(16));
|
||||
block.bnPrimeChainMultiplier = bnPrimeChainMultiplier;
|
||||
printf("nTriedMultiplier = %u\n", nTriedMultiplier); // Debugging
|
||||
printf("Probable prime chain found for block=%s!!\n Target: %s\n Chain: %s\n", block.GetHash().GetHex().c_str(),
|
||||
TargetToString(block.nBits).c_str(), GetPrimeChainName(nCandidateType, nChainLength).c_str());
|
||||
nProbableChainLength = nChainLength;
|
||||
|
@ -856,6 +801,13 @@ bool MineProbablePrimeChain(CBlock& block, mpz_class& mpzFixedMultiplier, bool&
|
|||
nPrimesHit++;
|
||||
if(TargetGetLength(nProbableChainLength) >= nStatsChainLength)
|
||||
nChainsHit++;
|
||||
// Debugging
|
||||
#if 0
|
||||
if(TargetGetLength(nProbableChainLength) >= 1)
|
||||
printf("Multiplier %u gave a prime\n", nTriedMultiplier);
|
||||
else
|
||||
printf("Multiplier %u gave nothing\n", nTriedMultiplier);
|
||||
#endif
|
||||
}
|
||||
|
||||
//if (fDebug && GetBoolArg("-printmining"))
|
||||
|
@ -913,17 +865,34 @@ static unsigned int int_invert(unsigned int a, unsigned int nPrime)
|
|||
return (inverse + nPrime) % nPrime;
|
||||
}
|
||||
|
||||
void CSieveOfEratosthenes::AddMultiplier(unsigned int *vMultipliers, const unsigned int nPrimeSeq, const unsigned int nSolvedMultiplier)
|
||||
void CSieveOfEratosthenes::ProcessMultiplier(sieve_word_t *vfComposites, const unsigned int nMinMultiplier, const unsigned int nMaxMultiplier, const std::vector<unsigned int>& vPrimes, unsigned int *vMultipliers, unsigned int nLayerSeq)
|
||||
{
|
||||
// Eliminate duplicates
|
||||
for (unsigned int i = 0; i < nHalfChainLength; i++)
|
||||
// Wipe the part of the array first
|
||||
if (nMinMultiplier < nMaxMultiplier)
|
||||
memset(vfComposites + GetWordNum(nMinMultiplier), 0, (nMaxMultiplier - nMinMultiplier + nWordBits - 1) / nWordBits * sizeof(sieve_word_t));
|
||||
|
||||
for (unsigned int nPrimeSeq = 1; nPrimeSeq < nPrimes; nPrimeSeq++)
|
||||
{
|
||||
unsigned int nStoredMultiplier = vMultipliers[nPrimeSeq * nHalfChainLength + i];
|
||||
if (nStoredMultiplier == 0xFFFFFFFF || nStoredMultiplier == nSolvedMultiplier)
|
||||
const unsigned int nPrime = vPrimes[nPrimeSeq];
|
||||
unsigned int nVariableMultiplier = vMultipliers[nPrimeSeq * nSieveLayers + nLayerSeq];
|
||||
if (nVariableMultiplier < nMinMultiplier)
|
||||
nVariableMultiplier += (nMinMultiplier - nVariableMultiplier + nPrime - 1) / nPrime * nPrime;
|
||||
#ifdef USE_ROTATE
|
||||
const unsigned int nRotateBits = nPrime % nWordBits;
|
||||
sieve_word_t lBitMask = GetBitMask(nVariableMultiplier);
|
||||
for (; nVariableMultiplier < nMaxMultiplier; nVariableMultiplier += nPrime)
|
||||
{
|
||||
vMultipliers[nPrimeSeq * nHalfChainLength + i] = nSolvedMultiplier;
|
||||
break;
|
||||
vfComposites[GetWordNum(nVariableMultiplier)] |= lBitMask;
|
||||
lBitMask = (lBitMask << nRotateBits) | (lBitMask >> (nWordBits - nRotateBits));
|
||||
}
|
||||
vMultipliers[nPrimeSeq * nSieveLayers + nLayerSeq] = nVariableMultiplier;
|
||||
#else
|
||||
for (; nVariableMultiplier < nMaxMultiplier; nVariableMultiplier += nPrime)
|
||||
{
|
||||
vfComposites[GetWordNum(nVariableMultiplier)] |= GetBitMask(nVariableMultiplier);
|
||||
}
|
||||
vMultipliers[nPrimeSeq * nSieveLayers + nLayerSeq] = nVariableMultiplier;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -933,42 +902,16 @@ void CSieveOfEratosthenes::AddMultiplier(unsigned int *vMultipliers, const unsig
|
|||
// False - sieve already completed
|
||||
bool CSieveOfEratosthenes::Weave()
|
||||
{
|
||||
// Faster GMP version
|
||||
this->nChainLength = TargetGetLength(nBits);
|
||||
this->nHalfChainLength = (nChainLength + 1) / 2;
|
||||
const unsigned int nMultiplierBytes = nPrimes * nSieveLayers * sizeof(unsigned int);
|
||||
unsigned int *vCunningham1Multipliers = (unsigned int *)malloc(nMultiplierBytes);
|
||||
unsigned int *vCunningham2Multipliers = (unsigned int *)malloc(nMultiplierBytes);
|
||||
|
||||
// Keep all variables local for max performance
|
||||
const unsigned int nChainLength = this->nChainLength;
|
||||
const unsigned int nHalfChainLength = this->nHalfChainLength;
|
||||
CBlockIndex* pindexPrev = this->pindexPrev;
|
||||
unsigned int nSieveSize = this->nSieveSize;
|
||||
const unsigned int nTotalPrimes = vPrimes.size();
|
||||
mpz_class mpzHash = this->mpzHash;
|
||||
mpz_class mpzFixedMultiplier = this->mpzFixedMultiplier;
|
||||
|
||||
// Process only a set percentage of the primes
|
||||
// Most composites are still found
|
||||
const unsigned int nPrimes = (uint64)nTotalPrimes * nSievePercentage / 100;
|
||||
this->nPrimes = nPrimes;
|
||||
|
||||
const unsigned int nMultiplierBytes = nPrimes * nHalfChainLength * sizeof(unsigned int);
|
||||
unsigned int *vCunningham1AMultipliers = (unsigned int *)malloc(nMultiplierBytes);
|
||||
unsigned int *vCunningham1BMultipliers = (unsigned int *)malloc(nMultiplierBytes);
|
||||
unsigned int *vCunningham2AMultipliers = (unsigned int *)malloc(nMultiplierBytes);
|
||||
unsigned int *vCunningham2BMultipliers = (unsigned int *)malloc(nMultiplierBytes);
|
||||
|
||||
memset(vCunningham1AMultipliers, 0xFF, nMultiplierBytes);
|
||||
memset(vCunningham1BMultipliers, 0xFF, nMultiplierBytes);
|
||||
memset(vCunningham2AMultipliers, 0xFF, nMultiplierBytes);
|
||||
memset(vCunningham2BMultipliers, 0xFF, nMultiplierBytes);
|
||||
memset(vCunningham1Multipliers, 0xFF, nMultiplierBytes);
|
||||
memset(vCunningham2Multipliers, 0xFF, nMultiplierBytes);
|
||||
|
||||
// bitsets that can be combined to obtain the final bitset of candidates
|
||||
sieve_word_t *vfCompositeCunningham1A = (sieve_word_t *)malloc(nCandidatesBytes);
|
||||
sieve_word_t *vfCompositeCunningham1B = (sieve_word_t *)malloc(nCandidatesBytes);
|
||||
sieve_word_t *vfCompositeCunningham2A = (sieve_word_t *)malloc(nCandidatesBytes);
|
||||
sieve_word_t *vfCompositeCunningham2B = (sieve_word_t *)malloc(nCandidatesBytes);
|
||||
|
||||
sieve_word_t *vfCandidates = this->vfCandidates;
|
||||
sieve_word_t *vfCompositeLayerCC1 = (sieve_word_t *)malloc(nCandidatesBytes);
|
||||
sieve_word_t *vfCompositeLayerCC2 = (sieve_word_t *)malloc(nCandidatesBytes);
|
||||
|
||||
// Check whether fixed multiplier fits in an unsigned long
|
||||
bool fUseLongForFixedMultiplier = mpzFixedMultiplier < ULONG_MAX;
|
||||
|
@ -982,12 +925,12 @@ bool CSieveOfEratosthenes::Weave()
|
|||
unsigned int nCombinedEndSeq = 1;
|
||||
unsigned int nFixedFactorCombinedMod = 0;
|
||||
|
||||
for (unsigned int nPrimeSeq = 1; nPrimeSeq < nPrimes; nPrimeSeq++)
|
||||
for (unsigned int nPrimeSeqLocal = 1; nPrimeSeqLocal < nPrimes; nPrimeSeqLocal++)
|
||||
{
|
||||
if (pindexPrev != pindexBest)
|
||||
break; // new block
|
||||
unsigned int nPrime = vPrimes[nPrimeSeq];
|
||||
if (nPrimeSeq >= nCombinedEndSeq)
|
||||
unsigned int nPrime = vPrimes[nPrimeSeqLocal];
|
||||
if (nPrimeSeqLocal >= nCombinedEndSeq)
|
||||
{
|
||||
// Combine multiple primes to produce a big divisor
|
||||
unsigned int nPrimeCombined = 1;
|
||||
|
@ -1015,7 +958,7 @@ bool CSieveOfEratosthenes::Weave()
|
|||
// Find the modulo inverse of fixed factor
|
||||
unsigned int nFixedInverse = int_invert(nFixedFactorMod, nPrime);
|
||||
if (!nFixedInverse)
|
||||
return error("CSieveOfEratosthenes::Weave(): int_invert of fixed factor failed for prime #%u=%u", nPrimeSeq, vPrimes[nPrimeSeq]);
|
||||
return error("CSieveOfEratosthenes::Weave(): int_invert of fixed factor failed for prime #%u=%u", nPrimeSeqLocal, vPrimes[nPrimeSeqLocal]);
|
||||
unsigned int nTwoInverse = (nPrime + 1) / 2;
|
||||
|
||||
// Check whether 32-bit arithmetic can be used for nFixedInverse
|
||||
|
@ -1024,145 +967,165 @@ bool CSieveOfEratosthenes::Weave()
|
|||
if (fUse32BArithmetic)
|
||||
{
|
||||
// Weave the sieve for the prime
|
||||
unsigned int nBiTwinSeq;
|
||||
for (nBiTwinSeq = 0; nBiTwinSeq < nChainLength; nBiTwinSeq++)
|
||||
for (unsigned int nChainSeq = 0; nChainSeq < nSieveLayers; nChainSeq++)
|
||||
{
|
||||
if (nBiTwinSeq % 2 == 0)
|
||||
{
|
||||
// Find the first number that's divisible by this prime
|
||||
unsigned int nSolvedMultiplier = nFixedInverse;
|
||||
AddMultiplier(vCunningham1AMultipliers, nPrimeSeq, nSolvedMultiplier);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find the first number that's divisible by this prime
|
||||
unsigned int nSolvedMultiplier = nPrime - nFixedInverse;
|
||||
AddMultiplier(vCunningham2AMultipliers, nPrimeSeq, nSolvedMultiplier);
|
||||
// Find the first number that's divisible by this prime
|
||||
vCunningham1Multipliers[nPrimeSeqLocal * nSieveLayers + nChainSeq] = nFixedInverse;
|
||||
vCunningham2Multipliers[nPrimeSeqLocal * nSieveLayers + nChainSeq] = nPrime - nFixedInverse;
|
||||
|
||||
// For next number in chain
|
||||
nFixedInverse = nFixedInverse * nTwoInverse % nPrime;
|
||||
}
|
||||
}
|
||||
|
||||
for (; nBiTwinSeq < 2 * nChainLength; nBiTwinSeq++)
|
||||
{
|
||||
if (nBiTwinSeq % 2 == 0)
|
||||
{
|
||||
// Find the first number that's divisible by this prime
|
||||
unsigned int nSolvedMultiplier = nFixedInverse;
|
||||
AddMultiplier(vCunningham1BMultipliers, nPrimeSeq, nSolvedMultiplier);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find the first number that's divisible by this prime
|
||||
unsigned int nSolvedMultiplier = nPrime - nFixedInverse;
|
||||
AddMultiplier(vCunningham2BMultipliers, nPrimeSeq, nSolvedMultiplier);
|
||||
|
||||
// For next number in chain
|
||||
nFixedInverse = nFixedInverse * nTwoInverse % nPrime;
|
||||
}
|
||||
// For next number in chain
|
||||
nFixedInverse = nFixedInverse * nTwoInverse % nPrime;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Weave the sieve for the prime
|
||||
unsigned int nBiTwinSeq;
|
||||
for (nBiTwinSeq = 0; nBiTwinSeq < nChainLength; nBiTwinSeq++)
|
||||
for (unsigned int nChainSeq = 0; nChainSeq < nSieveLayers; nChainSeq++)
|
||||
{
|
||||
if (nBiTwinSeq % 2 == 0)
|
||||
{
|
||||
// Find the first number that's divisible by this prime
|
||||
unsigned int nSolvedMultiplier = nFixedInverse;
|
||||
AddMultiplier(vCunningham1AMultipliers, nPrimeSeq, nSolvedMultiplier);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find the first number that's divisible by this prime
|
||||
unsigned int nSolvedMultiplier = nPrime - nFixedInverse;
|
||||
AddMultiplier(vCunningham2AMultipliers, nPrimeSeq, nSolvedMultiplier);
|
||||
// Find the first number that's divisible by this prime
|
||||
vCunningham1Multipliers[nPrimeSeqLocal * nSieveLayers + nChainSeq] = nFixedInverse;
|
||||
vCunningham2Multipliers[nPrimeSeqLocal * nSieveLayers + nChainSeq] = nPrime - nFixedInverse;
|
||||
|
||||
// For next number in chain
|
||||
nFixedInverse = (uint64)nFixedInverse * nTwoInverse % nPrime;
|
||||
}
|
||||
}
|
||||
|
||||
for (; nBiTwinSeq < 2 * nChainLength; nBiTwinSeq++)
|
||||
{
|
||||
if (nBiTwinSeq % 2 == 0)
|
||||
{
|
||||
// Find the first number that's divisible by this prime
|
||||
unsigned int nSolvedMultiplier = nFixedInverse;
|
||||
AddMultiplier(vCunningham1BMultipliers, nPrimeSeq, nSolvedMultiplier);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find the first number that's divisible by this prime
|
||||
unsigned int nSolvedMultiplier = nPrime - nFixedInverse;
|
||||
AddMultiplier(vCunningham2BMultipliers, nPrimeSeq, nSolvedMultiplier);
|
||||
|
||||
// For next number in chain
|
||||
nFixedInverse = (uint64)nFixedInverse * nTwoInverse % nPrime;
|
||||
}
|
||||
// For next number in chain
|
||||
nFixedInverse = (uint64)nFixedInverse * nTwoInverse % nPrime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Number of elements that are likely to fit in L1 cache
|
||||
const unsigned int nL1CacheElements = 200000;
|
||||
// NOTE: This needs to be a multiple of nWordBits
|
||||
const unsigned int nL1CacheElements = 224000;
|
||||
const unsigned int nArrayRounds = (nSieveSize + nL1CacheElements - 1) / nL1CacheElements;
|
||||
|
||||
// Calculate the number of CC1 and CC2 layers needed for BiTwin candidates
|
||||
const unsigned int nBiTwinCC1Layers = (nChainLength + 1) / 2;
|
||||
const unsigned int nBiTwinCC2Layers = nChainLength / 2;
|
||||
|
||||
// Only 50% of the array is used in extensions
|
||||
const unsigned int nExtensionsMinMultiplier = nSieveSize / 2;
|
||||
const unsigned int nExtensionsMinWord = nExtensionsMinMultiplier / nWordBits;
|
||||
|
||||
// Loop over each array one at a time for optimal L1 cache performance
|
||||
for (unsigned int j = 0; j < nArrayRounds; j++)
|
||||
{
|
||||
const unsigned int nMinMultiplier = nL1CacheElements * j;
|
||||
const unsigned int nMaxMultiplier = std::min(nL1CacheElements * (j + 1), nSieveSize);
|
||||
const unsigned int nExtMinMultiplier = std::max(nMinMultiplier, nExtensionsMinMultiplier);
|
||||
const unsigned int nMinWord = nMinMultiplier / nWordBits;
|
||||
const unsigned int nMaxWord = (nMaxMultiplier + nWordBits - 1) / nWordBits;
|
||||
const unsigned int nExtMinWord = std::max(nMinWord, nExtensionsMinWord);
|
||||
if (pindexPrev != pindexBest)
|
||||
break; // new block
|
||||
|
||||
ProcessMultiplier(vfCompositeCunningham1A, nMinMultiplier, nMaxMultiplier, vPrimes, vCunningham1AMultipliers);
|
||||
ProcessMultiplier(vfCompositeCunningham1B, nMinMultiplier, nMaxMultiplier, vPrimes, vCunningham1BMultipliers);
|
||||
ProcessMultiplier(vfCompositeCunningham2A, nMinMultiplier, nMaxMultiplier, vPrimes, vCunningham2AMultipliers);
|
||||
ProcessMultiplier(vfCompositeCunningham2B, nMinMultiplier, nMaxMultiplier, vPrimes, vCunningham2BMultipliers);
|
||||
|
||||
// Combine all the bitsets
|
||||
// vfCompositeCunningham1 = vfCompositeCunningham1A | vfCompositeCunningham1B
|
||||
// vfCompositeCunningham2 = vfCompositeCunningham2A | vfCompositeCunningham2B
|
||||
// vfCompositeBiTwin = vfCompositeCunningham1A | vfCompositeCunningham2A
|
||||
// vfCandidates = ~(vfCompositeCunningham1 & vfCompositeCunningham2 & vfCompositeBiTwin)
|
||||
{
|
||||
// Fast version
|
||||
const unsigned int nBytes = (nMaxMultiplier - nMinMultiplier + 7) / 8;
|
||||
sieve_word_t *pCandidates = (sieve_word_t *)vfCandidates + (nMinMultiplier / nWordBits);
|
||||
sieve_word_t *pCandidateBiTwin = (sieve_word_t *)vfCandidateBiTwin + (nMinMultiplier / nWordBits);
|
||||
sieve_word_t *pCandidateCunningham1 = (sieve_word_t *)vfCandidateCunningham1 + (nMinMultiplier / nWordBits);
|
||||
sieve_word_t *pCompositeCunningham1A = (sieve_word_t *)vfCompositeCunningham1A + (nMinMultiplier / nWordBits);
|
||||
sieve_word_t *pCompositeCunningham1B = (sieve_word_t *)vfCompositeCunningham1B + (nMinMultiplier / nWordBits);
|
||||
sieve_word_t *pCompositeCunningham2A = (sieve_word_t *)vfCompositeCunningham2A + (nMinMultiplier / nWordBits);
|
||||
sieve_word_t *pCompositeCunningham2B = (sieve_word_t *)vfCompositeCunningham2B + (nMinMultiplier / nWordBits);
|
||||
const unsigned int nWords = (nBytes + sizeof(sieve_word_t) - 1) / sizeof(sieve_word_t);
|
||||
for (unsigned int i = 0; i < nWords; i++)
|
||||
// Loop over the layers
|
||||
for (unsigned int nLayerSeq = 0; nLayerSeq < nSieveLayers; nLayerSeq++) {
|
||||
if (pindexPrev != pindexBest)
|
||||
break; // new block
|
||||
if (nLayerSeq < nChainLength)
|
||||
{
|
||||
const sieve_word_t lCompositeCunningham1 = pCompositeCunningham1A[i] | pCompositeCunningham1B[i];
|
||||
const sieve_word_t lCompositeCunningham2 = pCompositeCunningham2A[i] | pCompositeCunningham2B[i];
|
||||
const sieve_word_t lCompositeBiTwin = pCompositeCunningham1A[i] | pCompositeCunningham2A[i];
|
||||
pCandidateBiTwin[i] = ~lCompositeBiTwin;
|
||||
pCandidateCunningham1[i] = ~lCompositeCunningham1;
|
||||
pCandidates[i] = ~(lCompositeCunningham1 & lCompositeCunningham2 & lCompositeBiTwin);
|
||||
ProcessMultiplier(vfCompositeLayerCC1, nMinMultiplier, nMaxMultiplier, vPrimes, vCunningham1Multipliers, nLayerSeq);
|
||||
ProcessMultiplier(vfCompositeLayerCC2, nMinMultiplier, nMaxMultiplier, vPrimes, vCunningham2Multipliers, nLayerSeq);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Optimize: First halves of the arrays are not needed in the extensions
|
||||
ProcessMultiplier(vfCompositeLayerCC1, nExtMinMultiplier, nMaxMultiplier, vPrimes, vCunningham1Multipliers, nLayerSeq);
|
||||
ProcessMultiplier(vfCompositeLayerCC2, nExtMinMultiplier, nMaxMultiplier, vPrimes, vCunningham2Multipliers, nLayerSeq);
|
||||
}
|
||||
|
||||
// Apply the layer to the primary sieve arrays
|
||||
if (nLayerSeq < nChainLength)
|
||||
{
|
||||
if (nLayerSeq < nBiTwinCC1Layers && nLayerSeq < nBiTwinCC2Layers)
|
||||
{
|
||||
for (unsigned int nWord = nMinWord; nWord < nMaxWord; nWord++)
|
||||
{
|
||||
vfCompositeCunningham1[nWord] |= vfCompositeLayerCC1[nWord];
|
||||
vfCompositeCunningham2[nWord] |= vfCompositeLayerCC2[nWord];
|
||||
vfCompositeBiTwin[nWord] |= vfCompositeLayerCC1[nWord] | vfCompositeLayerCC2[nWord];
|
||||
}
|
||||
}
|
||||
else if (nLayerSeq < nBiTwinCC2Layers)
|
||||
{
|
||||
for (unsigned int nWord = nMinWord; nWord < nMaxWord; nWord++)
|
||||
{
|
||||
vfCompositeCunningham1[nWord] |= vfCompositeLayerCC1[nWord];
|
||||
vfCompositeCunningham2[nWord] |= vfCompositeLayerCC2[nWord];
|
||||
vfCompositeBiTwin[nWord] |= vfCompositeLayerCC1[nWord];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int nWord = nMinWord; nWord < nMaxWord; nWord++)
|
||||
{
|
||||
vfCompositeCunningham1[nWord] |= vfCompositeLayerCC1[nWord];
|
||||
vfCompositeCunningham2[nWord] |= vfCompositeLayerCC2[nWord];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply the layer to extensions
|
||||
for (unsigned int nExtensionSeq = 0; nExtensionSeq < nSieveExtensions; nExtensionSeq++)
|
||||
{
|
||||
const unsigned int nLayerOffset = nExtensionSeq + 1;
|
||||
if (nLayerSeq >= nLayerOffset && nLayerSeq < nChainLength + nLayerOffset)
|
||||
{
|
||||
const unsigned int nLayerExtendedSeq = nLayerSeq - nLayerOffset;
|
||||
sieve_word_t *vfExtCC1 = vfExtendedCompositeCunningham1 + nExtensionSeq * nCandidatesWords;
|
||||
sieve_word_t *vfExtCC2 = vfExtendedCompositeCunningham2 + nExtensionSeq * nCandidatesWords;
|
||||
sieve_word_t *vfExtTWN = vfExtendedCompositeBiTwin + nExtensionSeq * nCandidatesWords;
|
||||
if (nLayerExtendedSeq < nBiTwinCC1Layers && nLayerExtendedSeq < nBiTwinCC2Layers)
|
||||
{
|
||||
for (unsigned int nWord = nExtMinWord; nWord < nMaxWord; nWord++)
|
||||
{
|
||||
vfExtCC1[nWord] |= vfCompositeLayerCC1[nWord];
|
||||
vfExtCC2[nWord] |= vfCompositeLayerCC2[nWord];
|
||||
vfExtTWN[nWord] |= vfCompositeLayerCC1[nWord] | vfCompositeLayerCC2[nWord];
|
||||
}
|
||||
}
|
||||
else if (nLayerExtendedSeq < nBiTwinCC2Layers)
|
||||
{
|
||||
for (unsigned int nWord = nExtMinWord; nWord < nMaxWord; nWord++)
|
||||
{
|
||||
vfExtCC1[nWord] |= vfCompositeLayerCC1[nWord];
|
||||
vfExtCC2[nWord] |= vfCompositeLayerCC2[nWord];
|
||||
vfExtTWN[nWord] |= vfCompositeLayerCC1[nWord];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int nWord = nExtMinWord; nWord < nMaxWord; nWord++)
|
||||
{
|
||||
vfExtCC1[nWord] |= vfCompositeLayerCC1[nWord];
|
||||
vfExtCC2[nWord] |= vfCompositeLayerCC2[nWord];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Combine the bitsets
|
||||
// vfCandidates = ~(vfCompositeCunningham1 & vfCompositeCunningham2 & vfCompositeBiTwin)
|
||||
for (unsigned int i = nMinWord; i < nMaxWord; i++)
|
||||
vfCandidates[i] = ~(vfCompositeCunningham1[i] & vfCompositeCunningham2[i] & vfCompositeBiTwin[i]);
|
||||
|
||||
// Combine the extended bitsets
|
||||
for (unsigned int j = 0; j < nSieveExtensions; j++)
|
||||
for (unsigned int i = nExtMinWord; i < nMaxWord; i++)
|
||||
vfExtendedCandidates[j * nCandidatesWords + i] = ~(
|
||||
vfExtendedCompositeCunningham1[j * nCandidatesWords + i] &
|
||||
vfExtendedCompositeCunningham2[j * nCandidatesWords + i] &
|
||||
vfExtendedCompositeBiTwin[j * nCandidatesWords + i]);
|
||||
}
|
||||
|
||||
// The sieve has been partially weaved
|
||||
this->nPrimeSeq = nPrimes - 1;
|
||||
|
||||
free(vfCompositeCunningham1A);
|
||||
free(vfCompositeCunningham1B);
|
||||
free(vfCompositeCunningham2A);
|
||||
free(vfCompositeCunningham2B);
|
||||
|
||||
free(vCunningham1AMultipliers);
|
||||
free(vCunningham1BMultipliers);
|
||||
free(vCunningham2AMultipliers);
|
||||
free(vCunningham2BMultipliers);
|
||||
free(vfCompositeLayerCC1);
|
||||
free(vfCompositeLayerCC2);
|
||||
|
||||
free(vCunningham1Multipliers);
|
||||
free(vCunningham2Multipliers);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -1195,5 +1158,15 @@ double EstimateCandidatePrimeProbability(unsigned int nPrimorialMultiplier, unsi
|
|||
dFixedMultiplier *= vPrimes[i];
|
||||
for (unsigned int i = 0; vPrimes[i] <= nPrimorialHashFactor; i++)
|
||||
dFixedMultiplier /= vPrimes[i];
|
||||
return (1.781072 * log((double)std::max(1u, nSieveWeaveOptimalPrime)) / (255.0 * dLogTwo + dLogOneAndHalf + log(dFixedMultiplier) + log(nAverageCandidateMultiplier) + dLogTwo * nChainPrimeNum));
|
||||
|
||||
double dExtendedSieveWeightedSum = nSieveSize * 1.0;
|
||||
double dExtendedSieveCandidates = nSieveSize;
|
||||
for (unsigned int i = 0; i < nSieveExtensions; i++)
|
||||
{
|
||||
dExtendedSieveWeightedSum += nSieveSize / 2 * (2 << i);
|
||||
dExtendedSieveCandidates += nSieveSize / 2;
|
||||
}
|
||||
const double dExtendedSieveAverageMultiplier = dExtendedSieveWeightedSum / dExtendedSieveCandidates;
|
||||
|
||||
return (1.781072 * log((double)std::max(1u, nSieveWeaveOptimalPrime)) / (255.0 * dLogTwo + dLogOneAndHalf + log(dFixedMultiplier) + log(nAverageCandidateMultiplier) + dLogTwo * nChainPrimeNum + log(dExtendedSieveAverageMultiplier)));
|
||||
}
|
||||
|
|
239
src/prime.h
239
src/prime.h
|
@ -29,11 +29,12 @@ public:
|
|||
/* PRIMECOIN PROTOCOL */
|
||||
/**********************/
|
||||
|
||||
static const unsigned int nMaxRoundSievePercentage = 100;
|
||||
static const unsigned int nDefaultRoundSievePercentage = 70;
|
||||
static const unsigned int nDefaultRoundSievePercentageTestnet = 30;
|
||||
static const unsigned int nMinRoundSievePercentage = 1;
|
||||
extern unsigned int nRoundSievePercentage;
|
||||
extern std::vector<unsigned int> vPrimes;
|
||||
static const unsigned int nMaxSieveExtensions = 20;
|
||||
static const unsigned int nMinSieveExtensions = 0;
|
||||
static const unsigned int nDefaultSieveExtensions = 6;
|
||||
static const unsigned int nDefaultSieveExtensionsTestnet = 4;
|
||||
extern unsigned int nSieveExtensions;
|
||||
static const unsigned int nMaxSievePercentage = 100;
|
||||
static const unsigned int nDefaultSievePercentage = 10;
|
||||
static const unsigned int nMinSievePercentage = 1;
|
||||
|
@ -136,18 +137,43 @@ double EstimateCandidatePrimeProbability(unsigned int nPrimorialMultiplier, unsi
|
|||
typedef unsigned long sieve_word_t;
|
||||
|
||||
// Sieve of Eratosthenes for proof-of-work mining
|
||||
//
|
||||
// Includes the sieve extension feature from jhPrimeminer by jh000
|
||||
//
|
||||
// A layer of the sieve determines whether the CC1 or CC2 chain members near the
|
||||
// origin fixed_multiplier * candidate_multiplier * 2^k are known to be
|
||||
// composites.
|
||||
//
|
||||
// The default sieve is composed of layers 1 .. nChainLength.
|
||||
//
|
||||
// An extension i is composed of layers i .. i + nChainLength. The candidates
|
||||
// indexes from the extensions are multiplied by 2^i. The first half of the
|
||||
// candidates are covered by the default sieve and previous extensions.
|
||||
//
|
||||
// The larger numbers in the extensions have a slightly smaller probability of
|
||||
// being primes and take slightly longer to test but they can be calculated very
|
||||
// efficiently because the layers overlap.
|
||||
class CSieveOfEratosthenes
|
||||
{
|
||||
unsigned int nSieveSize; // size of the sieve
|
||||
unsigned int nSievePercentage; // weave up to a percentage of primes
|
||||
unsigned int nSieveExtensions; // extend the sieve a given number of times
|
||||
unsigned int nBits; // target of the prime chain to search for
|
||||
mpz_class mpzHash; // hash of the block header
|
||||
mpz_class mpzFixedMultiplier; // fixed round multiplier
|
||||
|
||||
// final set of candidates for probable primality checking
|
||||
sieve_word_t *vfCandidates;
|
||||
sieve_word_t *vfCandidateBiTwin;
|
||||
sieve_word_t *vfCandidateCunningham1;
|
||||
|
||||
sieve_word_t *vfCompositeBiTwin;
|
||||
sieve_word_t *vfCompositeCunningham1;
|
||||
sieve_word_t *vfCompositeCunningham2;
|
||||
|
||||
// extended sets
|
||||
sieve_word_t *vfExtendedCandidates;
|
||||
sieve_word_t *vfExtendedCompositeBiTwin;
|
||||
sieve_word_t *vfExtendedCompositeCunningham1;
|
||||
sieve_word_t *vfExtendedCompositeCunningham2;
|
||||
|
||||
static const unsigned int nWordBits = 8 * sizeof(sieve_word_t);
|
||||
unsigned int nCandidatesWords;
|
||||
unsigned int nCandidatesBytes;
|
||||
|
@ -155,64 +181,32 @@ class CSieveOfEratosthenes
|
|||
unsigned int nPrimeSeq; // prime sequence number currently being processed
|
||||
unsigned int nCandidateCount; // cached total count of candidates
|
||||
unsigned int nCandidateMultiplier; // current candidate for power test
|
||||
|
||||
unsigned int nChainLength;
|
||||
unsigned int nHalfChainLength;
|
||||
unsigned int nPrimes;
|
||||
|
||||
unsigned int nCandidateIndex; // internal candidate index
|
||||
bool fCandidateIsExtended; // is the current candidate in the extended part
|
||||
unsigned int nCandidateActiveExtension; // which extension is active
|
||||
|
||||
unsigned int nChainLength; // target chain length
|
||||
unsigned int nSieveLayers; // sieve layers
|
||||
unsigned int nPrimes; // number of times to weave the sieve
|
||||
|
||||
CBlockIndex* pindexPrev;
|
||||
|
||||
|
||||
unsigned int GetWordNum(unsigned int nBitNum) {
|
||||
return nBitNum / nWordBits;
|
||||
}
|
||||
|
||||
|
||||
sieve_word_t GetBitMask(unsigned int nBitNum) {
|
||||
return (sieve_word_t)1 << (nBitNum % nWordBits);
|
||||
}
|
||||
|
||||
void AddMultiplier(unsigned int *vMultipliers, const unsigned int nPrimeSeq, const unsigned int nSolvedMultiplier);
|
||||
|
||||
void ProcessMultiplier(sieve_word_t *vfComposites, const unsigned int nMinMultiplier, const unsigned int nMaxMultiplier, const std::vector<unsigned int>& vPrimes, unsigned int *vMultipliers)
|
||||
{
|
||||
// Wipe the part of the array first
|
||||
memset(vfComposites + GetWordNum(nMinMultiplier), 0, (nMaxMultiplier - nMinMultiplier + nWordBits - 1) / nWordBits * sizeof(sieve_word_t));
|
||||
|
||||
for (unsigned int nPrimeSeq = 1; nPrimeSeq < nPrimes; nPrimeSeq++)
|
||||
{
|
||||
const unsigned int nPrime = vPrimes[nPrimeSeq];
|
||||
#ifdef USE_ROTATE
|
||||
const unsigned int nRotateBits = nPrime % nWordBits;
|
||||
for (unsigned int i = 0; i < nHalfChainLength; i++)
|
||||
{
|
||||
unsigned int nVariableMultiplier = vMultipliers[nPrimeSeq * nHalfChainLength + i];
|
||||
if (nVariableMultiplier == 0xFFFFFFFF) break;
|
||||
sieve_word_t lBitMask = GetBitMask(nVariableMultiplier);
|
||||
for (; nVariableMultiplier < nMaxMultiplier; nVariableMultiplier += nPrime)
|
||||
{
|
||||
vfComposites[GetWordNum(nVariableMultiplier)] |= lBitMask;
|
||||
lBitMask = (lBitMask << nRotateBits) | (lBitMask >> (nWordBits - nRotateBits));
|
||||
}
|
||||
vMultipliers[nPrimeSeq * nHalfChainLength + i] = nVariableMultiplier;
|
||||
}
|
||||
#else
|
||||
for (unsigned int i = 0; i < nHalfChainLength; i++)
|
||||
{
|
||||
unsigned int nVariableMultiplier = vMultipliers[nPrimeSeq * nHalfChainLength + i];
|
||||
if (nVariableMultiplier == 0xFFFFFFFF) break;
|
||||
for (; nVariableMultiplier < nMaxMultiplier; nVariableMultiplier += nPrime)
|
||||
{
|
||||
vfComposites[GetWordNum(nVariableMultiplier)] |= GetBitMask(nVariableMultiplier);
|
||||
}
|
||||
vMultipliers[nPrimeSeq * nHalfChainLength + i] = nVariableMultiplier;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
void ProcessMultiplier(sieve_word_t *vfComposites, const unsigned int nMinMultiplier, const unsigned int nMaxMultiplier, const std::vector<unsigned int>& vPrimes, unsigned int *vMultipliers, unsigned int nLayerSeq);
|
||||
|
||||
public:
|
||||
CSieveOfEratosthenes(unsigned int nSieveSize, unsigned int nBits, mpz_class& mpzHash, mpz_class& mpzFixedMultiplier, CBlockIndex* pindexPrev)
|
||||
CSieveOfEratosthenes(unsigned int nSieveSize, unsigned int nSievePercentage, unsigned int nSieveExtensions, unsigned int nBits, mpz_class& mpzHash, mpz_class& mpzFixedMultiplier, CBlockIndex* pindexPrev)
|
||||
{
|
||||
this->nSieveSize = nSieveSize;
|
||||
this->nSievePercentage = nSievePercentage;
|
||||
this->nSieveExtensions = nSieveExtensions;
|
||||
this->nBits = nBits;
|
||||
this->mpzHash = mpzHash;
|
||||
this->mpzFixedMultiplier = mpzFixedMultiplier;
|
||||
|
@ -220,21 +214,46 @@ public:
|
|||
nPrimeSeq = 0;
|
||||
nCandidateCount = 0;
|
||||
nCandidateMultiplier = 0;
|
||||
nCandidateIndex = 0;
|
||||
fCandidateIsExtended = false;
|
||||
nCandidateActiveExtension = 0;
|
||||
nCandidatesWords = (nSieveSize + nWordBits - 1) / nWordBits;
|
||||
nCandidatesBytes = nCandidatesWords * sizeof(sieve_word_t);
|
||||
vfCandidates = (sieve_word_t *)malloc(nCandidatesBytes);
|
||||
vfCandidateBiTwin = (sieve_word_t *)malloc(nCandidatesBytes);
|
||||
vfCandidateCunningham1 = (sieve_word_t *)malloc(nCandidatesBytes);
|
||||
vfCompositeBiTwin = (sieve_word_t *)malloc(nCandidatesBytes);
|
||||
vfCompositeCunningham1 = (sieve_word_t *)malloc(nCandidatesBytes);
|
||||
vfCompositeCunningham2 = (sieve_word_t *)malloc(nCandidatesBytes);
|
||||
memset(vfCandidates, 0, nCandidatesBytes);
|
||||
memset(vfCandidateBiTwin, 0, nCandidatesBytes);
|
||||
memset(vfCandidateCunningham1, 0, nCandidatesBytes);
|
||||
memset(vfCompositeBiTwin, 0, nCandidatesBytes);
|
||||
memset(vfCompositeCunningham1, 0, nCandidatesBytes);
|
||||
memset(vfCompositeCunningham2, 0, nCandidatesBytes);
|
||||
vfExtendedCandidates = (sieve_word_t *)malloc(nSieveExtensions * nCandidatesBytes);
|
||||
vfExtendedCompositeBiTwin = (sieve_word_t *)malloc(nSieveExtensions * nCandidatesBytes);
|
||||
vfExtendedCompositeCunningham1 = (sieve_word_t *)malloc(nSieveExtensions * nCandidatesBytes);
|
||||
vfExtendedCompositeCunningham2 = (sieve_word_t *)malloc(nSieveExtensions * nCandidatesBytes);
|
||||
memset(vfExtendedCandidates, 0, nSieveExtensions * nCandidatesBytes);
|
||||
memset(vfExtendedCompositeBiTwin, 0, nSieveExtensions * nCandidatesBytes);
|
||||
memset(vfExtendedCompositeCunningham1, 0, nSieveExtensions * nCandidatesBytes);
|
||||
memset(vfExtendedCompositeCunningham2, 0, nSieveExtensions * nCandidatesBytes);
|
||||
nChainLength = TargetGetLength(nBits);
|
||||
nSieveLayers = nChainLength + nSieveExtensions;
|
||||
|
||||
// Process only a set percentage of the primes
|
||||
// Most composites are still found
|
||||
const unsigned int nTotalPrimes = vPrimes.size();
|
||||
nPrimes = (uint64)nTotalPrimes * nSievePercentage / 100;
|
||||
}
|
||||
|
||||
~CSieveOfEratosthenes()
|
||||
{
|
||||
free(vfCandidates);
|
||||
free(vfCandidateBiTwin);
|
||||
free(vfCandidateCunningham1);
|
||||
free(vfCompositeBiTwin);
|
||||
free(vfCompositeCunningham1);
|
||||
free(vfCompositeCunningham2);
|
||||
free(vfExtendedCandidates);
|
||||
free(vfExtendedCompositeBiTwin);
|
||||
free(vfExtendedCompositeCunningham1);
|
||||
free(vfExtendedCompositeCunningham2);
|
||||
}
|
||||
|
||||
// Get total number of candidates for power test
|
||||
|
@ -246,9 +265,10 @@ public:
|
|||
unsigned int nCandidates = 0;
|
||||
#ifdef __GNUC__
|
||||
for (unsigned int i = 0; i < nCandidatesWords; i++)
|
||||
{
|
||||
nCandidates += __builtin_popcountl(vfCandidates[i]);
|
||||
}
|
||||
for (unsigned int j = 0; j < nSieveExtensions; j++)
|
||||
for (unsigned int i = nCandidatesWords / 2; i < nCandidatesWords; i++)
|
||||
nCandidates += __builtin_popcountl(vfExtendedCandidates[j * nCandidatesWords + i]);
|
||||
#else
|
||||
for (unsigned int i = 0; i < nCandidatesWords; i++)
|
||||
{
|
||||
|
@ -259,6 +279,18 @@ public:
|
|||
lBits >>= 1;
|
||||
}
|
||||
}
|
||||
for (unsigned int j = 0; j < nSieveExtensions; j++)
|
||||
{
|
||||
for (unsigned int i = nCandidatesWords / 2; i < nCandidatesWords; i++)
|
||||
{
|
||||
sieve_word_t lBits = vfExtendedCandidates[j * nCandidatesWords + i];
|
||||
for (unsigned int j = 0; j < nWordBits; j++)
|
||||
{
|
||||
nCandidates += (lBits & 1);
|
||||
lBits >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
nCandidateCount = nCandidates;
|
||||
return nCandidates;
|
||||
|
@ -270,31 +302,92 @@ public:
|
|||
// False - scan complete, no more candidate and reset scan
|
||||
bool GetNextCandidateMultiplier(unsigned int& nVariableMultiplier, unsigned int& nCandidateType)
|
||||
{
|
||||
sieve_word_t lBits = vfCandidates[GetWordNum(nCandidateMultiplier)];
|
||||
sieve_word_t *vfActiveCandidates;
|
||||
sieve_word_t *vfActiveCompositeTWN;
|
||||
sieve_word_t *vfActiveCompositeCC1;
|
||||
|
||||
if (fCandidateIsExtended)
|
||||
{
|
||||
vfActiveCandidates = vfExtendedCandidates + nCandidateActiveExtension * nCandidatesWords;
|
||||
vfActiveCompositeTWN = vfExtendedCompositeBiTwin + nCandidateActiveExtension * nCandidatesWords;
|
||||
vfActiveCompositeCC1 = vfExtendedCompositeCunningham1 + nCandidateActiveExtension * nCandidatesWords;
|
||||
}
|
||||
else
|
||||
{
|
||||
vfActiveCandidates = vfCandidates;
|
||||
vfActiveCompositeTWN = vfCompositeBiTwin;
|
||||
vfActiveCompositeCC1 = vfCompositeCunningham1;
|
||||
}
|
||||
|
||||
// Acquire the current word from the bitmap
|
||||
sieve_word_t lBits = vfActiveCandidates[GetWordNum(nCandidateIndex)];
|
||||
|
||||
loop
|
||||
{
|
||||
nCandidateMultiplier++;
|
||||
if (nCandidateMultiplier >= nSieveSize)
|
||||
nCandidateIndex++;
|
||||
if (nCandidateIndex >= nSieveSize)
|
||||
{
|
||||
nCandidateMultiplier = 0;
|
||||
return false;
|
||||
// Check if extensions are available
|
||||
if (!fCandidateIsExtended && nSieveExtensions > 0)
|
||||
{
|
||||
fCandidateIsExtended = true;
|
||||
nCandidateActiveExtension = 0;
|
||||
nCandidateIndex = nSieveSize / 2;
|
||||
}
|
||||
else if (fCandidateIsExtended && nCandidateActiveExtension + 1 < nSieveExtensions)
|
||||
{
|
||||
nCandidateActiveExtension++;
|
||||
nCandidateIndex = nSieveSize / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Out of candidates
|
||||
fCandidateIsExtended = false;
|
||||
nCandidateActiveExtension = 0;
|
||||
nCandidateIndex = 0;
|
||||
nCandidateMultiplier = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fix the pointers
|
||||
if (fCandidateIsExtended)
|
||||
{
|
||||
vfActiveCandidates = vfExtendedCandidates + nCandidateActiveExtension * nCandidatesWords;
|
||||
vfActiveCompositeTWN = vfExtendedCompositeBiTwin + nCandidateActiveExtension * nCandidatesWords;
|
||||
vfActiveCompositeCC1 = vfExtendedCompositeCunningham1 + nCandidateActiveExtension * nCandidatesWords;
|
||||
}
|
||||
else
|
||||
{
|
||||
vfActiveCandidates = vfCandidates;
|
||||
vfActiveCompositeTWN = vfCompositeBiTwin;
|
||||
vfActiveCompositeCC1 = vfCompositeCunningham1;
|
||||
}
|
||||
}
|
||||
if (nCandidateMultiplier % nWordBits == 0)
|
||||
|
||||
if (nCandidateIndex % nWordBits == 0)
|
||||
{
|
||||
lBits = vfCandidates[GetWordNum(nCandidateMultiplier)];
|
||||
// Update the current word
|
||||
lBits = vfActiveCandidates[GetWordNum(nCandidateIndex)];
|
||||
|
||||
// Check if any bits are set
|
||||
if (lBits == 0)
|
||||
{
|
||||
// Skip an entire word
|
||||
nCandidateMultiplier += nWordBits - 1;
|
||||
nCandidateIndex += nWordBits - 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (lBits & GetBitMask(nCandidateMultiplier))
|
||||
|
||||
if (lBits & GetBitMask(nCandidateIndex))
|
||||
{
|
||||
if (fCandidateIsExtended)
|
||||
nCandidateMultiplier = nCandidateIndex * (2 << nCandidateActiveExtension);
|
||||
else
|
||||
nCandidateMultiplier = nCandidateIndex;
|
||||
nVariableMultiplier = nCandidateMultiplier;
|
||||
if (vfCandidateBiTwin[GetWordNum(nCandidateMultiplier)] & GetBitMask(nCandidateMultiplier))
|
||||
if (~vfActiveCompositeTWN[GetWordNum(nCandidateIndex)] & GetBitMask(nCandidateIndex))
|
||||
nCandidateType = PRIME_CHAIN_BI_TWIN;
|
||||
else if (vfCandidateCunningham1[GetWordNum(nCandidateMultiplier)] & GetBitMask(nCandidateMultiplier))
|
||||
else if (~vfActiveCompositeCC1[GetWordNum(nCandidateIndex)] & GetBitMask(nCandidateIndex))
|
||||
nCandidateType = PRIME_CHAIN_CUNNINGHAM1;
|
||||
else
|
||||
nCandidateType = PRIME_CHAIN_CUNNINGHAM2;
|
||||
|
|
|
@ -275,3 +275,90 @@ Value listprimerecords(const Array& params, bool fHelp)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Primecoin: list top prime chain within primecoin network
|
||||
Value listtopprimes(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() < 1 || params.size() > 2)
|
||||
throw runtime_error(
|
||||
"listtopprimes <primechain length> [primechain type]\n"
|
||||
"Returns the list of top prime chains in primecoin network.\n"
|
||||
"<primechain length> is integer like 10, 11, 12 etc.\n"
|
||||
"[primechain type] is optional type, among 1CC, 2CC and TWN");
|
||||
|
||||
int nPrimeChainLength = params[0].get_int();
|
||||
unsigned int nPrimeChainType = 0;
|
||||
if (params.size() > 1)
|
||||
{
|
||||
std::string strPrimeChainType = params[1].get_str();
|
||||
if (strPrimeChainType.compare("1CC") == 0)
|
||||
nPrimeChainType = PRIME_CHAIN_CUNNINGHAM1;
|
||||
else if (strPrimeChainType.compare("2CC") == 0)
|
||||
nPrimeChainType = PRIME_CHAIN_CUNNINGHAM2;
|
||||
else if (strPrimeChainType.compare("TWN") == 0)
|
||||
nPrimeChainType = PRIME_CHAIN_BI_TWIN;
|
||||
else
|
||||
throw runtime_error("Prime chain type must be 1CC, 2CC or TWN.");
|
||||
}
|
||||
|
||||
// Search for top prime chains
|
||||
unsigned int nRankingSize = 10; // ranking list size
|
||||
unsigned int nSortVectorSize = 64; // vector size for sort operation
|
||||
CBigNum bnPrimeQualify = 0; // minimum qualify value for ranking list
|
||||
vector<pair<CBigNum, uint256> > vSortedByOrigin;
|
||||
for (CBlockIndex* pindex = pindexGenesisBlock; pindex; pindex = pindex->pnext)
|
||||
{
|
||||
if (nPrimeChainLength != (int) TargetGetLength(pindex->nPrimeChainLength))
|
||||
continue; // length not matching, next block
|
||||
if (nPrimeChainType && nPrimeChainType != pindex->nPrimeChainType)
|
||||
continue; // type not matching, next block
|
||||
|
||||
CBlock block;
|
||||
block.ReadFromDisk(pindex); // read block
|
||||
CBigNum bnPrimeChainOrigin = CBigNum(block.GetHeaderHash()) * block.bnPrimeChainMultiplier; // compute prime chain origin
|
||||
|
||||
if (bnPrimeChainOrigin > bnPrimeQualify)
|
||||
vSortedByOrigin.push_back(make_pair(bnPrimeChainOrigin, block.GetHash()));
|
||||
|
||||
if (vSortedByOrigin.size() >= nSortVectorSize)
|
||||
{
|
||||
// Sort prime chain candidates
|
||||
sort(vSortedByOrigin.begin(), vSortedByOrigin.end());
|
||||
reverse(vSortedByOrigin.begin(), vSortedByOrigin.end());
|
||||
// Truncate candidate list
|
||||
while (vSortedByOrigin.size() > nRankingSize)
|
||||
vSortedByOrigin.pop_back();
|
||||
// Update minimum qualify value for top prime chains
|
||||
bnPrimeQualify = vSortedByOrigin.back().first;
|
||||
}
|
||||
}
|
||||
|
||||
// Final sort of prime chain candidates
|
||||
sort(vSortedByOrigin.begin(), vSortedByOrigin.end());
|
||||
reverse(vSortedByOrigin.begin(), vSortedByOrigin.end());
|
||||
// Truncate candidate list
|
||||
while (vSortedByOrigin.size() > nRankingSize)
|
||||
vSortedByOrigin.pop_back();
|
||||
|
||||
// Output top prime chains
|
||||
Array ret;
|
||||
BOOST_FOREACH(const PAIRTYPE(CBigNum, uint256)& item, vSortedByOrigin)
|
||||
{
|
||||
CBigNum bnPrimeChainOrigin = item.first;
|
||||
CBlockIndex* pindex = mapBlockIndex[item.second];
|
||||
CBlock block;
|
||||
block.ReadFromDisk(pindex); // read block
|
||||
Object entry;
|
||||
entry.push_back(Pair("time", DateTimeStrFormat("%Y-%m-%d %H:%M:%S UTC", pindex->GetBlockTime()).c_str()));
|
||||
entry.push_back(Pair("epoch", (boost::int64_t) pindex->GetBlockTime()));
|
||||
entry.push_back(Pair("height", pindex->nHeight));
|
||||
entry.push_back(Pair("ismine", pwalletMain->IsMine(block.vtx[0])));
|
||||
entry.push_back(Pair("primedigit", (int) bnPrimeChainOrigin.ToString().length()));
|
||||
entry.push_back(Pair("primechain", GetPrimeChainName(pindex->nPrimeChainType, pindex->nPrimeChainLength).c_str()));
|
||||
entry.push_back(Pair("primeorigin", bnPrimeChainOrigin.ToString().c_str()));
|
||||
entry.push_back(Pair("primorialform", GetPrimeOriginPrimorialForm(bnPrimeChainOrigin).c_str()));
|
||||
ret.push_back(entry);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -72,35 +72,38 @@ Value setsievepercentage(const Array& params, bool fHelp)
|
|||
if (params.size() > 0)
|
||||
nPercentage = params[0].get_int();
|
||||
|
||||
nPercentage = std::max(std::min(nPercentage, nMaxSievePercentage), nMinSievePercentage);
|
||||
|
||||
nSievePercentage = nPercentage;
|
||||
return Value::null;
|
||||
}
|
||||
|
||||
|
||||
Value getroundsievepercentage(const Array& params, bool fHelp)
|
||||
Value getsieveextensions(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 0)
|
||||
throw runtime_error(
|
||||
"getroundsievepercentage\n"
|
||||
"Returns the current sieve generation time percentage used by the mining algorithm.");
|
||||
"getsieveextensions\n"
|
||||
"Returns the number of times the sieve is extended.");
|
||||
|
||||
return (boost::int64_t)nRoundSievePercentage;
|
||||
return (boost::int64_t)nSieveExtensions;
|
||||
}
|
||||
|
||||
|
||||
Value setroundsievepercentage(const Array& params, bool fHelp)
|
||||
Value setsieveextensions(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() < 1)
|
||||
throw runtime_error(
|
||||
"setroundsievepercentage <roundsievepercentage>\n"
|
||||
"<roundsievepercentage> determines much time should be spent generating the sieve of candidate multipliers.\n"
|
||||
"The round primorial is dynamically adjusted based on this value.");
|
||||
"setsieveextensions <sieveextensions>\n"
|
||||
"<sieveextensions> determines the number of times the sieve will be extended.");
|
||||
|
||||
unsigned int nPercentage = nDefaultRoundSievePercentage;
|
||||
unsigned int nExtensions = (fTestNet) ? nDefaultSieveExtensionsTestnet : nDefaultSieveExtensions;
|
||||
if (params.size() > 0)
|
||||
nPercentage = params[0].get_int();
|
||||
nExtensions = params[0].get_int();
|
||||
|
||||
nRoundSievePercentage = nPercentage;
|
||||
nExtensions = std::max(std::min(nExtensions, nMaxSieveExtensions), nMinSieveExtensions);
|
||||
|
||||
nSieveExtensions = nExtensions;
|
||||
return Value::null;
|
||||
}
|
||||
|
||||
|
@ -147,9 +150,9 @@ Value getmininginfo(const Array& params, bool fHelp)
|
|||
obj.push_back(Pair("errors", GetWarnings("statusbar")));
|
||||
obj.push_back(Pair("generate", GetBoolArg("-gen")));
|
||||
obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
|
||||
obj.push_back(Pair("roundsievepercentage",(int)nRoundSievePercentage));
|
||||
obj.push_back(Pair("primespersec", getprimespersec(params, false)));
|
||||
obj.push_back(Pair("pooledtx", (uint64_t)mempool.size()));
|
||||
obj.push_back(Pair("sieveextensions",(int)nSieveExtensions));
|
||||
obj.push_back(Pair("sievepercentage",(int)nSievePercentage));
|
||||
obj.push_back(Pair("sievesize", (int)nSieveSize));
|
||||
obj.push_back(Pair("testnet", fTestNet));
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
const std::string CLIENT_NAME("Satoshi");
|
||||
|
||||
// Client version number
|
||||
#define CLIENT_VERSION_SUFFIX "-beta-hp9"
|
||||
#define CLIENT_VERSION_SUFFIX "-beta-hp10"
|
||||
|
||||
|
||||
// The following part of the code determines the CLIENT_BUILD variable.
|
||||
|
|
Loading…
Reference in New Issue