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
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.
@@ -159,6 +160,12 @@ Support for even older x86_64 without AES_NI or SSE2 is not availble.
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
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->stratum_gen_work = (void*)&std_stratum_gen_work;
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->work_decode = (void*)&std_le_work_decode;
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->set_work_data_endian = (void*)&do_nothing;
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* );
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 );
void ( *build_stratum_request ) ( char*, struct work*, struct stratum_ctx* );
char* ( *malloc_txs_request ) ( struct work* );
void ( *set_work_data_endian ) ( struct work* );
double ( *calc_network_diff ) ( struct work* );
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 jr2_build_stratum_request ( char *req, struct work *work );
char* std_malloc_txs_request( struct work *work );
// Default is do_nothing (assumed LE)
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 );
void std_build_extraheader( struct work *work, struct stratum_ctx *sctx );
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 );
}
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 };
size_t t;
char* req;
json_t *val;
char data_str[2 * sizeof(work->data) + 1];
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
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
memset( g_work->data, 0, sizeof(g_work->data) );
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[22] = 0x80000000;
g_work->data[31] = 0x00000280;
*/
}
#endif
// called only by thread 0, saves a backup of 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;
}
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.
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->scanhash = (void*)&hodl_scanhash;
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->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->do_this_thread = (void*)&hodl_do_this_thread;
gate->work_cmp_size = 76;
hodl_scratchbuf = (unsigned char*)malloc( 1 << 30 );
allow_getwork = false;
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 );
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 )
{
unsigned char merkle_root[64] = { 0 };
@@ -50,14 +79,23 @@ void lbry_build_extraheader( struct work* g_work, struct stratum_ctx* sctx )
// Increment extranonce2
for ( t = 0; t < sctx->xnonce2_size && !( ++sctx->job.xnonce2[t] ); t++ );
// 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) );
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 );
for ( int i = 0; i < 8; 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_NBITS_INDEX ] = le32dec(sctx->job.nbits);
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->get_max64 = (void*)&lbry_get_max64;
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->set_target = (void*)&lbry_set_target;
gate->ntime_index = LBRY_NTIME_INDEX;

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.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.
@@ -577,8 +577,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='cpuminer-opt'
PACKAGE_TARNAME='cpuminer-opt'
PACKAGE_VERSION='3.8.3.2'
PACKAGE_STRING='cpuminer-opt 3.8.3.2'
PACKAGE_VERSION='3.8.3.3'
PACKAGE_STRING='cpuminer-opt 3.8.3.3'
PACKAGE_BUGREPORT=''
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.
# This message is too long to be a string in the A/UX 3.1 sh.
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]...
@@ -1392,7 +1392,7 @@ fi
if test -n "$ac_init_help"; then
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
cat <<\_ACEOF
@@ -1497,7 +1497,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
cpuminer-opt configure 3.8.3.2
cpuminer-opt configure 3.8.3.3
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2000,7 +2000,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.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
$ $0 $@
@@ -2981,7 +2981,7 @@ fi
# Define the identity of the package.
PACKAGE='cpuminer-opt'
VERSION='3.8.3.2'
VERSION='3.8.3.3'
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
# values after options handling.
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
CONFIG_FILES = $CONFIG_FILES
@@ -6743,7 +6743,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.8.3.2
cpuminer-opt config.status 3.8.3.3
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.8.3.2])
AC_INIT([cpuminer-opt], [3.8.3.3])
AC_PREREQ([2.59c])
AC_CANONICAL_SYSTEM

View File

