Luke Dashjr 12 years ago
parent
commit
47898cd2b4
7 changed files with 237 additions and 45 deletions
  1. 8 0
      driver-cpu.c
  2. 1 0
      driver-cpu.h
  3. 1 1
      libblkmaker
  4. 14 5
      miner.c
  5. 3 0
      miner.h
  6. 208 39
      prime.c
  7. 2 0
      util.h

+ 8 - 0
driver-cpu.c

@@ -132,6 +132,8 @@ extern bool scanhash_sse2_32(struct thr_info*, const unsigned char *pmidstate, u
 	uint32_t max_nonce, uint32_t *last_nonce,
 	uint32_t max_nonce, uint32_t *last_nonce,
 	uint32_t nonce);
 	uint32_t nonce);
 
 
+extern bool scanhash_prime(struct thr_info *, const unsigned char *pmidstate, unsigned char *pdata, unsigned char *phash1, unsigned char *phash, const unsigned char *ptarget, uint32_t max_nonce, uint32_t *last_nonce, uint32_t nonce);
+
 extern bool scanhash_scrypt(struct thr_info *thr, int thr_id, unsigned char *pdata, unsigned char *scratchbuf,
 extern bool scanhash_scrypt(struct thr_info *thr, int thr_id, unsigned char *pdata, unsigned char *scratchbuf,
 	const unsigned char *ptarget,
 	const unsigned char *ptarget,
 	uint32_t max_nonce, unsigned long *hashes_done);
 	uint32_t max_nonce, unsigned long *hashes_done);
@@ -165,6 +167,9 @@ const char *algo_names[] = {
 #ifdef WANT_ALTIVEC_4WAY
 #ifdef WANT_ALTIVEC_4WAY
     [ALGO_ALTIVEC_4WAY] = "altivec_4way",
     [ALGO_ALTIVEC_4WAY] = "altivec_4way",
 #endif
 #endif
+#ifdef WANT_PRIMEPOW
+	[ALGO_PRIME] = "prime",
+#endif
 #ifdef WANT_SCRYPT
 #ifdef WANT_SCRYPT
     [ALGO_SCRYPT] = "scrypt",
     [ALGO_SCRYPT] = "scrypt",
 #endif
 #endif
@@ -196,6 +201,9 @@ static const sha256_func sha256_funcs[] = {
 #ifdef WANT_X8664_SSE4
 #ifdef WANT_X8664_SSE4
 	[ALGO_SSE4_64]		= (sha256_func)scanhash_sse4_64,
 	[ALGO_SSE4_64]		= (sha256_func)scanhash_sse4_64,
 #endif
 #endif
+#ifdef WANT_PRIMEPOW
+	[ALGO_PRIME]		= (sha256_func)scanhash_prime,
+#endif
 #ifdef WANT_SCRYPT
 #ifdef WANT_SCRYPT
 	[ALGO_SCRYPT]		= (sha256_func)scanhash_scrypt
 	[ALGO_SCRYPT]		= (sha256_func)scanhash_scrypt
 #endif
 #endif

+ 1 - 0
driver-cpu.h

@@ -60,6 +60,7 @@ enum sha256_algos {
 	ALGO_SSE2_64,		/* SSE2 for x86_64 */
 	ALGO_SSE2_64,		/* SSE2 for x86_64 */
 	ALGO_SSE4_64,		/* SSE4 for x86_64 */
 	ALGO_SSE4_64,		/* SSE4 for x86_64 */
 	ALGO_ALTIVEC_4WAY,	/* parallel Altivec */
 	ALGO_ALTIVEC_4WAY,	/* parallel Altivec */
+	ALGO_PRIME,
 	ALGO_SCRYPT,		/* scrypt */
 	ALGO_SCRYPT,		/* scrypt */
 	
 	
 	ALGO_FASTAUTO,		/* fast autodetect */
 	ALGO_FASTAUTO,		/* fast autodetect */

+ 1 - 1
libblkmaker

@@ -1 +1 @@
-Subproject commit 8f4bb3ee9f43405203fef6f64ca938dc7933a060
+Subproject commit a991c6917d6ab065c847c2547eb2ccb1d746143f

+ 14 - 5
miner.c

@@ -2359,8 +2359,9 @@ hashrate_pick_unit(float hashrate, unsigned char*unit)
 	while (hashrate >= 1000)
 	while (hashrate >= 1000)
 	{
 	{
 		hashrate /= 1e3;
 		hashrate /= 1e3;
-		if (likely(_unitchar[*unit] != '?'))
-			++*unit;
+		if (unlikely(_unitchar[*unit] == '?'))
+			break;
+		++*unit;
 	}
 	}
 }
 }
 
 
@@ -3120,8 +3121,13 @@ static char *submit_upstream_work_request(struct work *work)
 			req = blkmk_submit_foreign_jansson(work->tmpl, data, work->dataid, le32toh(*((uint32_t*)&work->data[76])));
 			req = blkmk_submit_foreign_jansson(work->tmpl, data, work->dataid, le32toh(*((uint32_t*)&work->data[76])));
 		else
 		else
 #endif
 #endif
-			req = blkmk_submit_jansson(work->tmpl, data, work->dataid, le32toh(*((uint32_t*)&work->data[76])));
+			req = blkmk_submit_jansson(work->tmpl, data, work->dataid, le32toh(*((uint32_t*)&work->data[76])), work->sig, work->sigsz);
 		s = json_dumps(req, 0);
 		s = json_dumps(req, 0);
+		{
+			char hex[1 + (work->sigsz * 2)];
+			bin2hex(hex, work->sig, work->sigsz);
+			applog(LOG_DEBUG, "SIGSUBMIT: %s\n", hex);
+		}
 		json_decref(req);
 		json_decref(req);
 		sd = malloc(161);
 		sd = malloc(161);
 		bin2hex(sd, data, 80);
 		bin2hex(sd, data, 80);
@@ -7427,7 +7433,7 @@ bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce)
 	/* Side effect: sets work->data for us */
 	/* Side effect: sets work->data for us */
 	res = test_nonce2(work, nonce);
 	res = test_nonce2(work, nonce);
 	
 	
