Add option --coinbase-sig
This commit is contained in:
parent
9c8cad615a
commit
788e4a3746
2 changed files with 71 additions and 34 deletions
101
cpu-miner.c
101
cpu-miner.c
|
@ -137,6 +137,7 @@ static char *rpc_userpass;
|
||||||
static char *rpc_user, *rpc_pass;
|
static char *rpc_user, *rpc_pass;
|
||||||
static int pk_script_size;
|
static int pk_script_size;
|
||||||
static unsigned char pk_script[25];
|
static unsigned char pk_script[25];
|
||||||
|
static char coinbase_sig[101] = "";
|
||||||
char *opt_cert;
|
char *opt_cert;
|
||||||
char *opt_proxy;
|
char *opt_proxy;
|
||||||
long opt_proxy_type;
|
long opt_proxy_type;
|
||||||
|
@ -185,6 +186,7 @@ Options:\n\
|
||||||
-s, --scantime=N upper bound on time spent scanning current work when\n\
|
-s, --scantime=N upper bound on time spent scanning current work when\n\
|
||||||
long polling is unavailable, in seconds (default: 5)\n\
|
long polling is unavailable, in seconds (default: 5)\n\
|
||||||
--coinbase-addr=ADDR payout address for solo mining\n\
|
--coinbase-addr=ADDR payout address for solo mining\n\
|
||||||
|
--coinbase-sig=TEXT data to insert in the coinbase when possible\n\
|
||||||
--no-longpoll disable long polling support\n\
|
--no-longpoll disable long polling support\n\
|
||||||
--no-getwork disable getwork support\n\
|
--no-getwork disable getwork support\n\
|
||||||
--no-gbt disable getblocktemplate support\n\
|
--no-gbt disable getblocktemplate support\n\
|
||||||
|
@ -225,6 +227,7 @@ static struct option const options[] = {
|
||||||
{ "benchmark", 0, NULL, 1005 },
|
{ "benchmark", 0, NULL, 1005 },
|
||||||
{ "cert", 1, NULL, 1001 },
|
{ "cert", 1, NULL, 1001 },
|
||||||
{ "coinbase-addr", 1, NULL, 1013 },
|
{ "coinbase-addr", 1, NULL, 1013 },
|
||||||
|
{ "coinbase-sig", 1, NULL, 1015 },
|
||||||
{ "config", 1, NULL, 'c' },
|
{ "config", 1, NULL, 'c' },
|
||||||
{ "debug", 0, NULL, 'D' },
|
{ "debug", 0, NULL, 'D' },
|
||||||
{ "help", 0, NULL, 'h' },
|
{ "help", 0, NULL, 'h' },
|
||||||
|
@ -351,6 +354,7 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
|
||||||
int tx_count, tx_size;
|
int tx_count, tx_size;
|
||||||
unsigned char txc_vi[9];
|
unsigned char txc_vi[9];
|
||||||
unsigned char (*merkle_tree)[32] = NULL;
|
unsigned char (*merkle_tree)[32] = NULL;
|
||||||
|
bool coinbase_append = false;
|
||||||
bool submit_coinbase = false;
|
bool submit_coinbase = false;
|
||||||
bool version_force = false;
|
bool version_force = false;
|
||||||
bool version_reduce = false;
|
bool version_reduce = false;
|
||||||
|
@ -364,7 +368,9 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
|
||||||
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, "submit/coinbase"))
|
if (!strcmp(s, "coinbase/append"))
|
||||||
|
coinbase_append = true;
|
||||||
|
else if (!strcmp(s, "submit/coinbase"))
|
||||||
submit_coinbase = true;
|
submit_coinbase = true;
|
||||||
else if (!strcmp(s, "version/force"))
|
else if (!strcmp(s, "version/force"))
|
||||||
version_force = true;
|
version_force = true;
|
||||||
|
@ -435,12 +441,13 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
|
||||||
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 ? strlen(cbtx_hex) / 2 : 0;
|
cbtx_size = cbtx_hex ? strlen(cbtx_hex) / 2 : 0;
|
||||||
cbtx = malloc(cbtx_size);
|
cbtx = malloc(cbtx_size + 100);
|
||||||
if (!cbtx_hex || !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;
|
||||||
if (!pk_script_size) {
|
if (!pk_script_size) {
|
||||||
applog(LOG_ERR, "No payout address provided");
|
applog(LOG_ERR, "No payout address provided");
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -450,43 +457,18 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
|
||||||
applog(LOG_ERR, "JSON invalid coinbasevalue");
|
applog(LOG_ERR, "JSON invalid coinbasevalue");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
int64_t cbvalue = json_is_integer(tmp) ? json_integer_value(tmp) : json_number_value(tmp);
|
cbvalue = json_is_integer(tmp) ? json_integer_value(tmp) : json_number_value(tmp);
|
||||||
cbtx = malloc(256);
|
cbtx = malloc(256);
|
||||||
le32enc((uint32_t *)cbtx, 1); /* version */
|
le32enc((uint32_t *)cbtx, 1); /* version */
|
||||||
cbtx[4] = 1; /* in-counter */
|
cbtx[4] = 1; /* in-counter */
|
||||||
memset(cbtx+5, 0x00, 32); /* prev txout hash */
|
memset(cbtx+5, 0x00, 32); /* prev txout hash */
|
||||||
le32enc((uint32_t *)(cbtx+37), 0xffffffff); /* prev txout index */
|
le32enc((uint32_t *)(cbtx+37), 0xffffffff); /* prev txout index */
|
||||||
|
cbtx_size = 43;
|
||||||
/* BIP 34: height in coinbase */
|
/* BIP 34: height in coinbase */
|
||||||
int h = work->height;
|
for (n = work->height; n; n >>= 8)
|
||||||
for (i = 0; h; i++) {
|
cbtx[cbtx_size++] = n & 0xff;
|
||||||
cbtx[43 + i] = h & 0xff;
|
cbtx[42] = cbtx_size - 43;
|
||||||
h >>= 8;
|
cbtx[41] = cbtx_size - 42; /* scriptsig length */
|
||||||
}
|
|
||||||
cbtx[42] = i;
|
|
||||||
cbtx_size = 43 + i;
|
|
||||||
tmp = json_object_get(val, "coinbaseaux");
|
|
||||||
if (tmp && json_is_object(tmp)) {
|
|
||||||
void *iter = json_object_iter(tmp);
|
|
||||||
while (iter) {
|
|
||||||
unsigned char buf[100];
|
|
||||||
const char *s = json_string_value(json_object_iter_value(iter));
|
|
||||||
n = s ? strlen(s) / 2 : 0;
|
|
||||||
if (!s || n > 100 || !hex2bin(buf, s, n)) {
|
|
||||||
applog(LOG_ERR, "JSON invalid coinbaseaux");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (cbtx_size - 42 + (n > 75 ? 2 : 1) + n <= 100) {
|
|
||||||
if (n > 75)
|
|
||||||
cbtx[cbtx_size++] = 0x4c; /* OP_PUSHDATA1 */
|
|
||||||
cbtx[cbtx_size++] = n;
|
|
||||||
memcpy(cbtx+cbtx_size, buf, n);
|
|
||||||
cbtx_size += n;
|
|
||||||
}
|
|
||||||
iter = json_object_iter_next(tmp, iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
cbtx[41] = cbtx_size - 42; /* txin-script length */
|
|
||||||
le32enc((uint32_t *)(cbtx+cbtx_size), 0xffffffff); /* sequence */
|
le32enc((uint32_t *)(cbtx+cbtx_size), 0xffffffff); /* sequence */
|
||||||
cbtx_size += 4;
|
cbtx_size += 4;
|
||||||
cbtx[cbtx_size++] = 1; /* out-counter */
|
cbtx[cbtx_size++] = 1; /* out-counter */
|
||||||
|
@ -498,6 +480,52 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
|
||||||
cbtx_size += pk_script_size;
|
cbtx_size += pk_script_size;
|
||||||
le32enc((uint32_t *)(cbtx+cbtx_size), 0); /* lock time */
|
le32enc((uint32_t *)(cbtx+cbtx_size), 0); /* lock time */
|
||||||
cbtx_size += 4;
|
cbtx_size += 4;
|
||||||
|
coinbase_append = true;
|
||||||
|
}
|
||||||
|
if (coinbase_append) {
|
||||||
|
unsigned char xsig[100];
|
||||||
|
int xsig_len = 0;
|
||||||
|
if (*coinbase_sig) {
|
||||||
|
n = strlen(coinbase_sig);
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tmp = json_object_get(val, "coinbaseaux");
|
||||||
|
if (tmp && json_is_object(tmp)) {
|
||||||
|
void *iter = json_object_iter(tmp);
|
||||||
|
while (iter) {
|
||||||
|
unsigned char buf[100];
|
||||||
|
const char *s = json_string_value(json_object_iter_value(iter));
|
||||||
|
n = s ? strlen(s) / 2 : 0;
|
||||||
|
if (!s || n > 100 || !hex2bin(buf, s, n)) {
|
||||||
|
applog(LOG_ERR, "JSON invalid coinbaseaux");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (cbtx[41] + xsig_len + n <= 100) {
|
||||||
|
memcpy(xsig+xsig_len, buf, n);
|
||||||
|
xsig_len += n;
|
||||||
|
}
|
||||||
|
iter = json_object_iter_next(tmp, iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (xsig_len) {
|
||||||
|
unsigned char *ssig_end = cbtx + 42 + cbtx[41];
|
||||||
|
int push_len = cbtx[41] + xsig_len < 76 ? 1 :
|
||||||
|
cbtx[41] + 2 + xsig_len > 100 ? 0 : 2;
|
||||||
|
n = xsig_len + push_len;
|
||||||
|
memmove(ssig_end + n, ssig_end, cbtx_size - 42 - cbtx[41]);
|
||||||
|
cbtx[41] += n;
|
||||||
|
if (push_len == 2)
|
||||||
|
*(ssig_end++) = 0x4c; /* OP_PUSHDATA1 */
|
||||||
|
if (push_len)
|
||||||
|
*(ssig_end++) = xsig_len;
|
||||||
|
memcpy(ssig_end, xsig, xsig_len);
|
||||||
|
cbtx_size += n;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
n = varint_encode(txc_vi, 1 + tx_count);
|
n = varint_encode(txc_vi, 1 + tx_count);
|
||||||
|
@ -1597,6 +1625,11 @@ static void parse_arg (int key, char *arg)
|
||||||
if (!pk_script_size)
|
if (!pk_script_size)
|
||||||
show_usage_and_exit(1);
|
show_usage_and_exit(1);
|
||||||
break;
|
break;
|
||||||
|
case 1015: /* --coinbase-sig */
|
||||||
|
if (strlen(arg) + 1 > sizeof(coinbase_sig))
|
||||||
|
show_usage_and_exit(1);
|
||||||
|
strcpy(coinbase_sig, arg);
|
||||||
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
use_syslog = true;
|
use_syslog = true;
|
||||||
break;
|
break;
|
||||||
|
|
4
minerd.1
4
minerd.1
|
@ -91,6 +91,10 @@ Set a payout address for solo mining.
|
||||||
This is only used in getblocktemplate mode,
|
This is only used in getblocktemplate mode,
|
||||||
and only if the server does not provide a coinbase transaction.
|
and only if the server does not provide a coinbase transaction.
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-\-coinbase\-sig\fR=\fITEXT\fR
|
||||||
|
Set a string to be included in the coinbase (if allowed by the server).
|
||||||
|
This is only used in getblocktemplate mode.
|
||||||
|
.TP
|
||||||
\fB\-c\fR, \fB\-\-config\fR=\fIFILE\fR
|
\fB\-c\fR, \fB\-\-config\fR=\fIFILE\fR
|
||||||
Load options from a configuration file.
|
Load options from a configuration file.
|
||||||
\fIFILE\fR must contain a JSON object
|
\fIFILE\fR must contain a JSON object
|
||||||
|
|
Loading…
Reference in a new issue