// Test probable prime chain for: nOrigin // Return value: // true - Probable prime chain found (one of nChainLength meeting target) // false - prime chain too short (none of nChainLength meeting target) static bool AllChainTest(mpz_t *bnPrimeChainOrigin, unsigned int nBits, bool fFermatTest, unsigned int *pnChainLengthCunningham1, unsigned int *pnChainLengthCunningham2, unsigned int *pnChainLengthBiTwin, unsigned int sievenumber) { *pnChainLengthCunningham1 = 0; *pnChainLengthCunningham2 = 0; *pnChainLengthBiTwin = 0; mpz_t mp; mpz_init(mp); // Test for Cunningham Chain of first kind if (sievenumber&1) { mpz_sub_ui(mp, *bnPrimeChainOrigin, 1); CunnChainTest(&mp, true, fFermatTest, pnChainLengthCunningham1); } // Test for Cunningham Chain of second kind if (sievenumber&2) { mpz_add_ui(mp, *bnPrimeChainOrigin, 1); CunnChainTest(&mp, false, fFermatTest, pnChainLengthCunningham2); } mpz_clear(mp); // Figure out BiTwin Chain length // BiTwin Chain allows a single prime at the end for odd length chain *pnChainLengthBiTwin = (TargetGetLength(*pnChainLengthCunningham1) > TargetGetLength(*pnChainLengthCunningham2)) ? (*pnChainLengthCunningham2 + TargetFromInt(TargetGetLength(*pnChainLengthCunningham2)+1)) : (*pnChainLengthCunningham1 + TargetFromInt(TargetGetLength(*pnChainLengthCunningham1))); return (*pnChainLengthCunningham1 >= nBits || *pnChainLengthCunningham2 >= nBits || *pnChainLengthBiTwin >= nBits); }
// Test probable prime chain for: nOrigin // Return value: // true - Probable prime chain found (one of nChainLength meeting target) // false - prime chain too short (none of nChainLength meeting target) bool ProbablePrimeChainTestFast2(const mpz_class& mpzPrimeChainOrigin, CPrimalityTestParams& testParams, uint32 sieveFlags, uint32 multiplier) { const unsigned int nBits = testParams.nBits; unsigned int& nChainLengthCunningham1 = testParams.nChainLengthCunningham1; unsigned int& nChainLengthCunningham2 = testParams.nChainLengthCunningham2; unsigned int& nChainLengthBiTwin = testParams.nChainLengthBiTwin; const bool fFermatTest = testParams.fFermatTest; mpz_class& mpzOriginMinusOne = testParams.mpzOriginMinusOne; mpz_class& mpzOriginPlusOne = testParams.mpzOriginPlusOne; nChainLengthCunningham1 = 0; nChainLengthCunningham2 = 0; nChainLengthBiTwin = 0; bool testCFirstKind = ((sieveFlags&SIEVE_FLAG_BT_COMPOSITE)!=0) || ((sieveFlags&SIEVE_FLAG_C2_COMPOSITE)!=0); // yes, C1 and C2 is switched bool testCSecondKind = ((sieveFlags&SIEVE_FLAG_BT_COMPOSITE)!=0) || ((sieveFlags&SIEVE_FLAG_C1_COMPOSITE)!=0); // Test for Cunningham Chain of first kind mpzOriginMinusOne = mpzPrimeChainOrigin - 1; if( testCFirstKind ) ProbableCunninghamChainTestFast(mpzOriginMinusOne, true, fFermatTest, nChainLengthCunningham1, testParams); else nChainLengthCunningham1 = 0; // Test for Cunningham Chain of second kind mpzOriginPlusOne = mpzPrimeChainOrigin + 1; if( testCSecondKind ) ProbableCunninghamChainTestFast(mpzOriginPlusOne, false, fFermatTest, nChainLengthCunningham2, testParams); else nChainLengthCunningham2 = 0; //// do we need to flag some bits as composite to avoid redundant chain checks? //uint32 redundancyCheckLength = min(nChainLengthCunningham1, nChainLengthCunningham2); //redundancyCheckLength >>= 24; //if( redundancyCheckLength >= 2 ) //{ // printf("."); // uint32 mask = 1<<(multiplier&7); // uint32 maskIdx = multiplier>>3; // for(uint32 r=0; r<redundancyCheckLength; r++) // { // uint8* maskC1 = cSieve->layerMaskC1+((cSieve->currentSieveLayerIdx+r)%cSieve->chainLength)*cSieve->maskBytes; // uint8* maskC2 = cSieve->layerMaskC1+((cSieve->currentSieveLayerIdx+r)%cSieve->chainLength)*cSieve->maskBytes; // maskC1[maskIdx] |= mask; // maskC2[maskIdx] |= mask; // } //} // verify if there is any chance to find a biTwin that worth calculation if (nChainLengthCunningham1 < 0x2000000 || nChainLengthCunningham2 < 0x2000000) return (nChainLengthCunningham1 >= nBits || nChainLengthCunningham2 >= nBits); // Figure out BiTwin Chain length // BiTwin Chain allows a single prime at the end for odd length chain nChainLengthBiTwin = (TargetGetLength(nChainLengthCunningham1) > TargetGetLength(nChainLengthCunningham2))? (nChainLengthCunningham2 + TargetFromInt(TargetGetLength(nChainLengthCunningham2)+1)) : (nChainLengthCunningham1 + TargetFromInt(TargetGetLength(nChainLengthCunningham1))); return (nChainLengthCunningham1 >= nBits || nChainLengthCunningham2 >= nBits || nChainLengthBiTwin >= nBits); }
// Test Probable Cunningham Chain for: n // fSophieGermain: // true - Test for Cunningham Chain of first kind (n, 2n+1, 4n+3, ...) // false - Test for Cunningham Chain of second kind (n, 2n-1, 4n-3, ...) // Return value: // true - Probable Cunningham Chain found (length at least 2) // false - Not Cunningham Chain static bool ProbableCunninghamChainTestFast(const mpz_class& n, bool fSophieGermain, bool fFermatTest, unsigned int& nProbableChainLength, CPrimalityTestParams& testParams, bool use_gpu_fermat_test) { nProbableChainLength = 0; mpz_class &N = testParams.N; N = n; if (!use_gpu_fermat_test && !FermatProbablePrimalityTestFast(N, nProbableChainLength, testParams, true)) { return false; } // Euler-Lagrange-Lifchitz test for the following numbers in chain while (true) { TargetIncrementLength(nProbableChainLength); N = N + N + (fSophieGermain? 1 : (-1)); if (fFermatTest) { if (!FermatProbablePrimalityTestFast(N, nProbableChainLength, testParams, true)) break; } else { if (!EulerLagrangeLifchitzPrimalityTestFast(N, fSophieGermain, nProbableChainLength, testParams, true)) break; } } return (TargetGetLength(nProbableChainLength) >= 2); }
std::string TargetToString(unsigned int nBits) { //return strprintf("%02x.%06x", TargetGetLength(nBits), TargetGetFractional(nBits)); stringstream ss; ss << std::hex << std::setw(2) << std::setfill('0') << TargetGetLength(nBits) << "." << std::setw(6) << std::setfill('0') << TargetGetFractional(nBits); return ss.str(); }
// Test Probable Cunningham Chain for: n // fSophieGermain: // true - Test for Cunningham Chain of first kind (n, 2n+1, 4n+3, ...) // false - Test for Cunningham Chain of second kind (n, 2n-1, 4n-3, ...) // Return value: // true - Probable Cunningham Chain found (length at least 2) // false - Not Cunningham Chain static bool CunnChainTest(mpz_t *n, bool fSophieGermain, bool fFermatTest, unsigned int *pnProbableChainLength) { *pnProbableChainLength = 0; mpz_t N; mpz_init_set(N, *n); // Fermat test for n first if (!PrimeTest(&N, pnProbableChainLength)) { mpz_clear(N); return false; } // Euler-Lagrange-Lifchitz test for the following numbers in chain while (true) { TargetIncrementLength(pnProbableChainLength); mpz_add(N, N, N); if (fSophieGermain) mpz_add_ui(N, N, 1); else mpz_sub_ui(N, N, 1); //disabled, see SpecialPrimeTest() comments for further information /*if (fFermatTest) { if (!PrimeTest(&N, pnProbableChainLength)) break; } else { if (!SpecialPrimeTest(&N, fSophieGermain, pnProbableChainLength)) break; }*/ if (!PrimeTest(&N, pnProbableChainLength)) break; } mpz_clear(N); #ifdef SUPERDEBUG printf("PCCT => %u (%u)\n", TargetGetLength(*pnProbableChainLength), *pnProbableChainLength); #endif return (TargetGetLength(*pnProbableChainLength) >= 2); }
int PrimeWorker::HandleRequest(zmq_pollitem_t *item) { proto::Request& req = mRequest; zmsg_t* msg = ReceiveRequest(req, item->socket); if(!msg) return 0; //req.PrintDebugString(); proto::Request::Type rtype = req.type(); proto::Reply::ErrType etype = proto::Reply::NONE; proto::Reply& rep = mReply; rep.Clear(); rep.set_type(rtype); rep.set_reqid(req.reqid()); if(!proto::Request::Type_IsValid(rtype)){ printf("ERROR: !proto::Request::Type_IsValid.\n"); rtype = proto::Request::NONE; etype = proto::Reply::INVALID; } while(etype == proto::Reply::NONE) { int vstatus = CheckVersion(req.version()); if(vstatus <= 0){ rep.set_errstr("Your miner version is no longer supported. Please upgrade."); etype = proto::Reply::VERSION; break; } if(rtype == proto::Request::CONNECT){ rep.mutable_sinfo()->CopyFrom(mServerInfo); if(vstatus == 1){ etype = proto::Reply::VERSION; rep.set_errstr("Your miner version will no longer be supported in the near future. Please upgrade."); } }else if(rtype == proto::Request::GETWORK){ if(!mCurrBlock.has_height()){ etype = proto::Reply::HEIGHT; break; } if(req.height() != mCurrHeight){ etype = proto::Reply::HEIGHT; break; } CBlock *pblock = &mBlockTemplate->block; IncrementExtraNonce(pblock, mIndexPrev, mExtraNonce); pblock->nTime = std::max(pblock->nTime, (unsigned int)GetAdjustedTime()); mNonceMap[pblock->hashMerkleRoot] = mExtraNonce; proto::Work* work = rep.mutable_work(); work->set_height(mCurrHeight); work->set_merkle(pblock->hashMerkleRoot.GetHex()); work->set_time(pblock->nTime); work->set_bits(pblock->nBits); }else if(rtype == proto::Request::SHARE){ if(!mCurrBlock.has_height()){ etype = proto::Reply::STALE; break; } if(!req.has_share()){ printf("ERROR: !req.has_share().\n"); etype = proto::Reply::INVALID; break; } const proto::Share& share = req.share(); if(share.height() != mCurrHeight){ etype = proto::Reply::STALE; break; } if(share.length() < mCurrBlock.minshare()){ printf("ERROR: share.length too short.\n"); etype = proto::Reply::INVALID; break; } uint256 merkleRoot; merkleRoot.SetHex(share.merkle()); unsigned extraNonce = mNonceMap[merkleRoot]; if(!extraNonce){ etype = proto::Reply::STALE; break; } unsigned nCandidateType = share.chaintype(); if(nCandidateType > 2){ printf("ERROR: share.chaintype invalid.\n"); etype = proto::Reply::INVALID; break; } CBlock *pblock = &mBlockTemplate->block; extraNonce--; IncrementExtraNonce(pblock, mIndexPrev, extraNonce); pblock->nTime = share.time(); pblock->nBits = share.bits(); pblock->nNonce = share.nonce(); uint256 headerHash = pblock->GetHeaderHash(); { uint256 headerHashClient; headerHashClient.SetHex(share.hash()); if(headerHashClient != headerHash){ printf("ERROR: headerHashClient != headerHash.\n"); etype = proto::Reply::INVALID; break; } } pblock->bnPrimeChainMultiplier.SetHex(share.multi()); uint256 blockhash = pblock->GetHash(); if(!mShares.insert(blockhash).second){ etype = proto::Reply::DUPLICATE; break; } CBigNum bnChainOrigin = CBigNum(headerHash) * pblock->bnPrimeChainMultiplier; unsigned int nChainLength = 0; bool isblock = ProbablePrimeChainTestForMiner(bnChainOrigin, pblock->nBits, nCandidateType+1, nChainLength); nChainLength = TargetGetLength(nChainLength); if(nChainLength >= mCurrBlock.minshare()){ if(isblock) isblock = CheckWork(pblock, *mWallet, mReserveKey); if(share.length() != nChainLength){ printf("ERROR: share.length() != nChainLength.\n"); etype = proto::Reply::INVALID; } mData.Clear(); proto::Share* mshare = mData.mutable_share(); mshare->CopyFrom(share); mshare->set_blockhash(blockhash.GetHex()); mshare->set_length(nChainLength); mshare->set_isblock(isblock); if(isblock){ mshare->set_genvalue(pblock->vtx[0].vout[0].nValue); } SendData(mData, mBackend); CBitcoinAddress address(share.addr()); if(!address.IsValid()){ printf("ERROR: invalid address for share: %s\n", share.addr().c_str()); etype = proto::Reply::INVALID; std::string errstr = "Your payment address '"; errstr.append(share.addr()); errstr.append("' is INVALID!!!"); rep.set_errstr(errstr); break; } }else{ printf("ERROR: share.length too short after test: %d/%d\n", nChainLength, share.length()); etype = proto::Reply::INVALID; break; } }else if(rtype == proto::Request::STATS){ if(!req.has_stats()){ printf("ERROR: !req.has_stats().\n"); etype = proto::Reply::INVALID; break; } const proto::ClientStats& stats = req.stats(); std::pair<std::string,uint64> key = std::make_pair(stats.addr(), stats.clientid() * stats.instanceid()); std::map<std::pair<std::string,uint64>, proto::Data>::iterator iter = mStats.find(key); if(iter != mStats.end()){ proto::ClientStats* s = mStats[key].mutable_clientstats(); s->set_version(std::min(s->version(), stats.version())); s->set_cpd(s->cpd() + stats.cpd()); s->set_errors(s->errors() + stats.errors()); s->set_temp(std::max(s->temp(), stats.temp())); s->set_latency(std::max(s->latency(), stats.latency())); s->set_ngpus(s->ngpus() + stats.ngpus()); /*if(s->name() != stats.name()){ s->mutable_name()->append("+"); s->mutable_name()->append(stats.name()); }*/ }else if(mStats.size() < 100000){ mStats[key].mutable_clientstats()->CopyFrom(stats); } } break; } if(req.height() < mCurrHeight){ rep.mutable_block()->CopyFrom(mCurrBlock); } mReqStats[std::make_pair(rtype,etype)]++; rep.set_error(etype); SendReply(rep, &msg, item->socket); zmsg_destroy(&msg); return 0; }
bool MinePrime(Reap_CPU_param* state, Work& tempwork) { uchar* tempdata = &tempwork.data[0]; uchar hash[32]; mysha256(hash,tempdata,80); mysha256(hash,hash,32); //does this need byte flipping? uint bits = *(uint*)&tempdata[72]; if (!(hash[31] & 0x80)) return false; //hash is too small, abort Mpz_w hashnum; set_mpz_to_hash(&hashnum.n, hash); if (mpz_fdiv_ui(hashnum.n, 2*3) != 0) return false; bool found=false; //5431526412865007455 mpz_t factor; mpz_init_set_str(factor, "5431526412865007455", 10); mpz_mul(hashnum.n,hashnum.n,factor); uint remainders[MAX_SIEVE_AMOUNT] = {}; for(int i=0; i<MAX_SIEVE_AMOUNT; ++i) { remainders[i] = mpz_fdiv_ui(hashnum.n,Primes::v[i]); } mpz_t newhashnum; mpz_init(newhashnum); for(uint h=1; h<500; ++h) { mpz_add(newhashnum,newhashnum,hashnum.n); uint c1=0,c2=0,tw=0; uint sievenumber = 0; for(uint i=16; i<MAX_SIEVE_AMOUNT; ++i) { sievenumber |= Sieve::Get(i,remainders[i]*h%Primes::v[i])^3; } sievenumber ^= 3; //cout << sievenumber << endl;; if (sievenumber == 0) continue; //TODO: fix second parameter, it should be bits! AllChainTest(&newhashnum, 0, true, &c1, &c2, &tw, sievenumber); uint c1_i = TargetGetLength(c1); uint c2_i = TargetGetLength(c2); uint tw_i = TargetGetLength(tw); const int minlength=5; /*{ if (c1_i >= minlength) cout << "First kind: " << c1_i << endl; if (c2_i >= minlength) cout << "Second kind: " << c2_i << endl; if (tw_i >= minlength) cout << "Twin kind: " << tw_i << endl; }*/ ++chainspersec[c1_i]; ++chainspersec[c2_i]; ++chainspersec[tw_i]; ++totalpersec; found = (c1_i >= minlength || c2_i >= minlength || tw_i >= minlength); if (found) { mpz_mul_ui(factor,factor,h); vector<uchar> auxdata = XPM_create_auxdata(&factor); Share share; CPU_Got_share(state,tempwork,auxdata);//tempdata,tempwork.target_share,current_server_id,tempwork.dataid,auxdata); } } return found; }
static void TargetDecrementLength(unsigned int& nBits) { if (TargetGetLength(nBits) > nTargetMinLength) nBits -= (1 << nFractionalBits); }
std::string TargetToString(unsigned int nBits) { char tmp[20]; sprintf(tmp, "%02x.%06x", TargetGetLength(nBits), TargetGetFractional(nBits)); return std::string(tmp); }
// Test probable prime chain for: nOrigin // Return value: // true - Probable prime chain found (one of nChainLength meeting target) // false - prime chain too short (none of nChainLength meeting target) bool ProbablePrimeChainTestFast2(const mpz_class& mpzPrimeChainOrigin, CPrimalityTestParams& testParams, uint32 sieveFlags, uint32 multiplier) { const unsigned int nBits = testParams.nBits; unsigned int& nChainLengthCunningham1 = testParams.nChainLengthCunningham1; unsigned int& nChainLengthCunningham2 = testParams.nChainLengthCunningham2; unsigned int& nChainLengthBiTwin = testParams.nChainLengthBiTwin; const bool fFermatTest = testParams.fFermatTest; mpz_class& mpzOriginMinusOne = testParams.mpzOriginMinusOne; mpz_class& mpzOriginPlusOne = testParams.mpzOriginPlusOne; nChainLengthCunningham1 = 0; nChainLengthCunningham2 = 0; nChainLengthBiTwin = 0; //sieveFlags = 0; // note: enabling the sieve optimization seems to decrease the rate of shares (remove this line to enable this future for non-gpu mode) bool testCFirstKind = ((sieveFlags&SIEVE_FLAG_BT_COMPOSITE)==0) || ((sieveFlags&SIEVE_FLAG_C1_COMPOSITE)==0); // yes, C1 and C2 are switched bool testCSecondKind = ((sieveFlags&SIEVE_FLAG_BT_COMPOSITE)==0) || ((sieveFlags&SIEVE_FLAG_C2_COMPOSITE)==0); bool testCFirstFast = (sieveFlags&SIEVE_FLAG_C1_COMPOSITE)!=0; // should be !=0? bool testCSecondFast = (sieveFlags&SIEVE_FLAG_C2_COMPOSITE)!=0; mpzOriginMinusOne = mpzPrimeChainOrigin - 1; // first kind origin mpzOriginPlusOne = mpzPrimeChainOrigin + 1; // second kind origin // detailed test //if( testCFirstKind && testCFirstFast == true ) //(sieveFlags&SIEVE_FLAG_C1_COMPOSITE)==0 ) //{ // for(uint32 i=0; i<5000; i++) // { // if( mpz_tdiv_ui(mpzOriginMinusOne.get_mpz_t(), vPrimes[i]) == 0 ) // __debugbreak(); // } //} //if( testCSecondKind && testCSecondFast == true )//(sieveFlags&SIEVE_FLAG_C2_COMPOSITE)==0 ) //{ // for(uint32 i=0; i<5000; i++) // { // if( mpz_tdiv_ui(mpzOriginPlusOne.get_mpz_t(), vPrimes[i]) == 0 ) // __debugbreak(); // } //} //printf("%d\n", fFermatTest?1:0); // Test for Cunningham Chain of first kind if( testCFirstKind ) { ProbableCunninghamChainTestFast(mpzOriginMinusOne, true, fFermatTest, nChainLengthCunningham1, testParams, testCFirstFast); //if( nChainLengthCunningham1 >= 0x04000000 ) //{ // //__debugbreak(); // mpz_class mpz_r; // mpz_class mpz_n1 = mpzPrimeChainOrigin - 1; // mpz_class mpz_n2 = mpzPrimeChainOrigin*2 - 1; // mpz_class mpz_n3 = mpzPrimeChainOrigin*4 - 1; // mpz_class mpz_n4 = mpzPrimeChainOrigin*8 - 1; // mpz_class mpz_e = mpz_n3 - 1; // mpz_class mpz_m = mpz_n1 * mpz_n2 * mpz_n3 * mpz_n4; // mpz_powm(mpz_r.get_mpz_t(), mpzTwo.get_mpz_t(), mpz_e.get_mpz_t(), mpz_m.get_mpz_t()); // bool isPrime = (mpz_r.get_mpz_t()->_mp_d[0]&0xFF)==0xFF; // printf("%08X isPrime: %s D: %016X\n", nChainLengthCunningham1, isPrime?"yes":"no", mpz_r.get_mpz_t()->_mp_d[0]); // if( isPrime == false ) // __debugbreak(); // //__debugbreak(); //} } else nChainLengthCunningham1 = 0; // Test for Cunningham Chain of second kind if( testCSecondKind ) ProbableCunninghamChainTestFast(mpzOriginPlusOne, false, fFermatTest, nChainLengthCunningham2, testParams, testCSecondFast); else nChainLengthCunningham2 = 0; //// do we need to flag some bits as composite to avoid redundant chain checks? //uint32 redundancyCheckLength = min(nChainLengthCunningham1, nChainLengthCunningham2); //redundancyCheckLength >>= 24; //if( redundancyCheckLength >= 2 ) //{ // printf("."); // uint32 mask = 1<<(multiplier&7); // uint32 maskIdx = multiplier>>3; // for(uint32 r=0; r<redundancyCheckLength; r++) // { // uint8* maskC1 = cSieve->layerMaskC1+((cSieve->currentSieveLayerIdx+r)%cSieve->chainLength)*cSieve->maskBytes; // uint8* maskC2 = cSieve->layerMaskC1+((cSieve->currentSieveLayerIdx+r)%cSieve->chainLength)*cSieve->maskBytes; // maskC1[maskIdx] |= mask; // maskC2[maskIdx] |= mask; // } //} // verify if there is any chance to find a biTwin that worth calculation if (nChainLengthCunningham1 < 0x2000000 || nChainLengthCunningham2 < 0x2000000) return (nChainLengthCunningham1 >= nBits || nChainLengthCunningham2 >= nBits); // Figure out BiTwin Chain length // BiTwin Chain allows a single prime at the end for odd length chain nChainLengthBiTwin = (TargetGetLength(nChainLengthCunningham1) > TargetGetLength(nChainLengthCunningham2))? (nChainLengthCunningham2 + TargetFromInt(TargetGetLength(nChainLengthCunningham2)+1)) : (nChainLengthCunningham1 + TargetFromInt(TargetGetLength(nChainLengthCunningham1))); return (nChainLengthCunningham1 >= nBits || nChainLengthCunningham2 >= nBits || nChainLengthBiTwin >= nBits); }
// 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 }
// Test probable prime chain for: nOrigin // Return value: // true - Probable prime chain found (one of nChainLength meeting target) // false - prime chain too short (none of nChainLength meeting target) static bool ProbablePrimeChainTestFast(const mpz_class& mpzPrimeChainOrigin, CPrimalityTestParams& testParams, uint sievenumber, bool use_gpu_fermat_test) { const unsigned int nBits = testParams.nBits; const unsigned int nBits_masked = nBits&TARGET_LENGTH_MASK; unsigned int& nChainLengthCunningham1 = testParams.nChainLengthCunningham1; unsigned int& nChainLengthCunningham2 = testParams.nChainLengthCunningham2; unsigned int& nChainLengthBiTwin = testParams.nChainLengthBiTwin; const bool fFermatTest = testParams.fFermatTest; mpz_class& mpzOriginMinusOne = testParams.mpzOriginMinusOne; mpz_class& mpzOriginPlusOne = testParams.mpzOriginPlusOne; nChainLengthCunningham1 = 0; nChainLengthCunningham2 = 0; nChainLengthBiTwin = 0; // Test for Cunningham Chain of first kind if (sievenumber&1) { mpzOriginMinusOne = mpzPrimeChainOrigin - 1; ProbableCunninghamChainTestFast(mpzOriginMinusOne, true, fFermatTest, nChainLengthCunningham1, testParams, use_gpu_fermat_test); if ((nChainLengthCunningham1&TARGET_FRACTIONAL_MASK) == 0) nChainLengthCunningham1 |= TARGET_FRACTIONAL_MASK; } // Test for Cunningham Chain of second kind if (sievenumber&2) { mpzOriginPlusOne = mpzPrimeChainOrigin + 1; ProbableCunninghamChainTestFast(mpzOriginPlusOne, false, fFermatTest, nChainLengthCunningham2, testParams, use_gpu_fermat_test); if ((nChainLengthCunningham2&TARGET_FRACTIONAL_MASK) == 0) nChainLengthCunningham2 |= TARGET_FRACTIONAL_MASK; } // Figure out BiTwin Chain length // BiTwin Chain allows a single prime at the end for odd length chain nChainLengthBiTwin = (TargetGetLength(nChainLengthCunningham1) > TargetGetLength(nChainLengthCunningham2))? (nChainLengthCunningham2 + TargetFromInt(TargetGetLength(nChainLengthCunningham2)+1)) : (nChainLengthCunningham1 + TargetFromInt(TargetGetLength(nChainLengthCunningham1))); uint c1 = TargetGetLength(nChainLengthCunningham1); uint c2 = TargetGetLength(nChainLengthCunningham2); uint tw = TargetGetLength(nChainLengthBiTwin); if (c1 >= 6) { cout << "C1 " << nChainLengthCunningham1 << " --> " << TargetToString(nChainLengthCunningham1) << " found!" << endl; } if (c2 >= 6) { cout << "C2 " << nChainLengthCunningham2 << " --> " << TargetToString(nChainLengthCunningham2) << " found!" << endl; } if (tw >= 6) { cout << "TW " << nChainLengthBiTwin << " --> " << TargetToString(nChainLengthBiTwin) << " found!" << endl; } ++chainspersec[c1]; ++chainspersec[c2]; ++chainspersec[tw]; ++totalpersec; return (nChainLengthCunningham1 >= nBits || nChainLengthCunningham2 >= nBits || nChainLengthBiTwin >= nBits); }