diff --git a/Makefile.am b/Makefile.am index 630b294..eb41711 100644 --- a/Makefile.am +++ b/Makefile.am @@ -55,9 +55,6 @@ cpuminer_SOURCES = \ algo/blake/mod_blakecoin.c \ algo/blake/blakecoin.c \ algo/blake/blakecoin-4way.c \ - algo/blake/decred-gate.c \ - algo/blake/decred.c \ - algo/blake/decred-4way.c \ algo/blake/pentablake-gate.c \ algo/blake/pentablake-4way.c \ algo/blake/pentablake.c \ diff --git a/RELEASE_NOTES b/RELEASE_NOTES index d5ea8a8..3c06614 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -65,6 +65,17 @@ If not what makes it happen or not happen? Change Log ---------- +v3.22.0 + +Stratum: faster netdiff calculation. +Merged a few updates from Pooler/cpuminer: + Use CURLOPT_POSTFIELDS in json_rpc_call, + Use CURLINFO_ACTIVESOCKET when supported, + JSONRPC speedup, + Speed up hex2bin function. +Small log improvements, notably more frequent hash rate reports. +Removed decred algo. + v3.21.5 All issues with v3.21.3 & v3.21.4 should be resolved. @@ -77,7 +88,7 @@ Changes since v3.21.2: Windows binaries support CPUs with up to 64 threads. Small optimizations to serialized vectoring. -v3.21.4 +v3.21.4 CANCELLED Reapply selected changes from v3.21.3. #392 #379 #389 Fixed misaligned address segfault solo mining. @@ -86,7 +97,6 @@ Reapply selected changes from v3.21.3. Windows binaries no longer support CPU groups, Windows binaries support CPUs with up to 64 threads. - v3.21.3.1 UNRELEASED Revert to 3.21.2 diff --git a/algo-gate-api.c b/algo-gate-api.c index 73ec286..80584a4 100644 --- a/algo-gate-api.c +++ b/algo-gate-api.c @@ -263,8 +263,6 @@ void init_algo_gate( algo_gate_t* gate ) gate->build_block_header = (void*)&std_build_block_header; gate->build_extraheader = (void*)&std_build_extraheader; gate->set_work_data_endian = (void*)&do_nothing; - gate->calc_network_diff = (void*)&std_calc_network_diff; - gate->ready_to_mine = (void*)&std_ready_to_mine; gate->resync_threads = (void*)&do_nothing; gate->do_this_thread = (void*)&return_true; gate->longpoll_rpc_call = (void*)&std_longpoll_rpc_call; @@ -308,7 +306,6 @@ bool register_algo_gate( int algo, algo_gate_t *gate ) case ALGO_BLAKECOIN: rc = register_blakecoin_algo ( gate ); break; case ALGO_BMW512: rc = register_bmw512_algo ( gate ); break; case ALGO_C11: rc = register_c11_algo ( gate ); break; - case ALGO_DECRED: rc = register_decred_algo ( gate ); break; case ALGO_DEEP: rc = register_deep_algo ( gate ); break; case ALGO_DMD_GR: rc = register_dmd_gr_algo ( gate ); break; case ALGO_GROESTL: rc = register_groestl_algo ( gate ); break; @@ -427,7 +424,6 @@ const char* const algo_alias_map[][2] = { "blake256r8", "blakecoin" }, { "blake256r8vnl", "vanilla" }, { "blake256r14", "blake" }, - { "blake256r14dcr", "decred" }, { "diamond", "dmd-gr" }, { "espers", "hmq1725" }, { "flax", "c11" }, diff --git a/algo-gate-api.h b/algo-gate-api.h index 0710802..8c06a09 100644 --- a/algo-gate-api.h +++ b/algo-gate-api.h @@ -144,7 +144,7 @@ void ( *gen_merkle_root ) ( char*, struct stratum_ctx* ); void ( *build_extraheader ) ( struct work*, struct stratum_ctx* ); void ( *build_block_header ) ( struct work*, uint32_t, uint32_t*, - uint32_t*, uint32_t, uint32_t, + uint32_t*, uint32_t, uint32_t, unsigned char* ); // Build mining.submit message @@ -155,19 +155,13 @@ char* ( *malloc_txs_request ) ( struct work* ); // Big endian or little endian void ( *set_work_data_endian ) ( struct work* ); -double ( *calc_network_diff ) ( struct work* ); - -// Wait for first work -bool ( *ready_to_mine ) ( struct work*, struct stratum_ctx*, int ); - // Diverge mining threads bool ( *do_this_thread ) ( int ); // After do_this_thread void ( *resync_threads ) ( int, struct work* ); -// No longer needed -json_t* (*longpoll_rpc_call) ( CURL*, int*, char* ); +json_t* ( *longpoll_rpc_call ) ( CURL*, int*, char* ); set_t optimizations; int ( *get_work_data_size ) (); @@ -286,8 +280,6 @@ char* std_malloc_txs_request( struct work *work ); // Default is do_nothing, little endian is assumed void set_work_data_big_endian( struct work *work ); -double std_calc_network_diff( struct work *work ); - void std_build_block_header( struct work* g_work, uint32_t version, uint32_t *prevhash, uint32_t *merkle_root, uint32_t ntime, uint32_t nbits, @@ -297,9 +289,6 @@ void std_build_extraheader( struct work *work, struct stratum_ctx *sctx ); json_t* std_longpoll_rpc_call( CURL *curl, int *err, char *lp_url ); -bool std_ready_to_mine( struct work* work, struct stratum_ctx* stratum, - int thr_id ); - int std_get_work_data_size(); // Gate admin functions diff --git a/algo/blake/decred-4way.c b/algo/blake/decred-4way.c deleted file mode 100644 index 9002b54..0000000 --- a/algo/blake/decred-4way.c +++ /dev/null @@ -1,74 +0,0 @@ -#include "decred-gate.h" -#include "blake-hash-4way.h" -#include -#include -#include -#include - -#if defined (DECRED_4WAY) - -static __thread blake256_4way_context blake_mid; - -void decred_hash_4way( void *state, const void *input ) -{ - uint32_t vhash[8*4] __attribute__ ((aligned (64))); -// uint32_t hash0[8] __attribute__ ((aligned (32))); -// uint32_t hash1[8] __attribute__ ((aligned (32))); -// uint32_t hash2[8] __attribute__ ((aligned (32))); -// uint32_t hash3[8] __attribute__ ((aligned (32))); - const void *tail = input + ( DECRED_MIDSTATE_LEN << 2 ); - int tail_len = 180 - DECRED_MIDSTATE_LEN; - blake256_4way_context ctx __attribute__ ((aligned (64))); - - memcpy( &ctx, &blake_mid, sizeof(blake_mid) ); - blake256_4way_update( &ctx, tail, tail_len ); - blake256_4way_close( &ctx, vhash ); - dintrlv_4x32( state, state+32, state+64, state+96, vhash, 256 ); -} - -int scanhash_decred_4way( struct work *work, uint32_t max_nonce, - uint64_t *hashes_done, struct thr_info *mythr ) -{ - uint32_t vdata[48*4] __attribute__ ((aligned (64))); - uint32_t hash[8*4] __attribute__ ((aligned (32))); - uint32_t _ALIGN(64) edata[48]; - uint32_t *pdata = work->data; - uint32_t *ptarget = work->target; - const uint32_t first_nonce = pdata[DECRED_NONCE_INDEX]; - uint32_t n = first_nonce; - const uint32_t HTarget = opt_benchmark ? 0x7f : ptarget[7]; - int thr_id = mythr->id; // thr_id arg is deprecated - - // copy to buffer guaranteed to be aligned. - memcpy( edata, pdata, 180 ); - - // use the old way until new way updated for size. - mm128_intrlv_4x32x( vdata, edata, edata, edata, edata, 180*8 ); - - blake256_4way_init( &blake_mid ); - blake256_4way_update( &blake_mid, vdata, DECRED_MIDSTATE_LEN ); - - uint32_t *noncep = vdata + DECRED_NONCE_INDEX * 4; - do { - * noncep = n; - *(noncep+1) = n+1; - *(noncep+2) = n+2; - *(noncep+3) = n+3; - - decred_hash_4way( hash, vdata ); - - for ( int i = 0; i < 4; i++ ) - if ( (hash+(i<<3))[7] <= HTarget ) - if ( fulltest( hash+(i<<3), ptarget ) && !opt_benchmark ) - { - pdata[DECRED_NONCE_INDEX] = n+i; - submit_solution( work, hash+(i<<3), mythr ); - } - n += 4; - } while ( (n < max_nonce) && !work_restart[thr_id].restart ); - - *hashes_done = n - first_nonce + 1; - return 0; -} - -#endif diff --git a/algo/blake/decred-gate.c b/algo/blake/decred-gate.c deleted file mode 100644 index bee00dd..0000000 --- a/algo/blake/decred-gate.c +++ /dev/null @@ -1,171 +0,0 @@ -#include "decred-gate.h" -#include -#include -#include - -uint32_t *decred_get_nonceptr( uint32_t *work_data ) -{ - return &work_data[ DECRED_NONCE_INDEX ]; -} - -long double decred_calc_network_diff( struct work* work ) -{ - // sample for diff 43.281 : 1c05ea29 - // todo: endian reversed on longpoll could be zr5 specific... - uint32_t nbits = work->data[ DECRED_NBITS_INDEX ]; - uint32_t bits = ( nbits & 0xffffff ); - int16_t shift = ( swab32(nbits) & 0xff ); // 0x1c = 28 - int m; - long double d = (long double)0x0000ffff / (long double)bits; - - for ( m = shift; m < 29; m++ ) - d *= 256.0; - for ( m = 29; m < shift; m++ ) - d /= 256.0; - if ( shift == 28 ) - d *= 256.0; // testnet - if ( opt_debug_diff ) - applog( LOG_DEBUG, "net diff: %f -> shift %u, bits %08x", (double)d, - shift, bits ); - return net_diff; -} - -void decred_decode_extradata( struct work* work, uint64_t* net_blocks ) -{ - // some random extradata to make the work unique - work->data[ DECRED_XNONCE_INDEX ] = (rand()*4); - work->height = work->data[32]; - if (!have_longpoll && work->height > *net_blocks + 1) - { - char netinfo[64] = { 0 }; - if ( net_diff > 0. ) - { - if (net_diff != work->targetdiff) - sprintf(netinfo, ", diff %.3f, target %.1f", net_diff, - work->targetdiff); - else - sprintf(netinfo, ", diff %.3f", net_diff); - } - applog(LOG_BLUE, "%s block %d%s", algo_names[opt_algo], work->height, - netinfo); - *net_blocks = work->height - 1; - } -} - -void decred_be_build_stratum_request( char *req, struct work *work, - struct stratum_ctx *sctx ) -{ - unsigned char *xnonce2str; - uint32_t ntime, nonce; - char ntimestr[9], noncestr[9]; - - be32enc( &ntime, work->data[ DECRED_NTIME_INDEX ] ); - be32enc( &nonce, work->data[ DECRED_NONCE_INDEX ] ); - bin2hex( ntimestr, (char*)(&ntime), sizeof(uint32_t) ); - bin2hex( noncestr, (char*)(&nonce), sizeof(uint32_t) ); - xnonce2str = abin2hex( (char*)( &work->data[ DECRED_XNONCE_INDEX ] ), - sctx->xnonce1_size ); - snprintf( req, JSON_BUF_LEN, - "{\"method\": \"mining.submit\", \"params\": [\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"], \"id\":4}", - rpc_user, work->job_id, xnonce2str, ntimestr, noncestr ); - free(xnonce2str); -} - -#if !defined(min) -#define min(a,b) (a>b ? (b) :(a)) -#endif - -void decred_build_extraheader( struct work* g_work, struct stratum_ctx* sctx ) -{ - uchar merkle_root[64] = { 0 }; - uint32_t extraheader[32] = { 0 }; - int headersize = 0; - uint32_t* extradata = (uint32_t*) sctx->xnonce1; - int i; - - // getwork over stratum, getwork merkle + header passed in coinb1 - memcpy(merkle_root, sctx->job.coinbase, 32); - headersize = min((int)sctx->job.coinbase_size - 32, - sizeof(extraheader) ); - memcpy( extraheader, &sctx->job.coinbase[32], headersize ); - - // Assemble block header - memset( g_work->data, 0, sizeof(g_work->data) ); - g_work->data[0] = le32dec( sctx->job.version ); - for ( i = 0; i < 8; i++ ) - g_work->data[1 + i] = swab32( - le32dec( (uint32_t *) sctx->job.prevhash + i ) ); - for ( i = 0; i < 8; i++ ) - g_work->data[9 + i] = swab32( be32dec( (uint32_t *) merkle_root + i ) ); - -// for ( i = 0; i < 8; i++ ) // prevhash -// g_work->data[1 + i] = swab32( g_work->data[1 + i] ); -// for ( i = 0; i < 8; i++ ) // merkle -// g_work->data[9 + i] = swab32( g_work->data[9 + i] ); - - for ( i = 0; i < headersize/4; i++ ) // header - g_work->data[17 + i] = extraheader[i]; - // extradata - - for ( i = 0; i < sctx->xnonce1_size/4; i++ ) - g_work->data[ DECRED_XNONCE_INDEX + i ] = extradata[i]; - for ( i = DECRED_XNONCE_INDEX + sctx->xnonce1_size/4; i < 45; i++ ) - g_work->data[i] = 0; - g_work->data[37] = (rand()*4) << 8; - // block header suffix from coinb2 (stake version) - memcpy( &g_work->data[44], - &sctx->job.coinbase[ sctx->job.coinbase_size-4 ], 4 ); - sctx->block_height = g_work->data[32]; - //applog_hex(work->data, 180); - //applog_hex(&work->data[36], 36); -} - -#undef min - -bool decred_ready_to_mine( struct work* work, struct stratum_ctx* stratum, - int thr_id ) -{ - if ( have_stratum && strcmp(stratum->job.job_id, work->job_id) ) - // need to regen g_work.. - return false; - if ( have_stratum && !work->data[0] && !opt_benchmark ) - { - sleep(1); - return false; - } - // extradata: prevent duplicates - work->data[ DECRED_XNONCE_INDEX ] += 1; - work->data[ DECRED_XNONCE_INDEX + 1 ] |= thr_id; - return true; -} - -int decred_get_work_data_size() { return DECRED_DATA_SIZE; } - -bool register_decred_algo( algo_gate_t* gate ) -{ -#if defined(DECRED_4WAY) - four_way_not_tested(); - gate->scanhash = (void*)&scanhash_decred_4way; - gate->hash = (void*)&decred_hash_4way; -#else - gate->scanhash = (void*)&scanhash_decred; - gate->hash = (void*)&decred_hash; -#endif - gate->optimizations = AVX2_OPT; -// gate->get_nonceptr = (void*)&decred_get_nonceptr; - gate->decode_extra_data = (void*)&decred_decode_extradata; - gate->build_stratum_request = (void*)&decred_be_build_stratum_request; - gate->work_decode = (void*)&std_be_work_decode; - gate->submit_getwork_result = (void*)&std_be_submit_getwork_result; - gate->build_extraheader = (void*)&decred_build_extraheader; - gate->ready_to_mine = (void*)&decred_ready_to_mine; - gate->nbits_index = DECRED_NBITS_INDEX; - gate->ntime_index = DECRED_NTIME_INDEX; - gate->nonce_index = DECRED_NONCE_INDEX; - gate->get_work_data_size = (void*)&decred_get_work_data_size; - gate->work_cmp_size = DECRED_WORK_COMPARE_SIZE; - allow_mininginfo = false; - have_gbt = false; - return true; -} - diff --git a/algo/blake/decred-gate.h b/algo/blake/decred-gate.h deleted file mode 100644 index 3910b50..0000000 --- a/algo/blake/decred-gate.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef __DECRED_GATE_H__ -#define __DECRED_GATE_H__ - -#include "algo-gate-api.h" -#include - -#define DECRED_NBITS_INDEX 29 -#define DECRED_NTIME_INDEX 34 -#define DECRED_NONCE_INDEX 35 -#define DECRED_XNONCE_INDEX 36 -#define DECRED_DATA_SIZE 192 -#define DECRED_WORK_COMPARE_SIZE 140 -#define DECRED_MIDSTATE_LEN 128 - -#if defined (__AVX2__) -//void blakehash_84way(void *state, const void *input); -//int scanhash_blake_8way( struct work *work, uint32_t max_nonce, -// uint64_t *hashes_done ); -#endif - -#if defined(__SSE4_2__) - #define DECRED_4WAY -#endif - -#if defined (DECRED_4WAY) -void decred_hash_4way(void *state, const void *input); -int scanhash_decred_4way( struct work *work, uint32_t max_nonce, - uint64_t *hashes_done, struct thr_info *mythr ); -#endif - -void decred_hash( void *state, const void *input ); -int scanhash_decred( struct work *work, uint32_t max_nonce, - uint64_t *hashes_done, struct thr_info *mythr ); - -#endif - diff --git a/algo/blake/decred.c b/algo/blake/decred.c deleted file mode 100644 index d60b32b..0000000 --- a/algo/blake/decred.c +++ /dev/null @@ -1,282 +0,0 @@ -#include "decred-gate.h" - -#if !defined(DECRED_8WAY) && !defined(DECRED_4WAY) - -#include "sph_blake.h" - -#include -#include -#include -#include - -/* -#ifndef min -#define min(a,b) (a>b ? b : a) -#endif -#ifndef max -#define max(a,b) (adata; - uint32_t *ptarget = work->target; - int thr_id = mythr->id; // thr_id arg is deprecated - -// #define DCR_NONCE_OFT32 35 - - const uint32_t first_nonce = pdata[DECRED_NONCE_INDEX]; - const uint32_t HTarget = opt_benchmark ? 0x7f : ptarget[7]; - - uint32_t n = first_nonce; - - ctx_midstate_done = false; - -#if 1 - memcpy(endiandata, pdata, 180); -#else - for (int k=0; k < (180/4); k++) - be32enc(&endiandata[k], pdata[k]); -#endif - - do { - //be32enc(&endiandata[DCR_NONCE_OFT32], n); - endiandata[DECRED_NONCE_INDEX] = n; - decred_hash(hash32, endiandata); - - if (hash32[7] <= HTarget && fulltest(hash32, ptarget)) - { - pdata[DECRED_NONCE_INDEX] = n; - submit_solution( work, hash32, mythr ); - } - - n++; - - } while (n < max_nonce && !work_restart[thr_id].restart); - - *hashes_done = n - first_nonce + 1; - pdata[DECRED_NONCE_INDEX] = n; - return 0; -} - -/* -uint32_t *decred_get_nonceptr( uint32_t *work_data ) -{ - return &work_data[ DECRED_NONCE_INDEX ]; -} - -double decred_calc_network_diff( struct work* work ) -{ - // sample for diff 43.281 : 1c05ea29 - // todo: endian reversed on longpoll could be zr5 specific... - uint32_t nbits = work->data[ DECRED_NBITS_INDEX ]; - uint32_t bits = ( nbits & 0xffffff ); - int16_t shift = ( swab32(nbits) & 0xff ); // 0x1c = 28 - int m; - double d = (double)0x0000ffff / (double)bits; - - for ( m = shift; m < 29; m++ ) - d *= 256.0; - for ( m = 29; m < shift; m++ ) - d /= 256.0; - if ( shift == 28 ) - d *= 256.0; // testnet - if ( opt_debug_diff ) - applog( LOG_DEBUG, "net diff: %f -> shift %u, bits %08x", d, - shift, bits ); - return net_diff; -} - -void decred_decode_extradata( struct work* work, uint64_t* net_blocks ) -{ - // some random extradata to make the work unique - work->data[ DECRED_XNONCE_INDEX ] = (rand()*4); - work->height = work->data[32]; - if (!have_longpoll && work->height > *net_blocks + 1) - { - char netinfo[64] = { 0 }; - if (net_diff > 0.) - { - if (net_diff != work->targetdiff) - sprintf(netinfo, ", diff %.3f, target %.1f", net_diff, - work->targetdiff); - else - sprintf(netinfo, ", diff %.3f", net_diff); - } - applog(LOG_BLUE, "%s block %d%s", algo_names[opt_algo], work->height, - netinfo); - *net_blocks = work->height - 1; - } -} - -void decred_be_build_stratum_request( char *req, struct work *work, - struct stratum_ctx *sctx ) -{ - unsigned char *xnonce2str; - uint32_t ntime, nonce; - char ntimestr[9], noncestr[9]; - - be32enc( &ntime, work->data[ DECRED_NTIME_INDEX ] ); - be32enc( &nonce, work->data[ DECRED_NONCE_INDEX ] ); - bin2hex( ntimestr, (char*)(&ntime), sizeof(uint32_t) ); - bin2hex( noncestr, (char*)(&nonce), sizeof(uint32_t) ); - xnonce2str = abin2hex( (char*)( &work->data[ DECRED_XNONCE_INDEX ] ), - sctx->xnonce1_size ); - snprintf( req, JSON_BUF_LEN, - "{\"method\": \"mining.submit\", \"params\": [\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"], \"id\":4}", - rpc_user, work->job_id, xnonce2str, ntimestr, noncestr ); - free(xnonce2str); -} -*/ -/* -// data shared between gen_merkle_root and build_extraheader. -__thread uint32_t decred_extraheader[32] = { 0 }; -__thread int decred_headersize = 0; - -void decred_gen_merkle_root( char* merkle_root, struct stratum_ctx* sctx ) -{ - // getwork over stratum, getwork merkle + header passed in coinb1 - memcpy(merkle_root, sctx->job.coinbase, 32); - decred_headersize = min((int)sctx->job.coinbase_size - 32, - sizeof(decred_extraheader) ); - memcpy( decred_extraheader, &sctx->job.coinbase[32], decred_headersize); -} -*/ - -/* -#define min(a,b) (a>b ? (b) :(a)) - -void decred_build_extraheader( struct work* g_work, struct stratum_ctx* sctx ) -{ - uchar merkle_root[64] = { 0 }; - uint32_t extraheader[32] = { 0 }; - int headersize = 0; - uint32_t* extradata = (uint32_t*) sctx->xnonce1; - size_t t; - int i; - - // getwork over stratum, getwork merkle + header passed in coinb1 - memcpy(merkle_root, sctx->job.coinbase, 32); - headersize = min((int)sctx->job.coinbase_size - 32, - sizeof(extraheader) ); - memcpy( extraheader, &sctx->job.coinbase[32], headersize ); - - // Increment extranonce2 - for ( t = 0; t < sctx->xnonce2_size && !( ++sctx->job.xnonce2[t] ); t++ ); - - // Assemble block header - memset( g_work->data, 0, sizeof(g_work->data) ); - g_work->data[0] = le32dec( sctx->job.version ); - for ( i = 0; i < 8; i++ ) - g_work->data[1 + i] = swab32( - le32dec( (uint32_t *) sctx->job.prevhash + i ) ); - for ( i = 0; i < 8; i++ ) - g_work->data[9 + i] = swab32( be32dec( (uint32_t *) merkle_root + i ) ); - -// for ( i = 0; i < 8; i++ ) // prevhash -// g_work->data[1 + i] = swab32( g_work->data[1 + i] ); -// for ( i = 0; i < 8; i++ ) // merkle -// g_work->data[9 + i] = swab32( g_work->data[9 + i] ); - - for ( i = 0; i < headersize/4; i++ ) // header - g_work->data[17 + i] = extraheader[i]; - // extradata - - for ( i = 0; i < sctx->xnonce1_size/4; i++ ) - g_work->data[ DECRED_XNONCE_INDEX + i ] = extradata[i]; - for ( i = DECRED_XNONCE_INDEX + sctx->xnonce1_size/4; i < 45; i++ ) - g_work->data[i] = 0; - g_work->data[37] = (rand()*4) << 8; - // block header suffix from coinb2 (stake version) - memcpy( &g_work->data[44], - &sctx->job.coinbase[ sctx->job.coinbase_size-4 ], 4 ); - sctx->bloc_height = g_work->data[32]; - //applog_hex(work->data, 180); - //applog_hex(&work->data[36], 36); -} - -#undef min - -bool decred_ready_to_mine( struct work* work, struct stratum_ctx* stratum, - int thr_id ) -{ - if ( have_stratum && strcmp(stratum->job.job_id, work->job_id) ) - // need to regen g_work.. - return false; - if ( have_stratum && !work->data[0] && !opt_benchmark ) - { - sleep(1); - return false; - } - // extradata: prevent duplicates - work->data[ DECRED_XNONCE_INDEX ] += 1; - work->data[ DECRED_XNONCE_INDEX + 1 ] |= thr_id; - return true; -} - - -bool register_decred_algo( algo_gate_t* gate ) -{ - gate->optimizations = SSE2_OPT; - gate->scanhash = (void*)&scanhash_decred; - gate->hash = (void*)&decred_hash; - gate->get_nonceptr = (void*)&decred_get_nonceptr; - gate->decode_extra_data = (void*)&decred_decode_extradata; - gate->build_stratum_request = (void*)&decred_be_build_stratum_request; - gate->work_decode = (void*)&std_be_work_decode; - gate->submit_getwork_result = (void*)&std_be_submit_getwork_result; - gate->build_extraheader = (void*)&decred_build_extraheader; - gate->ready_to_mine = (void*)&decred_ready_to_mine; - gate->nbits_index = DECRED_NBITS_INDEX; - gate->ntime_index = DECRED_NTIME_INDEX; - gate->nonce_index = DECRED_NONCE_INDEX; - gate->work_data_size = DECRED_DATA_SIZE; - gate->work_cmp_size = DECRED_WORK_COMPARE_SIZE; - allow_mininginfo = false; - have_gbt = false; - return true; -} -*/ - -#endif diff --git a/algo/ripemd/lbry-gate.c b/algo/ripemd/lbry-gate.c index d962f50..bb67b81 100644 --- a/algo/ripemd/lbry-gate.c +++ b/algo/ripemd/lbry-gate.c @@ -4,24 +4,6 @@ #include #include -long double lbry_calc_network_diff( struct work *work ) -{ - // sample for diff 43.281 : 1c05ea29 - // todo: endian reversed on longpoll could be zr5 specific... - - uint32_t nbits = swab32( work->data[ LBRY_NBITS_INDEX ] ); - uint32_t bits = (nbits & 0xffffff); - int16_t shift = (swab32(nbits) & 0xff); // 0x1c = 28 - long double d = (long double)0x0000ffff / (long double)bits; - - for (int m=shift; m < 29; m++) d *= 256.0; - for (int m=29; m < shift; m++) d /= 256.0; - if (opt_debug_diff) - applog(LOG_DEBUG, "net diff: %f -> shift %u, bits %08x", d, shift, bits); - - return d; -} - // std_le should work but it doesn't void lbry_le_build_stratum_request( char *req, struct work *work, struct stratum_ctx *sctx ) @@ -41,31 +23,6 @@ void lbry_le_build_stratum_request( char *req, struct work *work, free(xnonce2str); } -/* -void lbry_build_block_header( struct work* g_work, uint32_t version, - uint32_t *prevhash, uint32_t *merkle_root, - uint32_t ntime, uint32_t nbits ) -{ - int i; - memset( g_work->data, 0, sizeof(g_work->data) ); - g_work->data[0] = version; - - if ( have_stratum ) - for ( i = 0; i < 8; i++ ) - g_work->data[1 + i] = le32dec( prevhash + i ); - else - for (i = 0; i < 8; i++) - g_work->data[ 8-i ] = le32dec( prevhash + i ); - - for ( i = 0; i < 8; i++ ) - g_work->data[9 + i] = be32dec( merkle_root + i ); - - g_work->data[ LBRY_NTIME_INDEX ] = ntime; - g_work->data[ LBRY_NBITS_INDEX ] = nbits; - g_work->data[28] = 0x80000000; -} -*/ - void lbry_build_extraheader( struct work* g_work, struct stratum_ctx* sctx ) { unsigned char merkle_root[64] = { 0 }; @@ -112,9 +69,7 @@ bool register_lbry_algo( algo_gate_t* gate ) gate->hash = (void*)&lbry_hash; gate->optimizations = AVX2_OPT | AVX512_OPT | SHA_OPT; #endif - gate->calc_network_diff = (void*)&lbry_calc_network_diff; gate->build_stratum_request = (void*)&lbry_le_build_stratum_request; -// gate->build_block_header = (void*)&build_block_header; gate->build_extraheader = (void*)&lbry_build_extraheader; gate->ntime_index = LBRY_NTIME_INDEX; gate->nbits_index = LBRY_NBITS_INDEX; diff --git a/algo/x17/x17-4way.c b/algo/x17/x17-4way.c index 95a7d63..5c44a18 100644 --- a/algo/x17/x17-4way.c +++ b/algo/x17/x17-4way.c @@ -257,6 +257,7 @@ int scanhash_x17_8way( struct work *work, uint32_t max_nonce, const __m512i eight = m512_const1_64( 8 ); const bool bench = opt_benchmark; + // convert LE32 to LE64 edata[0] = mm128_swap64_32( casti_m128i( pdata, 0 ) ); edata[1] = mm128_swap64_32( casti_m128i( pdata, 1 ) ); edata[2] = mm128_swap64_32( casti_m128i( pdata, 2 ) ); @@ -470,6 +471,7 @@ int scanhash_x17_4way( struct work *work, uint32_t max_nonce, const __m256i four = m256_const1_64( 4 ); const bool bench = opt_benchmark; + // convert LE32 to LE64 edata[0] = mm128_swap64_32( casti_m128i( pdata, 0 ) ); edata[1] = mm128_swap64_32( casti_m128i( pdata, 1 ) ); edata[2] = mm128_swap64_32( casti_m128i( pdata, 2 ) ); diff --git a/configure b/configure index 35b1619..31de0b4 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.71 for cpuminer-opt 3.21.5. +# Generated by GNU Autoconf 2.71 for cpuminer-opt 3.22.0. # # # Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, @@ -608,8 +608,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='cpuminer-opt' PACKAGE_TARNAME='cpuminer-opt' -PACKAGE_VERSION='3.21.5' -PACKAGE_STRING='cpuminer-opt 3.21.5' +PACKAGE_VERSION='3.22.0' +PACKAGE_STRING='cpuminer-opt 3.22.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1360,7 +1360,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures cpuminer-opt 3.21.5 to adapt to many kinds of systems. +\`configure' configures cpuminer-opt 3.22.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1432,7 +1432,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of cpuminer-opt 3.21.5:";; + short | recursive ) echo "Configuration of cpuminer-opt 3.22.0:";; esac cat <<\_ACEOF @@ -1538,7 +1538,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -cpuminer-opt configure 3.21.5 +cpuminer-opt configure 3.22.0 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -1985,7 +1985,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by cpuminer-opt $as_me 3.21.5, which was +It was created by cpuminer-opt $as_me 3.22.0, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -3593,7 +3593,7 @@ fi # Define the identity of the package. PACKAGE='cpuminer-opt' - VERSION='3.21.5' + VERSION='3.22.0' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -7508,7 +7508,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by cpuminer-opt $as_me 3.21.5, which was +This file was extended by cpuminer-opt $as_me 3.22.0, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -7576,7 +7576,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -cpuminer-opt config.status 3.21.5 +cpuminer-opt config.status 3.22.0 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index dfdb0ff..1e79cf9 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([cpuminer-opt], [3.21.5]) +AC_INIT([cpuminer-opt], [3.22.0]) AC_PREREQ([2.59c]) AC_CANONICAL_SYSTEM diff --git a/cpu-miner.c b/cpu-miner.c index 5311a6c..e2ba90c 100644 --- a/cpu-miner.c +++ b/cpu-miner.c @@ -432,20 +432,18 @@ static bool work_decode( const json_t *val, struct work *work ) if ( unlikely( !algo_gate.work_decode( work ) ) ) return false; - if ( !allow_mininginfo ) - net_diff = algo_gate.calc_network_diff( work ); - else - net_diff = hash_to_diff( work->target ); - - work->targetdiff = net_diff; - stratum_diff = last_targetdiff = work->targetdiff; + // many of these aren't used solo. + net_diff = + work->targetdiff = + stratum_diff = + last_targetdiff = hash_to_diff( work->target ); work->sharediff = 0; algo_gate.decode_extra_data( work, &net_blocks ); return true; } -// good alternative for wallet mining, difficulty and net hashrate +// Only used for net_hashrate with GBT/getwork, data is from previous block. static const char *info_req = "{\"method\": \"getmininginfo\", \"params\": [], \"id\":8}\r\n"; @@ -471,17 +469,14 @@ static bool get_mininginfo( CURL *curl, struct work *work ) // "networkhashps": 56475980 if ( res ) { - // net_diff is a global that is set from the work hash target by - // both getwork and GBT. Don't overwrite it, define a local to override - // the global. - double net_diff = 0.; + double difficulty = 0.; json_t *key = json_object_get( res, "difficulty" ); if ( key ) { if ( json_is_object( key ) ) key = json_object_get( key, "proof-of-work" ); if ( json_is_real( key ) ) - net_diff = json_real_value( key ); + difficulty = json_real_value( key ); } key = json_object_get( res, "networkhashps" ); @@ -498,12 +493,13 @@ static bool get_mininginfo( CURL *curl, struct work *work ) net_blocks = json_integer_value( key ); if ( opt_debug ) - applog(LOG_INFO,"Mining info: diff %.5g, net_hashrate %f, height %d", - net_diff, net_hashrate, net_blocks ); - + applog( LOG_INFO,"getmininginfo: difficulty %.5g, networkhashps %.5g, blocks %d", difficulty, net_hashrate, net_blocks ); + if ( !work->height ) { // complete missing data from getwork + if ( opt_debug ) + applog( LOG_DEBUG, "work height set by getmininginfo" ); work->height = (uint32_t) net_blocks + 1; if ( work->height > g_work.height ) restart_threads(); @@ -535,9 +531,8 @@ static bool gbt_work_decode( const json_t *val, struct work *work ) json_t *tmp, *txa; bool rc = false; int i, n; - -// Segwit BEGIN bool segwit = false; + tmp = json_object_get( val, "rules" ); if ( tmp && json_is_array( tmp ) ) { @@ -555,8 +550,7 @@ static bool gbt_work_decode( const json_t *val, struct work *work ) } } } -// Segwit END - + tmp = json_object_get( val, "mutable" ); if ( tmp && json_is_array( tmp ) ) { @@ -638,7 +632,7 @@ static bool gbt_work_decode( const json_t *val, struct work *work ) goto out; } } - + /* find count and size of transactions */ txa = json_object_get(val, "transactions" ); if ( !txa || !json_is_array( txa ) ) @@ -713,12 +707,7 @@ static bool gbt_work_decode( const json_t *val, struct work *work ) cbtx[41] = cbtx_size - 42; /* scriptsig length */ le32enc( (uint32_t *)( cbtx+cbtx_size ), 0xffffffff ); /* sequence */ cbtx_size += 4; - -// Segwit BEGIN - //cbtx[cbtx_size++] = 1; /* out-counter */ - cbtx[cbtx_size++] = segwit ? 2 : 1; /* out-counter */ -// Segwit END - + cbtx[cbtx_size++] = segwit ? 2 : 1; /* out-counter */ le32enc( (uint32_t *)( cbtx+cbtx_size) , (uint32_t)cbvalue ); /* value */ le32enc( (uint32_t *)( cbtx+cbtx_size+4 ), cbvalue >> 32 ); cbtx_size += 8; @@ -726,7 +715,6 @@ static bool gbt_work_decode( const json_t *val, struct work *work ) memcpy( cbtx+cbtx_size, pk_script, pk_script_size ); cbtx_size += (int) pk_script_size; -// Segwit BEGIN if ( segwit ) { unsigned char (*wtree)[32] = calloc(tx_count + 2, 32); @@ -761,12 +749,11 @@ static bool gbt_work_decode( const json_t *val, struct work *work ) for ( i = 0; i < n; i++ ) sha256d( wtree[i], wtree[2*i], 64 ); } - memset( wtree[1], 0, 32 ); /* witness reserved value = 0 */ + memset( wtree[1], 0, 32 ); // witness reserved value = 0 sha256d( cbtx+cbtx_size, wtree[0], 64 ); cbtx_size += 32; free( wtree ); } -// Segwit END le32enc( (uint32_t *)( cbtx+cbtx_size ), 0 ); /* lock time */ cbtx_size += 4; @@ -785,10 +772,8 @@ static bool gbt_work_decode( const json_t *val, struct work *work ) xsig_len += n; } else - { applog( LOG_WARNING, "Signature does not fit in coinbase, skipping" ); - } } tmp = json_object_get( val, "coinbaseaux" ); if ( tmp && json_is_object( tmp ) ) @@ -815,8 +800,8 @@ static bool gbt_work_decode( const json_t *val, struct work *work ) if ( xsig_len ) { unsigned char *ssig_end = cbtx + 42 + cbtx[41]; - int push_len = cbtx[41] + xsig_len < 76 ? 1 : - cbtx[41] + 2 + xsig_len > 100 ? 0 : 2; + int push_len = cbtx[41] + xsig_len < 76 + ? 1 : cbtx[41] + 2 + xsig_len > 100 ? 0 : 2; n = xsig_len + push_len; memmove( ssig_end + n, ssig_end, cbtx_size - 42 - cbtx[41] ); cbtx[41] += n; @@ -843,7 +828,6 @@ static bool gbt_work_decode( const json_t *val, struct work *work ) const char *tx_hex = json_string_value( json_object_get( tmp, "data" ) ); const int tx_size = tx_hex ? (int) ( strlen( tx_hex ) / 2 ) : 0; -// Segwit BEGIN if ( segwit ) { const char *txid = json_string_value( json_object_get( tmp, "txid" ) ); @@ -856,8 +840,6 @@ static bool gbt_work_decode( const json_t *val, struct work *work ) } else { -// Segwit END - unsigned char *tx = (uchar*) malloc( tx_size ); if ( !tx_hex || !hex2bin( tx, tx_hex, tx_size ) ) { @@ -867,10 +849,7 @@ static bool gbt_work_decode( const json_t *val, struct work *work ) } sha256d( merkle_tree[1 + i], tx, tx_size ); free( tx ); - -// Segwit BEGIN } -// Segwit END if ( !submit_coinbase ) strcat( work->txs, tx_hex ); @@ -1080,12 +1059,11 @@ void report_summary_log( bool force ) timeval_subtract( &et, &now, &start_time ); timeval_subtract( &uptime, &total_hashes_time, &session_start ); - double share_time = (double)et.tv_sec + (double)et.tv_usec / 1e6; + double share_time = (double)et.tv_sec + (double)et.tv_usec * 1e-6; double ghrate = safe_div( total_hashes, (double)uptime.tv_sec, 0. ); double target_diff = exp32 * last_targetdiff; double shrate = safe_div( target_diff * (double)(accepts), share_time, 0. ); -// global_hashrate = ghrate; double sess_hrate = safe_div( exp32 * norm_diff_sum, (double)uptime.tv_sec, 0. ); double submit_rate = safe_div( (double)submits * 60., share_time, 0. ); @@ -1106,7 +1084,7 @@ void report_summary_log( bool force ) applog2( LOG_NOTICE, "Periodic Report %s %s", et_str, upt_str ); applog2( LOG_INFO, "Share rate %.2f/min %.2f/min", submit_rate, safe_div( (double)submitted_share_count*60., - ( (double)uptime.tv_sec + (double)uptime.tv_usec / 1e6 ), 0. ) ); + ( (double)uptime.tv_sec + (double)uptime.tv_usec * 1e-6 ), 0. ) ); applog2( LOG_INFO, "Hash rate %7.2f%sh/s %7.2f%sh/s (%.2f%sh/s)", shrate, shr_units, sess_hrate, sess_hr_units, ghrate, ghr_units ); @@ -1553,7 +1531,6 @@ const char *getwork_req = #define GBT_CAPABILITIES "[\"coinbasetxn\", \"coinbasevalue\", \"longpoll\", \"workid\"]" -// Segwit BEGIN #define GBT_RULES "[\"segwit\"]" static const char *gbt_req = "{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": " @@ -1562,16 +1539,6 @@ const char *gbt_lp_req = "{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": " GBT_CAPABILITIES ", \"rules\": " GBT_RULES ", \"longpollid\": \"%s\"}], \"id\":0}\r\n"; -/* -static const char *gbt_req = - "{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": " - GBT_CAPABILITIES "}], \"id\":0}\r\n"; -const char *gbt_lp_req = - "{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": " - GBT_CAPABILITIES ", \"longpollid\": \"%s\"}], \"id\":0}\r\n"; -*/ -// Segwit END - static bool get_upstream_work( CURL *curl, struct work *work ) { json_t *val; @@ -1649,46 +1616,46 @@ start: applog( LOG_BLUE, "New Block %d, Net Diff %.5g, Ntime %08x", work->height, net_diff, work->data[ algo_gate.ntime_index ] ); - - if ( !opt_quiet ) - { - double miner_hr = 0.; - double net_hr = net_hashrate; - double nd = net_diff * exp32; - char net_hr_units[4] = {0}; - char miner_hr_units[4] = {0}; - char net_ttf[32]; - char miner_ttf[32]; - - pthread_mutex_lock( &stats_lock ); - - for ( int i = 0; i < opt_n_threads; i++ ) - miner_hr += thr_hashrates[i]; - global_hashrate = miner_hr; - - pthread_mutex_unlock( &stats_lock ); - - if ( net_hr > 0. ) - sprintf_et( net_ttf, nd / net_hr ); - else - sprintf( net_ttf, "NA" ); - if ( miner_hr > 0. ) - sprintf_et( miner_ttf, nd / miner_hr ); - else - sprintf( miner_ttf, "NA" ); - - scale_hash_for_display ( &miner_hr, miner_hr_units ); - scale_hash_for_display ( &net_hr, net_hr_units ); - applog2( LOG_INFO, - "Miner TTF @ %.2f %sh/s %s, Net TTF @ %.2f %sh/s %s", - miner_hr, miner_hr_units, miner_ttf, net_hr, - net_hr_units, net_ttf ); - } - } // work->height > last_block_height + } else if ( memcmp( &work->data[1], &g_work.data[1], 32 ) ) applog( LOG_BLUE, "New Work: Block %d, Net Diff %.5g, Ntime %08x", - work->height, net_diff, + work->height, net_diff, work->data[ algo_gate.ntime_index ] ); + + if ( !opt_quiet ) + { + double miner_hr = 0.; + double net_hr = net_hashrate; + double nd = net_diff * exp32; + char net_hr_units[4] = {0}; + char miner_hr_units[4] = {0}; + char net_ttf[32]; + char miner_ttf[32]; + + pthread_mutex_lock( &stats_lock ); + + for ( int i = 0; i < opt_n_threads; i++ ) + miner_hr += thr_hashrates[i]; + global_hashrate = miner_hr; + + pthread_mutex_unlock( &stats_lock ); + + if ( net_hr > 0. ) + sprintf_et( net_ttf, nd / net_hr ); + else + sprintf( net_ttf, "NA" ); + if ( miner_hr > 0. ) + sprintf_et( miner_ttf, nd / miner_hr ); + else + sprintf( miner_ttf, "NA" ); + + scale_hash_for_display ( &miner_hr, miner_hr_units ); + scale_hash_for_display ( &net_hr, net_hr_units ); + applog2( LOG_INFO, + "Miner TTF @ %.2f %sh/s %s, Net TTF @ %.2f %sh/s %s", + miner_hr, miner_hr_units, miner_ttf, net_hr, + net_hr_units, net_ttf ); + } } // rc return rc; @@ -1898,9 +1865,9 @@ static void update_submit_stats( struct work *work, const void *hash ) bool submit_solution( struct work *work, const void *hash, struct thr_info *thr ) { - // Job went stale during hashing of a valid share. - if ( !opt_quiet && work_restart[ thr->id ].restart ) - applog( LOG_INFO, CL_LBL "Share may be stale, submitting anyway..." CL_N ); +// Job went stale during hashing of a valid share. +// if ( !opt_quiet && work_restart[ thr->id ].restart ) +// applog( LOG_INFO, CL_LBL "Share may be stale, submitting anyway..." CL_N ); work->sharediff = hash_to_diff( hash ); if ( likely( submit_work( thr, work ) ) ) @@ -1918,32 +1885,34 @@ bool submit_solution( struct work *work, const void *hash, if ( !opt_quiet ) { if ( have_stratum ) + { applog( LOG_INFO, "%d Submitted Diff %.5g, Block %d, Job %s", submitted_share_count, work->sharediff, work->height, work->job_id ); + if ( opt_debug && opt_extranonce ) + { + unsigned char *xnonce2str = abin2hex( work->xnonce2, + work->xnonce2_len ); + applog( LOG_INFO, "Xnonce2 %s", xnonce2str ); + free( xnonce2str ); + } + } else applog( LOG_INFO, "%d Submitted Diff %.5g, Block %d, Ntime %08x", submitted_share_count, work->sharediff, work->height, work->data[ algo_gate.ntime_index ] ); - } - if ( opt_debug ) - { - uint32_t* h = (uint32_t*)hash; - uint32_t* t = (uint32_t*)work->target; - uint32_t* d = (uint32_t*)work->data; + if ( opt_debug ) + { + uint32_t* h = (uint32_t*)hash; + uint32_t* t = (uint32_t*)work->target; + uint32_t* d = (uint32_t*)work->data; - unsigned char *xnonce2str = abin2hex( work->xnonce2, - work->xnonce2_len ); - applog(LOG_INFO,"Thread %d, Nonce %08x, Xnonce2 %s", thr->id, - work->data[ algo_gate.nonce_index ], xnonce2str ); - free( xnonce2str ); - applog(LOG_INFO,"Data[0:19]: %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x", d[0],d[1],d[2],d[3],d[4],d[5],d[6],d[7],d[8],d[9] ); - applog(LOG_INFO," : %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x", d[10],d[11],d[12],d[13],d[14],d[15],d[16],d[17],d[18],d[19]); - applog(LOG_INFO,"Hash[7:0]: %08x %08x %08x %08x %08x %08x %08x %08x", - h[7],h[6],h[5],h[4],h[3],h[2],h[1],h[0]); - applog(LOG_INFO,"Targ[7:0]: %08x %08x %08x %08x %08x %08x %08x %08x", - t[7],t[6],t[5],t[4],t[3],t[2],t[1],t[0]); + applog( LOG_INFO, "Data[ 0: 9]: %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x", d[0],d[1],d[2],d[3],d[4],d[5],d[6],d[7],d[8],d[9] ); + applog( LOG_INFO, "Data[10:19]: %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x", d[10],d[11],d[12],d[13],d[14],d[15],d[16],d[17],d[18],d[19] ); + applog( LOG_INFO, "Hash[ 7: 0]: %08x %08x %08x %08x %08x %08x %08x %08x", h[7],h[6],h[5],h[4],h[3],h[2],h[1],h[0] ); + applog( LOG_INFO, "Targ[ 7: 0]: %08x %08x %08x %08x %08x %08x %08x %08x", t[7],t[6],t[5],t[4],t[3],t[2],t[1],t[0] ); + } } return true; } @@ -2019,33 +1988,6 @@ void set_work_data_big_endian( struct work *work ) be32enc( work->data + i, work->data[i] ); } -// calculate net diff from nbits. -double std_calc_network_diff( struct work* work ) -{ - uint32_t nbits = work->data[ algo_gate.nbits_index ]; - uint32_t shift = nbits & 0xff; - uint32_t bits = bswap_32( nbits ) & 0x00ffffff; -/* - // sample for diff 43.281 : 1c05ea29 - // todo: endian reversed on longpoll could be zr5 specific... - int nbits_index = algo_gate.nbits_index; - uint32_t nbits = have_longpoll ? work->data[ nbits_index] - : swab32( work->data[ nbits_index ] ); - uint32_t bits = ( nbits & 0xffffff ); - int16_t shift = ( swab32(nbits) & 0xff ); // 0x1c = 28 -*/ - - int m; - long double d = (long double)0x0000ffff / (long double)bits; - for ( m = shift; m < 29; m++ ) - d *= 256.0; - for ( m = 29; m < shift; m++ ) - d /= 256.0; - if ( opt_debug_diff ) - applog(LOG_DEBUG, "net diff: %8f -> shift %u, bits %08x", (double)d, shift, bits); - return (double)d; -} - void std_get_new_work( struct work* work, struct work* g_work, int thr_id, uint32_t *end_nonce_ptr ) { @@ -2069,17 +2011,6 @@ void std_get_new_work( struct work* work, struct work* g_work, int thr_id, ++(*nonceptr); } -bool std_ready_to_mine( struct work* work, struct stratum_ctx* stratum, - int thr_id ) -{ - if ( have_stratum && !work->data[0] && !opt_benchmark ) - { - sleep(1); - return false; - } - return true; -} - static void stratum_gen_work( struct stratum_ctx *sctx, struct work *g_work ) { bool new_job; @@ -2096,7 +2027,7 @@ static void stratum_gen_work( struct stratum_ctx *sctx, struct work *g_work ) g_work->xnonce2 = (uchar*) realloc( g_work->xnonce2, sctx->xnonce2_size ); memcpy( g_work->xnonce2, sctx->job.xnonce2, sctx->xnonce2_size ); algo_gate.build_extraheader( g_work, sctx ); - net_diff = algo_gate.calc_network_diff( g_work ); + net_diff = nbits_to_diff( g_work->data[ algo_gate.nbits_index ] ); algo_gate.set_work_data_endian( g_work ); g_work->height = sctx->block_height; g_work->targetdiff = sctx->job.diff @@ -2133,7 +2064,7 @@ static void stratum_gen_work( struct stratum_ctx *sctx, struct work *g_work ) else if ( g_work->job_id && new_job ) applog( LOG_BLUE, "New Work: Block %d, Net diff %.5g, Job %s", sctx->block_height, net_diff, g_work->job_id ); - else if ( opt_debug ) + else if ( !opt_quiet ) { unsigned char *xnonce2str = bebin2hex( g_work->xnonce2, g_work->xnonce2_len ); @@ -2146,8 +2077,6 @@ static void stratum_gen_work( struct stratum_ctx *sctx, struct work *g_work ) if ( ( stratum_diff != sctx->job.diff ) || ( last_block_height != sctx->block_height ) ) { - static bool multipool = false; - if ( stratum.block_height < last_block_height ) multipool = true; if ( unlikely( !session_first_block ) ) session_first_block = stratum.block_height; last_block_height = stratum.block_height; @@ -2155,58 +2084,47 @@ static void stratum_gen_work( struct stratum_ctx *sctx, struct work *g_work ) last_targetdiff = g_work->targetdiff; if ( lowest_share < last_targetdiff ) lowest_share = 9e99; + } - if ( !opt_quiet ) - { - applog2( LOG_INFO, "Diff: Net %.5g, Stratum %.5g, Target %.5g", - net_diff, stratum_diff, g_work->targetdiff ); + if ( !opt_quiet ) + { + applog2( LOG_INFO, "Diff: Net %.5g, Stratum %.5g, Target %.5g", + net_diff, stratum_diff, g_work->targetdiff ); - if ( likely( hr > 0. ) ) - { - double nd = net_diff * exp32; - char hr_units[4] = {0}; - char block_ttf[32]; - char share_ttf[32]; + if ( likely( hr > 0. ) ) + { + double nd = net_diff * exp32; + char hr_units[4] = {0}; + char block_ttf[32]; + char share_ttf[32]; + static bool multipool = false; + + if ( stratum.block_height < last_block_height ) multipool = true; + + sprintf_et( block_ttf, nd / hr ); + sprintf_et( share_ttf, ( g_work->targetdiff * exp32 ) / hr ); + scale_hash_for_display ( &hr, hr_units ); + applog2( LOG_INFO, "TTF @ %.2f %sh/s: Block %s, Share %s", + hr, hr_units, block_ttf, share_ttf ); - sprintf_et( block_ttf, nd / hr ); - sprintf_et( share_ttf, ( g_work->targetdiff * exp32 ) / hr ); - scale_hash_for_display ( &hr, hr_units ); - applog2( LOG_INFO, "TTF @ %.2f %sh/s: Block %s, Share %s", - hr, hr_units, block_ttf, share_ttf ); - - if ( !multipool && last_block_height > session_first_block ) - { - struct timeval now, et; - gettimeofday( &now, NULL ); - timeval_subtract( &et, &now, &session_start ); - uint64_t net_ttf = - ( last_block_height - session_first_block ) == 0 ? 0 - : et.tv_sec / ( last_block_height - session_first_block ); - if ( net_diff > 0. && net_ttf ) - { - double net_hr = nd / net_ttf; - char net_hr_units[4] = {0}; - scale_hash_for_display ( &net_hr, net_hr_units ); - applog2( LOG_INFO, "Net hash rate (est) %.2f %sh/s", - net_hr, net_hr_units ); - } - } - } // hr > 0 - } // !quiet - } // new diff/block - -/* - if ( new_job && !( opt_quiet || stratum_errors ) ) - { - int mismatch = submitted_share_count - ( accepted_share_count - + stale_share_count - + rejected_share_count ); - if ( mismatch ) - applog( LOG_INFO, - CL_LBL "%d Submitted share pending, maybe stale" CL_N, - submitted_share_count ); - } -*/ + if ( !multipool && last_block_height > session_first_block ) + { + struct timeval now, et; + gettimeofday( &now, NULL ); + timeval_subtract( &et, &now, &session_start ); + uint64_t net_ttf = safe_div( et.tv_sec, + last_block_height - session_first_block, 0 ); + if ( net_diff > 0. && net_ttf ) + { + double net_hr = safe_div( nd, net_ttf, 0. ); + char net_hr_units[4] = {0}; + scale_hash_for_display ( &net_hr, net_hr_units ); + applog2( LOG_INFO, "Net hash rate (est) %.2f %sh/s", + net_hr, net_hr_units ); + } + } + } // hr > 0 + } // !quiet } static void *miner_thread( void *userdata ) @@ -2344,9 +2262,6 @@ static void *miner_thread( void *userdata ) } // do_this_thread algo_gate.resync_threads( thr_id, &work ); - if ( unlikely( !algo_gate.ready_to_mine( &work, &stratum, thr_id ) ) ) - continue; - // conditional mining if ( unlikely( !wanna_mine( thr_id ) ) ) { diff --git a/miner.h b/miner.h index 7bfc9f2..f9bba51 100644 --- a/miner.h +++ b/miner.h @@ -330,7 +330,7 @@ extern void cbin2hex(char *out, const char *in, size_t len); void bin2hex( char *s, const unsigned char *p, size_t len ); char *abin2hex( const unsigned char *p, size_t len ); char *bebin2hex( const unsigned char *p, size_t len ); -bool hex2bin( unsigned char *p, const char *hexstr, size_t len ); +bool hex2bin( unsigned char *p, const char *hexstr, const size_t len ); bool jobj_binary( const json_t *obj, const char *key, void *buf, size_t buflen ); int varint_encode( unsigned char *p, uint64_t n ); @@ -346,10 +346,7 @@ extern void memrev(unsigned char *p, size_t len); // number of hashes. // // https://en.bitcoin.it/wiki/Difficulty -// // hash = diff * 2**32 -// -// diff_to_hash = 2**32 = 0x100000000 = 4294967296 = exp32; #define EXP16 65536. #define EXP32 4294967296. @@ -363,8 +360,9 @@ extern const long double exp160; // 2**160 bool fulltest( const uint32_t *hash, const uint32_t *target ); bool valid_hash( const void*, const void* ); -double hash_to_diff( const void* ); +extern double hash_to_diff( const void* ); extern void diff_to_hash( uint32_t*, const double ); +extern double nbits_to_diff( uint32_t ); double hash_target_ratio( uint32_t* hash, uint32_t* target ); void work_set_target_ratio( struct work* work, const void *hash ); @@ -553,7 +551,6 @@ enum algos { ALGO_BMW, ALGO_BMW512, ALGO_C11, - ALGO_DECRED, ALGO_DEEP, ALGO_DMD_GR, ALGO_GROESTL, @@ -647,7 +644,6 @@ static const char* const algo_names[] = { "bmw", "bmw512", "c11", - "decred", "deep", "dmd-gr", "groestl", @@ -808,7 +804,6 @@ Options:\n\ bmw BMW 256\n\ bmw512 BMW 512\n\ c11 Chaincoin\n\ - decred Blake256r14dcr\n\ deep Deepcoin (DCN)\n\ dmd-gr Diamond\n\ groestl Groestl coin\n\ diff --git a/simd-utils/simd-256.h b/simd-utils/simd-256.h index 2580d7a..12ae43b 100644 --- a/simd-utils/simd-256.h +++ b/simd-utils/simd-256.h @@ -15,6 +15,8 @@ // // "_mm256_shuffle_epi8" and "_mm256_alignr_epi8" are restricted to 128 bit // lanes and data can't cross the 128 bit lane boundary. +// Full width byte shuffle is available with AVX512VL using the mask version +// with a full mask (-1). // Instructions that can move data across 128 bit lane boundary incur a // performance penalty over those that can't. // Some usage of index vectors may be encoded as if full vector shuffles are @@ -422,8 +424,7 @@ static inline __m256i mm256_shuflr128_x8( const __m256i v, const int c ) #define mm256_shuflr64_24( v ) _mm256_ror_epi64( v, 24 ) #else #define mm256_shuflr64_24( v ) \ - _mm256_shuffle_epi8( v, _mm256_set_epi64x( \ - 0x0a09080f0e0d0c0b, 0x0201000706050403, \ + _mm256_shuffle_epi8( v, m256_const2_64( \ 0x0a09080f0e0d0c0b, 0x0201000706050403 ) ) #endif @@ -431,8 +432,7 @@ static inline __m256i mm256_shuflr128_x8( const __m256i v, const int c ) #define mm256_shuflr64_16( v ) _mm256_ror_epi64( v, 16 ) #else #define mm256_shuflr64_16( v ) \ - _mm256_shuffle_epi8( v, _mm256_set_epi64x( \ - 0x09080f0e0d0c0b0a, 0x0100070605040302, \ + _mm256_shuffle_epi8( v, m256_const2_64( \ 0x09080f0e0d0c0b0a, 0x0100070605040302 ) ) #endif @@ -440,8 +440,7 @@ static inline __m256i mm256_shuflr128_x8( const __m256i v, const int c ) #define mm256_swap32_16( v ) _mm256_ror_epi32( v, 16 ) #else #define mm256_swap32_16( v ) \ - _mm256_shuffle_epi8( v, _mm256_set_epi64x( \ - 0x0d0c0f0e09080b0a, 0x0504070601000302, \ + _mm256_shuffle_epi8( v, m256_const2_64( \ 0x0d0c0f0e09080b0a, 0x0504070601000302 ) ) #endif #define mm256_shuflr32_16 mm256_swap32_16 @@ -456,35 +455,24 @@ static inline __m256i mm256_shuflr128_x8( const __m256i v, const int c ) 0x0c0f0e0d080b0a09, 0x0407060500030201 ) ) #endif -// NOTE: _mm256_shuffle_epi8, like most shuffles, is restricted to 128 bit -// lanes. AVX512, however, supports full vector 8 bit shuffle. The AVX512VL + -// AVX512BW intrinsic _mm256_mask_shuffle_epi8 with a NULL mask, can be used if -// needed for a shuffle that crosses 128 bit lanes. BSWAP doesn't therefore the -// AVX2 version will work here. The bswap control vector is coded to work -// with both versions, bit 4 is ignored in AVX2. - // Reverse byte order in elements, endian bswap. #define mm256_bswap_64( v ) \ _mm256_shuffle_epi8( v, \ - m256_const_64( 0x18191a1b1c1d1e1f, 0x1011121314151617, \ - 0x08090a0b0c0d0e0f, 0x0001020304050607 ) ) + m256_const2_64( 0x08090a0b0c0d0e0f, 0x0001020304050607 ) ) #define mm256_bswap_32( v ) \ _mm256_shuffle_epi8( v, \ - m256_const_64( 0x1c1d1e1f18191a1b, 0x1415161710111213, \ - 0x0c0d0e0f08090a0b, 0x0405060700010203 ) ) + m256_const2_64( 0x0c0d0e0f08090a0b, 0x0405060700010203 ) ) #define mm256_bswap_16( v ) \ _mm256_shuffle_epi8( v, \ - m256_const_64( 0x1e1f1c1d1a1b1819, 0x1617141512131011, \ - 0x0e0f0c0d0a0b0809, 0x0607040502030001, ) ) + m256_const2_64( 0x0e0f0c0d0a0b0809, 0x0607040502030001, ) ) // Source and destination are pointers, may point to same memory. // 8 byte qword * 8 qwords * 4 lanes = 256 bytes #define mm256_block_bswap_64( d, s ) do \ { \ - __m256i ctl = m256_const_64( 0x18191a1b1c1d1e1f, 0x1011121314151617, \ - 0x08090a0b0c0d0e0f, 0x0001020304050607 ) ; \ + __m256i ctl = m256_const2_64( 0x08090a0b0c0d0e0f, 0x0001020304050607 ) ; \ casti_m256i( d, 0 ) = _mm256_shuffle_epi8( casti_m256i( s, 0 ), ctl ); \ casti_m256i( d, 1 ) = _mm256_shuffle_epi8( casti_m256i( s, 1 ), ctl ); \ casti_m256i( d, 2 ) = _mm256_shuffle_epi8( casti_m256i( s, 2 ), ctl ); \ @@ -498,8 +486,7 @@ static inline __m256i mm256_shuflr128_x8( const __m256i v, const int c ) // 4 byte dword * 8 dwords * 8 lanes = 256 bytes #define mm256_block_bswap_32( d, s ) do \ { \ - __m256i ctl = m256_const_64( 0x1c1d1e1f18191a1b, 0x1415161710111213, \ - 0x0c0d0e0f08090a0b, 0x0405060700010203 ); \ + __m256i ctl = m256_const2_64( 0x0c0d0e0f08090a0b, 0x0405060700010203 ); \ casti_m256i( d, 0 ) = _mm256_shuffle_epi8( casti_m256i( s, 0 ), ctl ); \ casti_m256i( d, 1 ) = _mm256_shuffle_epi8( casti_m256i( s, 1 ), ctl ); \ casti_m256i( d, 2 ) = _mm256_shuffle_epi8( casti_m256i( s, 2 ), ctl ); \ diff --git a/simd-utils/simd-512.h b/simd-utils/simd-512.h index cad8300..dc3f14d 100644 --- a/simd-utils/simd-512.h +++ b/simd-utils/simd-512.h @@ -412,16 +412,16 @@ static inline __m512i mm512_shuflr_x32( const __m512i v, const int n ) #define mm512_shuflr_16( v ) \ _mm512_permutexvar_epi16( m512_const_64( \ 0x0000001F001E001D, 0x001C001B001A0019, \ - 0X0018001700160015, 0X0014001300120011, \ - 0X0010000F000E000D, 0X000C000B000A0009, \ - 0X0008000700060005, 0X0004000300020001 ), v ) + 0x0018001700160015, 0x0014001300120011, \ + 0x0010000F000E000D, 0x000C000B000A0009, \ + 0x0008000700060005, 0x0004000300020001 ), v ) #define mm512_shufll_16( v ) \ _mm512_permutexvar_epi16( m512_const_64( \ 0x001E001D001C001B, 0x001A001900180017, \ - 0X0016001500140013, 0X001200110010000F, \ - 0X000E000D000C000B, 0X000A000900080007, \ - 0X0006000500040003, 0X000200010000001F ), v ) + 0x0016001500140013, 0x001200110010000F, \ + 0x000E000D000C000B, 0x000A000900080007, \ + 0x0006000500040003, 0x000200010000001F ), v ) #define mm512_shuflr_8( v ) \ _mm512_shuffle_epi8( v, m512_const_64( \ diff --git a/util.c b/util.c index fde2d98..f71421a 100644 --- a/util.c +++ b/util.c @@ -44,28 +44,22 @@ #include #endif -//#include "miner.h" #include "elist.h" #include "algo-gate-api.h" #include "algo/sha/sha256d.h" -//extern pthread_mutex_t stats_lock; - -struct data_buffer { - void *buf; - size_t len; -}; - -struct upload_buffer { - const void *buf; - size_t len; - size_t pos; -}; - struct header_info { char *lp_path; char *reason; char *stratum_url; + size_t content_length; +}; + +struct data_buffer { + void *buf; + size_t len; + size_t allocated; + struct header_info *headers; }; struct tq_ent { @@ -127,7 +121,6 @@ void applog2( int prio, const char *fmt, ... ) int len; // struct tm tm; // time_t now = time(NULL); - // localtime_r(&now, &tm); switch ( prio ) @@ -395,67 +388,53 @@ static void databuf_free(struct data_buffer *db) static size_t all_data_cb(const void *ptr, size_t size, size_t nmemb, void *user_data) { - struct data_buffer *db = (struct data_buffer *) user_data; + struct data_buffer *db = user_data; size_t len = size * nmemb; - size_t oldlen, newlen; + size_t newalloc, reqalloc; void *newmem; static const unsigned char zero = 0; + static const size_t max_realloc_increase = 8 * 1024 * 1024; + static const size_t initial_alloc = 16 * 1024; - oldlen = db->len; - newlen = oldlen + len; + /* minimum required allocation size */ + reqalloc = db->len + len + 1; - newmem = realloc(db->buf, newlen + 1); - if (!newmem) - return 0; + if (reqalloc > db->allocated) { + if (db->len > 0) { + newalloc = db->allocated * 2; + } else { + if (db->headers->content_length > 0) + newalloc = db->headers->content_length + 1; + else + newalloc = initial_alloc; + } - db->buf = newmem; - db->len = newlen; - memcpy((uchar*) db->buf + oldlen, ptr, len); - memcpy((uchar*) db->buf + newlen, &zero, 1); /* null terminate */ + if (db->headers->content_length == 0) { + /* limit the maximum buffer increase */ + if (newalloc - db->allocated > max_realloc_increase) + newalloc = db->allocated + max_realloc_increase; + } + + /* ensure we have a big enough allocation */ + if (reqalloc > newalloc) + newalloc = reqalloc; + + newmem = realloc(db->buf, newalloc); + if (!newmem) + return 0; + + db->buf = newmem; + db->allocated = newalloc; + } + + memcpy(db->buf + db->len, ptr, len); /* append new data */ + memcpy(db->buf + db->len + len, &zero, 1); /* null terminate */ + + db->len += len; return len; } -static size_t upload_data_cb(void *ptr, size_t size, size_t nmemb, - void *user_data) -{ - struct upload_buffer *ub = (struct upload_buffer *) user_data; - size_t len = size * nmemb; - - if (len > ub->len - ub->pos) - len = ub->len - ub->pos; - - if (len) { - memcpy(ptr, ((uchar*)ub->buf) + ub->pos, len); - ub->pos += len; - } - - return len; -} - -#if LIBCURL_VERSION_NUM >= 0x071200 -static int seek_data_cb(void *user_data, curl_off_t offset, int origin) -{ - struct upload_buffer *ub = (struct upload_buffer *) user_data; - - switch (origin) { - case SEEK_SET: - ub->pos = (size_t) offset; - break; - case SEEK_CUR: - ub->pos += (size_t) offset; - break; - case SEEK_END: - ub->pos = ub->len + (size_t) offset; - break; - default: - return 1; /* CURL_SEEKFUNC_FAIL */ - } - - return 0; /* CURL_SEEKFUNC_OK */ -} -#endif - static size_t resp_hdr_cb(void *ptr, size_t size, size_t nmemb, void *user_data) { struct header_info *hi = (struct header_info *) user_data; @@ -505,6 +484,9 @@ static size_t resp_hdr_cb(void *ptr, size_t size, size_t nmemb, void *user_data) val = NULL; } + if (!strcasecmp("Content-Length", key)) + hi->content_length = strtoul(val, NULL, 10); + out: free(key); free(val); @@ -564,48 +546,37 @@ json_t *json_rpc_call(CURL *curl, const char *url, int rc; long http_rc; struct data_buffer all_data = {0}; - struct upload_buffer upload_data; char *json_buf; json_error_t err; struct curl_slist *headers = NULL; - char len_hdr[64]; char curl_err_str[CURL_ERROR_SIZE] = { 0 }; long timeout = (flags & JSON_RPC_LONGPOLL) ? opt_timeout : 30; struct header_info hi = {0}; /* it is assumed that 'curl' is freshly [re]initialized at this pt */ - if (opt_protocol) - curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); + if (opt_protocol) curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); curl_easy_setopt(curl, CURLOPT_URL, url); - if (opt_cert) - curl_easy_setopt(curl, CURLOPT_CAINFO, opt_cert); -// - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); - + if (opt_cert) curl_easy_setopt(curl, CURLOPT_CAINFO, opt_cert); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); curl_easy_setopt(curl, CURLOPT_ENCODING, ""); curl_easy_setopt(curl, CURLOPT_FAILONERROR, 0); curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, all_data_cb); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &all_data); - curl_easy_setopt(curl, CURLOPT_READFUNCTION, upload_data_cb); - curl_easy_setopt(curl, CURLOPT_READDATA, &upload_data); -#if LIBCURL_VERSION_NUM >= 0x071200 - curl_easy_setopt(curl, CURLOPT_SEEKFUNCTION, &seek_data_cb); - curl_easy_setopt(curl, CURLOPT_SEEKDATA, &upload_data); -#endif - curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_err_str); - if (opt_redirect) - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_err_str); + if (opt_redirect) curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, resp_hdr_cb); curl_easy_setopt(curl, CURLOPT_HEADERDATA, &hi); - if (opt_proxy) { + if (opt_proxy) + { curl_easy_setopt(curl, CURLOPT_PROXY, opt_proxy); curl_easy_setopt(curl, CURLOPT_PROXYTYPE, opt_proxy_type); } - if (userpass) { + if (userpass) + { curl_easy_setopt(curl, CURLOPT_USERPWD, userpass); curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); } @@ -613,23 +584,16 @@ json_t *json_rpc_call(CURL *curl, const char *url, if (flags & JSON_RPC_LONGPOLL) curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_keepalive_cb); #endif - curl_easy_setopt(curl, CURLOPT_POST, 1); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, rpc_req); if (opt_protocol) applog(LOG_DEBUG, "JSON protocol request:\n%s\n", rpc_req); - upload_data.buf = rpc_req; - upload_data.len = strlen(rpc_req); - upload_data.pos = 0; - sprintf(len_hdr, "Content-Length: %lu", - (unsigned long) upload_data.len); - headers = curl_slist_append(headers, "Content-Type: application/json"); - headers = curl_slist_append(headers, len_hdr); headers = curl_slist_append(headers, "User-Agent: " USER_AGENT); headers = curl_slist_append(headers, "X-Mining-Extensions: longpoll reject-reason"); - //headers = curl_slist_append(headers, "Accept:"); /* disable Accept hdr*/ - //headers = curl_slist_append(headers, "Expect:"); /* disable Expect hdr*/ + //headers = curl_slist_append(headers, "Accept:"); // disable Accept hdr + //headers = curl_slist_append(headers, "Expect:"); // disable Expect hdr curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); @@ -791,7 +755,6 @@ void memrev(unsigned char *p, size_t len) if ( len == 32 ) { __m128i *pv = (__m128i*)p; - __m128i t = mm128_bswap_128( pv[0] ); pv[0] = mm128_bswap_128( pv[1] ); pv[1] = t; @@ -841,32 +804,42 @@ char *bebin2hex(const unsigned char *p, size_t len) return s; } -bool hex2bin(unsigned char *p, const char *hexstr, size_t len) +bool hex2bin( unsigned char *p, const char *hexstr, const size_t len ) { - char hex_byte[3]; - char *ep; + if( hexstr == NULL ) return false; - hex_byte[2] = '\0'; - - while (*hexstr && len) { - if (!hexstr[1]) { - applog(LOG_ERR, "hex2bin str truncated"); - return false; - } - hex_byte[0] = hexstr[0]; - hex_byte[1] = hexstr[1]; - *p = (unsigned char) strtol(hex_byte, &ep, 16); - if (*ep) { - applog(LOG_ERR, "hex2bin failed on '%s'", hex_byte); - return false; - } - p++; - hexstr += 2; - len--; + size_t hexstr_len = strlen( hexstr ); + if( ( hexstr_len % 2 ) != 0 ) + { + applog( LOG_ERR, "hex2bin string truncated" ); + return false; + } + size_t bin_len = hexstr_len / 2; + if ( bin_len > len ) + { + applog( LOG_ERR, "hex2bin buffer too small" ); + return false; } - return(!len) ? true : false; -/* return (len == 0 && *hexstr == 0) ? true : false; */ + memset( p, 0, len ); + size_t i = 0; + while ( i < hexstr_len ) + { + char c = hexstr[i]; + unsigned char nibble; + if ( c >= '0' && c <= '9' ) nibble = (c - '0'); + else if ( c >= 'A' && c <= 'F' ) nibble = ( 10 + (c - 'A') ); + else if ( c >= 'a' && c <= 'f' ) nibble = ( 10 + (c - 'a') ); + else + { + applog( LOG_ERR, "hex2bin invalid hex" ); + return false; + } + p[(i / 2)] |= (nibble << ( (1 - (i % 2) ) * 4) ); + i++; + } + + return true; } int varint_encode(unsigned char *p, uint64_t n) @@ -1348,6 +1321,43 @@ inline bool valid_hash( const void *hash, const void *target ) #endif +inline double nbits_to_diff( uint32_t nbits ) +{ + long double diff; + uint32_t shift = nbits & 0xff; + uint32_t bits = bswap_32( nbits ) & 0x00ffffff; + int shift_off = (int)shift - 29; + + // diff = ( (2**16 -1) / ( 256**shift_off * bits ) + // With uint128 byte shift is good for 16 <= shift <= 41. As unlikely + // as this may seem necessary, check just in case. + + if ( shift_off >= -13 && shift_off <= 12 ) + { // fast + if ( shift_off == 0 ) + diff = (long double)0xffff / (long double)bits; + else if ( shift_off < 0 ) // shift < 29 + diff = (long double)( (uint128_t)0xffff << ( (-shift_off) *8 ) ) + / (long double)bits; + else // ( shift_off > 0 ) // shift > 29 + diff = (long double)0xffff + / (long double)( (uint128_t)bits << ( shift_off*8 ) ); + } + else + { // slow + int m; + diff = 0.; + for ( m = shift; m < 29; m++ ) diff *= 256.0; + for ( m = 29; m < shift; m++ ) diff /= 256.0; + } + + if ( opt_debug ) + applog( LOG_INFO, "nbits %08x: shift %u(%d), bits %06x, diff %8g", + nbits, shift, shift_off, bits, (double)diff ); + + return (double)diff; +} + #ifdef WIN32 #define socket_blocks() (WSAGetLastError() == WSAEWOULDBLOCK) #else @@ -1516,7 +1526,8 @@ out: return sret; } -#if LIBCURL_VERSION_NUM >= 0x071101 +#if LIBCURL_VERSION_NUM >= 0x071101 && LIBCURL_VERSION_NUM < 0x072d00 +//#if LIBCURL_VERSION_NUM >= 0x071101 static curl_socket_t opensocket_grab_cb(void *clientp, curlsocktype purpose, struct curl_sockaddr *addr) { @@ -1584,7 +1595,8 @@ bool stratum_connect(struct stratum_ctx *sctx, const char *url) #if LIBCURL_VERSION_NUM >= 0x070f06 curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_keepalive_cb); #endif -#if LIBCURL_VERSION_NUM >= 0x071101 +#if LIBCURL_VERSION_NUM >= 0x071101 && LIBCURL_VERSION_NUM < 0x072d00 +//#if LIBCURL_VERSION_NUM >= 0x071101 curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, opensocket_grab_cb); curl_easy_setopt(curl, CURLOPT_OPENSOCKETDATA, &sctx->sock); #endif @@ -1598,7 +1610,10 @@ bool stratum_connect(struct stratum_ctx *sctx, const char *url) return false; } -#if LIBCURL_VERSION_NUM < 0x071101 +#if LIBCURL_VERSION_NUM >= 0x072d00 + curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sctx->sock); +#elif LIBCURL_VERSION_NUM < 0x071101 +//#if LIBCURL_VERSION_NUM < 0x071101 /* CURLINFO_LASTSOCKET is broken on Win64; only use it as a last resort */ curl_easy_getinfo(curl, CURLINFO_LASTSOCKET, (long *)&sctx->sock); #endif @@ -1894,7 +1909,8 @@ static uint32_t getblocheight(struct stratum_ctx *sctx) // find 0xffff tag p = (uint8_t*) sctx->job.coinbase + 32; - m = p + 128; + m = p + sctx->job.coinbase_size - 32 - 2; +// m = p + 128; while (*p != 0xff && p < m) p++; while (*p == 0xff && p < m) p++; if (*(p-1) == 0xff && *(p-2) == 0xff) {