-	if (unlikely(res == TNR_BAD))
+	if (0&&unlikely(res == TNR_BAD))
 		{
 		{
 			inc_hw_errors(thr, work, nonce);
 			inc_hw_errors(thr, work, nonce);
 			ret = false;
 			ret = false;
@@ -9032,7 +9038,7 @@ static void raise_fd_limits(void)
 
 
 extern void bfg_init_threadlocal();
 extern void bfg_init_threadlocal();
 
 
-int xmain(int argc, char *argv[])
+int main(int argc, char *argv[])
 {
 {
 	struct sigaction handler;
 	struct sigaction handler;
 	struct thr_info *thr;
 	struct thr_info *thr;
@@ -9221,6 +9227,9 @@ int xmain(int argc, char *argv[])
 		opt_log_output = true;
 		opt_log_output = true;
 
 
 #ifdef WANT_CPUMINE
 #ifdef WANT_CPUMINE
+#ifdef WANT_PRIMEPOW
+	GeneratePrimeTable();
+#endif
 #ifdef USE_SCRYPT
 #ifdef USE_SCRYPT
 	if (opt_scrypt)
 	if (opt_scrypt)
 		set_scrypt_algo(&opt_algo);
 		set_scrypt_algo(&opt_algo);

+ 3 - 0
miner.h

@@ -1193,6 +1193,9 @@ struct work {
 	unsigned char	midstate[32];
 	unsigned char	midstate[32];
 	unsigned char	target[32];
 	unsigned char	target[32];
 	unsigned char	hash[32];
 	unsigned char	hash[32];
+	
+	uint8_t *sig;
+	size_t sigsz;
 
 
 	uint64_t	share_diff;
 	uint64_t	share_diff;
 
 

+ 208 - 39
prime.c

@@ -12,13 +12,15 @@
 #include "miner.h"
 #include "miner.h"
 
 
 #define nMaxSieveSize 1000000u
 #define nMaxSieveSize 1000000u
-#define nPrimeTableLimit 100000u //nMaxSieveSize
+#define nPrimeTableLimit nMaxSieveSize
+#define nPrimorialTableLimit 100000u
 
 
-#define PRIME_COUNT 9592 //78498
+#define PRIME_COUNT 78498
+#define PRIMORIAL_COUNT 9592
 
 
 static
 static
 unsigned vPrimes[PRIME_COUNT];
 unsigned vPrimes[PRIME_COUNT];
-mpz_t vPrimorials[PRIME_COUNT];
+mpz_t vPrimorials[PRIMORIAL_COUNT];
 
 
 static
 static
 int64_t GetTimeMicros()
 int64_t GetTimeMicros()
@@ -41,7 +43,6 @@ bool error(const char *fmt, ...)
 	return false;
 	return false;
 }
 }
 
 
-static
 void GeneratePrimeTable()
 void GeneratePrimeTable()
 {
 {
 	mpz_t bnOne;
 	mpz_t bnOne;
@@ -62,12 +63,16 @@ void GeneratePrimeTable()
 		if (!vfComposite[n])
 		if (!vfComposite[n])
 		{
 		{
 			vPrimes[i] = n;
 			vPrimes[i] = n;
-			mpz_init(vPrimorials[i]);
-			mpz_mul_ui(vPrimorials[i], *bnLastPrimorial, n);
-			bnLastPrimorial = &vPrimorials[i];
+			if (n < nPrimorialTableLimit)
+			{
+				mpz_init(vPrimorials[i]);
+				mpz_mul_ui(vPrimorials[i], *bnLastPrimorial, n);
+				bnLastPrimorial = &vPrimorials[i];
+			}
 			++i;
 			++i;
 		}
 		}
-	printf("GeneratePrimeTable() : prime table [1, %d] generated with %lu primes\n", nPrimeTableLimit, (unsigned long)i);
+	mpz_clear(bnOne);
+	applog(LOG_DEBUG, "GeneratePrimeTable() : prime table [1, %d] generated with %lu primes", nPrimeTableLimit, (unsigned long)i);
 }
 }
 
 
 #define nFractionalBits 24
 #define nFractionalBits 24
@@ -87,8 +92,13 @@ bool FermatProbablePrimalityTest(mpz_t *n, unsigned int *pnLength)
 	mpz_init(r);
 	mpz_init(r);
 	
 	
 	mpz_powm(r, a, e, *n);
 	mpz_powm(r, a, e, *n);
+	mpz_clear(a);
+	mpz_clear(e);
 	if (!mpz_cmp_ui(r, 1))
 	if (!mpz_cmp_ui(r, 1))
+	{
+		mpz_clear(r);
 		return true;
 		return true;
+	}
 	
 	
 	// Failed Fermat test, calculate fractional length
 	// Failed Fermat test, calculate fractional length
 	// nFractionalLength = ( (n-r) << nFractionalBits ) / n
 	// nFractionalLength = ( (n-r) << nFractionalBits ) / n
@@ -96,6 +106,7 @@ bool FermatProbablePrimalityTest(mpz_t *n, unsigned int *pnLength)
 	mpz_mul_2exp(r, r, nFractionalBits);
 	mpz_mul_2exp(r, r, nFractionalBits);
 	mpz_fdiv_q(r, r, *n);
 	mpz_fdiv_q(r, r, *n);
 	unsigned int nFractionalLength = mpz_get_ui(r);
 	unsigned int nFractionalLength = mpz_get_ui(r);
+	mpz_clear(r);
 	
 	
 	if (nFractionalLength >= (1 << nFractionalBits))
 	if (nFractionalLength >= (1 << nFractionalBits))
 		return error("FermatProbablePrimalityTest() : fractional assert");
 		return error("FermatProbablePrimalityTest() : fractional assert");
@@ -133,6 +144,8 @@ bool EulerLagrangeLifchitzPrimalityTest(mpz_t *n, bool fSophieGermain, unsigned
 	mpz_init(r);
 	mpz_init(r);
 	
 	
 	mpz_powm(r, a, e, *n);
 	mpz_powm(r, a, e, *n);
+	mpz_clear(a);
+	mpz_clear(e);
 	unsigned nMod8 = mpz_fdiv_ui(*n, 8);
 	unsigned nMod8 = mpz_fdiv_ui(*n, 8);
 	bool fPassedTest = false;
 	bool fPassedTest = false;
 	if (fSophieGermain && (nMod8 == 7)) // Euler & Lagrange
 	if (fSophieGermain && (nMod8 == 7)) // Euler & Lagrange
@@ -148,10 +161,16 @@ bool EulerLagrangeLifchitzPrimalityTest(mpz_t *n, bool fSophieGermain, unsigned
 	else if ((!fSophieGermain) && (nMod8 == 1)) // LifChitz
 	else if ((!fSophieGermain) && (nMod8 == 1)) // LifChitz
 		fPassedTest = !mpz_cmp_ui(r, 1);
 		fPassedTest = !mpz_cmp_ui(r, 1);
 	else
 	else
+	{
+		mpz_clear(r);
 		return error("EulerLagrangeLifchitzPrimalityTest() : invalid n %% 8 = %d, %s", nMod8, (fSophieGermain? "first kind" : "second kind"));
 		return error("EulerLagrangeLifchitzPrimalityTest() : invalid n %% 8 = %d, %s", nMod8, (fSophieGermain? "first kind" : "second kind"));
+	}
 
 
 	if (fPassedTest)
 	if (fPassedTest)
+	{
+		mpz_clear(r);
 		return true;
 		return true;
+	}
 	// Failed test, calculate fractional length
 	// Failed test, calculate fractional length
 	
 	
 	// derive Fermat test remainder
 	// derive Fermat test remainder
@@ -163,6 +182,7 @@ bool EulerLagrangeLifchitzPrimalityTest(mpz_t *n, bool fSophieGermain, unsigned
 	mpz_mul_2exp(r, r, nFractionalBits);
 	mpz_mul_2exp(r, r, nFractionalBits);
 	mpz_fdiv_q(r, r, *n);
 	mpz_fdiv_q(r, r, *n);
 	unsigned int nFractionalLength = mpz_get_ui(r);
 	unsigned int nFractionalLength = mpz_get_ui(r);
+	mpz_clear(r);
 	
 	
 	if (nFractionalLength >= (1 << nFractionalBits))
 	if (nFractionalLength >= (1 << nFractionalBits))
 		return error("EulerLagrangeLifchitzPrimalityTest() : fractional assert");
 		return error("EulerLagrangeLifchitzPrimalityTest() : fractional assert");
@@ -180,20 +200,37 @@ bool EulerLagrangeLifchitzPrimalityTest(mpz_t *n, bool fSophieGermain, unsigned
 static
 static
 bool ProbableCunninghamChainTest(mpz_t *n, bool fSophieGermain, bool fFermatTest, unsigned int *pnProbableChainLength)
 bool ProbableCunninghamChainTest(mpz_t *n, bool fSophieGermain, bool fFermatTest, unsigned int *pnProbableChainLength)
 {
 {
+#ifdef SUPERDEBUG
+	printf("ProbableCunninghamChainTest(");
+	mpz_out_str(stdout, 0x10, *n);
+	printf(", %d, %d, %u)\n", (int)fSophieGermain, (int)fFermatTest, *pnProbableChainLength);
+#endif
+	
 	*pnProbableChainLength = 0;
 	*pnProbableChainLength = 0;
 	mpz_t N;
 	mpz_t N;
 	mpz_init_set(N, *n);
 	mpz_init_set(N, *n);
 	
 	
 	// Fermat test for n first
 	// Fermat test for n first
 	if (!FermatProbablePrimalityTest(&N, pnProbableChainLength))
 	if (!FermatProbablePrimalityTest(&N, pnProbableChainLength))
+	{
+		mpz_clear(N);
 		return false;
 		return false;
+	}
+#ifdef SUPERDEBUG
+	printf("N=");
+	mpz_out_str(stdout, 0x10, N);
+	printf("\n");
+#endif
 
 
 	// Euler-Lagrange-Lifchitz test for the following numbers in chain
 	// Euler-Lagrange-Lifchitz test for the following numbers in chain
 	while (true)
 	while (true)
 	{
 	{
 		TargetIncrementLength(pnProbableChainLength);
 		TargetIncrementLength(pnProbableChainLength);
 		mpz_add(N, N, N);
 		mpz_add(N, N, N);
-		mpz_add_ui(N, N, (fSophieGermain? 1 : (-1)));
+		if (fSophieGermain)
+			mpz_add_ui(N, N, 1);
+		else
+			mpz_sub_ui(N, N, 1);
 		if (fFermatTest)
 		if (fFermatTest)
 		{
 		{
 			if (!FermatProbablePrimalityTest(&N, pnProbableChainLength))
 			if (!FermatProbablePrimalityTest(&N, pnProbableChainLength))
@@ -201,11 +238,23 @@ bool ProbableCunninghamChainTest(mpz_t *n, bool fSophieGermain, bool fFermatTest
 		}
 		}
 		else
 		else
 		{
 		{
+#ifdef SUPERDEBUG
+			if (!fSophieGermain)
+			{
+				printf("EulerLagrangeLifchitzPrimalityTest(");
+				mpz_out_str(stdout, 0x10, N);
+				printf(", 1, %d)\n", *pnProbableChainLength);
+			}
+#endif
 			if (!EulerLagrangeLifchitzPrimalityTest(&N, fSophieGermain, pnProbableChainLength))
 			if (!EulerLagrangeLifchitzPrimalityTest(&N, fSophieGermain, pnProbableChainLength))
 				break;
 				break;
 		}
 		}
 	}
 	}
+	mpz_clear(N);
 
 
+#ifdef SUPERDEBUG
+	printf("PCCT => %u (%u)\n", TargetGetLength(*pnProbableChainLength), *pnProbableChainLength);
+#endif
 	return (TargetGetLength(*pnProbableChainLength) >= 2);
 	return (TargetGetLength(*pnProbableChainLength) >= 2);
 }
 }
 
 
@@ -235,6 +284,7 @@ bool ProbablePrimeChainTest(mpz_t *bnPrimeChainOrigin, unsigned int nBits, bool
 	// Test for Cunningham Chain of second kind
 	// Test for Cunningham Chain of second kind
 	mpz_add_ui(mp, *bnPrimeChainOrigin, 1);
 	mpz_add_ui(mp, *bnPrimeChainOrigin, 1);
 	ProbableCunninghamChainTest(&mp, false, fFermatTest, pnChainLengthCunningham2);
 	ProbableCunninghamChainTest(&mp, false, fFermatTest, pnChainLengthCunningham2);
+	mpz_clear(mp);
 	// Figure out BiTwin Chain length
 	// Figure out BiTwin Chain length
 	// BiTwin Chain allows a single prime at the end for odd length chain
 	// 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)));
 	*pnChainLengthBiTwin = (TargetGetLength(*pnChainLengthCunningham1) > TargetGetLength(*pnChainLengthCunningham2)) ? (*pnChainLengthCunningham2 + TargetFromInt(TargetGetLength(*pnChainLengthCunningham2)+1)) : (*pnChainLengthCunningham1 + TargetFromInt(TargetGetLength(*pnChainLengthCunningham1)));
@@ -262,13 +312,15 @@ struct SieveOfEratosthenes {
 static
 static
 void psieve_reset(struct SieveOfEratosthenes *psieve)
 void psieve_reset(struct SieveOfEratosthenes *psieve)
 {
 {
-	// FIXME: if valid, free stuff?
+	mpz_clear(psieve->hashBlockHeader);
+	mpz_clear(psieve->bnFixedFactor);
 	psieve->valid = false;
 	psieve->valid = false;
 }
 }
 
 
 static
 static
 void psieve_init(struct SieveOfEratosthenes *psieve, unsigned nSieveSize, unsigned nBits, mpz_t *hashBlockHeader, mpz_t *bnFixedMultiplier)
 void psieve_init(struct SieveOfEratosthenes *psieve, unsigned nSieveSize, unsigned nBits, mpz_t *hashBlockHeader, mpz_t *bnFixedMultiplier)
 {
 {
+	assert(!psieve->valid);
 	*psieve = (struct SieveOfEratosthenes){
 	*psieve = (struct SieveOfEratosthenes){
 		.valid = true,
 		.valid = true,
 		.nSieveSize = nSieveSize,
 		.nSieveSize = nSieveSize,
@@ -301,12 +353,24 @@ bool psieve_Weave(struct SieveOfEratosthenes *psieve)
 	mpz_init(bnFixedInverse);
 	mpz_init(bnFixedInverse);
 	mpz_init_set_ui(p, nPrime);
 	mpz_init_set_ui(p, nPrime);
 	if (!mpz_invert(bnFixedInverse, psieve->bnFixedFactor, p))
 	if (!mpz_invert(bnFixedInverse, psieve->bnFixedFactor, p))
+	{
+		mpz_clear(p);
+		mpz_clear(bnFixedInverse);
 		return error("CSieveOfEratosthenes::Weave(): BN_mod_inverse of fixed factor failed for prime #%u=%u", psieve->nPrimeSeq, nPrime);
 		return error("CSieveOfEratosthenes::Weave(): BN_mod_inverse of fixed factor failed for prime #%u=%u", psieve->nPrimeSeq, nPrime);
+	}
 	mpz_t bnTwo, bnTwoInverse;
 	mpz_t bnTwo, bnTwoInverse;
 	mpz_init_set_ui(bnTwo, 2);
 	mpz_init_set_ui(bnTwo, 2);
 	mpz_init(bnTwoInverse);
 	mpz_init(bnTwoInverse);
 	if (!mpz_invert(bnTwoInverse, bnTwo, p))
 	if (!mpz_invert(bnTwoInverse, bnTwo, p))
+	{
+		mpz_clear(bnTwoInverse);
+		mpz_clear(bnTwo);
+		mpz_clear(p);
+		mpz_clear(bnFixedInverse);
 		return error("CSieveOfEratosthenes::Weave(): BN_mod_inverse of 2 failed for prime #%u=%u", psieve->nPrimeSeq, nPrime);
 		return error("CSieveOfEratosthenes::Weave(): BN_mod_inverse of 2 failed for prime #%u=%u", psieve->nPrimeSeq, nPrime);
+	}
+	mpz_clear(bnTwo);
+	mpz_clear(p);
 
 
 	mpz_t mp;
 	mpz_t mp;
 	mpz_init(mp);
 	mpz_init(mp);
@@ -333,6 +397,9 @@ bool psieve_Weave(struct SieveOfEratosthenes *psieve)
 			for (unsigned int nVariableMultiplier = nSolvedMultiplier; nVariableMultiplier < psieve->nSieveSize; nVariableMultiplier += nPrime)
 			for (unsigned int nVariableMultiplier = nSolvedMultiplier; nVariableMultiplier < psieve->nSieveSize; nVariableMultiplier += nPrime)
 				psieve->vfCompositeCunningham2[nVariableMultiplier] = true;
 				psieve->vfCompositeCunningham2[nVariableMultiplier] = true;
 	}
 	}
+	mpz_clear(mp);
+	mpz_clear(bnTwoInverse);
+	mpz_clear(bnFixedInverse);
 	++psieve->nPrimeSeq;
 	++psieve->nPrimeSeq;
 	return true;
 	return true;
 }
 }
@@ -358,8 +425,21 @@ bool psieve_GetNextCandidateMultiplier(struct SieveOfEratosthenes *psieve, unsig
 	}
 	}
 }
 }
 
 
+// Get total number of candidates for power test
+static
+unsigned int psieve_GetCandidateCount(struct SieveOfEratosthenes *psieve)
+{
+	unsigned int nCandidates = 0;
+	for (unsigned int nMultiplier = 0; nMultiplier < psieve->nSieveSize; nMultiplier++)
+	{
+		if (!psieve->vfCompositeCunningham1[nMultiplier] || !psieve->vfCompositeCunningham2[nMultiplier] || !psieve->vfCompositeBiTwin[nMultiplier])
+		nCandidates++;
+	}
+	return nCandidates;
+}
+
 // Mine probable prime chain of form: n = h * p# +/- 1
 // Mine probable prime chain of form: n = h * p# +/- 1
-bool MineProbablePrimeChain(struct SieveOfEratosthenes *psieve, const uint8_t *header, mpz_t *hash, mpz_t *bnFixedMultiplier, bool *pfNewBlock, unsigned *pnTriedMultiplier, unsigned *pnProbableChainLength, unsigned *pnTests, unsigned *pnPrimesHit)
+bool MineProbablePrimeChain(struct SieveOfEratosthenes *psieve, const uint8_t *header, mpz_t *hash, mpz_t *bnFixedMultiplier, bool *pfNewBlock, unsigned *pnTriedMultiplier, unsigned *pnProbableChainLength, unsigned *pnTests, unsigned *pnPrimesHit, struct work *work)
 {
 {
 	const uint32_t *pnbits = (void*)&header[72];
 	const uint32_t *pnbits = (void*)&header[72];
 	*pnProbableChainLength = 0;
 	*pnProbableChainLength = 0;
@@ -378,9 +458,16 @@ bool MineProbablePrimeChain(struct SieveOfEratosthenes *psieve, const uint8_t *h
 	{
 	{
 		// Build sieve
 		// Build sieve
 		nStart = GetTimeMicros();
 		nStart = GetTimeMicros();
+#ifdef SUPERDEBUG
+		fprintf(stderr, "psieve_init(?, %u, %08x, ", nMaxSieveSize, *pnbits);
+		mpz_out_str(stderr, 0x10, *hash);
+		fprintf(stderr, ", ");
+		mpz_out_str(stderr, 0x10, *bnFixedMultiplier);
+		fprintf(stderr, ")\n");
+#endif
 		psieve_init(psieve, nMaxSieveSize, *pnbits, hash, bnFixedMultiplier);
 		psieve_init(psieve, nMaxSieveSize, *pnbits, hash, bnFixedMultiplier);
 		while (psieve_Weave(psieve));
 		while (psieve_Weave(psieve));
-// 		printf("MineProbablePrimeChain() : new sieve (%u/%u) ready in %uus\n", psieve_GetCandidateCount(psieve), nMaxSieveSize, (unsigned int) (GetTimeMicros() - nStart));
+ 		applog(LOG_DEBUG, "MineProbablePrimeChain() : new sieve (%u/%u) ready in %uus", psieve_GetCandidateCount(psieve), nMaxSieveSize, (unsigned int) (GetTimeMicros() - nStart));
 	}
 	}
 
 
 	mpz_t bnChainOrigin;
 	mpz_t bnChainOrigin;
@@ -397,23 +484,60 @@ bool MineProbablePrimeChain(struct SieveOfEratosthenes *psieve, const uint8_t *h
 			// power tests completed for the sieve
 			// power tests completed for the sieve
 			psieve_reset(psieve);
 			psieve_reset(psieve);
 			*pfNewBlock = true; // notify caller to change nonce
 			*pfNewBlock = true; // notify caller to change nonce
+			mpz_clear(bnChainOrigin);
 			return false;
 			return false;
 		}
 		}
+#ifdef SUPERDEBUG
+		printf("nTriedMultiplier=%d\n", *pnTriedMultiplier=640150);
+#endif
 		mpz_mul(bnChainOrigin, *hash, *bnFixedMultiplier);
 		mpz_mul(bnChainOrigin, *hash, *bnFixedMultiplier);
 		mpz_mul_ui(bnChainOrigin, bnChainOrigin, *pnTriedMultiplier);
 		mpz_mul_ui(bnChainOrigin, bnChainOrigin, *pnTriedMultiplier);
 		unsigned int nChainLengthCunningham1 = 0;
 		unsigned int nChainLengthCunningham1 = 0;
 		unsigned int nChainLengthCunningham2 = 0;
 		unsigned int nChainLengthCunningham2 = 0;
 		unsigned int nChainLengthBiTwin = 0;
 		unsigned int nChainLengthBiTwin = 0;
+#ifdef SUPERDEBUG
+		printf("ProbablePrimeChainTest(bnChainOrigin=");
+		mpz_out_str(stdout, 0x10, bnChainOrigin);
+		printf(", nbits=%08lx, false, %d, %d, %d)\n", (unsigned long)*pnbits, nChainLengthCunningham1, nChainLengthCunningham2, nChainLengthBiTwin);
+#endif
 		if (ProbablePrimeChainTest(&bnChainOrigin, *pnbits, false, &nChainLengthCunningham1, &nChainLengthCunningham2, &nChainLengthBiTwin))
 		if (ProbablePrimeChainTest(&bnChainOrigin, *pnbits, false, &nChainLengthCunningham1, &nChainLengthCunningham2, &nChainLengthBiTwin))
 		{
 		{
-// TODO		    block.bnPrimeChainMultiplier = *bnFixedMultiplier * *pnTriedMultiplier;
+			// bnChainOrigin is not used again, so recycled here for the result
+
+			// block.bnPrimeChainMultiplier = *bnFixedMultiplier * *pnTriedMultiplier;
+			mpz_mul_ui(bnChainOrigin, *bnFixedMultiplier, *pnTriedMultiplier);
+			
+			size_t exportsz, resultoff;
+			uint8_t *export = mpz_export(NULL, &exportsz, -1, 1, -1, 0, bnChainOrigin);
+			assert(exportsz < 250);  // FIXME: bitcoin varint
+			resultoff = 1;
+			if (export[0] & 0x80)
+				++resultoff;
+			uint8_t *result = malloc(exportsz + resultoff);
+			result[0] = exportsz + resultoff - 1;
+			result[1] = '\0';
+			memcpy(&result[resultoff], export, exportsz);
+			if (mpz_sgn(bnChainOrigin) < 0)
+				result[1] |= 0x80;
+			free(export);
+			
+			work->sig = result;
+			work->sigsz = exportsz + resultoff;
+			
+			char hex[1 + (work->sigsz * 2)];
+			bin2hex(hex, work->sig, work->sigsz);
+			applog(LOG_DEBUG, "SIGNATURE: %s\n", hex);
+			
+			
 // 		    printf("Probable prime chain found for block=%s!!\n  Target: %s\n  Length: (%s %s %s)\n", block.GetHash().GetHex().c_str(),
 // 		    printf("Probable prime chain found for block=%s!!\n  Target: %s\n  Length: (%s %s %s)\n", block.GetHash().GetHex().c_str(),
 // 		    TargetToString(nbits).c_str(), TargetToString(nChainLengthCunningham1).c_str(), TargetToString(nChainLengthCunningham2).c_str(), TargetToString(nChainLengthBiTwin).c_str());
 // 		    TargetToString(nbits).c_str(), TargetToString(nChainLengthCunningham1).c_str(), TargetToString(nChainLengthCunningham2).c_str(), TargetToString(nChainLengthBiTwin).c_str());
+			applog(LOG_DEBUG, "Probable prime chain found for block");
 			*pnProbableChainLength = nChainLengthCunningham1;
 			*pnProbableChainLength = nChainLengthCunningham1;
 			if (*pnProbableChainLength < nChainLengthCunningham2)
 			if (*pnProbableChainLength < nChainLengthCunningham2)
 				*pnProbableChainLength = nChainLengthCunningham2;
 				*pnProbableChainLength = nChainLengthCunningham2;
 			if (*pnProbableChainLength < nChainLengthBiTwin)
 			if (*pnProbableChainLength < nChainLengthBiTwin)
 				*pnProbableChainLength = nChainLengthBiTwin;
 				*pnProbableChainLength = nChainLengthBiTwin;
+			mpz_clear(bnChainOrigin);
 		    return true;
 		    return true;
 		}
 		}
 		*pnProbableChainLength = nChainLengthCunningham1;
 		*pnProbableChainLength = nChainLengthCunningham1;
@@ -426,6 +550,7 @@ bool MineProbablePrimeChain(struct SieveOfEratosthenes *psieve, const uint8_t *h
 
 
 		nCurrent = GetTimeMicros();
 		nCurrent = GetTimeMicros();
 	}
 	}
+	mpz_clear(bnChainOrigin);
 	return false; // stop as timed out
 	return false; // stop as timed out
 }
 }
 
 
@@ -439,7 +564,7 @@ bool check_ends(const uint8_t *hash)
 static inline
 static inline
 void set_mpz_to_hash(mpz_t *hash, const uint8_t *hashb)
 void set_mpz_to_hash(mpz_t *hash, const uint8_t *hashb)
 {
 {
-	mpz_import(*hash, 4, 1, 8, -1, 0, hashb);
+	mpz_import(*hash, 8, -1, 4, -1, 0, hashb);
 }
 }
 
 
 unsigned int nPrimorialHashFactor = 7;
 unsigned int nPrimorialHashFactor = 7;
@@ -449,8 +574,10 @@ bool fIncrementPrimorial = true; // increase or decrease primorial factor
 unsigned current_prime = 3;  // index 3 is prime number 7
 unsigned current_prime = 3;  // index 3 is prime number 7
 int64_t nHPSTimerStart = 0;
 int64_t nHPSTimerStart = 0;
 
 
-void prime(uint8_t *header)
+bool prime(uint8_t *header, struct work *work)
 {
 {
+	bool rv = false;
+	
 	uint32_t *nonce = (void*)(&header[76]);
 	uint32_t *nonce = (void*)(&header[76]);
 	unsigned char hashb[32];
 	unsigned char hashb[32];
 	mpz_t hash, bnPrimeMin;
 	mpz_t hash, bnPrimeMin;
@@ -477,13 +604,17 @@ void prime(uint8_t *header)
 				break;
 				break;
 		}
 		}
 		if (unlikely(*nonce == 0xffffffff))
 		if (unlikely(*nonce == 0xffffffff))
-			return;
+		{
+			mpz_clear(hash);
+			mpz_clear(bnPrimeMin);
+			return false;
+		}
 		++*nonce;
 		++*nonce;
 	}
 	}
 	{
 	{
 		char hex[9];
 		char hex[9];
 		bin2hex(hex, nonce, 4);
 		bin2hex(hex, nonce, 4);
-		fprintf(stderr, "Pass 1 found: %s\n", hex);
+		applog(LOG_DEBUG, "Pass 1 found: %s", hex);
 	}
 	}
 	
 	
 	// primorial fixed multiplier
 	// primorial fixed multiplier
@@ -499,7 +630,7 @@ void prime(uint8_t *header)
 	if (fIncrementPrimorial)
 	if (fIncrementPrimorial)
 	{
 	{
 		++current_prime;
 		++current_prime;
-		if (current_prime >= PRIME_COUNT)
+		if (current_prime >= PRIMORIAL_COUNT)
 			quit(1, "primorial increment overflow");
 			quit(1, "primorial increment overflow");
 	}
 	}
 	else if (vPrimes[current_prime] > nPrimorialHashFactor)
 	else if (vPrimes[current_prime] > nPrimorialHashFactor)
@@ -526,10 +657,11 @@ void prime(uint8_t *header)
 		while (mpz_cmp(bnPrimorial, bnMultiplierMin) < 0)
 		while (mpz_cmp(bnPrimorial, bnMultiplierMin) < 0)
 		{
 		{
 			++current_prime;
 			++current_prime;
-			if (current_prime >= PRIME_COUNT)
+			if (current_prime >= PRIMORIAL_COUNT)
 				quit(1, "primorial minimum overflow");
 				quit(1, "primorial minimum overflow");
 			mpz_set(bnPrimorial, vPrimorials[current_prime]);
 			mpz_set(bnPrimorial, vPrimorials[current_prime]);
 		}
 		}
+		mpz_clear(bnMultiplierMin);
 		
 		
 		mpz_t bnFixedMultiplier;
 		mpz_t bnFixedMultiplier;
 		mpz_init(bnFixedMultiplier);
 		mpz_init(bnFixedMultiplier);
@@ -539,19 +671,27 @@ void prime(uint8_t *header)
 			mpz_t bnHashFactor;
 			mpz_t bnHashFactor;
 			mpz_init_set_ui(bnHashFactor, nHashFactor);
 			mpz_init_set_ui(bnHashFactor, nHashFactor);
 			mpz_fdiv_q(bnFixedMultiplier, bnPrimorial, bnHashFactor);
 			mpz_fdiv_q(bnFixedMultiplier, bnPrimorial, bnHashFactor);
+			mpz_clear(bnHashFactor);
 		}
 		}
 		else
 		else
 			mpz_set_ui(bnFixedMultiplier, 1);
 			mpz_set_ui(bnFixedMultiplier, 1);
+#ifdef SUPERDEBUG
+		fprintf(stderr,"bnFixedMultiplier=");
+		mpz_out_str(stderr, 0x10, bnFixedMultiplier);
+		fprintf(stderr, " nPrimorialMultiplier=%u nTriedMultiplier=%u\n", vPrimes[current_prime], nTriedMultiplier);
+#endif
 		
 		
 		
 		
 		// mine for prime chain
 		// mine for prime chain
 		unsigned int nProbableChainLength;
 		unsigned int nProbableChainLength;
-		if (MineProbablePrimeChain(&sieve, header, &hash, &bnFixedMultiplier, &fNewBlock, &nTriedMultiplier, &nProbableChainLength, &nTests, &nPrimesHit))
+		if (MineProbablePrimeChain(&sieve, header, &hash, &bnFixedMultiplier, &fNewBlock, &nTriedMultiplier, &nProbableChainLength, &nTests, &nPrimesHit, work))
 		{
 		{
 // TODO			CheckWork(pblock, *pwalletMain, reservekey);
 // TODO			CheckWork(pblock, *pwalletMain, reservekey);
-			fprintf(stderr, "CHECK WORK\n");
+			mpz_clear(bnFixedMultiplier);
+			rv = true;
 			break;
 			break;
 		}
 		}
+		mpz_clear(bnFixedMultiplier);
 		nRoundTests += nTests;
 		nRoundTests += nTests;
 		nRoundPrimesHit += nPrimesHit;
 		nRoundPrimesHit += nPrimesHit;
 
 
@@ -599,13 +739,14 @@ void prime(uint8_t *header)
 // 	    boost::this_thread::interruption_point();
 // 	    boost::this_thread::interruption_point();
 // 	    if (vNodes.empty())
 // 	    if (vNodes.empty())
 // 	        break;
 // 	        break;
-// 	    if (fNewBlock || pblock->nNonce >= 0xffff0000)
-// 	        break;
+	    if (fNewBlock /*|| pblock->nNonce >= 0xffff0000*/)
+	        break;
 // 	    if (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60)
 // 	    if (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60)
 // 	        break;
 // 	        break;
 // 	    if (pindexPrev != pindexBest)
 // 	    if (pindexPrev != pindexBest)
 // 	        break;
 // 	        break;
 	}
 	}
