/*
 * Used to print out the first 100 multipliers that passed the sieve
 * Useful to compare with other sieve implementations
 */
void cSieve_debug(mpz_class& mpzFixedMultiplier, uint32 chainLength, uint32 primeFactors, uint32 sieveSize)
{
	cSieve_prepare(mpzFixedMultiplier, chainLength, primeFactors, sieveSize);
	
	uint32 rows = 128;
	uint32 pixelsPerRow = cSieve->sieveSize / rows;

	uint8* pixelMap = (uint8*)malloc(cSieve->sieveSize*(cSieve->chainLength*2)*3);
	memset(pixelMap, 0x00, cSieve->sieveSize*cSieve->chainLength*2*3);
	uint32 pixelPerRow = cSieve->sieveSize;
	for(sint32 y=0; y<cSieve->chainLength; y++)
	{
		for(sint32 x=0; x<cSieve->sieveSize; x++)
		{
			uint32 rowY = y*cSieve->chainLength*2 + x / pixelsPerRow;
			uint32 maskBase = cSieve->maskBytes*rowY;
			uint32 maskIdx = x>>3;
			uint32 maskVal = 1<<(x&7);
			uint32 mC1 = cSieve->layerMaskC1[maskBase+maskIdx] & maskVal;
			uint32 mC2 = cSieve->layerMaskC2[maskBase+maskIdx] & maskVal;
			uint32 pIdx = (x+y*pixelsPerRow)*3;
			pixelMap[pIdx+0] = 0;
			pixelMap[pIdx+1] = 0;
			pixelMap[pIdx+2] = 0;
			if( mC1 == 0 )
				pixelMap[pIdx+2] = 0xFF;
			if( mC2 == 0 )
				pixelMap[pIdx+0] = 0xFF;
		}
	}	
	bitmap_t bmp;
	bmp.bitDepth = 24;
	bmp.data = pixelMap;
	bmp.sizeX = pixelsPerRow;
	bmp.sizeY = cSieve->chainLength*rows;
	printf("cSieve_debug(): Saving sieve debug image...\n");
	bmp_save("C:\\test\\sieve.bmp", &bmp);

	uint32 multiplier = 0;
	for(uint32 i=0; i<100; i++)
	{
		uint32 sieveFlags = 0;
		multiplier = cSieve_findNextMultiplier(&sieveFlags);
		if( multiplier == 0 )
			break;
		printf("cSieve mult[%04d]: %d\n", i, multiplier);
	}
}
示例#2
0
bool BitcoinMiner2_mineProbableChain(primecoinBlock_t* block, mpz_class& mpzFixedMultiplier, bool& fNewBlock, unsigned int& nTriedMultiplier, unsigned int& nProbableChainLength, 
										 unsigned int& nTests, unsigned int& nPrimesHit, sint32 threadIndex, mpz_class& mpzHash, unsigned int nPrimorialMultiplier)
{
	mpz_class mpzChainOrigin;
	mpz_class mpzFinalFixedMultiplier = mpzFixedMultiplier * mpzHash;
	mpz_class mpzTemp;
	uint32 nTime = GetTickCount();
	cSieve_prepare(mpzFinalFixedMultiplier, block->nBits>>24);
	nTime = GetTickCount()-nTime;
	//printf("cSieve prep time: %d\n", nTime);

	unsigned int nPrimorialSeq = 0;
	while (vPrimes[nPrimorialSeq + 1] <= nPrimorialMultiplier)
		nPrimorialSeq++;
	// Allocate GMP variables for primality tests
	CPrimalityTestParams testParams(block->nBits, nPrimorialSeq);
	{
		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();
	}
	// References to counters;
	unsigned int& nChainLengthCunningham1 = testParams.nChainLengthCunningham1;
	unsigned int& nChainLengthCunningham2 = testParams.nChainLengthCunningham2;
	unsigned int& nChainLengthBiTwin = testParams.nChainLengthBiTwin;

	uint32 debugStats_primes = 0;
	uint32 debugStats_multipliersTested = 0;
	
	while( block->serverData.blockHeight == jhMiner_getCurrentWorkBlockHeight(block->threadIndex) )
	{
		uint32 sieveFlags;
		uint32 multiplier = cSieve_findNextMultiplier(&sieveFlags);
		if( multiplier == 0 )
		{
			// mix in next layer
			//printf("Layer finished [%d]\n", cSieve->currentSieveLayerIdx);
			if( cSieve_sieveNextLayer() == false )
				break;
			mpzFinalFixedMultiplier = cSieve->mpzFixedMultiplier;
			//printf("[%02d] debugStats_multipliersTested: %d\n", cSieve->currentSieveLayerIdx, debugStats_multipliersTested);
			//printf("[%02d] debugStats_primes: %d\n", cSieve->currentSieveLayerIdx, debugStats_primes);
			//double primality = (double)debugStats_primes / (double)debugStats_multipliersTested;
			//printf("[%02d] debugStats_primality: %lf\n", cSieve->currentSieveLayerIdx, primality);
			debugStats_primes = 0;
			debugStats_multipliersTested = 0;
			continue;
		}
		 
		//// test for sieve bugs C1
		//if( (sieveFlags&SIEVE_FLAG_C1_COMPOSITE)==0 && (rand()%10)==0 )
		//{
		//	// test c1
		//	for(uint32 lt=0; lt<cSieve->chainLength; lt++)
		//	{
		//		uint32 aMult = 1<<lt;
		//		mpzChainOrigin = mpzFinalFixedMultiplier * multiplier * aMult - 1;	
		//		for(uint32 f=0; f<cSieve->numPrimeFactors; f++)
		//		{
		//			uint32 mod = mpz_mod_ui(mpzTemp.get_mpz_t(), mpzChainOrigin.get_mpz_t(), vPrimes[f]);
		//			if( mod == 0 )
		//				printf("c1 div by %d possible\n", vPrimes[f]);//__debugbreak();
		//		}
		//	}
		//}
		//// test for sieve bugs C2
		//if( (sieveFlags&SIEVE_FLAG_C2_COMPOSITE)==0 && (rand()%10)==0 )
		//{
		//	// test c1
		//	for(uint32 lt=0; lt<cSieve->chainLength; lt++)
		//	{
		//		uint32 aMult = 1<<lt;
		//		mpzChainOrigin = mpzFinalFixedMultiplier * multiplier * aMult + 1;	
		//		for(uint32 f=0; f<cSieve->numPrimeFactors; f++)
		//		{
		//			uint32 mod = mpz_mod_ui(mpzTemp.get_mpz_t(), mpzChainOrigin.get_mpz_t(), vPrimes[f]);
		//			if( mod == 0 )
		//				printf("c2 div by %d possible\n", vPrimes[f]);//__debugbreak();
		//		}
		//	}
		//}
		// test for sieve bugs BT
		//if( (sieveFlags&SIEVE_FLAG_BT_COMPOSITE)==0 )
		//{
		//	// test c1
		//	mpzChainOrigin = mpzFinalFixedMultiplier * multiplier + 1;	
		//	for(uint32 f=0; f<cSieve->numPrimeFactors; f++)
		//	{
		//		uint32 mod = mpz_mod_ui(mpzTemp.get_mpz_t(), mpzChainOrigin.get_mpz_t(), vPrimes[f]);
		//		if( mod == 0 )
		//			printf("bt-c2 div by %d possible\n", vPrimes[f]);
		//	}
		//	// test c2
		//	mpzChainOrigin = mpzFinalFixedMultiplier * multiplier - 1;	
		//	for(uint32 f=0; f<cSieve->numPrimeFactors; f++)
		//	{
		//		uint32 mod = mpz_mod_ui(mpzTemp.get_mpz_t(), mpzChainOrigin.get_mpz_t(), vPrimes[f]);
		//		if( mod == 0 )
		//			printf("bt-c2 div by %d possible\n", vPrimes[f]);
		//	}
		//}

		//mpzChainOrigin = mpzFinalFixedMultiplier * multiplier;		
		mpz_mul_ui(mpzChainOrigin.get_mpz_t(), mpzFinalFixedMultiplier.get_mpz_t(), multiplier);
		nChainLengthCunningham1 = 0;
		nChainLengthCunningham2 = 0;
		nChainLengthBiTwin = 0;

		bool canSubmitAsShare = ProbablePrimeChainTestFast2(mpzChainOrigin, testParams, sieveFlags, multiplier);
		nProbableChainLength = max(max(nChainLengthCunningham1, nChainLengthCunningham2), nChainLengthBiTwin);

		if( nProbableChainLength >= 0x01000000 )
			debugStats_primes++;
		debugStats_multipliersTested++;
		//bool canSubmitAsShare = ProbablePrimeChainTestFast(mpzChainOrigin, testParams);
		//CBigNum bnChainOrigin;
		//bnChainOrigin.SetHex(mpzChainOrigin.get_str(16));
		//bool canSubmitAsShare = ProbablePrimeChainTestBN(bnChainOrigin, block->serverData.nBitsForShare, false, nChainLengthCunningham1, nChainLengthCunningham2, nChainLengthBiTwin);
		


		if( nProbableChainLength >= 0x04000000 )
		{
			sint32 chainDif = (nProbableChainLength>>24) - 7;
			primeStats.nChainHit += pow(8, (float)chainDif);
			//primeStats.nChainHit += pow(8, ((float)((double)nProbableChainLength  / (double)0x1000000))-7.0);
			//primeStats.nChainHit += pow(8, floor((float)((double)nProbableChainLength  / (double)0x1000000)) - 7);
			nTests = 0;
			primeStats.fourChainCount ++;
			if (nProbableChainLength >= 0x5000000)
			{
				primeStats.fiveChainCount ++;
				if (nProbableChainLength >= 0x6000000)
				{
					primeStats.sixChainCount ++;
					if (nProbableChainLength >= 0x7000000)
						primeStats.sevenChainCount ++;
				}
			}
		}
		//if( nBitsGen >= 0x03000000 )
		//	printf("%08X\n", nBitsGen);
		primeStats.primeChainsFound++;
		//if( nProbableChainLength > 0x03000000 )
		//	primeStats.qualityPrimesFound++;
		if( nProbableChainLength > primeStats.bestPrimeChainDifficulty )
			primeStats.bestPrimeChainDifficulty = nProbableChainLength;
		
		if(nProbableChainLength >= block->serverData.nBitsForShare)
		{
			// note: mpzPrimeChainMultiplier does not include the blockHash multiplier
			mpz_div(block->mpzPrimeChainMultiplier.get_mpz_t(), mpzChainOrigin.get_mpz_t(), mpzHash.get_mpz_t());
			//mpz_lsh(block->mpzPrimeChainMultiplier.get_mpz_t(), mpzFixedMultiplier.get_mpz_t(), multiplier);
			// update server data
			block->serverData.client_shareBits = nProbableChainLength;
			// generate block raw data
			uint8 blockRawData[256] = {0};
			memcpy(blockRawData, block, 80);
			uint32 writeIndex = 80;
			sint32 lengthBN = 0;
			CBigNum bnPrimeChainMultiplier;
			bnPrimeChainMultiplier.SetHex(block->mpzPrimeChainMultiplier.get_str(16));
			std::vector<unsigned char> bnSerializeData = bnPrimeChainMultiplier.getvch();
			lengthBN = bnSerializeData.size();
			*(uint8*)(blockRawData+writeIndex) = (uint8)lengthBN; // varInt (we assume it always has a size low enough for 1 byte)
			writeIndex += 1;
			memcpy(blockRawData+writeIndex, &bnSerializeData[0], lengthBN);
			writeIndex += lengthBN;	
			// switch endianness
			for(uint32 f=0; f<256/4; f++)
			{
				*(uint32*)(blockRawData+f*4) = _swapEndianessU32(*(uint32*)(blockRawData+f*4));
			}
			time_t now = time(0);
			struct tm * timeinfo;
			timeinfo = localtime (&now);
			char sNow [80];
			strftime (sNow, 80, "%x - %X",timeinfo);

			printf("%s - SHARE FOUND !!! (Th#: %u Multiplier: %d Layer: %d) ---  DIFF: %f    %s    %s\n", 
				sNow, threadIndex, multiplier, cSieve->currentSieveLayerIdx, (float)((double)nProbableChainLength  / (double)0x1000000), 
				nProbableChainLength >= 0x6000000 ? ">6":"", nProbableChainLength >= 0x7000000 ? ">7":"");

			// submit this share
			if (jhMiner_pushShare_primecoin(blockRawData, block))
				primeStats.foundShareCount ++;
			//printf("Probable prime chain found for block=%s!!\n  Target: %s\n  Length: (%s %s %s)\n", block.GetHash().GetHex().c_str(),TargetToString(block.nBits).c_str(), TargetToString(nChainLengthCunningham1).c_str(), TargetToString(nChainLengthCunningham2).c_str(), TargetToString(nChainLengthBiTwin).c_str());
			//nProbableChainLength = max(max(nChainLengthCunningham1, nChainLengthCunningham2), nChainLengthBiTwin);
			// since we are using C structs here we have to make sure the memory for the CBigNum in the block is freed again
			//delete *psieve;
			//*psieve = NULL;
			//block->bnPrimeChainMultiplier = NULL;
			RtlZeroMemory(blockRawData, 256);
			//delete *psieve;
			//*psieve = NULL;
			// dont quit if we find a share, there could be other shares in the remaining prime candidates
			nTests = 0;   // tehere is a good chance to find more shares so search a litle more.
			//block->nonce++;
			//return true;
			//break;
			//if (multipleShare)
		}
	}