@ -239,7 +239,7 @@ int swork_id;
struct stratum_share {
struct stratum_share {
UT_hash_handle hh ;
UT_hash_handle hh ;
bool block ;
bool block ;
struct work work ;
struct work * work ;
int id ;
int id ;
} ;
} ;
@ -1469,9 +1469,7 @@ static void calc_diff(struct work *work, int known);
static void gen_gbt_work ( struct pool * pool , struct work * work )
static void gen_gbt_work ( struct pool * pool , struct work * work )
{
{
unsigned char * merkleroot ;
unsigned char * merkleroot ;
char * cbhex ;
memset ( work - > job_id , 0 , 64 ) ;
mutex_lock ( & pool - > gbt_lock ) ;
mutex_lock ( & pool - > gbt_lock ) ;
__build_gbt_coinbase ( pool ) ;
__build_gbt_coinbase ( pool ) ;
merkleroot = __gbt_merkleroot ( pool ) ;
merkleroot = __gbt_merkleroot ( pool ) ;
@ -1483,15 +1481,13 @@ static void gen_gbt_work(struct pool *pool, struct work *work)
memcpy ( work - > target , pool - > gbt_target , 32 ) ;
memcpy ( work - > target , pool - > gbt_target , 32 ) ;
cbhex = bin2hex ( pool - > gbt_coinbase , pool - > coinbase_len ) ;
work - > gbt_coinbase = bin2hex ( pool - > gbt_coinbase , pool - > coinbase_len ) ;
sprintf ( work - > gbt_coinbase , " %s " , cbhex ) ;
free ( cbhex ) ;
/* For encoding the block data on submission */
/* For encoding the block data on submission */
work - > gbt_txns = pool - > gbt_txns + 1 ;
work - > gbt_txns = pool - > gbt_txns + 1 ;
if ( pool - > gbt_workid )
if ( pool - > gbt_workid )
sprintf ( work - > job_id , " %s " , pool - > gbt_workid ) ;
work - > job_id = strdup ( pool - > gbt_workid ) ;
mutex_unlock ( & pool - > gbt_lock ) ;
mutex_unlock ( & pool - > gbt_lock ) ;
memcpy ( work - > data + 4 + 32 , merkleroot , 32 ) ;
memcpy ( work - > data + 4 + 32 , merkleroot , 32 ) ;
@ -2307,7 +2303,7 @@ static bool submit_upstream_work(struct work *work, CURL *curl, bool resubmit)
/* build JSON-RPC request */
/* build JSON-RPC request */
if ( work - > gbt ) {
if ( work - > gbt ) {
char gbt_block [ 102 4] , * varint , * header ;
char gbt_block [ 4096 ] , * varint , * header ;
unsigned char data [ 80 ] ;
unsigned char data [ 80 ] ;
flip80 ( data , work - > data ) ;
flip80 ( data , work - > data ) ;
@ -2334,7 +2330,7 @@ static bool submit_upstream_work(struct work *work, CURL *curl, bool resubmit)
free ( varint ) ;
free ( varint ) ;
strcat ( gbt_block , work - > gbt_coinbase ) ;
strcat ( gbt_block , work - > gbt_coinbase ) ;
if ( strlen ( work - > job_id ) )
if ( work - > job_id )
sprintf ( s , " { \" id \" : 0, \" method \" : \" submitblock \" , \" params \" : [ \" %s \" , { \" workid \" : \" %s \" }]} " , gbt_block , work - > job_id ) ;
sprintf ( s , " { \" id \" : 0, \" method \" : \" submitblock \" , \" params \" : [ \" %s \" , { \" workid \" : \" %s \" }]} " , gbt_block , work - > job_id ) ;
else
else
sprintf ( s , " { \" id \" : 0, \" method \" : \" submitblock \" , \" params \" : [ \" %s \" , {}]} " , gbt_block ) ;
sprintf ( s , " { \" id \" : 0, \" method \" : \" submitblock \" , \" params \" : [ \" %s \" , {}]} " , gbt_block ) ;
@ -2634,8 +2630,25 @@ static struct work *make_work(void)
return work ;
return work ;
}
}
static void free_work ( struct work * work )
/* This is the central place all work that is about to be retired should be
* cleaned to remove any dynamically allocated arrays within the struct */
void clean_work ( struct work * work )
{
free ( work - > job_id ) ;
free ( work - > nonce2 ) ;
free ( work - > ntime ) ;
free ( work - > gbt_coinbase ) ;
work - > job_id = NULL ;
work - > nonce2 = NULL ;
work - > ntime = NULL ;
work - > gbt_coinbase = NULL ;
}
/* All dynamically allocated work structs should be freed here to not leak any
* ram from arrays allocated within the work struct */
void free_work ( struct work * work )
{
{
clean_work ( work ) ;
free ( work ) ;
free ( work ) ;
}
}
@ -2948,11 +2961,37 @@ static void roll_work(struct work *work)
work - > id = total_work + + ;
work - > id = total_work + + ;
}
}
/* Duplicates any dynamically allocated arrays within the work struct to
* prevent a copied work struct from freeing ram belonging to another struct */
void __copy_work ( struct work * work , struct work * base_work )
{
clean_work ( work ) ;
memcpy ( work , base_work , sizeof ( struct work ) ) ;
if ( work - > job_id )
work - > job_id = strdup ( base_work - > job_id ) ;
if ( work - > nonce2 )
work - > nonce2 = strdup ( base_work - > nonce2 ) ;
if ( work - > ntime )
work - > ntime = strdup ( base_work - > ntime ) ;
if ( work - > gbt_coinbase )
work - > gbt_coinbase = strdup ( base_work - > gbt_coinbase ) ;
}
/* Generates a copy of an existing work struct, creating fresh heap allocations
* for all dynamically allocated arrays within the struct */
struct work * copy_work ( struct work * base_work )
{
struct work * work = make_work ( ) ;
__copy_work ( work , base_work ) ;
return work ;
}
static struct work * make_clone ( struct work * work )
static struct work * make_clone ( struct work * work )
{
{
struct work * work_clone = make_work ( ) ;
struct work * work_clone = copy_work ( work ) ;
memcpy ( work_clone , work , sizeof ( struct work ) ) ;
work_clone - > clone = true ;
work_clone - > clone = true ;
gettimeofday ( ( struct timeval * ) & ( work_clone - > tv_cloned ) , NULL ) ;
gettimeofday ( ( struct timeval * ) & ( work_clone - > tv_cloned ) , NULL ) ;
work_clone - > longpoll = false ;
work_clone - > longpoll = false ;
@ -3016,7 +3055,7 @@ static void gen_stratum_work(struct pool *pool, struct work *work);
static void * get_work_thread ( void * userdata )
static void * get_work_thread ( void * userdata )
{
{
struct workio_cmd * wc = ( struct workio_cmd * ) userdata ;
struct workio_cmd * wc = ( struct workio_cmd * ) userdata ;
struct work * ret_work = NULL ;
struct work * ret_work = NULL ;
struct curl_ent * ce = NULL ;
struct curl_ent * ce = NULL ;
struct pool * pool ;
struct pool * pool ;
@ -3232,7 +3271,7 @@ static void *submit_work_thread(void *userdata)
char * noncehex ;
char * noncehex ;
char s [ 1024 ] ;
char s [ 1024 ] ;
memcpy ( & sshare - > work , work , sizeof ( struct work ) ) ;
sshare - > work = copy_work ( work ) ;
mutex_lock ( & sshare_lock ) ;
mutex_lock ( & sshare_lock ) ;
/* Give the stratum share a unique id */
/* Give the stratum share a unique id */
sshare - > id = swork_id + + ;
sshare - > id = swork_id + + ;
@ -4538,7 +4577,7 @@ out_unlock:
static void stratum_share_result ( json_t * val , json_t * res_val , json_t * err_val ,
static void stratum_share_result ( json_t * val , json_t * res_val , json_t * err_val ,
struct stratum_share * sshare )
struct stratum_share * sshare )
{
{
struct work * work = & sshare - > work ;
struct work * work = sshare - > work ;
uint64_t sharediff = share_diff ( work ) ;
uint64_t sharediff = share_diff ( work ) ;
char hashshow [ 65 ] ;
char hashshow [ 65 ] ;
uint32_t * hash32 ;
uint32_t * hash32 ;
@ -4602,6 +4641,7 @@ static bool parse_stratum_response(struct pool *pool, char *s)
goto out ;
goto out ;
}
}
stratum_share_result ( val , res_val , err_val , sshare ) ;
stratum_share_result ( val , res_val , err_val , sshare ) ;
free_work ( sshare - > work ) ;
free ( sshare ) ;
free ( sshare ) ;
ret = true ;
ret = true ;
@ -4621,8 +4661,9 @@ static void clear_stratum_shares(struct pool *pool)
mutex_lock ( & sshare_lock ) ;
mutex_lock ( & sshare_lock ) ;
HASH_ITER ( hh , stratum_shares , sshare , tmpshare ) {
HASH_ITER ( hh , stratum_shares , sshare , tmpshare ) {
if ( sshare - > work . pool = = pool ) {
if ( sshare - > work - > pool = = pool ) {
HASH_DEL ( stratum_shares , sshare ) ;
HASH_DEL ( stratum_shares , sshare ) ;
free_work ( sshare - > work ) ;
free ( sshare ) ;
free ( sshare ) ;
cleared + + ;
cleared + + ;
}
}
@ -5129,17 +5170,13 @@ static void gen_stratum_work(struct pool *pool, struct work *work)
{
{
unsigned char * coinbase , merkle_root [ 32 ] , merkle_sha [ 64 ] , * merkle_hash ;
unsigned char * coinbase , merkle_root [ 32 ] , merkle_sha [ 64 ] , * merkle_hash ;
int len , cb1_len , n1_len , cb2_len , i ;
int len , cb1_len , n1_len , cb2_len , i ;
char header [ 260 ] , * nonce2 ;
uint32_t * data32 , * swap32 ;
uint32_t * data32 , * swap32 ;
char header [ 260 ] ;
memset ( work - > job_id , 0 , 64 ) ;
memset ( work - > nonce2 , 0 , 64 ) ;
memset ( work - > ntime , 0 , 16 ) ;
mutex_lock ( & pool - > pool_lock ) ;
mutex_lock ( & pool - > pool_lock ) ;
/* Generate coinbase */
/* Generate coinbase */
nonce2 = bin2hex ( ( const unsigned char * ) & pool - > nonce2 , pool - > n2size ) ;
work - > nonce2 = bin2hex ( ( const unsigned char * ) & pool - > nonce2 , pool - > n2size ) ;
pool - > nonce2 + + ;
pool - > nonce2 + + ;
cb1_len = strlen ( pool - > swork . coinbase1 ) / 2 ;
cb1_len = strlen ( pool - > swork . coinbase1 ) / 2 ;
n1_len = strlen ( pool - > nonce1 ) / 2 ;
n1_len = strlen ( pool - > nonce1 ) / 2 ;
@ -5148,7 +5185,7 @@ static void gen_stratum_work(struct pool *pool, struct work *work)
coinbase = alloca ( len + 1 ) ;
coinbase = alloca ( len + 1 ) ;
hex2bin ( coinbase , pool - > swork . coinbase1 , cb1_len ) ;
hex2bin ( coinbase , pool - > swork . coinbase1 , cb1_len ) ;
hex2bin ( coinbase + cb1_len , pool - > nonce1 , n1_len ) ;
hex2bin ( coinbase + cb1_len , pool - > nonce1 , n1_len ) ;
hex2bin ( coinbase + cb1_len + n1_len , nonce2 , pool - > n2size ) ;
hex2bin ( coinbase + cb1_len + n1_len , work - > nonce2 , pool - > n2size ) ;
hex2bin ( coinbase + cb1_len + n1_len + pool - > n2size , pool - > swork . coinbase2 , cb2_len ) ;
hex2bin ( coinbase + cb1_len + n1_len + pool - > n2size , pool - > swork . coinbase2 , cb2_len ) ;
/* Generate merkle root */
/* Generate merkle root */
@ -5181,10 +5218,8 @@ static void gen_stratum_work(struct pool *pool, struct work *work)
work - > sdiff = pool - > swork . diff ;
work - > sdiff = pool - > swork . diff ;
/* Copy parameters required for share submission */
/* Copy parameters required for share submission */
sprintf ( work - > job_id , " %s " , pool - > swork . job_id ) ;
work - > job_id = strdup ( pool - > swork . job_id ) ;
sprintf ( work - > nonce2 , " %s " , nonce2 ) ;
work - > ntime = strdup ( pool - > swork . ntime ) ;
sprintf ( work - > ntime , " %s " , pool - > swork . ntime ) ;
free ( nonce2 ) ;
mutex_unlock ( & pool - > pool_lock ) ;
mutex_unlock ( & pool - > pool_lock ) ;
@ -5225,6 +5260,8 @@ static void get_work(struct work *work, struct thr_info *thr, const int thr_id)
* should not be restarted */
* should not be restarted */
thread_reportout ( thr ) ;
thread_reportout ( thr ) ;
clean_work ( work ) ;
if ( opt_benchmark ) {
if ( opt_benchmark ) {
get_benchmark_work ( work ) ;
get_benchmark_work ( work ) ;
goto out ;
goto out ;
@ -5298,7 +5335,7 @@ retry:
pool_resus ( pool ) ;
pool_resus ( pool ) ;
}
}
memcpy ( work , work_heap , sizeof ( struct work ) ) ;
__copy_work ( work , work_heap ) ;
free_work ( work_heap ) ;
free_work ( work_heap ) ;
out :
out :
@ -5307,7 +5344,7 @@ out:
work - > mined = true ;
work - > mined = true ;
}
}
bool submit_work_sync ( struct thr_info * thr , const struct work * work_in , struct timeval * tv_work_found )
bool submit_work_sync ( struct thr_info * thr , struct work * work_in , struct timeval * tv_work_found )
{
{
struct workio_cmd * wc ;
struct workio_cmd * wc ;
@ -5318,10 +5355,9 @@ bool submit_work_sync(struct thr_info *thr, const struct work *work_in, struct t
return false ;
return false ;
}
}
wc - > work = make_work ( ) ;
wc - > work = copy_work ( work_in ) ;
wc - > cmd = WC_SUBMIT_WORK ;
wc - > cmd = WC_SUBMIT_WORK ;
wc - > thr = thr ;
wc - > thr = thr ;
memcpy ( wc - > work , work_in , sizeof ( * work_in ) ) ;
if ( tv_work_found )
if ( tv_work_found )
memcpy ( & ( wc - > work - > tv_work_found ) , tv_work_found , sizeof ( struct timeval ) ) ;
memcpy ( & ( wc - > work - > tv_work_found ) , tv_work_found , sizeof ( struct timeval ) ) ;