From 2763aba1144dec45f193cf08adb5cbe4570a07a4 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 26 Jan 2016 00:23:22 +0000 Subject: [PATCH 1/9] Keep a count of total size of all non-generation transactions in templates --- blkmaker_jansson.c | 8 +++++++- blktemplate.h | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/blkmaker_jansson.c b/blkmaker_jansson.c index fcf803f..2094a75 100644 --- a/blkmaker_jansson.c +++ b/blkmaker_jansson.c @@ -213,9 +213,15 @@ const char *blktmpl_add_jansson(blktemplate_t *tmpl, const json_t *json, time_t v = json_object_get(json, "transactions"); size_t txns = tmpl->txncount = json_array_size(v); tmpl->txns = calloc(txns, sizeof(*tmpl->txns)); + tmpl->txns_datasz = 0; for (size_t i = 0; i < txns; ++i) - if ((s = parse_txn(&tmpl->txns[i], json_array_get(v, i)))) + { + struct blktxn_t * const txn = &tmpl->txns[i]; + if ((s = parse_txn(txn, json_array_get(v, i)))) { return s; + } + tmpl->txns_datasz += txn->datasz; + } if ((v = json_object_get(json, "coinbasetxn")) && json_is_object(v)) { diff --git a/blktemplate.h b/blktemplate.h index 7bed8ec..d8aa1e4 100644 --- a/blktemplate.h +++ b/blktemplate.h @@ -134,6 +134,8 @@ typedef struct { unsigned aux_count; struct blkaux_t *auxs; + + unsigned long txns_datasz; } blktemplate_t; extern blktemplate_t *blktmpl_create(); From 24aabb0e55a8047d477183703d8465ff0720a3af Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 26 Jan 2016 00:36:01 +0000 Subject: [PATCH 2/9] Bugfix: Allocate temporary space on the heap rather than the stack, and use the actual transaction data size for the buffer --- blkmaker.c | 29 +++++++++++++++++++++++++---- blktemplate.h | 2 ++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/blkmaker.c b/blkmaker.c index 7bc1421..68f3272 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -47,6 +47,8 @@ bool _blkmk_dblsha256(void *hash, const void *data, size_t datasz) { #define dblsha256 _blkmk_dblsha256 +#define max_varint_size (9) + uint64_t blkmk_init_generation3(blktemplate_t * const tmpl, const void * const script, const size_t scriptsz, bool * const inout_newcb) { if (tmpl->cbtxn && !(*inout_newcb && (tmpl->mutations & BMM_GENERATE))) { @@ -482,29 +484,48 @@ char varintEncode(unsigned char *out, uint64_t n) { char *blkmk_assemble_submission_(blktemplate_t * const tmpl, const unsigned char * const data, const unsigned int dataid, blknonce_t nonce, const bool foreign) { - unsigned char blk[80 + 8 + 1000000]; + const bool incl_gentxn = (foreign || (!(tmpl->mutations & BMAb_TRUNCATE && !dataid))); + const bool incl_alltxn = (foreign || !(tmpl->mutations & BMAb_COINBASE)); + + size_t blkbuf_sz = libblkmaker_blkheader_size; + if (incl_gentxn) { + blkbuf_sz += max_varint_size + tmpl->cbtxn->datasz; + if (incl_alltxn) { + blkbuf_sz += tmpl->txns_datasz; + } + } + + unsigned char * const blk = malloc(blkbuf_sz); + if (!blk) { + return NULL; + } + memcpy(blk, data, 76); nonce = htonl(nonce); memcpy(&blk[76], &nonce, 4); size_t offs = 80; - if (foreign || (!(tmpl->mutations & BMAb_TRUNCATE && !dataid))) - { + if (incl_gentxn) { offs += varintEncode(&blk[offs], 1 + tmpl->txncount); if (!_blkmk_extranonce(tmpl, &blk[offs], dataid, &offs)) + { + free(blk); return NULL; + } - if (foreign || !(tmpl->mutations & BMAb_COINBASE)) + if (incl_alltxn) { for (unsigned long i = 0; i < tmpl->txncount; ++i) { memcpy(&blk[offs], tmpl->txns[i].data, tmpl->txns[i].datasz); offs += tmpl->txns[i].datasz; } + } } char *blkhex = malloc((offs * 2) + 1); _blkmk_bin2hex(blkhex, blk, offs); + free(blk); return blkhex; } diff --git a/blktemplate.h b/blktemplate.h index d8aa1e4..90049b0 100644 --- a/blktemplate.h +++ b/blktemplate.h @@ -24,6 +24,8 @@ typedef uint32_t blktime_t; typedef int16_t blktime_diff_t; typedef uint32_t blknonce_t; +#define libblkmaker_blkheader_size (80) + struct blktxn_t { unsigned char *data; size_t datasz; From ef78f03a58b8c761ce9ed2b7137d903785cbbd40 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 26 Jan 2016 00:39:19 +0000 Subject: [PATCH 3/9] Make an abstract size variable for libblkmaker_coinbase_size_limit --- blkmaker.c | 6 +++--- blktemplate.h | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/blkmaker.c b/blkmaker.c index 68f3272..96b1e49 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -95,7 +95,7 @@ uint64_t blkmk_init_generation3(blktemplate_t * const tmpl, const void * const s for (unsigned i = 0; i < tmpl->aux_count; ++i) { struct blkaux_t * const aux = &tmpl->auxs[i]; - if ((size_t)data[41] + aux->datasz > 100) + if ((size_t)data[41] + aux->datasz > libblkmaker_coinbase_size_limit) { free(data); return 0; @@ -256,7 +256,7 @@ bool _blkmk_append_cb(blktemplate_t * const tmpl, void * const vout, const void unsigned char *in = tmpl->cbtxn->data; size_t insz = tmpl->cbtxn->datasz; - if (in[cbScriptSigLen] > 100 - appendsz) + if (in[cbScriptSigLen] > libblkmaker_coinbase_size_limit - appendsz) return false; int cbPostScriptSig = cbScriptSigLen + 1 + in[cbScriptSigLen]; @@ -294,7 +294,7 @@ ssize_t blkmk_append_coinbase_safe2(blktemplate_t * const tmpl, const void * con if (extranoncesz == sizeof(unsigned int)) ++extranoncesz; } - size_t availsz = 100 - extranoncesz - tmpl->cbtxn->data[cbScriptSigLen]; + size_t availsz = libblkmaker_coinbase_size_limit - extranoncesz - tmpl->cbtxn->data[cbScriptSigLen]; if (appendsz > availsz) return availsz; diff --git a/blktemplate.h b/blktemplate.h index 90049b0..67c5311 100644 --- a/blktemplate.h +++ b/blktemplate.h @@ -25,6 +25,7 @@ typedef int16_t blktime_diff_t; typedef uint32_t blknonce_t; #define libblkmaker_blkheader_size (80) +#define libblkmaker_coinbase_size_limit (100) struct blktxn_t { unsigned char *data; From f1ede0aec7a95283a6f5d0bdbfcbe0b2826fd26e Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 26 Jan 2016 03:40:39 +0000 Subject: [PATCH 4/9] Bugfix: Check full block size against limit when creating/appending the coinbase --- blkmaker.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/blkmaker.c b/blkmaker.c index 96b1e49..bf00504 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -120,6 +120,11 @@ uint64_t blkmk_init_generation3(blktemplate_t * const tmpl, const void * const s memset(&data[off], 0, 4); // lock time off += 4; + if (tmpl->txns_datasz + off > tmpl->sizelimit) { + free(data); + return 0; + } + struct blktxn_t *txn = calloc(1, sizeof(*tmpl->cbtxn)); if (!txn) { @@ -259,6 +264,10 @@ bool _blkmk_append_cb(blktemplate_t * const tmpl, void * const vout, const void if (in[cbScriptSigLen] > libblkmaker_coinbase_size_limit - appendsz) return false; + if (tmpl->cbtxn->datasz + tmpl->txns_datasz + appendsz > tmpl->sizelimit) { + return false; + } + int cbPostScriptSig = cbScriptSigLen + 1 + in[cbScriptSigLen]; if (appended_at_offset) *appended_at_offset = cbPostScriptSig; @@ -295,6 +304,16 @@ ssize_t blkmk_append_coinbase_safe2(blktemplate_t * const tmpl, const void * con ++extranoncesz; } size_t availsz = libblkmaker_coinbase_size_limit - extranoncesz - tmpl->cbtxn->data[cbScriptSigLen]; + { + const size_t current_blocksize = tmpl->cbtxn->datasz + tmpl->txns_datasz; + if (current_blocksize > tmpl->sizelimit) { + return false; + } + const size_t availsz2 = tmpl->sizelimit - current_blocksize; + if (availsz2 < availsz) { + availsz = availsz2; + } + } if (appendsz > availsz) return availsz; From a22129364acccef153ea4001d995d487e20589e3 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 26 Jan 2016 04:26:02 +0000 Subject: [PATCH 5/9] Refactor construction of block submissions to allow for results from get_mdata --- blkmaker.c | 38 ++++++++++++++++++++++++++++++++------ private.h | 1 + 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/blkmaker.c b/blkmaker.c index bf00504..bd87439 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -501,9 +501,9 @@ char varintEncode(unsigned char *out, uint64_t n) { return L; } -char *blkmk_assemble_submission_(blktemplate_t * const tmpl, const unsigned char * const data, const unsigned int dataid, blknonce_t nonce, const bool foreign) +static char *blkmk_assemble_submission2_internal(blktemplate_t * const tmpl, const unsigned char * const data, const void * const extranonce, const size_t extranoncesz, blknonce_t nonce, const bool foreign) { - const bool incl_gentxn = (foreign || (!(tmpl->mutations & BMAb_TRUNCATE && !dataid))); + const bool incl_gentxn = (foreign || (!(tmpl->mutations & BMAb_TRUNCATE && !extranoncesz))); const bool incl_alltxn = (foreign || !(tmpl->mutations & BMAb_COINBASE)); size_t blkbuf_sz = libblkmaker_blkheader_size; @@ -527,10 +527,17 @@ char *blkmk_assemble_submission_(blktemplate_t * const tmpl, const unsigned char if (incl_gentxn) { offs += varintEncode(&blk[offs], 1 + tmpl->txncount); - if (!_blkmk_extranonce(tmpl, &blk[offs], dataid, &offs)) - { - free(blk); - return NULL; + // Essentially _blkmk_extranonce + if (extranoncesz) { + if (!_blkmk_append_cb(tmpl, &blk[offs], extranonce, extranoncesz, NULL)) { + free(blk); + return NULL; + } + + offs += tmpl->cbtxn->datasz + extranoncesz; + } else { + memcpy(&blk[offs], tmpl->cbtxn->data, tmpl->cbtxn->datasz); + offs += tmpl->cbtxn->datasz; } if (incl_alltxn) { @@ -548,3 +555,22 @@ char *blkmk_assemble_submission_(blktemplate_t * const tmpl, const unsigned char return blkhex; } + +char *blkmk_assemble_submission2_(blktemplate_t * const tmpl, const unsigned char * const data, const void * const extranonce, const size_t extranoncesz, const blknonce_t nonce, const bool foreign) +{ + if (extranoncesz == sizeof(unsigned int)) { + // Avoid overlapping with blkmk_get_data use + unsigned char extended_extranonce[extranoncesz + 1]; + memcpy(extended_extranonce, extranonce, extranoncesz); + extended_extranonce[extranoncesz] = 0; + return blkmk_assemble_submission2_internal(tmpl, data, extended_extranonce, extranoncesz + 1, nonce, foreign); + } + return blkmk_assemble_submission2_internal(tmpl, data, extranonce, extranoncesz, nonce, foreign); +} + +char *blkmk_assemble_submission_(blktemplate_t * const tmpl, const unsigned char * const data, const unsigned int dataid, const blknonce_t nonce, const bool foreign) +{ + const void * const extranonce = &dataid; + const size_t extranoncesz = dataid ? sizeof(dataid) : 0; + return blkmk_assemble_submission2_internal(tmpl, data, extranonce, extranoncesz, nonce, foreign); +} diff --git a/private.h b/private.h index f149223..86c4705 100644 --- a/private.h +++ b/private.h @@ -10,6 +10,7 @@ extern bool _blkmk_dblsha256(void *hash, const void *data, size_t datasz); extern bool blkmk_sample_data_(blktemplate_t *, uint8_t *, unsigned int dataid); extern char *blkmk_assemble_submission_(blktemplate_t *, const unsigned char *data, unsigned int dataid, blknonce_t nonce, bool foreign); +extern char *blkmk_assemble_submission2_(blktemplate_t *, const unsigned char *data, const void *extranonce, size_t extranoncesz, blknonce_t nonce, bool foreign); // blktemplate.c extern void _blktxn_free(struct blktxn_t *); From e3465d35aadeb3a4d4ad98b0e2333cc718c78850 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 26 Jan 2016 04:35:10 +0000 Subject: [PATCH 6/9] Refactor blkmk_assemble_submission2_ to work with either extranonce/mdata or dataid/data --- blkmaker.c | 15 ++++++++++----- private.h | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/blkmaker.c b/blkmaker.c index bd87439..8d09f8d 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -556,9 +556,16 @@ static char *blkmk_assemble_submission2_internal(blktemplate_t * const tmpl, con return blkhex; } -char *blkmk_assemble_submission2_(blktemplate_t * const tmpl, const unsigned char * const data, const void * const extranonce, const size_t extranoncesz, const blknonce_t nonce, const bool foreign) +char *blkmk_assemble_submission2_(blktemplate_t * const tmpl, const unsigned char * const data, const void *extranonce, size_t extranoncesz, const unsigned int dataid, const blknonce_t nonce, const bool foreign) { - if (extranoncesz == sizeof(unsigned int)) { + if (dataid) { + if (extranoncesz) { + // Cannot specify both! + return NULL; + } + extranonce = &dataid; + extranoncesz = sizeof(dataid); + } else if (extranoncesz == sizeof(unsigned int)) { // Avoid overlapping with blkmk_get_data use unsigned char extended_extranonce[extranoncesz + 1]; memcpy(extended_extranonce, extranonce, extranoncesz); @@ -570,7 +577,5 @@ char *blkmk_assemble_submission2_(blktemplate_t * const tmpl, const unsigned cha char *blkmk_assemble_submission_(blktemplate_t * const tmpl, const unsigned char * const data, const unsigned int dataid, const blknonce_t nonce, const bool foreign) { - const void * const extranonce = &dataid; - const size_t extranoncesz = dataid ? sizeof(dataid) : 0; - return blkmk_assemble_submission2_internal(tmpl, data, extranonce, extranoncesz, nonce, foreign); + return blkmk_assemble_submission2_(tmpl, data, NULL, 0, dataid, nonce, foreign); } diff --git a/private.h b/private.h index 86c4705..19aa6e6 100644 --- a/private.h +++ b/private.h @@ -10,7 +10,7 @@ extern bool _blkmk_dblsha256(void *hash, const void *data, size_t datasz); extern bool blkmk_sample_data_(blktemplate_t *, uint8_t *, unsigned int dataid); extern char *blkmk_assemble_submission_(blktemplate_t *, const unsigned char *data, unsigned int dataid, blknonce_t nonce, bool foreign); -extern char *blkmk_assemble_submission2_(blktemplate_t *, const unsigned char *data, const void *extranonce, size_t extranoncesz, blknonce_t nonce, bool foreign); +extern char *blkmk_assemble_submission2_(blktemplate_t *, const unsigned char *data, const void *extranonce, size_t extranoncesz, unsigned int dataid, blknonce_t nonce, bool foreign); // blktemplate.c extern void _blktxn_free(struct blktxn_t *); From 58aa6a3573585d5fdc69b6cd9ff345e9a86927e1 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 26 Jan 2016 04:41:16 +0000 Subject: [PATCH 7/9] Refactor to eliminate blkmk_assemble_submission_ wrapper --- blkmaker.c | 5 ----- blkmaker_jansson.c | 10 +++++----- private.h | 1 - 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/blkmaker.c b/blkmaker.c index 8d09f8d..f8d815d 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -574,8 +574,3 @@ char *blkmk_assemble_submission2_(blktemplate_t * const tmpl, const unsigned cha } return blkmk_assemble_submission2_internal(tmpl, data, extranonce, extranoncesz, nonce, foreign); } - -char *blkmk_assemble_submission_(blktemplate_t * const tmpl, const unsigned char * const data, const unsigned int dataid, const blknonce_t nonce, const bool foreign) -{ - return blkmk_assemble_submission2_(tmpl, data, NULL, 0, dataid, nonce, foreign); -} diff --git a/blkmaker_jansson.c b/blkmaker_jansson.c index 2094a75..8eb2059 100644 --- a/blkmaker_jansson.c +++ b/blkmaker_jansson.c @@ -311,7 +311,7 @@ json_t *blktmpl_propose_jansson(blktemplate_t * const tmpl, const uint32_t caps, uint8_t sdata[0x4c]; if (!blkmk_sample_data_(tmpl, sdata, dataid)) goto err; - char *blkhex = blkmk_assemble_submission_(tmpl, sdata, dataid, 0, foreign); + char *blkhex = blkmk_assemble_submission2_(tmpl, sdata, NULL, 0, dataid, 0, foreign); if (!blkhex) goto err; if (!(ja = json_string(blkhex))) @@ -328,8 +328,8 @@ err: } static -json_t *_blkmk_submit_jansson(blktemplate_t *tmpl, const unsigned char *data, unsigned int dataid, blknonce_t nonce, bool foreign) { - char *blkhex = blkmk_assemble_submission_(tmpl, data, dataid, nonce, foreign); +json_t *_blkmk_submit_jansson(blktemplate_t *tmpl, const unsigned char *data, const void * const extranonce, const size_t extranoncesz, unsigned int dataid, blknonce_t nonce, bool foreign) { + char *blkhex = blkmk_assemble_submission2_(tmpl, data, extranonce, extranoncesz, dataid, nonce, foreign); if (!blkhex) return NULL; @@ -378,9 +378,9 @@ err: } json_t *blkmk_submit_jansson(blktemplate_t *tmpl, const unsigned char *data, unsigned int dataid, blknonce_t nonce) { - return _blkmk_submit_jansson(tmpl, data, dataid, nonce, false); + return _blkmk_submit_jansson(tmpl, data, NULL, 0, dataid, nonce, false); } json_t *blkmk_submit_foreign_jansson(blktemplate_t *tmpl, const unsigned char *data, unsigned int dataid, blknonce_t nonce) { - return _blkmk_submit_jansson(tmpl, data, dataid, nonce, true); + return _blkmk_submit_jansson(tmpl, data, NULL, 0, dataid, nonce, true); } diff --git a/private.h b/private.h index 19aa6e6..550c35d 100644 --- a/private.h +++ b/private.h @@ -9,7 +9,6 @@ // blkmaker.c extern bool _blkmk_dblsha256(void *hash, const void *data, size_t datasz); extern bool blkmk_sample_data_(blktemplate_t *, uint8_t *, unsigned int dataid); -extern char *blkmk_assemble_submission_(blktemplate_t *, const unsigned char *data, unsigned int dataid, blknonce_t nonce, bool foreign); extern char *blkmk_assemble_submission2_(blktemplate_t *, const unsigned char *data, const void *extranonce, size_t extranoncesz, unsigned int dataid, blknonce_t nonce, bool foreign); // blktemplate.c From 7bf7e80a6a2d09e25888e1325612797fcf81037c Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 26 Jan 2016 04:41:39 +0000 Subject: [PATCH 8/9] Bugfix: Expose blkmk_submitm_jansson for submitting results for blkmk_get_mdata --- blkmaker_jansson.c | 4 ++++ blkmaker_jansson.h | 1 + 2 files changed, 5 insertions(+) diff --git a/blkmaker_jansson.c b/blkmaker_jansson.c index 8eb2059..3717572 100644 --- a/blkmaker_jansson.c +++ b/blkmaker_jansson.c @@ -384,3 +384,7 @@ json_t *blkmk_submit_jansson(blktemplate_t *tmpl, const unsigned char *data, uns json_t *blkmk_submit_foreign_jansson(blktemplate_t *tmpl, const unsigned char *data, unsigned int dataid, blknonce_t nonce) { return _blkmk_submit_jansson(tmpl, data, NULL, 0, dataid, nonce, true); } + +json_t *blkmk_submitm_jansson(blktemplate_t * const tmpl, const unsigned char *data, const void * const extranonce, const size_t extranoncesz, const blknonce_t nonce, const bool foreign) { + return _blkmk_submit_jansson(tmpl, data, extranonce, extranoncesz, 0, nonce, foreign); +} diff --git a/blkmaker_jansson.h b/blkmaker_jansson.h index 08a5d6e..6308488 100644 --- a/blkmaker_jansson.h +++ b/blkmaker_jansson.h @@ -14,6 +14,7 @@ extern const char *blktmpl_add_jansson(blktemplate_t *, const json_t *, time_t t extern json_t *blktmpl_propose_jansson(blktemplate_t *, uint32_t caps, bool foreign); extern json_t *blkmk_submit_jansson(blktemplate_t *, const unsigned char *data, unsigned int dataid, blknonce_t); extern json_t *blkmk_submit_foreign_jansson(blktemplate_t *, const unsigned char *data, unsigned int dataid, blknonce_t); +extern json_t *blkmk_submitm_jansson(blktemplate_t *, const unsigned char *data, const void *extranonce, size_t extranoncesz, blknonce_t, bool foreign); #ifdef __cplusplus } From c94e438c9159ace5983d2b8d3c7785831cd39bd7 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 26 Jan 2016 04:47:25 +0000 Subject: [PATCH 9/9] Bugfix: Always avoid data/mdata size conflict in blkmk_append_coinbase_safe2 since nothing else checks merkle_only (nor has it available to check) --- blkmaker.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/blkmaker.c b/blkmaker.c index f8d815d..f0b8974 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -295,13 +295,13 @@ ssize_t blkmk_append_coinbase_safe2(blktemplate_t * const tmpl, const void * con return -1; size_t datasz = tmpl->cbtxn->datasz; + if (extranoncesz == sizeof(unsigned int)) { + ++extranoncesz; + } else if (!merkle_only) { if (extranoncesz < sizeof(unsigned int)) extranoncesz = sizeof(unsigned int); - else - if (extranoncesz == sizeof(unsigned int)) - ++extranoncesz; } size_t availsz = libblkmaker_coinbase_size_limit - extranoncesz - tmpl->cbtxn->data[cbScriptSigLen]; {