diff --git a/blkmaker.c b/blkmaker.c index f4710cd..d5d84cf 100644 --- a/blkmaker.c +++ b/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; } diff --git a/blkmaker.h b/blkmaker.h index 3a78451..1f95d0a 100644 --- a/blkmaker.h +++ b/blkmaker.h @@ -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 diff --git a/blkmaker_jansson.c b/blkmaker_jansson.c index dbe83a5..695ed1f 100644 --- a/blkmaker_jansson.c +++ b/blkmaker_jansson.c @@ -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) diff --git a/blkmaker_jansson.h b/blkmaker_jansson.h index 4a0a872..9830283 100644 --- a/blkmaker_jansson.h +++ b/blkmaker_jansson.h @@ -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 diff --git a/blktemplate.c b/blktemplate.c index 36ad0f0..016a2a3 100644 --- a/blktemplate.c +++ b/blktemplate.c @@ -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 diff --git a/blktemplate.h b/blktemplate.h index da737a4..1cf7405 100644 --- a/blktemplate.h +++ b/blktemplate.h @@ -111,6 +111,7 @@ typedef struct { // TEMPORARY HACK libblkmaker_hash_t _mrklroot; + unsigned int next_dataid; } blktemplate_t; extern blktemplate_t *blktmpl_create(); diff --git a/example.c b/example.c index 1ae95cf..a98332e 100644 --- a/example.c +++ b/example.c @@ -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);