Compare commits

..

4 Commits

Author SHA1 Message Date
Jay D Dee
51a1d91abd v3.14.2 2020-05-30 21:20:44 -04:00
Jay D Dee
13563e2598 v3.14.1 2020-05-21 13:00:29 -04:00
Jay D Dee
9571f85d53 v3.14.0 2020-05-20 13:56:35 -04:00
Jay D Dee
0e69756634 v3.13.2-segwit-test 2020-05-18 18:17:27 -04:00
10 changed files with 377 additions and 201 deletions

View File

@@ -65,6 +65,35 @@ If not what makes it happen or not happen?
Change Log
----------
v3.14.2
The second line of the Share Accepted log is no longer displayed,
new Xnonce log is added and other small log tweaks.
#265: Cleanup use of mutex.
v3.14.1
GBT and getwork log changes:
fixed missing TTF in New Block log,
ntime no longer byte-swapped for display in New Work log,
fixed zero effective hash rate in Periodic Report log,
deleted "Current block is..." log.
Renamed stratum "New Job" log to "New Work" to be consistent with the solo
version of the log. Added more data to both versions.
v3.14.0
Changes to solo mining:
- segwit is supported by getblocktemplate,
- longpolling is not working and is disabled,
- Periodic Report log is output,
- New Block log includes TTF estimates,
- Stratum thread no longer created when using getwork or GBT.
Fixed BUG log mining sha256d.
v3.13.1.1
Fixed Windows crash mining minotaur algo.

View File

