This commit is contained in:
Jay D Dee
2018-02-25 14:15:07 -05:00
parent c24a4bdbc2
commit 157508bd07
10 changed files with 653 additions and 457 deletions

View File

@@ -90,7 +90,8 @@ Additional optional compile flags, add the following to CFLAGS to activate:
SPH may give slightly better performance on algos that use sha256 when using SPH may give slightly better performance on algos that use sha256 when using
openssl 1.0.1 or older. Openssl 1.0.2 adds AVX2 and 1.1 adds SHA and perform openssl 1.0.1 or older. Openssl 1.0.2 adds AVX2 and 1.1 adds SHA and perform
better than SPH. better than SPH. This option is ignored when 4-way is used, even for CPUs
with SHA.
Start mining. Start mining.
@@ -159,6 +160,12 @@ Support for even older x86_64 without AES_NI or SSE2 is not availble.
Change Log Change Log
---------- ----------
v3.8.3.3
Integrated getblocktemplate with algo_gate.
Added support for hodl gbt (untested).
Reworked some recent quick fixes.
v3.8.3.2 v3.8.3.2
Reverted gbt changes from v3.8.0 that broke getwork. Reverted gbt changes from v3.8.0 that broke getwork.

View File

@@ -119,9 +119,11 @@ void init_algo_gate( algo_gate_t* gate )
gate->gen_merkle_root = (void*)&sha256d_gen_merkle_root; gate->gen_merkle_root = (void*)&sha256d_gen_merkle_root;
gate->stratum_gen_work = (void*)&std_stratum_gen_work; gate->stratum_gen_work = (void*)&std_stratum_gen_work;
gate->build_stratum_request = (void*)&std_le_build_stratum_request; gate->build_stratum_request = (void*)&std_le_build_stratum_request;
gate->malloc_txs_request = (void*)&std_malloc_txs_request;
gate->set_target = (void*)&std_set_target; gate->set_target = (void*)&std_set_target;
gate->work_decode = (void*)&std_le_work_decode; gate->work_decode = (void*)&std_le_work_decode;
gate->submit_getwork_result = (void*)&std_le_submit_getwork_result; gate->submit_getwork_result = (void*)&std_le_submit_getwork_result;
gate->build_block_header = (void*)&std_build_block_header;
gate->build_extraheader = (void*)&std_build_extraheader; gate->build_extraheader = (void*)&std_build_extraheader;
gate->set_work_data_endian = (void*)&do_nothing; gate->set_work_data_endian = (void*)&do_nothing;
gate->calc_network_diff = (void*)&std_calc_network_diff; gate->calc_network_diff = (void*)&std_calc_network_diff;

View File

@@ -127,7 +127,10 @@ void ( *set_target) ( struct work*, double );
bool ( *submit_getwork_result ) ( CURL*, struct work* ); bool ( *submit_getwork_result ) ( CURL*, struct work* );
void ( *gen_merkle_root ) ( char*, struct stratum_ctx* ); void ( *gen_merkle_root ) ( char*, struct stratum_ctx* );
void ( *build_extraheader ) ( struct work*, 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 );
void ( *build_stratum_request ) ( char*, struct work*, struct stratum_ctx* ); void ( *build_stratum_request ) ( char*, struct work*, struct stratum_ctx* );
char* ( *malloc_txs_request ) ( struct work* );
void ( *set_work_data_endian ) ( struct work* ); void ( *set_work_data_endian ) ( struct work* );
double ( *calc_network_diff ) ( struct work* ); double ( *calc_network_diff ) ( struct work* );
bool ( *ready_to_mine ) ( struct work*, struct stratum_ctx*, int ); bool ( *ready_to_mine ) ( struct work*, struct stratum_ctx*, int );
@@ -228,11 +231,17 @@ void std_le_build_stratum_request( char *req, struct work *work );
void std_be_build_stratum_request( char *req, struct work *work ); void std_be_build_stratum_request( char *req, struct work *work );
void jr2_build_stratum_request ( char *req, struct work *work ); void jr2_build_stratum_request ( char *req, struct work *work );
char* std_malloc_txs_request( struct work *work );
// Default is do_nothing (assumed LE) // Default is do_nothing (assumed LE)
void set_work_data_big_endian( struct work *work ); void set_work_data_big_endian( struct work *work );
double std_calc_network_diff( 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 );
void std_build_extraheader( struct work *work, struct stratum_ctx *sctx ); void std_build_extraheader( struct work *work, struct stratum_ctx *sctx );
json_t* std_longpoll_rpc_call( CURL *curl, int *err, char *lp_url ); json_t* std_longpoll_rpc_call( CURL *curl, int *err, char *lp_url );

View File

