Support for extranonce using BIP 23 coinbase/append mutation
This commit is contained in:
56
blkmaker.c
56
blkmaker.c
@@ -24,14 +24,11 @@ bool dblsha256(void *hash, const void *data, size_t datasz) {
|
||||
}
|
||||
|
||||
static
|
||||
bool build_merkle_root(unsigned char *mrklroot_out, blktemplate_t *tmpl) {
|
||||
if (!tmpl->cbtxn)
|
||||
return false;
|
||||
|
||||
bool build_merkle_root(unsigned char *mrklroot_out, blktemplate_t *tmpl, unsigned char *cbtxndata, size_t cbtxndatasz) {
|
||||
size_t hashcount = tmpl->txncount + 1;
|
||||
unsigned char hashes[(hashcount + 1) * 32];
|
||||
|
||||
if (!dblsha256(&hashes[0], tmpl->cbtxn->data, tmpl->cbtxn->datasz))
|
||||
if (!dblsha256(&hashes[0], cbtxndata, cbtxndatasz))
|
||||
return false;
|
||||
for (int i = 0; i < tmpl->txncount; ++i)
|
||||
if (!dblsha256(&hashes[32 * (i + 1)], tmpl->txns[i].data, tmpl->txns[i].datasz))
|
||||
@@ -56,7 +53,31 @@ bool build_merkle_root(unsigned char *mrklroot_out, blktemplate_t *tmpl) {
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t blkmk_get_data(blktemplate_t *tmpl, void *buf, size_t bufsz, time_t usetime, int16_t *out_expire) {
|
||||
static const int cbScriptSigLen = 4 + 1 + 36;
|
||||
|
||||
bool _blkmk_extranonce(void *vout, void *vin, size_t insz, unsigned int workid) {
|
||||
unsigned char *out = vout;
|
||||
unsigned char *in = vin;
|
||||
|
||||
if (in[cbScriptSigLen] > 100 - sizeof(workid))
|
||||
return false;
|
||||
|
||||
int cbPostScriptSig = cbScriptSigLen + 1 + in[cbScriptSigLen];
|
||||
|
||||
memcpy(out, in, cbPostScriptSig+1);
|
||||
out[cbScriptSigLen] += sizeof(workid);
|
||||
|
||||
unsigned char *outPostScriptSig = &out[cbPostScriptSig];
|
||||
unsigned int *outExtranonce = (void*)outPostScriptSig;
|
||||
outPostScriptSig += sizeof(workid);
|
||||
*outExtranonce = workid;
|
||||
|
||||
memcpy(outPostScriptSig, &in[cbPostScriptSig], insz - cbPostScriptSig);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t blkmk_get_data(blktemplate_t *tmpl, void *buf, size_t bufsz, time_t usetime, int16_t *out_expire, unsigned int *out_dataid) {
|
||||
if (!(blkmk_time_left(tmpl, usetime) && blkmk_work_left(tmpl)))
|
||||
return 0;
|
||||
if (bufsz < 76)
|
||||
@@ -66,8 +87,21 @@ size_t blkmk_get_data(blktemplate_t *tmpl, void *buf, size_t bufsz, time_t useti
|
||||
|
||||
my_htole32(&cbuf[0], tmpl->version);
|
||||
memcpy(&cbuf[4], &tmpl->prevblk, 32);
|
||||
if (!build_merkle_root(&cbuf[36], tmpl))
|
||||
|
||||
unsigned char cbtxndata[tmpl->cbtxn->datasz + sizeof(*out_dataid)];
|
||||
size_t cbtxndatasz = tmpl->cbtxn->datasz;
|
||||
*out_dataid = tmpl->next_dataid++;
|
||||
if (*out_dataid)
|
||||
{
|
||||
if (!_blkmk_extranonce(cbtxndata, tmpl->cbtxn->data, tmpl->cbtxn->datasz, *out_dataid))
|
||||
return 0;
|
||||
cbtxndatasz += sizeof(*out_dataid);
|
||||
}
|
||||
else
|
||||
memcpy(cbtxndata, tmpl->cbtxn->data, cbtxndatasz);
|
||||
if (!build_merkle_root(&cbuf[36], tmpl, cbtxndata, cbtxndatasz))
|
||||
return 0;
|
||||
|
||||
blktime_t timehdr = tmpl->curtime + difftime(usetime, tmpl->_time_rcvd);
|
||||
if (timehdr > tmpl->maxtime)
|
||||
timehdr = tmpl->maxtime;
|
||||
@@ -89,8 +123,10 @@ blktime_diff_t blkmk_time_left(const blktemplate_t *tmpl, time_t nowtime) {
|
||||
}
|
||||
|
||||
unsigned long blkmk_work_left(const blktemplate_t *tmpl) {
|
||||
// TODO
|
||||
// TEMPORARY HACK
|
||||
return (tmpl->version && !tmpl->_mrklroot[0]) ? 1 : 0;
|
||||
if (!tmpl->version)
|
||||
return 0;
|
||||
if (!(tmpl->mutations & (BMM_CBAPPEND | BMM_CBSET)))
|
||||
return 1;
|
||||
return UINT_MAX - tmpl->next_dataid;
|
||||
return BLKMK_UNLIMITED_WORK_COUNT;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
extern bool (*blkmk_sha256_impl)(void *hash_out, const void *data, size_t datasz);
|
||||
|
||||
extern size_t blkmk_get_data(blktemplate_t *, void *buf, size_t bufsz, time_t usetime, int16_t *out_expire);
|
||||
extern size_t blkmk_get_data(blktemplate_t *, void *buf, size_t bufsz, time_t usetime, int16_t *out_expire, unsigned int *out_dataid);
|
||||
extern blktime_diff_t blkmk_time_left(const blktemplate_t *, time_t nowtime);
|
||||
extern unsigned long blkmk_work_left(const blktemplate_t *);
|
||||
#define BLKMK_UNLIMITED_WORK_COUNT ULONG_MAX
|
||||
|
||||
@@ -267,18 +267,23 @@ void my_bin2hex(char *out, const void *data, size_t datasz) {
|
||||
}
|
||||
}
|
||||
|
||||
json_t *blkmk_submit_jansson(blktemplate_t *tmpl, const unsigned char *data, blknonce_t nonce) {
|
||||
json_t *blkmk_submit_jansson(blktemplate_t *tmpl, const unsigned char *data, unsigned int dataid, blknonce_t nonce) {
|
||||
unsigned char blk[80 + 8 + 1000000];
|
||||
memcpy(blk, data, 76);
|
||||
*(uint32_t*)(&blk[76]) = htonl(nonce);
|
||||
size_t offs = 80;
|
||||
|
||||
if (!(tmpl->mutations & BMAb_TRUNCATE))
|
||||
if (!(tmpl->mutations & BMAb_TRUNCATE && !dataid))
|
||||
{
|
||||
offs += varintEncode(&blk[offs], 1 + tmpl->txncount);
|
||||
|
||||
memcpy(&blk[offs], tmpl->cbtxn->data, tmpl->cbtxn->datasz);
|
||||
offs += tmpl->cbtxn->datasz;
|
||||
if (dataid)
|
||||
{
|
||||
*(int*)&blk[offs] = dataid;
|
||||
offs += sizeof(dataid);
|
||||
}
|
||||
|
||||
if (!(tmpl->mutations & BMAb_COINBASE))
|
||||
for (int i = 0; i < tmpl->txncount; ++i)
|
||||
|
||||
@@ -7,6 +7,6 @@
|
||||
|
||||
extern json_t *blktmpl_request_jansson(gbt_capabilities_t extracaps);
|
||||
extern const char *blktmpl_add_jansson(blktemplate_t *, const json_t *, time_t time_rcvd);
|
||||
extern json_t *blkmk_submit_jansson(blktemplate_t *, const unsigned char *data, blknonce_t);
|
||||
extern json_t *blkmk_submit_jansson(blktemplate_t *, const unsigned char *data, unsigned int dataid, blknonce_t);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -67,7 +67,7 @@ gbt_capabilities_t blktmpl_addcaps(const blktemplate_t *tmpl) {
|
||||
// For now, it's a simple "filled" vs "not filled"
|
||||
if (tmpl->version)
|
||||
return 0;
|
||||
return GBT_CBTXN | GBT_WORKID | BMM_TIMEINC;
|
||||
return GBT_CBTXN | GBT_WORKID | BMM_TIMEINC | BMM_CBAPPEND;
|
||||
}
|
||||
|
||||
static
|
||||
|
||||
@@ -111,6 +111,7 @@ typedef struct {
|
||||
|
||||
// TEMPORARY HACK
|
||||
libblkmaker_hash_t _mrklroot;
|
||||
unsigned int next_dataid;
|
||||
} blktemplate_t;
|
||||
|
||||
extern blktemplate_t *blktmpl_create();
|
||||
|
||||
@@ -60,10 +60,11 @@ int main(int argc, char**argv) {
|
||||
{
|
||||
unsigned char data[80], hash[32];
|
||||
size_t datasz;
|
||||
unsigned int dataid;
|
||||
uint32_t nonce;
|
||||
|
||||
datasz = blkmk_get_data(tmpl, data, sizeof(data), time(NULL), NULL);
|
||||
assert(datasz <= sizeof(data));
|
||||
datasz = blkmk_get_data(tmpl, data, sizeof(data), time(NULL), NULL, &dataid);
|
||||
assert(datasz >= 76 && datasz <= sizeof(data));
|
||||
|
||||
// mine the right nonce
|
||||
// this is iterating in native order, even though SHA256 is big endian, because we don't implement noncerange
|
||||
@@ -84,7 +85,7 @@ int main(int argc, char**argv) {
|
||||
printf("Found nonce: 0x%8" PRIx32 " \n", nonce);
|
||||
nonce = ntohl(nonce);
|
||||
|
||||
req = blkmk_submit_jansson(tmpl, data, nonce);
|
||||
req = blkmk_submit_jansson(tmpl, data, dataid, nonce);
|
||||
assert(req);
|
||||
// send req to server
|
||||
send_json(req);
|
||||
|
||||
Reference in New Issue
Block a user