/* cpu and memory intensive function to transform a 80 byte buffer into a 32 byte output scratchpad size needs to be at least 63 + (128 * r * p) + (256 * r + 64) + (128 * r * N) bytes r = 1, p = 1, N = 1024 */ uint256 scrypt_blockhash(const uint8_t* input) { uint8_t scratchpad[SCRYPT_BUFFER_SIZE]; uint32_t X[32]; uint256 result = 0; uint32_t *V = (uint32_t *)(((uintptr_t)(scratchpad) + 63) & ~ (uintptr_t)(63)); PKCS5_PBKDF2_HMAC((const char*)input, 80, input, 80, 1, EVP_sha256(), 128, (unsigned char *)X); uint16_t i, j, k; for (i = 0; i < 1024; i++) { memcpy(&V[i * 32], X, 128); xor_salsa8(&X[0], &X[16]); xor_salsa8(&X[16], &X[0]); } for (i = 0; i < 1024; i++) { j = 32 * (X[16] & 1023); for (k = 0; k < 32; k++) X[k] ^= V[j + k]; xor_salsa8(&X[0], &X[16]); xor_salsa8(&X[16], &X[0]); } PKCS5_PBKDF2_HMAC((const char*)input, 80, (const unsigned char*)X, 128, 1, EVP_sha256(), 32, (unsigned char*)&result); return result; }
void pluck_hash(uint32_t *hash, const uint32_t *data, uchar *hashbuffer, const int N) { int size = N * 1024; sha256_hash(hashbuffer, (void*)data, BLOCK_HEADER_SIZE); memset(&hashbuffer[32], 0, 32); for(int i = 64; i < size - 32; i += 32) { uint32_t _ALIGN(64) randseed[16]; uint32_t _ALIGN(64) randbuffer[16]; uint32_t _ALIGN(64) joint[16]; //i-4 because we use integers for all references against this, and we don't want to go 3 bytes over the defined area //we could use size here, but then it's probable to use 0 as the value in most cases int randmax = i - 4; //setup randbuffer to be an array of random indexes memcpy(randseed, &hashbuffer[i - 64], 64); if(i > 128) memcpy(randbuffer, &hashbuffer[i - 128], 64); //else memset(randbuffer, 0, 64); xor_salsa8((void*)randbuffer, (void*)randseed, i); memcpy(joint, &hashbuffer[i - 32], 32); //use the last hash value as the seed for (int j = 32; j < 64; j += 4) { //every other time, change to next random index //randmax - 32 as otherwise we go beyond memory that's already been written to uint32_t rand = randbuffer[(j - 32) >> 2] % (randmax - 32); joint[j >> 2] = *((uint32_t *)&hashbuffer[rand]); } sha256_hash512((uint32_t*) &hashbuffer[i], joint); //setup randbuffer to be an array of random indexes //use last hash value and previous hash value(post-mixing) memcpy(randseed, &hashbuffer[i - 32], 64); if(i > 128) memcpy(randbuffer, &hashbuffer[i - 128], 64); //else memset(randbuffer, 0, 64); xor_salsa8((void*)randbuffer, (void*)randseed, i); //use the last hash value as the seed for (int j = 0; j < 32; j += 2) { uint32_t rand = randbuffer[j >> 1] % randmax; *((uint32_t *)(hashbuffer + rand)) = *((uint32_t *)(hashbuffer + j + randmax)); } } memcpy(hash, hashbuffer, 32); }
void dfescrypt_cpu(uint32_t n, uint32_t *input, uint32_t *output, uint32_t *midstate) { uint32_t* X = (uint32_t*) malloc(sizeof(uint32_t)*32*n); uint32_t* tstates = (uint32_t*) malloc(sizeof(uint32_t)*8*n); uint32_t* ostates = (uint32_t*) malloc(sizeof(uint32_t)*8*n); uint32_t *V; uint32_t i, j, k; uint32_t iterations = HybridcoinMiner_Scrypt_Iterations; char scratchpad[SCRYPT_SCRATCHPAD_SIZE]; V = (uint32_t *)(((uintptr_t)(scratchpad) + 63) & ~ (uintptr_t)(63)); if(NULL == X || NULL == tstates || NULL == ostates){ LOG_FATAL("unable to allocate buffer for Scrypt input!\n"); } #pragma omp parallel for for (int64_t i = 0; i < (int64_t)n; i++) { memcpy(&tstates[i*8], midstate, 32); SHA256_before(&tstates[i*8], &ostates[i*8], &input[20*i], &X[i*32]); } //SCRYPT CORE for (int64_t p = 0; p < (int64_t)n; p++) { uint32_t *Y = &X[p*32]; for (i = 0; i < iterations; i++) { memcpy(&V[i * 32], Y, 128); xor_salsa8(&Y[0], &Y[16]); xor_salsa8(&Y[16], &Y[0]); } for (i = 0; i < iterations; i++) { j = 32 * (Y[16] & (iterations-1)); for (k = 0; k < 32; k++) Y[k] ^= V[j + k]; xor_salsa8(&Y[0], &Y[16]); xor_salsa8(&Y[16], &Y[0]); } } #pragma omp parallel for for (int64_t i = 0; i < (int64_t)n; i++) { SHA256_after(&tstates[i*8], &ostates[i*8], &output[i*8], &X[i*32]); } free(X); free(tstates); free(ostates); }
static inline void scrypt_core(uint32_t *X, uint32_t *V, int N) { uint32_t i, j, k; for (i = 0; i < N; i++) { memcpy(&V[i * 32], X, 128); xor_salsa8(&X[0], &X[16]); xor_salsa8(&X[16], &X[0]); } for (i = 0; i < N; i++) { j = 32 * (X[16] & (N - 1)); for (k = 0; k < 32; k++) X[k] ^= V[j + k]; xor_salsa8(&X[0], &X[16]); xor_salsa8(&X[16], &X[0]); } }
static inline void scrypt_core(unsigned int *X, unsigned int *V) { unsigned int i, j, k; for (i = 0; i < 1024; i++) { memcpy(&V[i * 32], X, 128); xor_salsa8(&X[0], &X[16]); xor_salsa8(&X[16], &X[0]); } for (i = 0; i < 1024; i++) { j = 32 * (X[16] & 1023); for (k = 0; k < 32; k++) X[k] ^= V[j + k]; xor_salsa8(&X[0], &X[16]); xor_salsa8(&X[16], &X[0]); } }