@@ -42,15 +42,83 @@ void hodl_le_build_stratum_request( char* req, struct work* work,
free( xnonce2str ); free( xnonce2str );
} }
void hodl_build_extraheader( struct work* g_work, struct stratum_ctx *sctx ) char* hodl_malloc_txs_request( struct work *work )
{ {
uchar merkle_root[64] = { 0 }; char* req;
size_t t; json_t *val;
char data_str[2 * sizeof(work->data) + 1];
int i; int i;
algo_gate.gen_merkle_root( merkle_root, sctx ); for ( i = 0; i < ARRAY_SIZE(work->data); i++ )
be32enc( work->data + i, work->data[i] );
bin2hex( data_str, (unsigned char *)work->data, 88 );
if ( work->workid )
{
char *params;
val = json_object();
json_object_set_new( val, "workid", json_string( work->workid ) );
params = json_dumps( val, 0 );
json_decref( val );
req = malloc( 128 + 2*88 + strlen( work->txs ) + strlen( params ) );
sprintf( req,
"{\"method\": \"submitblock\", \"params\": [\"%s%s\", %s], \"id\":1}\r\n",
data_str, work->txs, params);
free( params );
}
else
{
req = malloc( 128 + 2*88 + strlen(work->txs));
sprintf( req,
"{\"method\": \"submitblock\", \"params\": [\"%s%s\"], \"id\":1}\r\n",
data_str, work->txs);
}
return req;
}
void hodl_build_block_header( struct work* g_work, uint32_t version,
uint32_t *prevhash, uint32_t *merkle_tree,
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_tree + i );
g_work->data[ algo_gate.ntime_index ] = ntime;
g_work->data[ algo_gate.nbits_index ] = nbits;
g_work->data[22] = 0x80000000;
g_work->data[31] = 0x00000280;
}
// hodl build_extra_header is redundant, hodl can use std_build_extra_header
// and call hodl_build_block_header.
#if 0
void hodl_build_extraheader( struct work* g_work, struct stratum_ctx *sctx )
{
uchar merkle_tree[64] = { 0 };
size_t t;
// int i;
algo_gate.gen_merkle_root( merkle_tree, sctx );
// Increment extranonce2 // Increment extranonce2
for ( t = 0; t < sctx->xnonce2_size && !( ++sctx->job.xnonce2[t] ); t++ ); for ( t = 0; t < sctx->xnonce2_size && !( ++sctx->job.xnonce2[t] ); t++ );
algo_gate.build_block_header( g_work, le32dec( sctx->job.version ),
(uint32_t*) sctx->job.prevhash, (uint32_t*) merkle_tree,
le32dec( sctx->job.ntime ), le32dec( sctx->job.nbits ) );
/*
// Assemble block header // Assemble block header
memset( g_work->data, 0, sizeof(g_work->data) ); memset( g_work->data, 0, sizeof(g_work->data) );
g_work->data[0] = le32dec( sctx->job.version ); g_work->data[0] = le32dec( sctx->job.version );
@@ -63,7 +131,9 @@ void hodl_build_extraheader( struct work* g_work, struct stratum_ctx *sctx )
g_work->data[ algo_gate.nbits_index ] = le32dec( sctx->job.nbits ); g_work->data[ algo_gate.nbits_index ] = le32dec( sctx->job.nbits );
g_work->data[22] = 0x80000000; g_work->data[22] = 0x80000000;
g_work->data[31] = 0x00000280; g_work->data[31] = 0x00000280;
*/
} }
#endif
// called only by thread 0, saves a backup of g_work // called only by thread 0, saves a backup of g_work
void hodl_get_new_work( struct work* work, struct work* g_work) void hodl_get_new_work( struct work* work, struct work* g_work)
@@ -73,6 +143,22 @@ void hodl_get_new_work( struct work* work, struct work* g_work)
hodl_work.data[ algo_gate.nonce_index ] = ( clock() + rand() ) % 9999; hodl_work.data[ algo_gate.nonce_index ] = ( clock() + rand() ) % 9999;
} }
json_t *hodl_longpoll_rpc_call( CURL *curl, int *err, char* lp_url )
{
json_t *val;
char *req = NULL;
if ( have_gbt )
{
req = malloc( strlen( gbt_lp_req ) + strlen( lp_id ) + 1 );
sprintf( req, gbt_lp_req, lp_id );
}
val = json_rpc_call( curl, lp_url, rpc_userpass,
req ? req : getwork_req, err, JSON_RPC_LONGPOLL );
free( req );
return val;
}
// called by every thread, copies the backup to each thread's work. // called by every thread, copies the backup to each thread's work.
void hodl_resync_threads( struct work* work ) void hodl_resync_threads( struct work* work )
{ {
@@ -112,13 +198,17 @@ bool register_hodl_algo( algo_gate_t* gate )
gate->optimizations = SSE2_OPT | AES_OPT | AVX_OPT | AVX2_OPT; gate->optimizations = SSE2_OPT | AES_OPT | AVX_OPT | AVX2_OPT;
gate->scanhash = (void*)&hodl_scanhash; gate->scanhash = (void*)&hodl_scanhash;
gate->get_new_work = (void*)&hodl_get_new_work; gate->get_new_work = (void*)&hodl_get_new_work;
gate->longpoll_rpc_call = (void*)&hodl_longpoll_rpc_call;
gate->set_target = (void*)&hodl_set_target; gate->set_target = (void*)&hodl_set_target;
gate->build_stratum_request = (void*)&hodl_le_build_stratum_request; gate->build_stratum_request = (void*)&hodl_le_build_stratum_request;
gate->build_extraheader = (void*)&hodl_build_extraheader; gate->malloc_txs_request = (void*)&hodl_malloc_txs_request;
gate->build_block_header = (void*)&hodl_build_block_header;
// gate->build_extraheader = (void*)&hodl_build_extraheader;
gate->resync_threads = (void*)&hodl_resync_threads; gate->resync_threads = (void*)&hodl_resync_threads;
gate->do_this_thread = (void*)&hodl_do_this_thread; gate->do_this_thread = (void*)&hodl_do_this_thread;
gate->work_cmp_size = 76; gate->work_cmp_size = 76;
hodl_scratchbuf = (unsigned char*)malloc( 1 << 30 ); hodl_scratchbuf = (unsigned char*)malloc( 1 << 30 );
allow_getwork = false;
return ( hodl_scratchbuf != NULL ); return ( hodl_scratchbuf != NULL );
} }