+	mpz_clear(bnPrimorial);
 
 
 	// Primecoin: estimate time to block
 	// Primecoin: estimate time to block
 	nTimeExpected = (GetTimeMicros() - nPrimeTimerStart) / max(1u, nRoundTests);
 	nTimeExpected = (GetTimeMicros() - nPrimeTimerStart) / max(1u, nRoundTests);
@@ -613,26 +754,54 @@ void prime(uint8_t *header)
 //TODO
 //TODO
 // 	for (unsigned int n = 1; n < TargetGetLength(pblock->nBits); n++)
 // 	for (unsigned int n = 1; n < TargetGetLength(pblock->nBits); n++)
 // 	     nTimeExpected = nTimeExpected * max(1u, nRoundTests) * 3 / max(1u, nRoundPrimesHit);
 // 	     nTimeExpected = nTimeExpected * max(1u, nRoundTests) * 3 / max(1u, nRoundPrimesHit);
-	printf("PrimecoinMiner() : Round primorial=%u tests=%u primes=%u expected=%us\n", vPrimes[current_prime], nRoundTests, nRoundPrimesHit, (unsigned int)(nTimeExpected/1000000));
+	applog(LOG_DEBUG, "PrimecoinMiner() : Round primorial=%u tests=%u primes=%u expected=%us", vPrimes[current_prime], nRoundTests, nRoundPrimesHit, (unsigned int)(nTimeExpected/1000000));
+
+	mpz_clear(hash);
+	mpz_clear(bnPrimeMin);
+	
+	return rv;
 }
 }
 
 
