bool MineProbablePrimeChainFast(PrimecoinBlockHeader &header, CSieveOfEratosthenesL1Ext *sieve, mpz_class &blockHeaderHash, mpz_class &primorial, unsigned int& nProbableChainLength, unsigned int& nTests, unsigned int& nPrimesHit, CPrimalityTestParams &testParams, const PrimeSource &primeSource, uint64_t *foundChains) { timeMark sieveBegin = getTimeMark(); mpz_class hashMultiplier = blockHeaderHash*primorial; sieve->reset(gSieveSize, chainLengthFromBits(header.bits), gWeaveDepth, hashMultiplier); sieve->Weave(); timeMark sieveEnd = getTimeMark(); if (gDebug) { fprintf(stderr, " * sieve %.3lfmsec: %u@%u/%u ", usDiff(sieveBegin, sieveEnd) / 1000.0, sieve->GetCandidateCount(), gSieveSize, gWeaveDepth); } nTests = 0; nPrimesHit = 0; unsigned nTriedMultiplier; mpz_class bnChainOrigin; unsigned int &nChainLength = testParams.chainLength; unsigned int &nCandidateType = testParams.candidateType; sieve->resetCandidateIterator(); while (true) { nTests++; if (!sieve->GetNextCandidateMultiplier(nTriedMultiplier, nCandidateType)) { timeMark primalityTestEnd = getTimeMark(); if (gDebug) { fprintf(stderr, " primality Fermat test %.3lfmsec\n", usDiff(sieveEnd, primalityTestEnd) / 1000.0); } return false; } bnChainOrigin = hashMultiplier; bnChainOrigin *= nTriedMultiplier; nChainLength = 0; if (ProbablePrimeChainTestFast(bnChainOrigin, testParams)) { uint8_t buffer[256]; BIGNUM *xxx = 0; mpz_class targetMultiplier = primorial*nTriedMultiplier; BN_dec2bn(&xxx, targetMultiplier.get_str().c_str()); BN_bn2mpi(xxx, buffer); header.multiplier[0] = buffer[3]; std::reverse_copy(buffer+4, buffer+4+buffer[3], header.multiplier+1); fprintf(stderr, "targetMultiplier=%s\n", targetMultiplier.get_str().c_str()); return true; } nProbableChainLength = nChainLength; if (chainLengthFromBits(nProbableChainLength) >= 1) { foundChains[chainLengthFromBits(nProbableChainLength)]++; nPrimesHit++; } } return false; }
// Mine probable prime chain of form: n = h * p# +/- 1 bool MineProbablePrimeChain(Reap_CPU_param* state, Work& tempwork, CSieveOfEratosthenes& psieve, mpz_class& mpzFixedMultiplier, bool& fNewBlock, unsigned int& nTriedMultiplier, unsigned int& nProbableChainLength, unsigned int& nTests, unsigned int& nPrimesHit, unsigned int& nChainsHit, mpz_class& mpzHash, unsigned int nPrimorialMultiplier) { nProbableChainLength = 0; nPrimesHit = 0; nChainsHit = 0; //const unsigned int nBits = block.nBits; const unsigned int nBits = *(uint*)&tempwork.data[72]; bool use_gpu_fermat_test = globalconfs.coin.config.GetValue<bool>("use_gpu_fermat_test"); if (fNewBlock && psieve.inited) { // Must rebuild the sieve psieve.Deinit(); } fNewBlock = false; int64 nStart; // microsecond timer if (!psieve.inited) { // Build sieve nStart = ticker()*1000; psieve.InitAndWeave(state, nSieveSize, nBits, mpzHash, mpzFixedMultiplier); if (globalconfs.coin.config.GetValue<bool>("debug")) printf("MineProbablePrimeChain() : new sieve (%lu/%u) ready in %uus\n", psieve.CandidateList.size(), nSieveSize, (unsigned int) (ticker()*1000 - nStart)); } mpz_class mpzHashMultiplier = mpzHash * mpzFixedMultiplier; mpz_class mpzChainOrigin; // Determine the sequence number of the round primorial unsigned int nPrimorialSeq = 0; while (vPrimes[nPrimorialSeq + 1] <= nPrimorialMultiplier) nPrimorialSeq++; // Allocate GMP variables for primality tests CPrimalityTestParams testParams(nBits, nPrimorialSeq); nStart = ticker()*1000; // References to counters; unsigned int& nChainLengthCunningham1 = testParams.nChainLengthCunningham1; unsigned int& nChainLengthCunningham2 = testParams.nChainLengthCunningham2; unsigned int& nChainLengthBiTwin = testParams.nChainLengthBiTwin; //cout << "PSIEVIOSIE" << psieve.CandidateList.size() << endl; for(uint i=0; i<psieve.CandidateList.size(); ++i) { nTriedMultiplier = psieve.CandidateList[i]&0x3FFFFFFFU; uint sievenumber = psieve.CandidateList[i]>>30; if (sievenumber == 0) sievenumber=3; if (nTriedMultiplier == 0) //will crash otherwise continue; ++nTests; if (tempwork.time != current_work.time) { //cout << "Tempwork.time != curnetopqi" << tempwork.time << " " << current_work.time << endl; break; } mpzChainOrigin = mpzHashMultiplier * (nTriedMultiplier&0x3FFFFFFFU); nChainLengthCunningham1 = 0; nChainLengthCunningham2 = 0; nChainLengthBiTwin = 0; if (ProbablePrimeChainTestFast(mpzChainOrigin, testParams, sievenumber, use_gpu_fermat_test)) { mpz_t mpzPrimeChainMultiplier; mpz_init(mpzPrimeChainMultiplier); mpz_mul_ui(mpzPrimeChainMultiplier,mpzFixedMultiplier.get_mpz_t(),nTriedMultiplier); { //gmp_printf("Found chain! Mult: %Zx\n",mpzPrimeChainMultiplier); vector<uchar> auxdata = XPM_create_auxdata(&mpzPrimeChainMultiplier); CPU_Got_share(state,tempwork,auxdata); } mpz_clear(mpzPrimeChainMultiplier); nProbableChainLength = std::max(std::max(nChainLengthCunningham1, nChainLengthCunningham2), nChainLengthBiTwin); return true; } nProbableChainLength = std::max(std::max(nChainLengthCunningham1, nChainLengthCunningham2), nChainLengthBiTwin); if(TargetGetLength(nProbableChainLength) >= 1) nPrimesHit++; if(TargetGetLength(nProbableChainLength) >= nStatsChainLength) nChainsHit++; } // power tests completed for the sieve //if (fDebug && GetBoolArg("-printmining")) //printf("MineProbablePrimeChain() : %u tests (%u primes and %u %d-chains) in %uus\n", nTests, nPrimesHit, nChainsHit, nStatsChainLength, (unsigned int) (GetTimeMicros() - nStart)); psieve.Deinit(); fNewBlock = true; // notify caller to change nonce return false; // stop as new block arrived }