View File

@@ -40,6 +40,35 @@ void lbry_le_build_stratum_request( char *req, struct work *work,
rpc_user, work->job_id, xnonce2str, ntimestr, noncestr ); rpc_user, work->job_id, xnonce2str, ntimestr, noncestr );
free(xnonce2str); free(xnonce2str);
} }
// don't use lbry_build_block_header, it can't handle clasim, do it inline
// in lbry_build_extraheader. The side effect is no gbt support for lbry.
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 );
// for ( int i = 0; i < 8; i++ )
// g_work->data[17 + i] = claim[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 ) void lbry_build_extraheader( struct work* g_work, struct stratum_ctx* sctx )
{ {
unsigned char merkle_root[64] = { 0 }; unsigned char merkle_root[64] = { 0 };
@@ -50,14 +79,23 @@ void lbry_build_extraheader( struct work* g_work, struct stratum_ctx* sctx )
// Increment extranonce2 // Increment extranonce2
for ( t = 0; t < sctx->xnonce2_size && !( ++sctx->job.xnonce2[t] ); t++ ); for ( t = 0; t < sctx->xnonce2_size && !( ++sctx->job.xnonce2[t] ); t++ );
// Assemble block header // Assemble block header
// algo_gate.build_block_header( g_work, le32dec( sctx->job.version ),
// (uint32_t*) sctx->job.prevhash, (uint32_t*) merkle_root,
// le32dec( sctx->job.ntime ), le32dec( sctx->job.nbits ) );
memset( g_work->data, 0, sizeof(g_work->data) ); memset( g_work->data, 0, sizeof(g_work->data) );
g_work->data[0] = le32dec( sctx->job.version ); g_work->data[0] = le32dec( sctx->job.version );
for ( i = 0; i < 8; i++ ) for ( i = 0; i < 8; i++ )
g_work->data[1 + i] = le32dec( (uint32_t *) sctx->job.prevhash + i ); g_work->data[1 + i] = le32dec( (uint32_t *) sctx->job.prevhash + i );
for ( i = 0; i < 8; i++ ) for ( i = 0; i < 8; i++ )
g_work->data[9 + i] = be32dec( (uint32_t *) merkle_root + i ); g_work->data[9 + i] = be32dec( (uint32_t *) merkle_root + i );
for ( int i = 0; i < 8; i++ ) for ( int i = 0; i < 8; i++ )
g_work->data[17 + i] = ((uint32_t*)sctx->job.claim)[i]; g_work->data[17 + i] = ((uint32_t*)sctx->job.claim)[i];
g_work->data[ LBRY_NTIME_INDEX ] = le32dec(sctx->job.ntime); g_work->data[ LBRY_NTIME_INDEX ] = le32dec(sctx->job.ntime);
g_work->data[ LBRY_NBITS_INDEX ] = le32dec(sctx->job.nbits); g_work->data[ LBRY_NBITS_INDEX ] = le32dec(sctx->job.nbits);
g_work->data[28] = 0x80000000; g_work->data[28] = 0x80000000;
@@ -86,6 +124,7 @@ bool register_lbry_algo( algo_gate_t* gate )
gate->calc_network_diff = (void*)&lbry_calc_network_diff; gate->calc_network_diff = (void*)&lbry_calc_network_diff;
gate->get_max64 = (void*)&lbry_get_max64; gate->get_max64 = (void*)&lbry_get_max64;
gate->build_stratum_request = (void*)&lbry_le_build_stratum_request; 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->build_extraheader = (void*)&lbry_build_extraheader;
gate->set_target = (void*)&lbry_set_target; gate->set_target = (void*)&lbry_set_target;
gate->ntime_index = LBRY_NTIME_INDEX; gate->ntime_index = LBRY_NTIME_INDEX;

20
configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for cpuminer-opt 3.8.3.2. # Generated by GNU Autoconf 2.69 for cpuminer-opt 3.8.3.3.
# #
# #
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -577,8 +577,8 @@ MAKEFLAGS=
# Identity of this package. # Identity of this package.
PACKAGE_NAME='cpuminer-opt' PACKAGE_NAME='cpuminer-opt'
PACKAGE_TARNAME='cpuminer-opt' PACKAGE_TARNAME='cpuminer-opt'
PACKAGE_VERSION='3.8.3.2' PACKAGE_VERSION='3.8.3.3'
PACKAGE_STRING='cpuminer-opt 3.8.3.2' PACKAGE_STRING='cpuminer-opt 3.8.3.3'
PACKAGE_BUGREPORT='' PACKAGE_BUGREPORT=''
PACKAGE_URL='' PACKAGE_URL=''
@@ -1321,7 +1321,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # 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. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
\`configure' configures cpuminer-opt 3.8.3.2 to adapt to many kinds of systems. \`configure' configures cpuminer-opt 3.8.3.3 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1392,7 +1392,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of cpuminer-opt 3.8.3.2:";; short | recursive ) echo "Configuration of cpuminer-opt 3.8.3.3:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@@ -1497,7 +1497,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
cpuminer-opt configure 3.8.3.2 cpuminer-opt configure 3.8.3.3
generated by GNU Autoconf 2.69 generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc. Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2000,7 +2000,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by cpuminer-opt $as_me 3.8.3.2, which was It was created by cpuminer-opt $as_me 3.8.3.3, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@ $ $0 $@
@@ -2981,7 +2981,7 @@ fi
# Define the identity of the package. # Define the identity of the package.
PACKAGE='cpuminer-opt' PACKAGE='cpuminer-opt'
VERSION='3.8.3.2' VERSION='3.8.3.3'
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
@@ -6677,7 +6677,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by cpuminer-opt $as_me 3.8.3.2, which was This file was extended by cpuminer-opt $as_me 3.8.3.3, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@@ -6743,7 +6743,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\ ac_cs_version="\\
cpuminer-opt config.status 3.8.3.2 cpuminer-opt config.status 3.8.3.3
configured by $0, generated by GNU Autoconf 2.69, configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\" with options \\"\$ac_cs_config\\"

View File

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

View File

@@ -177,7 +177,7 @@ static struct work g_work = {{ 0 }};
time_t g_work_time = 0; time_t g_work_time = 0;
static pthread_mutex_t g_work_lock; static pthread_mutex_t g_work_lock;
static bool submit_old = false; static bool submit_old = false;
static char* lp_id; char* lp_id;
static void workio_cmd_free(struct workio_cmd *wc); static void workio_cmd_free(struct workio_cmd *wc);
@@ -434,7 +434,8 @@ static bool get_mininginfo(CURL *curl, struct work *work)
} }
// hodl needs 4 but leave it at 3 until gbt better understood // hodl needs 4 but leave it at 3 until gbt better understood
#define BLOCK_VERSION_CURRENT 3 //#define BLOCK_VERSION_CURRENT 3
#define BLOCK_VERSION_CURRENT 4
static bool gbt_work_decode( const json_t *val, struct work *work ) static bool gbt_work_decode( const json_t *val, struct work *work )
{ {
@@ -455,25 +456,24 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
bool rc = false; bool rc = false;
tmp = json_object_get( val, "mutable" ); tmp = json_object_get( val, "mutable" );
if (tmp && json_is_array(tmp)) { if ( tmp && json_is_array( tmp ) )
{
n = (int) json_array_size( tmp ); n = (int) json_array_size( tmp );
for (i = 0; i < n; i++) { for ( i = 0; i < n; i++ )
{
const char *s = json_string_value( json_array_get( tmp, i ) ); const char *s = json_string_value( json_array_get( tmp, i ) );
if ( !s ) if ( !s )
continue; continue;
if (!strcmp(s, "coinbase/append")) if ( !strcmp( s, "coinbase/append" ) ) coinbase_append = true;
coinbase_append = true; else if ( !strcmp( s, "submit/coinbase" ) ) submit_coinbase = true;
else if (!strcmp(s, "submit/coinbase")) else if ( !strcmp( s, "version/force" ) ) version_force = true;
submit_coinbase = true; else if ( !strcmp( s, "version/reduce" ) ) version_reduce = true;
else if (!strcmp(s, "version/force"))
version_force = true;
else if (!strcmp(s, "version/reduce"))
version_reduce = true;
} }
} }
tmp = json_object_get( val, "height" ); tmp = json_object_get( val, "height" );
if (!tmp || !json_is_integer(tmp)) { if ( !tmp || !json_is_integer( tmp ) )
{
applog( LOG_ERR, "JSON invalid height" ); applog( LOG_ERR, "JSON invalid height" );
goto out; goto out;
} }
@@ -481,20 +481,26 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
applog( LOG_BLUE, "Current block is %d", work->height ); applog( LOG_BLUE, "Current block is %d", work->height );
tmp = json_object_get(val, "version"); tmp = json_object_get(val, "version");
if (!tmp || !json_is_integer(tmp)) { if ( !tmp || !json_is_integer( tmp ) )
{
applog( LOG_ERR, "JSON invalid version" ); applog( LOG_ERR, "JSON invalid version" );
goto out; goto out;
} }
version = (uint32_t) json_integer_value( tmp ); version = (uint32_t) json_integer_value( tmp );
if ((version & 0xffU) > BLOCK_VERSION_CURRENT) { if ( (version & 0xffU) > BLOCK_VERSION_CURRENT )
if (version_reduce) { {
if ( version_reduce )
{
version = ( version & ~0xffU ) | BLOCK_VERSION_CURRENT; version = ( version & ~0xffU ) | BLOCK_VERSION_CURRENT;
} else if (have_gbt && allow_getwork && !version_force) { }
applog(LOG_DEBUG, "Switching to getwork, gbt version %d", else if ( have_gbt && allow_getwork && !version_force )
version); {
applog( LOG_DEBUG, "Switching to getwork, gbt version %d", version );
have_gbt = false; have_gbt = false;
goto out; goto out;
} else if (!version_force) { }
else if ( !version_force )
{
applog(LOG_ERR, "Unrecognized block version: %u", version); applog(LOG_ERR, "Unrecognized block version: %u", version);
goto out; goto out;
} }
@@ -508,29 +514,34 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
} }
tmp = json_object_get( val, "curtime" ); tmp = json_object_get( val, "curtime" );
if (!tmp || !json_is_integer(tmp)) { if ( !tmp || !json_is_integer( tmp ) )
{
applog( LOG_ERR, "JSON invalid curtime" ); applog( LOG_ERR, "JSON invalid curtime" );
goto out; goto out;
} }
curtime = (uint32_t) json_integer_value(tmp); curtime = (uint32_t) json_integer_value(tmp);
if (unlikely(!jobj_binary(val, "bits", &bits, sizeof(bits)))) { if ( unlikely( !jobj_binary( val, "bits", &bits, sizeof(bits) ) ) )
{
applog(LOG_ERR, "JSON invalid bits"); applog(LOG_ERR, "JSON invalid bits");
goto out; goto out;
} }
/* find count and size of transactions */ /* find count and size of transactions */
txa = json_object_get(val, "transactions" ); txa = json_object_get(val, "transactions" );
if (!txa || !json_is_array(txa)) { if ( !txa || !json_is_array( txa ) )
{
applog( LOG_ERR, "JSON invalid transactions" ); applog( LOG_ERR, "JSON invalid transactions" );
goto out; goto out;
} }
tx_count = (int) json_array_size( txa ); tx_count = (int) json_array_size( txa );
tx_size = 0; tx_size = 0;
for (i = 0; i < tx_count; i++) { for ( i = 0; i < tx_count; i++ )
{
const json_t *tx = json_array_get( txa, i ); const json_t *tx = json_array_get( txa, i );
const char *tx_hex = json_string_value( json_object_get( tx, "data" ) ); const char *tx_hex = json_string_value( json_object_get( tx, "data" ) );
if (!tx_hex) { if ( !tx_hex )
{
applog( LOG_ERR, "JSON invalid transactions" ); applog( LOG_ERR, "JSON invalid transactions" );
goto out; goto out;
} }
@@ -539,30 +550,39 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
/* build coinbase transaction */ /* build coinbase transaction */
tmp = json_object_get( val, "coinbasetxn" ); tmp = json_object_get( val, "coinbasetxn" );
if (tmp) { if ( tmp )
{
const char *cbtx_hex = json_string_value( json_object_get( tmp, "data" )); const char *cbtx_hex = json_string_value( json_object_get( tmp, "data" ));
cbtx_size = cbtx_hex ? (int) strlen( cbtx_hex ) / 2 : 0; cbtx_size = cbtx_hex ? (int) strlen( cbtx_hex ) / 2 : 0;
cbtx = (uchar*) malloc( cbtx_size + 100 ); cbtx = (uchar*) malloc( cbtx_size + 100 );
if (cbtx_size < 60 || !hex2bin(cbtx, cbtx_hex, cbtx_size)) { if ( cbtx_size < 60 || !hex2bin( cbtx, cbtx_hex, cbtx_size ) )
{
applog( LOG_ERR, "JSON invalid coinbasetxn" ); applog( LOG_ERR, "JSON invalid coinbasetxn" );
goto out; goto out;
} }
} else { }
else
{
int64_t cbvalue; int64_t cbvalue;
if (!pk_script_size) { if ( !pk_script_size )
if (allow_getwork) { {
if ( allow_getwork )
{
applog( LOG_INFO, "No payout address provided, switching to getwork"); applog( LOG_INFO, "No payout address provided, switching to getwork");
have_gbt = false; have_gbt = false;
} else }
else
applog( LOG_ERR, "No payout address provided" ); applog( LOG_ERR, "No payout address provided" );
goto out; goto out;
} }
tmp = json_object_get( val, "coinbasevalue" ); tmp = json_object_get( val, "coinbasevalue" );
if (!tmp || !json_is_number(tmp)) { if ( !tmp || !json_is_number( tmp ) )
{
applog( LOG_ERR, "JSON invalid coinbasevalue" ); applog( LOG_ERR, "JSON invalid coinbasevalue" );
goto out; goto out;
} }
cbvalue = (int64_t) (json_is_integer(tmp) ? json_integer_value(tmp) : json_number_value(tmp)); cbvalue = (int64_t) ( json_is_integer( tmp ) ? json_integer_value( tmp )
: json_number_value( tmp ) );
cbtx = (uchar*) malloc(256); cbtx = (uchar*) malloc(256);
le32enc( (uint32_t *)cbtx, 1 ); /* version */ le32enc( (uint32_t *)cbtx, 1 ); /* version */
cbtx[4] = 1; /* in-counter */ cbtx[4] = 1; /* in-counter */
@@ -591,13 +611,18 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
{ {
unsigned char xsig[100]; unsigned char xsig[100];
int xsig_len = 0; int xsig_len = 0;
if (*coinbase_sig) { if ( *coinbase_sig )
{
n = (int) strlen( coinbase_sig ); n = (int) strlen( coinbase_sig );
if (cbtx[41] + xsig_len + n <= 100) { if ( cbtx[41] + xsig_len + n <= 100 )
{
memcpy( xsig+xsig_len, coinbase_sig, n ); memcpy( xsig+xsig_len, coinbase_sig, n );
xsig_len += n; xsig_len += n;
} else { }
applog(LOG_WARNING, "Signature does not fit in coinbase, skipping"); else
{
applog( LOG_WARNING,
"Signature does not fit in coinbase, skipping" );
} }
} }
tmp = json_object_get( val, "coinbaseaux" ); tmp = json_object_get( val, "coinbaseaux" );
@@ -609,11 +634,13 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
unsigned char buf[100]; unsigned char buf[100];
const char *s = json_string_value( json_object_iter_value( iter ) ); const char *s = json_string_value( json_object_iter_value( iter ) );
n = s ? (int) ( strlen(s) / 2 ) : 0; n = s ? (int) ( strlen(s) / 2 ) : 0;
if (!s || n > 100 || !hex2bin(buf, s, n)) { if ( !s || n > 100 || !hex2bin( buf, s, n ) )
{
applog(LOG_ERR, "JSON invalid coinbaseaux"); applog(LOG_ERR, "JSON invalid coinbaseaux");
break; break;
} }
if (cbtx[41] + xsig_len + n <= 100) { if ( cbtx[41] + xsig_len + n <= 100 )
{
memcpy( xsig+xsig_len, buf, n ); memcpy( xsig+xsig_len, buf, n );
xsig_len += n; xsig_len += n;
} }
@@ -675,16 +702,9 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
} }
/* assemble block header */ /* assemble block header */
work->data[0] = swab32(version); algo_gate.build_block_header( work, swab32( version ),
for (i = 0; i < 8; i++) (uint32_t*) prevhash, (uint32_t*) merkle_tree,
work->data[8 - i] = le32dec(prevhash + i); swab32( curtime ), le32dec( &bits ) );
for (i = 0; i < 8; i++)
work->data[9 + i] = be32dec((uint32_t *)merkle_tree[0] + i);
work->data[17] = swab32(curtime);
work->data[18] = le32dec(&bits);
memset(work->data + 19, 0x00, 52);
work->data[20] = 0x80000000;
work->data[31] = 0x00000280;
if ( unlikely( !jobj_binary(val, "target", target, sizeof(target)) ) ) if ( unlikely( !jobj_binary(val, "target", target, sizeof(target)) ) )
{ {
@@ -697,7 +717,8 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
tmp = json_object_get( val, "workid" ); tmp = json_object_get( val, "workid" );
if ( tmp ) if ( tmp )
{ {
if (!json_is_string(tmp)) { if ( !json_is_string( tmp ) )
{
applog( LOG_ERR, "JSON invalid workid" ); applog( LOG_ERR, "JSON invalid workid" );
goto out; goto out;
} }
@@ -716,7 +737,8 @@ out:
{ {
char *lp_uri; char *lp_uri;
tmp = json_object_get( val, "longpolluri" ); tmp = json_object_get( val, "longpolluri" );
lp_uri = json_is_string(tmp) ? strdup(json_string_value(tmp)) : rpc_url; lp_uri = json_is_string( tmp ) ? strdup( json_string_value( tmp ) )
: rpc_url;
have_longpoll = true; have_longpoll = true;
tq_push(thr_info[longpoll_thr_id].q, lp_uri); tq_push(thr_info[longpoll_thr_id].q, lp_uri);
} }
@@ -1050,45 +1072,12 @@ bool jr2_submit_getwork_result( CURL *curl, struct work *work )
return true; return true;
} }
static bool submit_upstream_work( CURL *curl, struct work *work ) char* std_malloc_txs_request( struct work *work )
{ {
json_t *val, *res;
char req[JSON_BUF_LEN];
int i;
/* pass if the previous hash is not the current previous hash */
if ( !submit_old && memcmp( &work->data[1], &g_work.data[1], 32 ) )
{
if (opt_debug)
applog(LOG_DEBUG, "DEBUG: stale work detected, discarding");
return true;
}
if ( !have_stratum && allow_mininginfo )
{
struct work wheight;
get_mininginfo( curl, &wheight );
if ( work->height && work->height <= net_blocks )
{
if (opt_debug)
applog(LOG_WARNING, "block %u was already solved", work->height);
return true;
}
}
if ( have_stratum )
{
stratum.sharediff = work->sharediff;
algo_gate.build_stratum_request( req, work, &stratum );
if ( unlikely( !stratum_send_line( &stratum, req ) ) )
{
applog(LOG_ERR, "submit_upstream_work stratum_send_line failed");
return false;
}
return true;
}
else if (work->txs)
{
char data_str[2 * sizeof(work->data) + 1];
char *req; char *req;
json_t *val;
char data_str[2 * sizeof(work->data) + 1];
int i;
for ( i = 0; i < ARRAY_SIZE(work->data); i++ ) for ( i = 0; i < ARRAY_SIZE(work->data); i++ )
be32enc( work->data + i, work->data[i] ); be32enc( work->data + i, work->data[i] );
@@ -1100,7 +1089,8 @@ static bool submit_upstream_work( CURL *curl, struct work *work )
json_object_set_new( val, "workid", json_string( work->workid ) ); json_object_set_new( val, "workid", json_string( work->workid ) );
params = json_dumps( val, 0 ); params = json_dumps( val, 0 );
json_decref( val ); json_decref( val );
req = (char*) malloc(128 + 2 * 80 + strlen(work->txs) + strlen(params)); req = (char*) malloc( 128 + 2 * 80 + strlen( work->txs )
+ strlen( params ) );
sprintf( req, sprintf( req,
"{\"method\": \"submitblock\", \"params\": [\"%s%s\", %s], \"id\":4}\r\n", "{\"method\": \"submitblock\", \"params\": [\"%s%s\", %s], \"id\":4}\r\n",
data_str, work->txs, params ); data_str, work->txs, params );
@@ -1113,9 +1103,52 @@ static bool submit_upstream_work( CURL *curl, struct work *work )
"{\"method\": \"submitblock\", \"params\": [\"%s%s\"], \"id\":4}\r\n", "{\"method\": \"submitblock\", \"params\": [\"%s%s\"], \"id\":4}\r\n",
data_str, work->txs); data_str, work->txs);
} }
return req;
}
static bool submit_upstream_work( CURL *curl, struct work *work )
{
/* pass if the previous hash is not the current previous hash */
if ( !submit_old && memcmp( &work->data[1], &g_work.data[1], 32 ) )
{
if (opt_debug)
applog(LOG_DEBUG, "DEBUG: stale work detected, discarding");
return true;
}
if ( !have_stratum && allow_mininginfo )
{
struct work wheight;
get_mininginfo( curl, &wheight );
if ( work->height && work->height <= net_blocks )
{
if (opt_debug)
applog(LOG_WARNING, "block %u was already solved", work->height);
return true;
}
}
if ( have_stratum )
{
char req[JSON_BUF_LEN];
stratum.sharediff = work->sharediff;
algo_gate.build_stratum_request( req, work, &stratum );
if ( unlikely( !stratum_send_line( &stratum, req ) ) )
{
applog(LOG_ERR, "submit_upstream_work stratum_send_line failed");
return false;
}
return true;
}
else if ( work->txs )
{
char *req = NULL;
json_t *val, *res;
req = algo_gate.malloc_txs_request( work );
val = json_rpc_call( curl, rpc_url, rpc_userpass, req, NULL, 0 ); val = json_rpc_call( curl, rpc_url, rpc_userpass, req, NULL, 0 );
free( req ); free( req );
if ( unlikely( !val ) ) if ( unlikely( !val ) )
{ {
applog( LOG_ERR, "submit_upstream_work json_rpc_call failed" ); applog( LOG_ERR, "submit_upstream_work json_rpc_call failed" );
@@ -1149,7 +1182,7 @@ static bool submit_upstream_work( CURL *curl, struct work *work )
return algo_gate.submit_getwork_result( curl, work ); return algo_gate.submit_getwork_result( curl, work );
} }
static const char *getwork_req = const char *getwork_req =
"{\"method\": \"getwork\", \"params\": [], \"id\":0}\r\n"; "{\"method\": \"getwork\", \"params\": [], \"id\":0}\r\n";
#define GBT_CAPABILITIES "[\"coinbasetxn\", \"coinbasevalue\", \"longpoll\", \"workid\"]" #define GBT_CAPABILITIES "[\"coinbasetxn\", \"coinbasevalue\", \"longpoll\", \"workid\"]"
@@ -1157,7 +1190,7 @@ static const char *getwork_req =
static const char *gbt_req = static const char *gbt_req =
"{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": " "{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": "
GBT_CAPABILITIES "}], \"id\":0}\r\n"; GBT_CAPABILITIES "}], \"id\":0}\r\n";
static const char *gbt_lp_req = const char *gbt_lp_req =
"{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": " "{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": "
GBT_CAPABILITIES ", \"longpollid\": \"%s\"}], \"id\":0}\r\n"; GBT_CAPABILITIES ", \"longpollid\": \"%s\"}], \"id\":0}\r\n";
@@ -1180,8 +1213,8 @@ start:
else else
{ {
val = json_rpc_call( curl, rpc_url, rpc_userpass, val = json_rpc_call( curl, rpc_url, rpc_userpass,
have_gbt ? gbt_req : getwork_req, have_gbt ? gbt_req : getwork_req, &err,
&err, have_gbt ? JSON_RPC_QUIET_404 : 0); have_gbt ? JSON_RPC_QUIET_404 : 0);
} }
gettimeofday( &tv_end, NULL ); gettimeofday( &tv_end, NULL );
@@ -1881,7 +1914,7 @@ static void *miner_thread( void *userdata )
gettimeofday( (struct timeval *) &tv_start, NULL ); gettimeofday( (struct timeval *) &tv_start, NULL );
// Scan for nonce // Scan for nonce
nonce_found = (bool) algo_gate.scanhash( thr_id, &work, max_nonce, nonce_found = algo_gate.scanhash( thr_id, &work, max_nonce,
&hashes_done ); &hashes_done );
// record scanhash elapsed time // record scanhash elapsed time
@@ -1896,37 +1929,31 @@ static void *miner_thread( void *userdata )
pthread_mutex_unlock( &stats_lock ); pthread_mutex_unlock( &stats_lock );
} }
// if nonce(s) submit work // if nonce(s) found submit work
if ( nonce_found && !opt_benchmark ) if ( nonce_found && !opt_benchmark )
{ { // 4 way with multiple nonces, copy individually to work and submit.
/* if ( nonce_found > 1 )
int num_submitted = 0;
for ( int n = 0; n < nonce_found; n++ ) for ( int n = 0; n < nonce_found; n++ )
{ {
*algo_gate.get_nonceptr( work.data ) = work.nonces[n]; *algo_gate.get_nonceptr( work.data ) = work.nonces[n];
if ( submit_work( mythr, &work ) ) if ( submit_work( mythr, &work ) )
{
applog( LOG_NOTICE, "Share submitted." ); applog( LOG_NOTICE, "Share submitted." );
num_submitted++;
}
else else
{ {
applog( LOG_WARNING, "Failed to submit share." ); applog( LOG_WARNING, "Failed to submit share." );
break; break;
} }
} }
// must be a one way algo, nonce is already in work data else
if ( !num_submitted ) { // only 1 nonce, in work ready to submit.
{
*/
if ( !submit_work( mythr, &work ) ) if ( !submit_work( mythr, &work ) )
{ {
applog( LOG_WARNING, "Failed to submit share." ); applog( LOG_WARNING, "Failed to submit share." );
break; break;
} }
applog( LOG_NOTICE, "Share submitted." ); applog( LOG_NOTICE, "Share submitted." );
// } }
// prevent stale work in solo // prevent stale work in solo
// we can't submit twice a block! // we can't submit twice a block!
@@ -2236,27 +2263,45 @@ out:
return ret; return ret;
} }
void std_build_extraheader( struct work* g_work, struct stratum_ctx* sctx ) // used by stratum and gbt
void std_build_block_header( struct work* g_work, uint32_t version,
uint32_t *prevhash, uint32_t *merkle_tree,
uint32_t ntime, uint32_t nbits )
{ {
uchar merkle_root[64] = { 0 };
size_t t;
int i; int i;
algo_gate.gen_merkle_root( merkle_root, sctx ); 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_tree + i );
g_work->data[ algo_gate.ntime_index ] = ntime;
g_work->data[ algo_gate.nbits_index ] = nbits;
g_work->data[20] = 0x80000000;
g_work->data[31] = 0x00000280;
}
void std_build_extraheader( struct work* g_work, struct stratum_ctx* sctx )
{
uchar merkle_tree[64] = { 0 };
size_t t;
algo_gate.gen_merkle_root( merkle_tree, sctx );
// Increment extranonce2 // Increment extranonce2
for ( t = 0; t < sctx->xnonce2_size && !( ++sctx->job.xnonce2[t] ); t++ ); for ( t = 0; t < sctx->xnonce2_size && !( ++sctx->job.xnonce2[t] ); t++ );
// Assemble block header // 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] = le32dec( (uint32_t *) sctx->job.prevhash + i );
for ( i = 0; i < 8; i++ )
g_work->data[9 + i] = be32dec( (uint32_t *) merkle_root + i );
g_work->data[ algo_gate.ntime_index ] = le32dec(sctx->job.ntime); algo_gate.build_block_header( g_work, le32dec( sctx->job.version ),
g_work->data[ algo_gate.nbits_index ] = le32dec(sctx->job.nbits); (uint32_t*) sctx->job.prevhash, (uint32_t*) merkle_tree,
g_work->data[20] = 0x80000000; le32dec( sctx->job.ntime ), le32dec(sctx->job.nbits) );
g_work->data[31] = 0x00000280;
} }
void std_stratum_gen_work( struct stratum_ctx *sctx, struct work *g_work ) void std_stratum_gen_work( struct stratum_ctx *sctx, struct work *g_work )

View File

@@ -648,6 +648,10 @@ extern int opt_timeout;
extern bool want_longpoll; extern bool want_longpoll;
extern bool have_longpoll; extern bool have_longpoll;
extern bool have_gbt; extern bool have_gbt;
extern char* lp_id;
extern char *rpc_userpass;
extern const char *gbt_lp_req;
extern const char *getwork_req;
extern bool allow_getwork; extern bool allow_getwork;
extern bool want_stratum; extern bool want_stratum;
extern bool have_stratum; extern bool have_stratum;