-void main()
+#if 0
+void pmain()
 {
 {
+	setbuf(stderr, NULL);
+	setbuf(stdout, NULL);
 	GeneratePrimeTable();
 	GeneratePrimeTable();
 	unsigned char array[80] = {
 	unsigned char array[80] = {
-		0x02, 0x00, 0x00, 0x00,
-		
-		0x06, 0x21, 0x15, 0xa0, 0xb9, 0x7d, 0x83, 0x26, 0xff, 0xad, 0x2b, 0x82, 0x46, 0x25, 0x4e, 0x67,
-		0xf9, 0x3a, 0xfb, 0x6a, 0xf5, 0xa2, 0x78, 0x80, 0x13, 0x53, 0xc7, 0x4d, 0xba, 0x17, 0x3d, 0x96,
-		
-		0xee, 0x52, 0x24, 0xd0, 0xf6, 0xcd, 0x53, 0x50, 0x8c, 0x4b, 0x63, 0x39, 0x1d, 0x28, 0x86, 0x9d,
-		0x35, 0x21, 0xeb, 0x8d, 0x43, 0xbe, 0x82, 0xcf, 0x58, 0x48, 0x1d, 0xa0, 0xd0, 0xe4, 0x13, 0x72,
-		
-		0x30, 0xb3, 0xd9, 0x51,
-		
-		0x00, 0x00, 0x00, 0x07,
-		
-		0x1d, 0x00, 0x00, 0x00
+		0x02,0x00,0x00,0x00,
+		0x59,0xf7,0x56,0x1c,0x21,0x25,0xc1,0xad,0x0d,0xee,0xbd,0x05,0xb8,0x41,0x38,0xab,
+		0x2e,0xfb,0x65,0x40,0xc8,0xc7,0xa3,0xef,0x90,0x3d,0x75,0x8c,0x03,0x1c,0x7a,0xcc,
+		0x8d,0x27,0x4d,0xeb,0x7b,0x6a,0xf8,0xe0,0x44,0x2d,0x7c,0xf6,0xb9,0x71,0x12,0xd8,
+		0x61,0x60,0x5b,0x1f,0xa5,0xa3,0xf7,0x4f,0x61,0xe3,0x59,0x67,0x03,0xc2,0xfb,0x56,
+		0xed,0x78,0xdb,0x51,
+		0xd5,0xbe,0x38,0x07,
+		0xe8,0x02,0x00,0x00,
 	};
 	};
 	prime(array);
 	prime(array);
-}
+}
+#endif
+
+bool scanhash_prime(struct thr_info *thr, const unsigned char *pmidstate, unsigned char *pdata, unsigned char *phash1, unsigned char *phash, const unsigned char *ptarget, uint32_t max_nonce, uint32_t *last_nonce, uint32_t nonce)
+{
+	struct work *work = (struct work *)(&pmidstate[-offsetof(struct work, midstate)]);
+	
+	unsigned char header[80];
+	swap32yes(header, pdata, 80 / 4);
+#if 0
+	memcpy(header,(unsigned char[80]){
+		0x02,0x00,0x00,0x00,
+		0x59,0xf7,0x56,0x1c,0x21,0x25,0xc1,0xad,0x0d,0xee,0xbd,0x05,0xb8,0x41,0x38,0xab,
+		0x2e,0xfb,0x65,0x40,0xc8,0xc7,0xa3,0xef,0x90,0x3d,0x75,0x8c,0x03,0x1c,0x7a,0xcc,
+		0x8d,0x27,0x4d,0xeb,0x7b,0x6a,0xf8,0xe0,0x44,0x2d,0x7c,0xf6,0xb9,0x71,0x12,0xd8,
+		0x61,0x60,0x5b,0x1f,0xa5,0xa3,0xf7,0x4f,0x61,0xe3,0x59,0x67,0x03,0xc2,0xfb,0x56,
+		0xed,0x78,0xdb,0x51,
+		0xd5,0xbe,0x38,0x07,
+		0xe8,0x02,0x00,0x00,
+	},80);
+#endif
+	bool rv = prime(header, work);
+	swap32yes(pdata, header, 80 / 4);
+	return rv;
+}
+

+ 2 - 0
util.h

@@ -181,6 +181,8 @@ void bytes_cpy(bytes_t *dst, const bytes_t *src)
 {
 {
 	dst->allocsz = src->allocsz;
 	dst->allocsz = src->allocsz;
 	dst->sz = src->sz;
 	dst->sz = src->sz;
+	if (!dst->allocsz)
+		return;
 	size_t half;
 	size_t half;
 	while (dst->sz <= (half = dst->allocsz / 2))
 	while (dst->sz <= (half = dst->allocsz / 2))
 		dst->allocsz = half;
 		dst->allocsz = half;