diff --git a/blkmaker.c b/blkmaker.c index c86c9a6..0933aad 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -150,7 +150,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; @@ -175,6 +175,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) { @@ -378,9 +383,13 @@ 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; + 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; @@ -408,15 +417,25 @@ 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 = 100 - extranoncesz - tmpl->cbtxn->data[cbScriptSigLen]; + 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; @@ -641,36 +660,81 @@ unsigned long blkmk_work_left(const blktemplate_t *tmpl) { return BLKMK_UNLIMITED_WORK_COUNT; } -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) { - unsigned char blk[80 + 8 + 1000000]; + 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; + 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); size_t cbtxnlen = 0; - if (!_blkmk_extranonce(tmpl, &blk[offs], dataid, &cbtxnlen)) - return NULL; + // Essentially _blkmk_extranonce + if (extranoncesz) { + if (!_blkmk_append_cb(tmpl, &blk[offs], extranonce, extranoncesz, NULL)) { + free(blk); + return NULL; + } + + cbtxnlen += tmpl->cbtxn->datasz + extranoncesz; + } else { + memcpy(&blk[offs], tmpl->cbtxn->data, tmpl->cbtxn->datasz); + cbtxnlen += tmpl->cbtxn->datasz; + } if (!_blkmk_insert_witness_commitment(tmpl, &blk[offs], &cbtxnlen)) { return NULL; } offs += cbtxnlen; - 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; } + +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 (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); + 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); +} diff --git a/blkmaker_jansson.c b/blkmaker_jansson.c index a22e5fb..3e515bf 100644 --- a/blkmaker_jansson.c +++ b/blkmaker_jansson.c @@ -224,9 +224,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)) { @@ -316,7 +322,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))) @@ -333,8 +339,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; @@ -383,9 +389,13 @@ 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); +} + +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 } diff --git a/blktemplate.h b/blktemplate.h index 4f3bb76..32ec6c5 100644 --- a/blktemplate.h +++ b/blktemplate.h @@ -24,6 +24,9 @@ typedef uint32_t blktime_t; 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; size_t datasz; @@ -136,6 +139,8 @@ typedef struct { unsigned aux_count; struct blkaux_t *auxs; + unsigned long txns_datasz; + bool _calculated_witness; libblkmaker_hash_t *_witnessmrklroot; } blktemplate_t; diff --git a/private.h b/private.h index fcbf02b..715f956 100644 --- a/private.h +++ b/private.h @@ -9,7 +9,7 @@ // 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 extern void _blktxn_free(struct blktxn_t *);