void protoshares_process_8(minerProtosharesBlock_t* block) { // generate mid hash using sha256 (header hash) uint8 midHash[32]; sha256_ctx c256; sha256_init(&c256); sha256_update(&c256, (unsigned char*)block, 80); sha256_final(&c256, midHash); sha256_init(&c256); sha256_update(&c256, (unsigned char*)midHash, 32); sha256_final(&c256, midHash); // init collision map if( __collisionMap == NULL ) __collisionMap = (uint32*)malloc(sizeof(uint32)*COLLISION_TABLE_SIZE); uint32* collisionIndices = __collisionMap; memset(collisionIndices, 0x00, sizeof(uint32)*COLLISION_TABLE_SIZE); // start search // uint8 midHash[64]; uint8 tempHash[32+4]; sha512_ctx c512; uint64 resultHashStorage[8*CACHED_HASHES]; memcpy(tempHash+4, midHash, 32); for(uint32 n=0; n<MAX_MOMENTUM_NONCE; n += BIRTHDAYS_PER_HASH * CACHED_HASHES) { if( block->height != monitorCurrentBlockHeight ) break; for(uint32 m=0; m<CACHED_HASHES; m++) { sha512_init(&c512); *(uint32*)tempHash = n+m*8; sha512_update_final(&c512, tempHash, 32+4, (unsigned char*)(resultHashStorage+8*m)); } for(uint32 m=0; m<CACHED_HASHES; m++) { uint64* resultHash = resultHashStorage + 8*m; uint32 i = n + m*8; for(uint32 f=0; f<8; f++) { uint64 birthday = resultHash[f] >> (64ULL-SEARCH_SPACE_BITS); uint32 collisionKey = (uint32)((birthday>>18) & COLLISION_KEY_MASK); birthday %= COLLISION_TABLE_SIZE; if( collisionIndices[birthday] ) { if( ((collisionIndices[birthday]&COLLISION_KEY_MASK) != collisionKey) || protoshares_revalidateCollision(block, midHash, collisionIndices[birthday]&~COLLISION_KEY_MASK, i+f) == false ) { // invalid collision -> ignore } } collisionIndices[birthday] = i+f | collisionKey; // we have 6 bits available for validation } } } }
void ProtoshareOpenCL::protoshare_process(minerProtosharesBlock_t* block) { #ifdef MEASURE_TIME uint32 overhead = getTimeMilliseconds(); #endif block->nonce = 0; uint32 target = *(uint32*)(block->targetShare + 28); // OpenCLDevice* device = OpenCLMain::getInstance().getDevice(device_num); uint32 midHash[8]; // midHash = sha256(sha256(block)) sha256_ctx c256; sha256_init(&c256); sha256_update(&c256, (unsigned char*)block, 80); sha256_final(&c256, (unsigned char*)midHash); sha256_init(&c256); sha256_update(&c256, (unsigned char*)midHash, 32); sha256_final(&c256, (unsigned char*)midHash); union { cl_ulong b64[16]; cl_uint b32[32]; } hash_state; hash_state.b32[0] = 0; // Reserved for nonce hash_state.b32[1] = midHash[0]; hash_state.b32[2] = midHash[1]; hash_state.b32[3] = midHash[2]; hash_state.b32[4] = midHash[3]; hash_state.b32[5] = midHash[4]; hash_state.b32[6] = midHash[5]; hash_state.b32[7] = midHash[6]; hash_state.b32[8] = midHash[7]; hash_state.b32[9] = 0x80; // High 1 bit to mark end of input // Swap the non-zero b64's except the first (so we can mix in the nonce later) for (uint8 i = 1; i < 5; ++i) { hash_state.b64[i] = SWAP64(hash_state.b64[i]); } #ifdef MEASURE_TIME printf("Hashing...\n"); uint32 begin = getTimeMilliseconds(); #endif // Calculate all hashes kernel_hash->resetArgs(); kernel_hash->addScalarULong(hash_state.b64[0]); kernel_hash->addScalarULong(hash_state.b64[1]); kernel_hash->addScalarULong(hash_state.b64[2]); kernel_hash->addScalarULong(hash_state.b64[3]); kernel_hash->addScalarULong(hash_state.b64[4]); kernel_hash->addGlobalArg(hash_list); kernel_hash->addGlobalArg(index_list); q->enqueueWriteBuffer(mid_hash, hash_state.b32, 10 * sizeof(cl_uint)); q->enqueueKernel1D(kernel_hash, MAX_MOMENTUM_NONCE / BIRTHDAYS_PER_HASH / vect_type, wgs); #ifdef MEASURE_TIME q->finish(); printf("Resetting...\n"); uint32 hash_end = getTimeMilliseconds(); #endif // Reset index list and find collisions cl_uint result_qty = 0; cl_uint result_a[256]; cl_uint result_b[256]; kernel_reset->resetArgs(); kernel_reset->addGlobalArg(hash_list); kernel_reset->addGlobalArg(index_list); kernel_reset->addGlobalArg(nonce_a); kernel_reset->addGlobalArg(nonce_b); kernel_reset->addGlobalArg(nonce_qty); q->enqueueWriteBuffer(nonce_qty, &result_qty, sizeof(cl_uint)); q->enqueueKernel1D(kernel_reset, (1 << buckets_log2), wgs); q->enqueueReadBuffer(nonce_a, result_a, sizeof(cl_uint) * 256); q->enqueueReadBuffer(nonce_b, result_b, sizeof(cl_uint) * 256); q->enqueueReadBuffer(nonce_qty, &result_qty, sizeof(cl_uint)); q->finish(); #ifdef MEASURE_TIME uint32 end = getTimeMilliseconds(); uint32 warmup_skips = 3; if (totalTableCount > warmup_skips) { // Allow some warmup time totalOverhead += (begin - overhead); totalHashTime += (hash_end - begin); totalResetTime += (end - hash_end); } printf("Found %2d collisions in %4d ms (Hash: %4d ms, Reset: %4d ms, Overhead: %4d)\n", result_qty * 2, (end - begin), (hash_end - begin), (end - hash_end), (begin - overhead)); if (totalTableCount > 0 && totalTableCount % 10 == 0) { printf("\nAVG TIMES - Total: %4d, Hash: %4d, Reset: %4d, Overhead: %4d\n\n", (totalHashTime + totalResetTime) / (totalTableCount - warmup_skips), totalHashTime / (totalTableCount - warmup_skips), totalResetTime / (totalTableCount - warmup_skips), totalOverhead / (totalTableCount - warmup_skips)); } #endif for (uint32 i = 0; i < result_qty; i++) { protoshares_revalidateCollision(block, (uint8 *)midHash, result_a[i], result_b[i]); } totalTableCount++; }
void protoshares_process_512(minerProtosharesBlock_t* block, uint32** __collisionMap) { uint8 midHash[32]; sha256_ctx c256; sha256_init(&c256); sha256_update(&c256, (unsigned char*)block, 80); sha256_final(&c256, midHash); sha256_init(&c256); sha256_update(&c256, (unsigned char*)midHash, 32); sha256_final(&c256, midHash); // init collision map if( *__collisionMap == NULL ) { *__collisionMap = (uint32*)malloc(sizeof(uint32)*COLLISION_TABLE_SIZE); } uint32* collisionIndices = *__collisionMap; memset(collisionIndices, 0x00, sizeof(uint32)*COLLISION_TABLE_SIZE); uint8 inHash[32+4]; uint64 outHash[BIRTHDAYS_PER_HASH]; sha512_ctx c512; memcpy(inHash+4, midHash, 32); // count full loop time uint32 firstTick = GetTickCount(); //for (uint32 n = 0; n < MAX_MOMENTUM_NONCE; n+= BIRTHDAYS_PER_HASH) { uint32 n = 0; while (1) { if( block->height != monitorCurrentBlockHeight ) break; if( n >= MAX_MOMENTUM_NONCE ) { //only normal exits count uint32 lastTick = GetTickCount(); looptime += (lastTick - firstTick); numloops++; break; } inline_sha512_init(&c512); *(uint32*)inHash = n; // sha512_update_final(&c512, inHash, 36, (unsigned char*)(outHash)); inline_sha512_update(&c512, inHash, 36); inline_sha512_final(&c512, (unsigned char*)(outHash)); //inline_sha512(inHash, 36, (unsigned char*)(outHash)); // unroll the loop #ifndef UNROLL_LOOPS for(uint32 f=0; f<BIRTHDAYS_PER_HASH; f++) { uint32 birthdayB = outHash[f] >> (64ULL-SEARCH_SPACE_BITS); uint32 collisionKey = (uint32)((birthdayB>>18) & COLLISION_KEY_MASK); uint32 birthday = birthdayB & (COLLISION_TABLE_SIZE-1); if( collisionIndices[birthday] && ((collisionIndices[birthday]&COLLISION_KEY_MASK) == collisionKey)) { protoshares_revalidateCollision(block, midHash, collisionIndices[birthday]&~COLLISION_KEY_MASK, n+f); } else { collisionIndices[birthday] = n+f | collisionKey; // we have 6 bits available for validation } } #else { uint64 birthdayB = outHash[0] >> (64ULL-SEARCH_SPACE_BITS); uint32 collisionKey = (uint32)((birthdayB>>18) & COLLISION_KEY_MASK); uint64 birthday = birthdayB & (COLLISION_TABLE_SIZE-1); if( collisionIndices[birthday] && ((collisionIndices[birthday]&COLLISION_KEY_MASK) == collisionKey)) { protoshares_revalidateCollision(block, midHash, collisionIndices[birthday]&~COLLISION_KEY_MASK, n); } else { collisionIndices[birthday] = n | collisionKey; // we have 6 bits available for validation } } { uint64 birthdayB = outHash[1] >> (64ULL-SEARCH_SPACE_BITS); uint32 collisionKey = (uint32)((birthdayB>>18) & COLLISION_KEY_MASK); uint64 birthday = birthdayB & (COLLISION_TABLE_SIZE-1); if( collisionIndices[birthday] && ((collisionIndices[birthday]&COLLISION_KEY_MASK) == collisionKey)) { protoshares_revalidateCollision(block, midHash, collisionIndices[birthday]&~COLLISION_KEY_MASK, n+1); } else { collisionIndices[birthday] = n+1 | collisionKey; // we have 6 bits available for validation } } { uint64 birthdayB = outHash[2] >> (64ULL-SEARCH_SPACE_BITS); uint32 collisionKey = (uint32)((birthdayB>>18) & COLLISION_KEY_MASK); uint64 birthday = birthdayB & (COLLISION_TABLE_SIZE-1); if( collisionIndices[birthday] && ((collisionIndices[birthday]&COLLISION_KEY_MASK) == collisionKey)) { protoshares_revalidateCollision(block, midHash, collisionIndices[birthday]&~COLLISION_KEY_MASK, n+2); } else { collisionIndices[birthday] = n+2 | collisionKey; // we have 6 bits available for validation } } { uint64 birthdayB = outHash[3] >> (64ULL-SEARCH_SPACE_BITS); uint32 collisionKey = (uint32)((birthdayB>>18) & COLLISION_KEY_MASK); uint64 birthday = birthdayB & (COLLISION_TABLE_SIZE-1); if( collisionIndices[birthday] && ((collisionIndices[birthday]&COLLISION_KEY_MASK) == collisionKey)) { protoshares_revalidateCollision(block, midHash, collisionIndices[birthday]&~COLLISION_KEY_MASK, n+3); } else { collisionIndices[birthday] = n+3 | collisionKey; // we have 6 bits available for validation } } { uint64 birthdayB = outHash[4] >> (64ULL-SEARCH_SPACE_BITS); uint32 collisionKey = (uint32)((birthdayB>>18) & COLLISION_KEY_MASK); uint64 birthday = birthdayB & (COLLISION_TABLE_SIZE-1); if( collisionIndices[birthday] && ((collisionIndices[birthday]&COLLISION_KEY_MASK) == collisionKey)) { protoshares_revalidateCollision(block, midHash, collisionIndices[birthday]&~COLLISION_KEY_MASK, n+4); } else { collisionIndices[birthday] = n+4 | collisionKey; // we have 6 bits available for validation } } { uint64 birthdayB = outHash[5] >> (64ULL-SEARCH_SPACE_BITS); uint32 collisionKey = (uint32)((birthdayB>>18) & COLLISION_KEY_MASK); uint64 birthday = birthdayB & (COLLISION_TABLE_SIZE-1); if( collisionIndices[birthday] && ((collisionIndices[birthday]&COLLISION_KEY_MASK) == collisionKey)) { protoshares_revalidateCollision(block, midHash, collisionIndices[birthday]&~COLLISION_KEY_MASK, n+5); } else { collisionIndices[birthday] = n+5 | collisionKey; // we have 6 bits available for validation } } { uint64 birthdayB = outHash[6] >> (64ULL-SEARCH_SPACE_BITS); uint32 collisionKey = (uint32)((birthdayB>>18) & COLLISION_KEY_MASK); uint64 birthday = birthdayB & (COLLISION_TABLE_SIZE-1); if( collisionIndices[birthday] && ((collisionIndices[birthday]&COLLISION_KEY_MASK) == collisionKey)) { protoshares_revalidateCollision(block, midHash, collisionIndices[birthday]&~COLLISION_KEY_MASK, n+6); } else { collisionIndices[birthday] = n+6 | collisionKey; // we have 6 bits available for validation } } { uint64 birthdayB = outHash[7] >> (64ULL-SEARCH_SPACE_BITS); uint32 collisionKey = (uint32)((birthdayB>>18) & COLLISION_KEY_MASK); uint64 birthday = birthdayB & (COLLISION_TABLE_SIZE-1); if( collisionIndices[birthday] && ((collisionIndices[birthday]&COLLISION_KEY_MASK) == collisionKey)) { protoshares_revalidateCollision(block, midHash, collisionIndices[birthday]&~COLLISION_KEY_MASK, n+7); } else { collisionIndices[birthday] = n+7 | collisionKey; // we have 6 bits available for validation } } #endif n+=BIRTHDAYS_PER_HASH; } }