@@ -177,7 +177,7 @@ static struct work g_work = {{ 0 }};
time_t g_work_time = 0;
static pthread_mutex_t g_work_lock;
static bool submit_old = false;
static char* lp_id;
char* lp_id;
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
#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 )
{
@@ -455,25 +456,24 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
bool rc = false;
tmp = json_object_get( val, "mutable" );
if (tmp && json_is_array(tmp)) {
if ( tmp && json_is_array( 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 ) );
if ( !s )
continue;
if (!strcmp(s, "coinbase/append"))
coinbase_append = true;
else if (!strcmp(s, "submit/coinbase"))
submit_coinbase = true;
else if (!strcmp(s, "version/force"))
version_force = true;
else if (!strcmp(s, "version/reduce"))
version_reduce = true;
if ( !strcmp( s, "coinbase/append" ) ) coinbase_append = true;
else if ( !strcmp( s, "submit/coinbase" ) ) submit_coinbase = 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" );
if (!tmp || !json_is_integer(tmp)) {
if ( !tmp || !json_is_integer( tmp ) )
{
applog( LOG_ERR, "JSON invalid height" );
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 );
tmp = json_object_get(val, "version");
if (!tmp || !json_is_integer(tmp)) {
if ( !tmp || !json_is_integer( tmp ) )
{
applog( LOG_ERR, "JSON invalid version" );
goto out;
}
version = (uint32_t) json_integer_value( tmp );
if ((version & 0xffU) > BLOCK_VERSION_CURRENT) {
if (version_reduce) {
if ( (version & 0xffU) > BLOCK_VERSION_CURRENT )
{
if ( version_reduce )
{
version = ( version & ~0xffU ) | BLOCK_VERSION_CURRENT;
} else if (have_gbt && allow_getwork && !version_force) {
applog(LOG_DEBUG, "Switching to getwork, gbt version %d",
version);
}
else if ( have_gbt && allow_getwork && !version_force )
{
applog( LOG_DEBUG, "Switching to getwork, gbt version %d", version );
have_gbt = false;
goto out;
} else if (!version_force) {
}
else if ( !version_force )
{
applog(LOG_ERR, "Unrecognized block version: %u", version);
goto out;
}
@@ -508,29 +514,34 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
}
tmp = json_object_get( val, "curtime" );
if (!tmp || !json_is_integer(tmp)) {
if ( !tmp || !json_is_integer( tmp ) )
{
applog( LOG_ERR, "JSON invalid curtime" );
goto out;
}
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");
goto out;
}
/* find count and size of 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" );
goto out;
}
tx_count = (int) json_array_size( txa );
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 char *tx_hex = json_string_value( json_object_get( tx, "data" ) );
if (!tx_hex) {
if ( !tx_hex )
{
applog( LOG_ERR, "JSON invalid transactions" );
goto out;
}
@@ -539,30 +550,39 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
/* build coinbase transaction */
tmp = json_object_get( val, "coinbasetxn" );
if (tmp) {
if ( tmp )
{
const char *cbtx_hex = json_string_value( json_object_get( tmp, "data" ));
cbtx_size = cbtx_hex ? (int) strlen( cbtx_hex ) / 2 : 0;
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" );
goto out;
}
} else {
}
else
{
int64_t cbvalue;
if (!pk_script_size) {
if (allow_getwork) {
if ( !pk_script_size )
{
if ( allow_getwork )
{
applog( LOG_INFO, "No payout address provided, switching to getwork");
have_gbt = false;
} else
}
else
applog( LOG_ERR, "No payout address provided" );
goto out;
}
tmp = json_object_get( val, "coinbasevalue" );
if (!tmp || !json_is_number(tmp)) {
if ( !tmp || !json_is_number( tmp ) )
{
applog( LOG_ERR, "JSON invalid coinbasevalue" );
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);
le32enc( (uint32_t *)cbtx, 1 ); /* version */
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];
int xsig_len = 0;
if (*coinbase_sig) {
if ( *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 );
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" );
@@ -609,11 +634,13 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
unsigned char buf[100];
const char *s = json_string_value( json_object_iter_value( iter ) );
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");
break;
}
if (cbtx[41] + xsig_len + n <= 100) {
if ( cbtx[41] + xsig_len + n <= 100 )
{
memcpy( xsig+xsig_len, buf, n );
xsig_len += n;
}
@@ -675,16 +702,9 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
}
/* assemble block header */
work->data[0] = swab32(version);
for (i = 0; i < 8; i++)
work->data[8 - i] = le32dec(prevhash + i);
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;
algo_gate.build_block_header( work, swab32( version ),
(uint32_t*) prevhash, (uint32_t*) merkle_tree,
swab32( curtime ), le32dec( &bits ) );
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" );
if ( tmp )
{
if (!json_is_string(tmp)) {
if ( !json_is_string( tmp ) )
{
applog( LOG_ERR, "JSON invalid workid" );
goto out;
}
@@ -716,7 +737,8 @@ out:
{
char *lp_uri;
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;
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;
}
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;
json_t *val;
char data_str[2 * sizeof(work->data) + 1];
int i;
for ( i = 0; i < ARRAY_SIZE(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 ) );
params = json_dumps( val, 0 );
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,
"{\"method\": \"submitblock\", \"params\": [\"%s%s\", %s], \"id\":4}\r\n",
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",
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 );
free( req );
if ( unlikely( !val ) )
{
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 );
}
static const char *getwork_req =
const char *getwork_req =
"{\"method\": \"getwork\", \"params\": [], \"id\":0}\r\n";
#define GBT_CAPABILITIES "[\"coinbasetxn\", \"coinbasevalue\", \"longpoll\", \"workid\"]"
@@ -1157,7 +1190,7 @@ static const char *getwork_req =
static const char *gbt_req =
"{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": "
GBT_CAPABILITIES "}], \"id\":0}\r\n";
static const char *gbt_lp_req =
const char *gbt_lp_req =
"{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": "
GBT_CAPABILITIES ", \"longpollid\": \"%s\"}], \"id\":0}\r\n";
@@ -1180,8 +1213,8 @@ start:
else
{
val = json_rpc_call( curl, rpc_url, rpc_userpass,
have_gbt ? gbt_req : getwork_req,
&err, have_gbt ? JSON_RPC_QUIET_404 : 0);
have_gbt ? gbt_req : getwork_req, &err,
have_gbt ? JSON_RPC_QUIET_404 : 0);
}
gettimeofday( &tv_end, NULL );
@@ -1881,7 +1914,7 @@ static void *miner_thread( void *userdata )
gettimeofday( (struct timeval *) &tv_start, NULL );
// 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 );
// record scanhash elapsed time
@@ -1896,37 +1929,31 @@ static void *miner_thread( void *userdata )
pthread_mutex_unlock( &stats_lock );
}
// if nonce(s) submit work
// if nonce(s) found submit work
if ( nonce_found && !opt_benchmark )
{
/*
int num_submitted = 0;
{ // 4 way with multiple nonces, copy individually to work and submit.
if ( nonce_found > 1 )
for ( int n = 0; n < nonce_found; n++ )
{
*algo_gate.get_nonceptr( work.data ) = work.nonces[n];
if ( submit_work( mythr, &work ) )
{
applog( LOG_NOTICE, "Share submitted." );
num_submitted++;
}
else
{
applog( LOG_WARNING, "Failed to submit share." );
break;
}
}
// must be a one way algo, nonce is already in work data
if ( !num_submitted )
{
*/
else
{ // only 1 nonce, in work ready to submit.
if ( !submit_work( mythr, &work ) )
{
applog( LOG_WARNING, "Failed to submit share." );
break;
}
applog( LOG_NOTICE, "Share submitted." );
// }
}
// prevent stale work in solo
// we can't submit twice a block!
@@ -2236,27 +2263,45 @@ out:
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;
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
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] = 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);
g_work->data[ algo_gate.nbits_index ] = le32dec(sctx->job.nbits);
g_work->data[20] = 0x80000000;
g_work->data[31] = 0x00000280;
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) );
}
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 have_longpoll;
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 want_stratum;
extern bool have_stratum;