void argon2hash(void *output, const void *input) { unsigned int t_costs = 2; unsigned int m_costs = 16; unsigned int Nfactor = m_costs/2; const uint32_t r = SCRYPT_R; const uint32_t p = SCRYPT_P; scrypt_aligned_alloc YX, V; uint8_t *X, *Y; uint32_t N, chunk_bytes, i; N = (1 << (Nfactor + 1)); chunk_bytes = SCRYPT_BLOCK_BYTES * r * 2; V = scrypt_alloc((uint64_t)N * chunk_bytes); YX = scrypt_alloc((p + 1) * chunk_bytes); /* 1: X = PBKDF2(password, salt) */ Y = YX.ptr; X = Y + chunk_bytes; argon2_hash(output, input, t_costs, m_costs, N, X, Y, V.ptr, p, r); scrypt_free(&V); scrypt_free(&YX); }
/* simple cpu test (util.c) */ void scryptjanehash(void *output, const void *input ) { scrypt_aligned_alloc YX, V; uint8_t *X, *Y; uint32_t chunk_bytes; uint32_t N = (1 << ( opt_scrypt_n + 1)); const uint32_t r = SCRYPT_R; const uint32_t p = SCRYPT_P; memset(output, 0, 32); chunk_bytes = SCRYPT_BLOCK_BYTES * r * 2; if (!scrypt_alloc((uint64_t)N * chunk_bytes, &V)) return; if (!scrypt_alloc((p + 1) * chunk_bytes, &YX)) { scrypt_free(&V); return; } Y = YX.ptr; X = Y + chunk_bytes; scrypt_N_1_1((unsigned char*)input, 80, (unsigned char*)input, 80, N, (unsigned char*)output, 32, X, Y, V.ptr); scrypt_free(&V); scrypt_free(&YX); }
void scrypt(const uint8_t *password, size_t password_len, const uint8_t *salt, size_t salt_len, uint8_t Nfactor, uint8_t rfactor, uint8_t pfactor, uint8_t *out, size_t bytes) { scrypt_aligned_alloc YX, V; uint8_t *X, *Y; uint32_t N, r, p, chunk_bytes, i; #if !defined(SCRYPT_CHOOSE_COMPILETIME) scrypt_ROMixfn scrypt_ROMix = scrypt_getROMix(); #endif #if !defined(SCRYPT_TEST) static int power_on_self_test = 0; if (!power_on_self_test) { power_on_self_test = 1; if (!scrypt_power_on_self_test()) scrypt_fatal_error("scrypt: power on self test failed"); } #endif if (Nfactor > scrypt_maxN) scrypt_fatal_error("scrypt: N out of range"); if (rfactor > scrypt_maxr) scrypt_fatal_error("scrypt: r out of range"); if (pfactor > scrypt_maxp) scrypt_fatal_error("scrypt: p out of range"); N = (1 << (Nfactor + 1)); r = (1 << rfactor); p = (1 << pfactor); chunk_bytes = SCRYPT_BLOCK_BYTES * r * 2; V = scrypt_alloc((uint64_t)N * chunk_bytes); YX = scrypt_alloc((p + 1) * chunk_bytes); //printf("%d-%d-%d\n" ,N,r,p); //printf("%d\n", chunk_bytes); //printf("%d\n", (uint64_t)N * chunk_bytes); /* 1: X = PBKDF2(password, salt) */ Y = YX.ptr; X = Y + chunk_bytes; scrypt_pbkdf2(password, password_len, salt, salt_len, 1, X, chunk_bytes * p); /* 2: X = ROMix(X) */ for (i = 0; i < p; i++) scrypt_ROMix((scrypt_mix_word_t *)(X + (chunk_bytes * i)), (scrypt_mix_word_t *)Y, (scrypt_mix_word_t *)V.ptr, N, r); /* 3: Out = PBKDF2(password, X) */ scrypt_pbkdf2(password, password_len, X, chunk_bytes * p, 1, out, bytes); scrypt_ensure_zero(YX.ptr, (p + 1) * chunk_bytes); scrypt_free(&V); scrypt_free(&YX); }
static int scrypt_power_on_self_test() { const scrypt_test_setting *t; uint8_t test_digest[64]; uint32_t i; int res = 7, scrypt_valid; scrypt_aligned_alloc YX, V; uint8_t *X, *Y; uint32_t N, chunk_bytes; const uint32_t r = SCRYPT_R; const uint32_t p = SCRYPT_P; if (!scrypt_test_mix()) { #if !defined(SCRYPT_TEST) scrypt_fatal_error("scrypt: mix function power-on-self-test failed"); #endif res &= ~1; } if (!scrypt_test_hash()) { #if !defined(SCRYPT_TEST) scrypt_fatal_error("scrypt: hash function power-on-self-test failed"); #endif res &= ~2; } for (i = 0, scrypt_valid = 1; post_settings[i].pw; i++) { t = post_settings + i; N = (1 << (t->Nfactor + 1)); chunk_bytes = SCRYPT_BLOCK_BYTES * r * 2; V = scrypt_alloc((uint64_t)N * chunk_bytes); YX = scrypt_alloc((p + 1) * chunk_bytes); Y = YX.ptr; X = Y + chunk_bytes; scrypt_N_1_1((uint8_t *)t->pw, strlen(t->pw), (uint8_t *)t->salt, strlen(t->salt), N, test_digest, sizeof(test_digest), X, Y, V.ptr); scrypt_valid &= scrypt_verify(post_vectors[i], test_digest, sizeof(test_digest)); scrypt_free(&V); scrypt_free(&YX); } if (!scrypt_valid) { #if !defined(SCRYPT_TEST) scrypt_fatal_error("scrypt: scrypt power-on-self-test failed"); #endif res &= ~4; } return res; }
void my_scrypt(const uint8_t *password, size_t password_len, const uint8_t *salt, size_t salt_len, uint8_t *out) { scrypt_aligned_alloc YX, V; uint8_t *X, *Y; #if !defined(SCRYPT_CHOOSE_COMPILETIME) scrypt_ROMixfn scrypt_ROMix = scrypt_getROMix(); #endif /* #if !defined(SCRYPT_TEST) static int power_on_self_test = 0; if (!power_on_self_test) { power_on_self_test = 1; if (!scrypt_power_on_self_test()) scrypt_fatal_error("scrypt: power on self test failed"); } #endif */ V = scrypt_alloc((uint64_t)512 * chunk_bytes); YX = scrypt_alloc(2 * chunk_bytes); /* 1: X = PBKDF2(password, salt) */ Y = YX.ptr; X = Y + chunk_bytes; scrypt_pbkdf2(password, password_len, salt, salt_len, 1, X, chunk_bytes); /* 2: X = ROMix(X) */ scrypt_ROMix((scrypt_mix_word_t *)X, (scrypt_mix_word_t *)Y, (scrypt_mix_word_t *)V.ptr, 512, 1); /* 3: Out = PBKDF2(password, X) */ scrypt_pbkdf2(password, password_len, X, chunk_bytes, 1, out, 32); scrypt_ensure_zero(YX.ptr, 2 * chunk_bytes); scrypt_free(&V); scrypt_free(&YX); }
int scanhash_argon2(int thr_id, uint32_t *pdata, const uint32_t *ptarget, uint32_t max_nonce, uint64_t *hashes_done) { uint32_t n = pdata[19] - 1; const uint32_t first_nonce = pdata[19]; const uint32_t Htarg = ptarget[7]; uint32_t hash64[8] __attribute__((aligned(32))); uint32_t endiandata[32]; scrypt_aligned_alloc YX, V; uint8_t *X, *Y; uint32_t N, chunk_bytes; unsigned int t_costs = 2; unsigned int m_costs = 16; unsigned int Nfactor = m_costs/2; const uint32_t r = SCRYPT_R; const uint32_t p = SCRYPT_P; int i; uint64_t htmax[] = { 0, 0xF, 0xFF, 0xFFF, 0xFFFF, 0xFFFFF, 0xFFFFFF, 0xFFFFFFF, 0x10000000 }; uint32_t masks[] = { 0xFFFFFFFF, 0xFFFFFFF0, 0xFFFFFF00, 0xFFFFF000, 0xFFFF0000, 0xFFF00000, 0xFF000000, 0xF0000000, 0 }; // we need bigendian data... for (int kk=0; kk < 32; kk++) { be32enc(&endiandata[kk], (pdata)[kk]); }; N = (1 << (Nfactor + 1)); chunk_bytes = SCRYPT_BLOCK_BYTES * r * 2; V = scrypt_alloc((uint64_t)N * chunk_bytes); YX = scrypt_alloc((p + 1) * chunk_bytes); Y = YX.ptr; X = Y + chunk_bytes; #ifdef DEBUG_ALGO printf("[%d] Htarg=%X\n", thr_id, Htarg); #endif for (int m=0; m < sizeof(masks); m++) { if (Htarg <= htmax[m]) { uint32_t mask = masks[m]; do { pdata[19] = ++n; be32enc(&endiandata[19], n); argon2_hash(hash64, endiandata, t_costs, m_costs, N, X, Y, V.ptr, p, r); #ifndef DEBUG_ALGO if ((!(hash64[7] & mask)) && fulltest(hash64, ptarget)) { *hashes_done = n - first_nonce + 1; pdata[19] = n; scrypt_free(&V); scrypt_free(&YX); return 1; } #else if (!(n % 0x1000) && !thr_id) printf("."); if (!(hash64[7] & mask)) { printf("[%d]",thr_id); if (fulltest(hash64, ptarget)) { *hashes_done = n - first_nonce + 1; scrypt_free(&V); scrypt_free(&YX); return true; } } #endif } while (n < max_nonce && !work_restart[thr_id].restart); break; } } scrypt_free(&V); scrypt_free(&YX); *hashes_done = n - first_nonce + 1; pdata[19] = n; return 0; }
int scanhash_scrypt_jane(int thr_id, uint32_t *pdata, const uint32_t *ptarget, uint32_t max_nonce, struct timeval *tv_start, struct timeval *tv_end, unsigned long *hashes_done) { const uint32_t Htarg = ptarget[7]; static int s_Nfactor = 0; if (s_Nfactor == 0 && strlen(jane_params) > 0) applog(LOG_INFO, "Given scrypt-jane parameters: %s", jane_params); int Nfactor = GetNfactor(bswap_32x4(pdata[17])); if (Nfactor > scrypt_maxN) { scrypt_fatal_error("scrypt: N out of range"); } if (Nfactor != s_Nfactor) { // all of this isn't very thread-safe... N = (1 << (Nfactor + 1)); applog(LOG_INFO, "Nfactor is %d (N=%d)!", Nfactor, N); if (s_Nfactor != 0) { // handle N-factor increase at runtime // by adjusting the lookup_gap by factor 2 if (s_Nfactor == Nfactor-1) for (int i=0; i < 8; ++i) device_lookup_gap[i] *= 2; } s_Nfactor = Nfactor; } int throughput = cuda_throughput(thr_id); if(throughput == 0) return -1; gettimeofday(tv_start, NULL); uint32_t *data[2] = { new uint32_t[20*throughput], new uint32_t[20*throughput] }; uint32_t* hash[2] = { cuda_hashbuffer(thr_id,0), cuda_hashbuffer(thr_id,1) }; uint32_t n = pdata[19]; /* byte swap pdata into data[0]/[1] arrays */ for (int k=0; k<2; ++k) { for(int z=0;z<20;z++) data[k][z] = bswap_32x4(pdata[z]); for(int i=1;i<throughput;++i) memcpy(&data[k][20*i], &data[k][0], 20*sizeof(uint32_t)); } if (parallel == 2) prepare_keccak512(thr_id, pdata); scrypt_aligned_alloc Xbuf[2] = { scrypt_alloc(128 * throughput), scrypt_alloc(128 * throughput) }; scrypt_aligned_alloc Vbuf = scrypt_alloc((uint64_t)N * 128); scrypt_aligned_alloc Ybuf = scrypt_alloc(128); uint32_t nonce[2]; uint32_t* cuda_X[2] = { cuda_transferbuffer(thr_id,0), cuda_transferbuffer(thr_id,1) }; #if !defined(SCRYPT_CHOOSE_COMPILETIME) scrypt_ROMixfn scrypt_ROMix = scrypt_getROMix(); #endif int cur = 0, nxt = 1; int iteration = 0; do { nonce[nxt] = n; if (parallel < 2) { for(int i=0;i<throughput;++i) { uint32_t tmp_nonce = n++; data[nxt][20*i + 19] = bswap_32x4(tmp_nonce); } for(int i=0;i<throughput;++i) scrypt_pbkdf2_1((unsigned char *)&data[nxt][20*i], 80, (unsigned char *)&data[nxt][20*i], 80, Xbuf[nxt].ptr + 128 * i, 128); memcpy(cuda_X[nxt], Xbuf[nxt].ptr, 128 * throughput); cuda_scrypt_serialize(thr_id, nxt); cuda_scrypt_HtoD(thr_id, cuda_X[nxt], nxt); cuda_scrypt_core(thr_id, nxt, N); cuda_scrypt_done(thr_id, nxt); cuda_scrypt_DtoH(thr_id, cuda_X[nxt], nxt, false); cuda_scrypt_flush(thr_id, nxt); if(!cuda_scrypt_sync(thr_id, cur)) { return -1; } memcpy(Xbuf[cur].ptr, cuda_X[cur], 128 * throughput); for(int i=0;i<throughput;++i) scrypt_pbkdf2_1((unsigned char *)&data[cur][20*i], 80, Xbuf[cur].ptr + 128 * i, 128, (unsigned char *)(&hash[cur][8*i]), 32); #define VERIFY_ALL 0 #if VERIFY_ALL { /* 2: X = ROMix(X) */ for(int i=0;i<throughput;++i) scrypt_ROMix_1((scrypt_mix_word_t *)(Xbuf[cur].ptr + 128 * i), (scrypt_mix_word_t *)Ybuf.ptr, (scrypt_mix_word_t *)Vbuf.ptr, N); unsigned int err = 0; for(int i=0;i<throughput;++i) { unsigned char *ref = (Xbuf[cur].ptr + 128 * i); unsigned char *dat = (unsigned char*)(cuda_X[cur] + 32 * i); if (memcmp(ref, dat, 128) != 0) { err++; #if 0 uint32_t *ref32 = (uint32_t*) ref; uint32_t *dat32 = (uint32_t*) dat; for (int j=0; j<32; ++j) { if (ref32[j] != dat32[j]) fprintf(stderr, "ref32[i=%d][j=%d] = $%08x / $%08x\n", i, j, ref32[j], dat32[j]); } #endif } } if (err > 0) fprintf(stderr, "%d out of %d hashes differ.\n", err, throughput); } #endif } else { n += throughput; cuda_scrypt_serialize(thr_id, nxt); pre_keccak512(thr_id, nxt, nonce[nxt], throughput); cuda_scrypt_core(thr_id, nxt, N); cuda_scrypt_flush(thr_id, nxt); post_keccak512(thr_id, nxt, nonce[nxt], throughput); cuda_scrypt_done(thr_id, nxt); cuda_scrypt_DtoH(thr_id, hash[nxt], nxt, true); if(!cuda_scrypt_sync(thr_id, cur)) { return -1; } } if(iteration > 0) { for(int i=0;i<throughput;++i) { volatile unsigned char *hashc = (unsigned char *)(&hash[cur][8*i]); if (hash[cur][8*i+7] <= Htarg && fulltest(&hash[cur][8*i], ptarget)) { uint32_t tmp_nonce = nonce[cur]+i; uint32_t thash[8], tdata[20]; for(int z=0;z<20;z++) tdata[z] = bswap_32x4(pdata[z]); tdata[19] = bswap_32x4(tmp_nonce); scrypt_pbkdf2_1((unsigned char *)tdata, 80, (unsigned char *)tdata, 80, Xbuf[cur].ptr + 128 * i, 128); scrypt_ROMix_1((scrypt_mix_word_t *)(Xbuf[cur].ptr + 128 * i), (scrypt_mix_word_t *)(Ybuf.ptr), (scrypt_mix_word_t *)(Vbuf.ptr), N); scrypt_pbkdf2_1((unsigned char *)tdata, 80, Xbuf[cur].ptr + 128 * i, 128, (unsigned char *)thash, 32); if (memcmp(thash, &hash[cur][8*i], 32) == 0) { //applog(LOG_INFO, "GPU #%d: %s result validates on CPU.", device_map[thr_id], device_name[thr_id]); *hashes_done = n - pdata[19]; pdata[19] = tmp_nonce; scrypt_free(&Vbuf); scrypt_free(&Ybuf); scrypt_free(&Xbuf[0]); scrypt_free(&Xbuf[1]); delete[] data[0]; delete[] data[1]; gettimeofday(tv_end, NULL); return 1; } else { applog(LOG_INFO, "GPU #%d: %s result does not validate on CPU (i=%d, s=%d)!", device_map[thr_id], device_name[thr_id], i, cur); } } } } cur = (cur+1)&1; nxt = (nxt+1)&1; ++iteration; } while (n <= max_nonce && !work_restart[thr_id].restart); scrypt_free(&Vbuf); scrypt_free(&Ybuf); scrypt_free(&Xbuf[0]); scrypt_free(&Xbuf[1]); delete[] data[0]; delete[] data[1]; *hashes_done = n - pdata[19]; pdata[19] = n; gettimeofday(tv_end, NULL); return 0; }
int scanhash_scrypt_jane(int thr_id, uint32_t *pdata, const uint32_t *ptarget, uint32_t max_nonce, unsigned long *hashes_done) { const uint32_t Htarg = ptarget[7]; int Nfactor = GetNfactor(bswap_32x4(pdata[17])); if (Nfactor > scrypt_maxN) { scrypt_fatal_error("scrypt: N out of range"); } N = (1 << (Nfactor + 1)); parallel = 0; int throughput = cuda_throughput(thr_id); uint32_t *data[2] = { new uint32_t[20*throughput], new uint32_t[20*throughput] }; uint32_t *hash = new uint32_t[8*throughput]; uint32_t n = pdata[19] - 1; // int i; #if !defined(SCRYPT_TEST) static int power_on_self_test = 0; if (!power_on_self_test) { power_on_self_test = 1; if (!scrypt_power_on_self_test()) scrypt_fatal_error("scrypt: power on self test failed"); } #endif /* byte swap pdata into data[0]/[1] arrays */ for (int k=0; k<2; ++k) { for(int z=0;z<20;z++) data[k][z] = bswap_32x4(pdata[z]); for(int i=1;i<throughput;++i) memcpy(&data[k][20*i], &data[k][0], 20*sizeof(uint32_t)); } scrypt_aligned_alloc Xbuf[2] = { scrypt_alloc(128 * throughput), scrypt_alloc(128 * throughput) }; scrypt_aligned_alloc Vbuf = scrypt_alloc((uint64_t)N * 128); scrypt_aligned_alloc Ybuf = scrypt_alloc(128); uint32_t nonce[2]; uint32_t* cuda_X[2] = { cuda_transferbuffer(thr_id,0), cuda_transferbuffer(thr_id,1) }; #if !defined(SCRYPT_CHOOSE_COMPILETIME) scrypt_ROMixfn scrypt_ROMix = scrypt_getROMix(); #endif int cur = 0, nxt = 1; nonce[cur] = n+1; for(int i=0;i<throughput;++i) { uint32_t tmp_nonce = ++n; data[cur][20*i + 19] = bswap_32x4(tmp_nonce); } /* 1: X = PBKDF2(password, salt) */ for(int i=0;i<throughput;++i) scrypt_pbkdf2_1((unsigned char *)&data[cur][20*i], 80, (unsigned char *)&data[cur][20*i], 80, Xbuf[cur].ptr + 128 * i, 128); /* 2: X = ROMix(X) in CUDA */ memcpy(cuda_X[cur], Xbuf[cur].ptr, 128 * throughput); cuda_scrypt_HtoD(thr_id, cuda_X[cur], cur); cuda_scrypt_serialize(thr_id, cur); cuda_scrypt_core(thr_id, cur, N); cuda_scrypt_done(thr_id, cur); cuda_scrypt_DtoH(thr_id, cuda_X[cur], cur); cuda_scrypt_flush(thr_id, cur); do { nonce[nxt] = n+1; for(int i=0;i<throughput;++i) { uint32_t tmp_nonce = ++n; data[nxt][20*i + 19] = bswap_32x4(tmp_nonce); } /* 1: X = PBKDF2(password, salt) */ for(int i=0;i<throughput;++i) scrypt_pbkdf2_1((unsigned char *)&data[nxt][20*i], 80, (unsigned char *)&data[nxt][20*i], 80, Xbuf[nxt].ptr + 128 * i, 128); /* 2: X = ROMix(X) in CUDA */ memcpy(cuda_X[nxt], Xbuf[nxt].ptr, 128 * throughput); cuda_scrypt_HtoD(thr_id, cuda_X[nxt], nxt); cuda_scrypt_serialize(thr_id, nxt); cuda_scrypt_core(thr_id, nxt, N); cuda_scrypt_done(thr_id, nxt); cuda_scrypt_DtoH(thr_id, cuda_X[nxt], nxt); cuda_scrypt_flush(thr_id, nxt); cuda_scrypt_sync(thr_id, cur); #define VERIFY_ALL 0 #if VERIFY_ALL { /* 2: X = ROMix(X) */ for(int i=0;i<throughput;++i) scrypt_ROMix_1((scrypt_mix_word_t *)(Xbuf[cur].ptr + 128 * i), (scrypt_mix_word_t *)Ybuf.ptr, (scrypt_mix_word_t *)Vbuf.ptr, N); unsigned int err = 0; for(int i=0;i<throughput;++i) { unsigned char *ref = (Xbuf[cur].ptr + 128 * i); unsigned char *dat = (unsigned char*)(cuda_X[cur] + 32 * i); if (memcmp(ref, dat, 128) != 0) { err++; #if 0 uint32_t *ref32 = (uint32_t*) ref; uint32_t *dat32 = (uint32_t*) dat; for (int j=0; j<32; ++j) { if (ref32[j] != dat32[j]) fprintf(stderr, "ref32[i=%d][j=%d] = $%08x / $%08x\n", i, j, ref32[j], dat32[j]); } #endif } } if (err > 0) fprintf(stderr, "%d out of %d hashes differ.\n", err, throughput); } #endif memcpy(Xbuf[cur].ptr, cuda_X[cur], 128 * throughput); /* 3: Out = PBKDF2(password, X) */ for(int i=0;i<throughput;++i) scrypt_pbkdf2_1((unsigned char *)&data[cur][20*i], 80, Xbuf[cur].ptr + 128 * i, 128, (unsigned char *)&hash[8*i], 32); for(int i=0;i<throughput;++i) { volatile unsigned char *hashc = (unsigned char *)&hash[8*i]; if (hash[8*i+7] <= Htarg && fulltest(&hash[8*i], ptarget)) { uint32_t tmp_nonce = nonce[cur]+i; uint32_t thash[8], tdata[20]; for(int z=0;z<20;z++) tdata[z] = bswap_32x4(pdata[z]); tdata[19] = bswap_32x4(tmp_nonce); scrypt_pbkdf2_1((unsigned char *)tdata, 80, (unsigned char *)tdata, 80, Xbuf[cur].ptr + 128 * i, 128); scrypt_ROMix_1((scrypt_mix_word_t *)(Xbuf[cur].ptr + 128 * i), (scrypt_mix_word_t *)(Ybuf.ptr), (scrypt_mix_word_t *)(Vbuf.ptr), N); scrypt_pbkdf2_1((unsigned char *)tdata, 80, Xbuf[cur].ptr + 128 * i, 128, (unsigned char *)thash, 32); if (memcmp(thash, &hash[8*i], 32) == 0) { *hashes_done = (n-throughput) - pdata[19] + 1; pdata[19] = tmp_nonce; scrypt_free(&Vbuf); scrypt_free(&Ybuf); scrypt_free(&Xbuf[0]); scrypt_free(&Xbuf[1]); delete[] data[0]; delete[] data[1]; delete[] hash; return 1; } else { applog(LOG_INFO, "GPU #%d: %s result does not validate on CPU (i=%d, s=%d)!", device_map[thr_id], device_name[thr_id], i, cur); } } } cur = (cur+1)&1; nxt = (nxt+1)&1; } while ((n-throughput) < max_nonce && !work_restart[thr_id].restart); scrypt_free(&Vbuf); scrypt_free(&Ybuf); scrypt_free(&Xbuf[0]); scrypt_free(&Xbuf[1]); delete[] data[0]; delete[] data[1]; delete[] hash; *hashes_done = (n-throughput) - pdata[19] + 1; pdata[19] = (n-throughput); return 0; }
int scanhash_scryptjane( int thr_id, struct work *work, uint32_t max_nonce, uint64_t *hashes_done) { scrypt_aligned_alloc YX, V; uint8_t *X, *Y; uint32_t N, chunk_bytes; const uint32_t r = SCRYPT_R; const uint32_t p = SCRYPT_P; uint32_t *pdata = work->data; uint32_t *ptarget = work->target; uint32_t _ALIGN(64) endiandata[20]; const uint32_t first_nonce = pdata[19]; uint32_t nonce = first_nonce; if (opt_benchmark) ptarget[7] = 0x00ff; for (int k = 0; k < 19; k++) be32enc(&endiandata[k], pdata[k]); //Nfactor = GetNfactor(data[17], ntime); //if (Nfactor > scrypt_maxN) { // return 1; // //scrypt_fatal_error("scrypt: N out of range"); //} N = (1 << ( opt_scrypt_n + 1)); chunk_bytes = SCRYPT_BLOCK_BYTES * r * 2; if (!scrypt_alloc((uint64_t)N * chunk_bytes, &V)) return 1; if (!scrypt_alloc((p + 1) * chunk_bytes, &YX)) { scrypt_free(&V); return 1; } Y = YX.ptr; X = Y + chunk_bytes; do { const uint32_t Htarg = ptarget[7]; uint32_t hash[8]; be32enc(&endiandata[19], nonce); scrypt_N_1_1((unsigned char *)endiandata, 80, (unsigned char *)endiandata, 80, N, (unsigned char *)hash, 32, X, Y, V.ptr); if (hash[7] <= Htarg && fulltest(hash, ptarget)) { pdata[19] = nonce; *hashes_done = pdata[19] - first_nonce; scrypt_free(&V); scrypt_free(&YX); return 1; } nonce++; } while (nonce < max_nonce && !work_restart[thr_id].restart); pdata[19] = nonce; *hashes_done = pdata[19] - first_nonce + 1; scrypt_free(&V); scrypt_free(&YX); return 0; }