@@ -128,7 +128,7 @@ bool ( *miner_thread_init ) ( int );
void ( *get_new_work ) ( struct work*, struct work*, int, uint32_t* );
// Decode getwork blockheader
bool ( *work_decode ) ( const json_t*, struct work* );
bool ( *work_decode ) ( struct work* );
// Extra getwork data
void ( *decode_extra_data ) ( struct work*, uint64_t* );
@@ -227,8 +227,8 @@ void std_get_new_work( struct work *work, struct work *g_work, int thr_id,
void sha256d_gen_merkle_root( char *merkle_root, struct stratum_ctx *sctx );
void SHA256_gen_merkle_root ( char *merkle_root, struct stratum_ctx *sctx );
bool std_le_work_decode( const json_t *val, struct work *work );
bool std_be_work_decode( const json_t *val, struct work *work );
bool std_le_work_decode( struct work *work );
bool std_be_work_decode( struct work *work );
bool std_le_submit_getwork_result( CURL *curl, struct work *work );
bool std_be_submit_getwork_result( CURL *curl, struct work *work );

View File

@@ -99,9 +99,13 @@ void hodl_build_block_header( struct work* g_work, uint32_t version,
// called only by thread 0, saves a backup of g_work
void hodl_get_new_work( struct work* work, struct work* g_work)
{
work_free( &hodl_work );
work_copy( &hodl_work, g_work );
hodl_work.data[ algo_gate.nonce_index ] = ( clock() + rand() ) % 9999;
pthread_mutex_lock( &g_work_lock );
work_free( &hodl_work );
work_copy( &hodl_work, g_work );
hodl_work.data[ algo_gate.nonce_index ] = ( clock() + rand() ) % 9999;
pthread_mutex_unlock( &g_work_lock );
}
json_t *hodl_longpoll_rpc_call( CURL *curl, int *err, char* lp_url )

View File

@@ -156,6 +156,8 @@ int scanhash_zr5( struct work *work, uint32_t max_nonce,
void zr5_get_new_work( struct work* work, struct work* g_work, int thr_id,
uint32_t* end_nonce_ptr )
{
pthread_mutex_lock( &g_work_lock );
// ignore POK in first word
const int wkcmp_sz = 72; // (19-1) * sizeof(uint32_t)
uint32_t *nonceptr = work->data + algo_gate.nonce_index;
@@ -171,6 +173,8 @@ void zr5_get_new_work( struct work* work, struct work* g_work, int thr_id,
}
else
++(*nonceptr);
pthread_mutex_unlock( &g_work_lock );
}
void zr5_display_pok( struct work* work )

View File

@@ -479,8 +479,8 @@ static inline void sha256d_ms(uint32_t *hash, uint32_t *W,
void sha256d_ms_4way(uint32_t *hash, uint32_t *data,
const uint32_t *midstate, const uint32_t *prehash);
static inline int scanhash_sha256d_4way(int thr_id, struct work *work,
uint32_t max_nonce, uint64_t *hashes_done)
static inline int scanhash_sha256d_4way( struct work *work,
uint32_t max_nonce, uint64_t *hashes_done, struct thr_info *mythr )
{
uint32_t *pdata = work->data;
uint32_t *ptarget = work->target;
@@ -492,6 +492,7 @@ static inline int scanhash_sha256d_4way(int thr_id, struct work *work,
uint32_t n = pdata[19] - 1;
const uint32_t first_nonce = pdata[19];
const uint32_t Htarg = ptarget[7];
int thr_id = mythr->id;
int i, j;
memcpy(data, pdata + 16, 64);
@@ -521,10 +522,8 @@ static inline int scanhash_sha256d_4way(int thr_id, struct work *work,
if (swab32(hash[4 * 7 + i]) <= Htarg) {
pdata[19] = data[4 * 3 + i];
sha256d_80_swap(hash, pdata);
if (fulltest(hash, ptarget)) {
*hashes_done = n - first_nonce + 1;
return 1;
}
if ( fulltest( hash, ptarget ) && !opt_benchmark )
submit_solution( work, hash, mythr );
}
}
} while (n < max_nonce && !work_restart[thr_id].restart);
@@ -541,8 +540,8 @@ static inline int scanhash_sha256d_4way(int thr_id, struct work *work,
void sha256d_ms_8way(uint32_t *hash, uint32_t *data,
const uint32_t *midstate, const uint32_t *prehash);
static inline int scanhash_sha256d_8way(int thr_id, struct work *work,
uint32_t max_nonce, uint64_t *hashes_done)
static inline int scanhash_sha256d_8way( struct work *work,
uint32_t max_nonce, uint64_t *hashes_done, struct thr_info *mythr )
{
uint32_t *pdata = work->data;
uint32_t *ptarget = work->target;
@@ -554,6 +553,7 @@ static inline int scanhash_sha256d_8way(int thr_id, struct work *work,
uint32_t n = pdata[19] - 1;
const uint32_t first_nonce = pdata[19];
const uint32_t Htarg = ptarget[7];
int thr_id = mythr->id;
int i, j;
memcpy(data, pdata + 16, 64);
@@ -583,10 +583,8 @@ static inline int scanhash_sha256d_8way(int thr_id, struct work *work,
if (swab32(hash[8 * 7 + i]) <= Htarg) {
pdata[19] = data[8 * 3 + i];
sha256d_80_swap(hash, pdata);
if (fulltest(hash, ptarget)) {
*hashes_done = n - first_nonce + 1;
return 1;
}
if ( fulltest( hash, ptarget ) && !opt_benchmark )
submit_solution( work, hash, mythr );
}
}
} while (n < max_nonce && !work_restart[thr_id].restart);
@@ -614,13 +612,11 @@ int scanhash_sha256d( struct work *work,
#ifdef HAVE_SHA256_8WAY
if (sha256_use_8way())
return scanhash_sha256d_8way(thr_id, work,
max_nonce, hashes_done);
return scanhash_sha256d_8way( work, max_nonce, hashes_done, mythr );
#endif
#ifdef HAVE_SHA256_4WAY
if (sha256_use_4way())
return scanhash_sha256d_4way(thr_id, work,
max_nonce, hashes_done);
return scanhash_sha256d_4way( work, max_nonce, hashes_done, mythr );
#endif
memcpy(data, pdata + 16, 64);
@@ -657,7 +653,7 @@ int scanhash_SHA256d( struct work *work, const uint32_t max_nonce,
uint32_t n = pdata[19] - 1;
const uint32_t first_nonce = pdata[19];
const uint32_t Htarg = ptarget[7];
int thr_id = mythr->id; // thr_id arg is deprecated
int thr_id = mythr->id;
memcpy( data, pdata, 80 );

20
configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for cpuminer-opt 3.13.1.1.
# Generated by GNU Autoconf 2.69 for cpuminer-opt 3.14.2.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -577,8 +577,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='cpuminer-opt'
PACKAGE_TARNAME='cpuminer-opt'
PACKAGE_VERSION='3.13.1.1'
PACKAGE_STRING='cpuminer-opt 3.13.1.1'
PACKAGE_VERSION='3.14.2'
PACKAGE_STRING='cpuminer-opt 3.14.2'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1332,7 +1332,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.13.1.1 to adapt to many kinds of systems.
\`configure' configures cpuminer-opt 3.14.2 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1404,7 +1404,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of cpuminer-opt 3.13.1.1:";;
short | recursive ) echo "Configuration of cpuminer-opt 3.14.2:";;
esac
cat <<\_ACEOF
@@ -1509,7 +1509,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
cpuminer-opt configure 3.13.1.1
cpuminer-opt configure 3.14.2
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2012,7 +2012,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.13.1.1, which was
It was created by cpuminer-opt $as_me 3.14.2, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2993,7 +2993,7 @@ fi
# Define the identity of the package.
PACKAGE='cpuminer-opt'
VERSION='3.13.1.1'
VERSION='3.14.2'
cat >>confdefs.h <<_ACEOF
@@ -6690,7 +6690,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.13.1.1, which was
This file was extended by cpuminer-opt $as_me 3.14.2, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -6756,7 +6756,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
cpuminer-opt config.status 3.13.1.1
cpuminer-opt config.status 3.14.2
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"

View File

@@ -1,4 +1,4 @@
AC_INIT([cpuminer-opt], [3.13.1.1])
AC_INIT([cpuminer-opt], [3.14.2])
AC_PREREQ([2.59c])
AC_CANONICAL_SYSTEM

View File

@@ -2,8 +2,8 @@
* Copyright 2010 Jeff Garzik
* Copyright 2012-2014 pooler
* Copyright 2014 Lucas Jones
* Copyright 2014 Tanguy Pruvot
* Copyright 2016 Jay D Dee
* Copyright 2014-2016 Tanguy Pruvot
* Copyright 2016-2020 Jay D Dee
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -88,7 +88,7 @@ bool opt_protocol = false;
bool opt_benchmark = false;
bool opt_redirect = true;
bool opt_extranonce = true;
bool want_longpoll = true;
bool want_longpoll = false;
bool have_longpoll = false;
bool have_gbt = true;
bool allow_getwork = true;
@@ -215,7 +215,7 @@ static char const short_options[] =
static struct work g_work __attribute__ ((aligned (64))) = {{ 0 }};
time_t g_work_time = 0;
static pthread_mutex_t g_work_lock;
pthread_mutex_t g_work_lock;
static bool submit_old = false;
char* lp_id;
@@ -398,24 +398,12 @@ void work_copy(struct work *dest, const struct work *src)
int std_get_work_data_size() { return STD_WORK_DATA_SIZE; }
// Default
bool std_le_work_decode( const json_t *val, struct work *work )
bool std_le_work_decode( struct work *work )
{
int i;
const int data_size = algo_gate.get_work_data_size();
const int target_size = sizeof(work->target);
const int adata_sz = data_size / 4;
const int adata_sz = algo_gate.get_work_data_size() / 4;
const int atarget_sz = ARRAY_SIZE(work->target);
if (unlikely( !jobj_binary(val, "data", work->data, data_size) ))
{
applog(LOG_ERR, "JSON invalid data");
return false;
}
if (unlikely( !jobj_binary(val, "target", work->target, target_size) ))
{
applog(LOG_ERR, "JSON invalid target");
return false;
}
for ( i = 0; i < adata_sz; i++ )
work->data[i] = le32dec( work->data + i );
for ( i = 0; i < atarget_sz; i++ )
@@ -423,24 +411,12 @@ bool std_le_work_decode( const json_t *val, struct work *work )
return true;
}
bool std_be_work_decode( const json_t *val, struct work *work )
bool std_be_work_decode( struct work *work )
{
int i;
const int data_size = algo_gate.get_work_data_size();
const int target_size = sizeof(work->target);
const int adata_sz = data_size / 4;
const int adata_sz = algo_gate.get_work_data_size() / 4;
const int atarget_sz = ARRAY_SIZE(work->target);
if (unlikely( !jobj_binary(val, "data", work->data, data_size) ))
{
applog(LOG_ERR, "JSON invalid data");
return false;
}
if (unlikely( !jobj_binary(val, "target", work->target, target_size) ))
{
applog(LOG_ERR, "JSON invalid target");
return false;
}
for ( i = 0; i < adata_sz; i++ )
work->data[i] = be32dec( work->data + i );
for ( i = 0; i < atarget_sz; i++ )
@@ -450,14 +426,31 @@ bool std_be_work_decode( const json_t *val, struct work *work )
static bool work_decode( const json_t *val, struct work *work )
{
if ( !algo_gate.work_decode( val, work ) )
const int data_size = algo_gate.get_work_data_size();
const int target_size = sizeof(work->target);
if (unlikely( !jobj_binary(val, "data", work->data, data_size) ))
{
applog(LOG_ERR, "JSON invalid data");
return false;
}
if (unlikely( !jobj_binary(val, "target", work->target, target_size) ))
{
applog(LOG_ERR, "JSON invalid target");
return false;
}
if ( unlikely( !algo_gate.work_decode( work ) ) )
return false;
if ( !allow_mininginfo )
net_diff = algo_gate.calc_network_diff( work );
work->targetdiff = hash_to_diff( work->target );
stratum_diff = last_targetdiff = work->targetdiff;
work->sharediff = 0;
algo_gate.decode_extra_data( work, &net_blocks );
return true;
}
@@ -477,8 +470,7 @@ static bool get_mininginfo( CURL *curl, struct work *work )
if ( !val && curl_err == -1 )
{
allow_mininginfo = false;
if ( opt_debug )
applog( LOG_DEBUG, "getmininginfo not supported" );
applog( LOG_NOTICE, "\"getmininginfo\" not supported, some stats not available" );
return false;
}
@@ -494,7 +486,7 @@ static bool get_mininginfo( CURL *curl, struct work *work )
if ( json_is_object( key ) )
key = json_object_get( key, "proof-of-work" );
if ( json_is_real( key ) )
net_diff = json_real_value( key );
net_diff = work->targetdiff = json_real_value( key );
}
key = json_object_get( res, "networkhashps" );
@@ -563,6 +555,23 @@ static bool gbt_work_decode( const json_t *val, struct work *work )
json_t *tmp, *txa;
bool rc = false;
// Segwit BEGIN
bool segwit = false;
tmp = json_object_get( val, "rules" );
if ( tmp && json_is_array( tmp ) )
{
n = json_array_size( tmp );
for ( i = 0; i < n; i++ )
{
const char *s = json_string_value( json_array_get( tmp, i ) );
if ( !s )
continue;
if ( !strcmp( s, "segwit" ) || !strcmp( s, "!segwit" ) )
segwit = true;
}
}
// Segwit END
tmp = json_object_get( val, "mutable" );
if ( tmp && json_is_array( tmp ) )
{
@@ -586,7 +595,6 @@ static bool gbt_work_decode( const json_t *val, struct work *work )
goto out;
}
work->height = (int) json_integer_value( tmp );
applog( LOG_BLUE, "Current block is %d", work->height );
tmp = json_object_get(val, "version");
if ( !tmp || !json_is_integer( tmp ) )
@@ -595,7 +603,6 @@ static bool gbt_work_decode( const json_t *val, struct work *work )
goto out;
}
version = (uint32_t) json_integer_value( tmp );
// yescryptr8g uses block version 5 and sapling.
if ( opt_sapling )
work->sapling = true;
@@ -721,13 +728,61 @@ 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;
cbtx[ cbtx_size++ ] = 1; /* out-counter */
// Segwit BEGIN
//cbtx[cbtx_size++] = 1; /* out-counter */
cbtx[cbtx_size++] = segwit ? 2 : 1; /* out-counter */
// Segwit END
le32enc( (uint32_t *)( cbtx+cbtx_size) , (uint32_t)cbvalue ); /* value */
le32enc( (uint32_t *)( cbtx+cbtx_size+4 ), cbvalue >> 32 );
cbtx_size += 8;
cbtx[ cbtx_size++ ] = (uint8_t) pk_script_size; /* txout-script length */
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);
memset(cbtx+cbtx_size, 0, 8); /* value */
cbtx_size += 8;
cbtx[cbtx_size++] = 38; /* txout-script length */
cbtx[cbtx_size++] = 0x6a; /* txout-script */
cbtx[cbtx_size++] = 0x24;
cbtx[cbtx_size++] = 0xaa;
cbtx[cbtx_size++] = 0x21;
cbtx[cbtx_size++] = 0xa9;
cbtx[cbtx_size++] = 0xed;
for ( i = 0; i < tx_count; i++ )
{
const json_t *tx = json_array_get( txa, i );
const json_t *hash = json_object_get(tx, "hash" );
if ( !hash || !hex2bin( wtree[1+i],
json_string_value( hash ), 32 ) )
{
applog(LOG_ERR, "JSON invalid transaction hash");
free(wtree);
goto out;
}
memrev( wtree[1+i], 32 );
}
n = tx_count + 1;
while ( n > 1 )
{
if ( n % 2 )
memcpy( wtree[n], wtree[n-1], 32 );
n = ( n + 1 ) / 2;
for ( i = 0; i < n; i++ )
sha256d( wtree[i], wtree[2*i], 64 );
}
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;
coinbase_append = true;
@@ -795,21 +850,43 @@ static bool gbt_work_decode( const json_t *val, struct work *work )
bin2hex( work->txs + 2*n, cbtx, cbtx_size );
/* generate merkle root */
merkle_tree = (uchar(*)[32]) calloc(((1 + tx_count + 1) & ~1), 32);
sha256d(merkle_tree[0], cbtx, cbtx_size);
merkle_tree = (uchar(*)[32]) calloc( ( (1 + tx_count + 1) & ~1 ), 32 );
sha256d( merkle_tree[0], cbtx, cbtx_size );
for ( i = 0; i < tx_count; i++ )
{
tmp = json_array_get( txa, i );
const char *tx_hex = json_string_value( json_object_get( tmp, "data" ) );
const int tx_size = tx_hex ? (int) ( strlen( tx_hex ) / 2 ) : 0;
unsigned char *tx = (uchar*) malloc( tx_size );
if ( !tx_hex || !hex2bin( tx, tx_hex, tx_size ) )
// Segwit BEGIN
if ( segwit )
{
applog( LOG_ERR, "JSON invalid transactions" );
free( tx );
goto out;
const char *txid = json_string_value( json_object_get( tmp, "txid" ) );
if ( !txid || !hex2bin( merkle_tree[1 + i], txid, 32 ) )
{
applog(LOG_ERR, "JSON invalid transaction txid");
goto out;
}
memrev( merkle_tree[1 + i], 32 );
}
sha256d( merkle_tree[1 + i], tx, tx_size );
else
{
// Segwit END
unsigned char *tx = (uchar*) malloc( tx_size );
if ( !tx_hex || !hex2bin( tx, tx_hex, tx_size ) )
{
applog( LOG_ERR, "JSON invalid transactions" );
free( tx );
goto out;
}
sha256d( merkle_tree[1 + i], tx, tx_size );
free( tx );
// Segwit BEGIN
}
// Segwit END
if ( !submit_coinbase )
strcat( work->txs, tx_hex );
}
@@ -832,7 +909,7 @@ static bool gbt_work_decode( const json_t *val, struct work *work )
swab32( curtime ), le32dec( &bits ),
final_sapling_hash );
if ( unlikely( !jobj_binary(val, "target", target, sizeof(target)) ) )
if ( unlikely( !jobj_binary( val, "target", target, sizeof(target) ) ) )
{
applog( LOG_ERR, "JSON invalid target" );
goto out;
@@ -1031,7 +1108,6 @@ void report_summary_log( bool force )
solved, solved_block_count );
applog2( LOG_INFO, "Hi/Lo Share Diff %.5g / %.5g",
highest_share, lowest_share );
}
bool lowdiff_debug = false;
@@ -1039,7 +1115,7 @@ bool lowdiff_debug = false;
static int share_result( int result, struct work *work,
const char *reason )
{
double share_time = 0., share_ratio = 0.;
double share_time = 0.; //, share_ratio = 0.;
double hashrate = 0.;
int latency = 0;
struct share_stats_t my_stats = {0};
@@ -1051,7 +1127,7 @@ static int share_result( int result, struct work *work,
bool solved = false;
bool stale = false;
char *acol = NULL, *bcol = NULL, *scol = NULL, *rcol = NULL;
// Mutex while we grab a snapshot of the stats.
pthread_mutex_lock( &stats_lock );
if ( likely( share_stats[ s_get_ptr ].submit_time.tv_sec ) )
@@ -1080,8 +1156,11 @@ static int share_result( int result, struct work *work,
sizeof last_submit_time );
}
/*
share_ratio = my_stats.net_diff == 0. ? 0. : my_stats.share_diff /
my_stats.net_diff;
*/
// check result
if ( likely( result ) )
{
@@ -1162,13 +1241,12 @@ static int share_result( int result, struct work *work,
else if ( stale ) scol = CL_WHT CL_YL2;
else rcol = CL_WHT CL_RED;
}
else
bcol = acol = scol = rcol = "\0";
applog( LOG_NOTICE, "%d %s%s %s%s %s%s %s%s" CL_N ", %.3f sec (%dms)",
my_stats.share_count, acol, ares, scol, sres, rcol, rres, bcol,
bres, share_time, latency );
/*
if ( !opt_quiet )
{
if ( have_stratum )
@@ -1182,6 +1260,7 @@ static int share_result( int result, struct work *work,
my_stats.share_diff, share_ratio, bcol, height );
}
}
*/
if ( unlikely( opt_debug || !( opt_quiet || result || stale ) ) )
{
@@ -1405,12 +1484,24 @@ 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\": "
GBT_CAPABILITIES ", \"rules\": " GBT_RULES "}], \"id\":0}\r\n";
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 )
{
@@ -1468,27 +1559,37 @@ start:
if ( rc )
{
if ( opt_protocol )
json_decref( val );
get_mininginfo( curl, work );
report_summary_log( false );
if ( opt_protocol | opt_debug )
{
timeval_subtract( &diff, &tv_end, &tv_start );
applog( LOG_DEBUG, "got new work in %.2f ms",
applog( LOG_INFO, "%s new work received in %.2f ms",
( have_gbt ? "GBT" : "GetWork" ),
( 1000.0 * diff.tv_sec ) + ( 0.001 * diff.tv_usec ) );
}
json_decref( val );
// store work height in solo
get_mininginfo(curl, work);
if ( work->height > last_block_height )
{
last_block_height = work->height;
applog( LOG_BLUE, "New Block %d, Net Diff %.5g, Target Diff %.5g, Ntime %08x",
work->height, net_diff, work->targetdiff,
bswap_32( work->data[ algo_gate.ntime_index ] ) );
last_targetdiff = net_diff;
if ( !opt_quiet && net_diff && net_hashrate )
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;
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++ )
@@ -1497,28 +1598,27 @@ start:
pthread_mutex_unlock( &stats_lock );
if ( miner_hr )
{
double net_hr = net_hashrate;
char net_hr_units[4] = {0};
char miner_hr_units[4] = {0};
char net_ttf[32];
char miner_ttf[32];
if ( net_hr > 0. )
sprintf_et( net_ttf, ( net_diff * exp32 ) / net_hr );
else
sprintf( net_ttf, "NA" );
if ( miner_hr > 0. )
sprintf_et( miner_ttf, ( net_diff * exp32 ) / miner_hr );
else
sprintf( miner_ttf, "NA" );
sprintf_et( net_ttf, ( work->targetdiff * exp32 ) / net_hr );
sprintf_et( miner_ttf, ( work->targetdiff * exp32 ) / miner_hr );
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 );
}
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, Ntime %08lx",
bswap_32( work->data[ algo_gate.ntime_index ] ) );
applog( LOG_BLUE, "New Work: Block %d, Net Diff %.5g, Ntime %08x",
work->height, net_diff,
work->data[ algo_gate.ntime_index ] );
} // rc
return rc;
@@ -1732,6 +1832,14 @@ bool submit_solution( struct work *work, const void *hash,
if ( likely( submit_work( thr, work ) ) )
{
update_submit_stats( work, hash );
if unlikely( !have_stratum && !have_longpoll )
{ // block solved, force getwork
pthread_mutex_lock( &g_work_lock );
g_work_time = 0;
pthread_mutex_unlock( &g_work_lock );
}
if ( !opt_quiet )
{
if ( have_stratum )
@@ -1852,6 +1960,8 @@ void std_get_new_work( struct work* work, struct work* g_work, int thr_id,
uint32_t *nonceptr = work->data + algo_gate.nonce_index;
bool force_new_work = false;
pthread_mutex_lock( &g_work_lock );
if ( have_stratum )
force_new_work = work->job_id ? strtoul( work->job_id, NULL, 16 )
!= strtoul( g_work->job_id, NULL, 16 )
@@ -1867,6 +1977,8 @@ void std_get_new_work( struct work* work, struct work* g_work, int thr_id,
}
else
++(*nonceptr);
pthread_mutex_unlock( &g_work_lock );
}
bool std_ready_to_mine( struct work* work, struct stratum_ctx* stratum,
@@ -1882,7 +1994,13 @@ bool std_ready_to_mine( struct work* work, struct stratum_ctx* stratum,
static void stratum_gen_work( struct stratum_ctx *sctx, struct work *g_work )
{
// Safer than testing the job id
bool new_job = *get_stratum_job_ntime()
!= g_work->data[ algo_gate.ntime_index ];
pthread_mutex_lock( &g_work_lock );
pthread_mutex_lock( &sctx->work_lock );
free( g_work->job_id );
g_work->job_id = strdup( sctx->job.job_id );
g_work->xnonce2_len = sctx->xnonce2_size;
@@ -1893,38 +2011,40 @@ static void stratum_gen_work( struct stratum_ctx *sctx, struct work *g_work )
algo_gate.set_work_data_endian( g_work );
g_work->height = sctx->block_height;
g_work->targetdiff = sctx->job.diff
/ ( opt_target_factor * opt_diff_factor );
/ ( opt_target_factor * opt_diff_factor );
diff_to_hash( g_work->target, g_work->targetdiff );
pthread_mutex_unlock( &sctx->work_lock );
g_work_time = time(NULL);
restart_threads();
if ( opt_debug )
{
unsigned char *xnonce2str = abin2hex( g_work->xnonce2,
g_work->xnonce2_len );
applog( LOG_DEBUG, "DEBUG: job_id='%s' extranonce2=%s ntime=%08x",
g_work->job_id, xnonce2str, swab32( g_work->data[17] ) );
free( xnonce2str );
}
pthread_mutex_unlock( &sctx->work_lock );
pthread_mutex_unlock( &g_work_lock );
double hr = 0.;
pthread_mutex_lock( &stats_lock );
double hr = 0.;
for ( int i = 0; i < opt_n_threads; i++ )
hr += thr_hashrates[i];
global_hashrate = hr;
pthread_mutex_unlock( &stats_lock );
if ( stratum_diff != sctx->job.diff )
applog( LOG_BLUE, "New Diff %g, Block %d, Job %s",
applog( LOG_BLUE, "New Stratum Diff %g, Block %d, Job %s",
sctx->job.diff, sctx->block_height, g_work->job_id );
else if ( last_block_height != sctx->block_height )
applog( LOG_BLUE, "New Block %d, Job %s",
sctx->block_height, g_work->job_id );
else if ( g_work->job_id )
applog( LOG_BLUE,"New Job %s", g_work->job_id );
else if ( new_job && g_work->job_id )
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 )
{
unsigned char *xnonce2str = abin2hex( g_work->xnonce2,
g_work->xnonce2_len );
applog( LOG_INFO, "Extranonce2 %s, Block %d, Net Diff %.5g",
xnonce2str, sctx->block_height, net_diff );
free( xnonce2str );
}
// Update data and calculate new estimates.
if ( ( stratum_diff != sctx->job.diff )
@@ -1952,7 +2072,7 @@ static void stratum_gen_work( struct stratum_ctx *sctx, struct work *g_work )
char share_ttf[32];
sprintf_et( block_ttf, ( net_diff * exp32 ) / hr );
sprintf_et( share_ttf, g_work->targetdiff * exp32 / 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 );
@@ -1968,10 +2088,8 @@ static void stratum_gen_work( struct stratum_ctx *sctx, struct work *g_work )
if ( net_diff && net_ttf )
{
double net_hr = net_diff * exp32 / net_ttf;
// char net_ttf_str[32];
char net_hr_units[4] = {0};
// sprintf_et( net_ttf_str, net_ttf );
scale_hash_for_display ( &net_hr, net_hr_units );
applog2( LOG_INFO, "Net hash rate (est) %.2f %sh/s",
net_hr, net_hr_units );
@@ -2099,35 +2217,33 @@ static void *miner_thread( void *userdata )
{
if ( have_stratum )
{
pthread_mutex_lock( &g_work_lock );
if ( *nonceptr >= end_nonce )
stratum_gen_work( &stratum, &g_work );
algo_gate.get_new_work( &work, &g_work, thr_id, &end_nonce );
pthread_mutex_unlock( &g_work_lock );
if ( *nonceptr >= end_nonce )
stratum_gen_work( &stratum, &g_work );
}
else
{
int scantime = have_longpoll ? LP_SCANTIME : opt_scantime;
pthread_mutex_lock( &g_work_lock );
if ( time(NULL) - g_work_time >= scantime
|| *nonceptr >= end_nonce )
if ( ( ( time(NULL) - g_work_time ) >= scantime )
|| ( *nonceptr >= end_nonce ) )
{
if ( unlikely( !get_work( mythr, &g_work ) ) )
{
pthread_mutex_unlock( &g_work_lock );
applog( LOG_ERR, "work retrieval failed, exiting "
"mining thread %d", thr_id );
pthread_mutex_unlock( &g_work_lock );
goto out;
}
g_work_time = time(NULL);
restart_threads();
}
algo_gate.get_new_work( &work, &g_work, thr_id, &end_nonce );
pthread_mutex_unlock( &g_work_lock );
}
algo_gate.get_new_work( &work, &g_work, thr_id, &end_nonce );
} // do_this_thread
algo_gate.resync_threads( &work );
@@ -2142,7 +2258,7 @@ static void *miner_thread( void *userdata )
// LP_SCANTIME overrides opt_scantime option, is this right?
// adjust max_nonce to meet target scan time. Startum and longpoll
// adjust max_nonce to meet target scan time. Stratum and longpoll
// can go longer because they can rely on restart_threads to signal
// an early abort. get_work on the other hand can't rely on
// restart_threads so need a much shorter scantime
@@ -2213,6 +2329,7 @@ static void *miner_thread( void *userdata )
hashes_done / ( diff.tv_sec + diff.tv_usec * 1e-6 );
pthread_mutex_unlock( &stats_lock );
}
// If unsubmiited nonce(s) found, submit now.
if ( unlikely( nonce_found && !opt_benchmark ) )
{
@@ -2240,34 +2357,47 @@ static void *miner_thread( void *userdata )
}
#if !(defined(__WINDOWS__) || defined(_WIN64) || defined(_WIN32))
// Display CPU temperature and clock rate.
if (!opt_quiet && mythr->id == 0 )
{
int temp = cpu_temp(0);
static struct timeval cpu_temp_time = {0};
timeval_subtract( &diff, &tv_end, &cpu_temp_time );
int wait = temp >= 80 ? 30 : temp >= 70 ? 60 : 120;
if ( ( diff.tv_sec > wait ) || ( temp > hi_temp ) )
// Display CPU temperature and clock rate.
int curr_temp, prev_hi_temp;
static struct timeval cpu_temp_time = {0};
pthread_mutex_lock( &stats_lock );
prev_hi_temp = hi_temp;
curr_temp = cpu_temp(0);
timeval_subtract( &diff, &tv_end, &cpu_temp_time );
if ( curr_temp > hi_temp ) hi_temp = curr_temp;
pthread_mutex_unlock( &stats_lock );
if ( !opt_quiet || ( curr_temp >= 80 ) )
{
int wait_time = curr_temp >= 80 ? 30 : curr_temp >= 70 ? 60 : 120;
if ( ( diff.tv_sec > wait_time ) || ( curr_temp > prev_hi_temp ) )
{
char tempstr[32];
float lo_freq = 0., hi_freq = 0.;
memcpy( &cpu_temp_time, &tv_end, sizeof(cpu_temp_time) );
linux_cpu_hilo_freq( &lo_freq, &hi_freq );
memcpy( &cpu_temp_time, &tv_end, sizeof(cpu_temp_time) );
if ( use_colors && ( temp >= 70 ) )
if ( use_colors && ( curr_temp >= 70 ) )
{
if ( temp >= 80 )
sprintf( tempstr, "%s%d C%s", CL_WHT CL_RED, temp, CL_N );
if ( curr_temp >= 80 )
sprintf( tempstr, "%s%d C%s",
CL_WHT CL_RED, curr_temp, CL_N );
else
sprintf( tempstr, "%s%d C%s", CL_WHT CL_YLW, temp, CL_N );
sprintf( tempstr, "%s%d C%s",
CL_WHT CL_YLW, curr_temp, CL_N );
}
else
sprintf( tempstr, "%d C", temp );
sprintf( tempstr, "%d C", curr_temp );
applog( LOG_NOTICE,"CPU temp: curr %s (max %d), Freq: %.3f/%.3f GHz",
tempstr, hi_temp, lo_freq / 1e6, hi_freq / 1e6 );
if ( temp > hi_temp ) hi_temp = temp;
tempstr, prev_hi_temp, lo_freq / 1e6, hi_freq / 1e6 );
}
}
#endif
// display hashrate
@@ -2293,25 +2423,25 @@ static void *miner_thread( void *userdata )
&& thr_id == opt_n_threads - 1 ) )
{
double hashrate = 0.;
pthread_mutex_lock( &stats_lock );
for ( i = 0; i < opt_n_threads; i++ )
hashrate += thr_hashrates[i];
global_hashrate = hashrate;
pthread_mutex_unlock( &stats_lock );
if ( hashrate != 0. )
if ( opt_benchmark )
{
global_hashrate = hashrate;
if ( opt_benchmark )
{
char hr[16];
char hr_units[2] = {0,0};
scale_hash_for_display( &hashrate, hr_units );
sprintf( hr, "%.2f", hashrate );
char hr[16];
char hr_units[2] = {0,0};
scale_hash_for_display( &hashrate, hr_units );
sprintf( hr, "%.2f", hashrate );
#if ((defined(_WIN64) || defined(__WINDOWS__)) || defined(_WIN32))
applog( LOG_NOTICE, "Total: %s %sH/s", hr, hr_units );
applog( LOG_NOTICE, "Total: %s %sH/s", hr, hr_units );
#else
applog( LOG_NOTICE, "Total: %s %sH/s, CPU temp: %dC",
hr, hr_units, (uint32_t)cpu_temp(0) );
applog( LOG_NOTICE, "Total: %s %sH/s, CPU temp: %dC",
hr, hr_units, (uint32_t)cpu_temp(0) );
#endif
}
}
} // benchmark
} // miner_thread loop
@@ -2629,35 +2759,30 @@ static void *stratum_thread(void *userdata )
report_summary_log( ( stratum_diff != stratum.job.diff )
&& ( stratum_diff != 0. ) );
if ( stratum.job.job_id
&& ( !g_work_time || strcmp( stratum.job.job_id, g_work.job_id ) ) )
{
pthread_mutex_lock( &g_work_lock );
if ( stratum.job.job_id && ( !g_work_time
|| ( *get_stratum_job_ntime()
!= g_work.data[ algo_gate.ntime_index ] ) ) )
stratum_gen_work( &stratum, &g_work );
time( &g_work_time );
pthread_mutex_unlock( &g_work_lock );
restart_threads();
}
if ( likely( stratum_socket_full( &stratum, opt_timeout ) ) )
{
if ( likely( s = stratum_recv_line( &stratum ) ) )
{
if ( likely( !stratum_handle_method( &stratum, s ) ) )
stratum_handle_response( s );
free( s );
}
else
{
applog(LOG_WARNING, "Stratum connection interrupted");
stratum_disconnect( &stratum );
}
}
else
{
applog(LOG_ERR, "Stratum connection timeout");
stratum_disconnect( &stratum );
}
if ( likely( stratum_socket_full( &stratum, opt_timeout ) ) )
{
if ( likely( s = stratum_recv_line( &stratum ) ) )
{
if ( likely( !stratum_handle_method( &stratum, s ) ) )
stratum_handle_response( s );
free( s );
}
else
{
applog(LOG_WARNING, "Stratum connection interrupted");
stratum_disconnect( &stratum );
}
}
else
{
applog(LOG_ERR, "Stratum connection timeout");
stratum_disconnect( &stratum );
}
} // loop
out:
@@ -3217,7 +3342,7 @@ static void show_credits()
{
printf("\n ********** "PACKAGE_NAME" "PACKAGE_VERSION" *********** \n");
printf(" A CPU miner with multi algo support and optimized for CPUs\n");
printf(" with AVX512, SHA and VAES extensions.\n");
printf(" with AVX512, SHA and VAES extensions by JayDDee.\n");
printf(" BTC donation address: 12tdvfF7KmAsihBXQXynT6E6th2c2pByTT\n\n");
}

View File

@@ -313,6 +313,10 @@ size_t address_to_script( unsigned char *out, size_t outsz, const char *addr );
int timeval_subtract( struct timeval *result, struct timeval *x,
struct timeval *y);
// Segwit BEGIN
extern void memrev(unsigned char *p, size_t len);
// Segwit END
// Bitcoin formula for converting difficulty to an equivalent
// number of hashes.
//
@@ -752,6 +756,7 @@ extern double opt_diff_factor;
extern double opt_target_factor;
extern bool opt_randomize;
extern bool allow_mininginfo;
extern pthread_mutex_t g_work_lock;
extern time_t g_work_time;
extern bool opt_stratum_stats;
extern int num_cpus;

13
util.c
View File

@@ -747,6 +747,19 @@ err_out:
return cfg;
}
// Segwit BEGIN
void memrev(unsigned char *p, size_t len)
{
unsigned char c, *q;
for (q = p + len - 1; p < q; p++, q--) {
c = *p;
*p = *q;
*q = c;
}
}
// Segwit END
void cbin2hex(char *out, const char *in, size_t len)
{
if (out) {