From 74e674632ecabd90facd44cc60e89c16026a6fc9 Mon Sep 17 00:00:00 2001 From: Huang Le <4tarhl@gmail.com> Date: Fri, 15 Aug 2014 15:37:46 +0800 Subject: [PATCH 01/19] Import varintDecode from BFGMiner --- AUTHORS | 1 + blkmaker.c | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/AUTHORS b/AUTHORS index b50c216..8bfab83 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,2 +1,3 @@ Luke Dashjr Andy Alness +Huang Le <4tarhl@gmail.com> diff --git a/blkmaker.c b/blkmaker.c index 8e01c6c..6aede42 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -47,6 +47,32 @@ bool _blkmk_dblsha256(void *hash, const void *data, size_t datasz) { #define dblsha256 _blkmk_dblsha256 +static +size_t varintDecode(const uint8_t *p, size_t size, uint64_t *n) +{ + if (size > 8 && p[0] == 0xff) + { + *n = upk_u64le(p, 1); + return 9; + } + if (size > 4 && p[0] == 0xfe) + { + *n = upk_u32le(p, 1); + return 5; + } + if (size > 2 && p[0] == 0xfd) + { + *n = upk_u16le(p, 1); + return 3; + } + if (size > 0 && p[0] <= 0xfc) + { + *n = p[0]; + return 1; + } + return 0; +} + static char varintEncode(unsigned char *out, uint64_t n) { if (n < 0xfd) From 29f6df9585581c3783a2efad84058522fdc16072 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Sat, 9 Jan 2016 21:21:08 +0000 Subject: [PATCH 02/19] Support for segregated witness commitments when server provides "txid" that does not match "hash" --- blkmaker.c | 142 +++++++++++++++++++++++++++++++++++++++++++-- blkmaker_jansson.c | 10 ++++ blktemplate.c | 2 + blktemplate.h | 4 ++ 4 files changed, 153 insertions(+), 5 deletions(-) diff --git a/blkmaker.c b/blkmaker.c index 6aede42..417b95b 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 Luke Dashjr + * Copyright 2012-2016 Luke Dashjr * * This program is free software; you can redistribute it and/or modify it * under the terms of the standard MIT license. See COPYING for more details. @@ -73,6 +73,8 @@ size_t varintDecode(const uint8_t *p, size_t size, uint64_t *n) return 0; } +#define max_varint_size (9) + static char varintEncode(unsigned char *out, uint64_t n) { if (n < 0xfd) @@ -251,7 +253,11 @@ bool blkmk_build_merkle_branches(blktemplate_t * const tmpl) unsigned char hashes[(hashcount + 1) * 32]; for (i = 0; i < tmpl->txncount; ++i) - memcpy(&hashes[0x20 * (i + 1)], tmpl->txns[i].hash_, 0x20); + { + struct blktxn_t * const txn = &tmpl->txns[i]; + txnhash_t * const txid = txn->txid ? txn->txid : txn->hash_; + memcpy(&hashes[0x20 * (i + 1)], txid, 0x20); + } for (i = 0; i < branchcount; ++i) { @@ -301,6 +307,69 @@ bool build_merkle_root(unsigned char *mrklroot_out, blktemplate_t *tmpl, unsigne return true; } +static +bool _blkmk_calculate_witness_mrklroot(blktemplate_t * const tmpl, libblkmaker_hash_t * const out, bool * const witness_needed) { + if (!blkmk_hash_transactions(tmpl)) + return false; + + // Step 1: Populate hashes with the witness hashes for all transactions + size_t hashcount = tmpl->txncount + 1; + libblkmaker_hash_t hashes[hashcount + 1]; // +1 for when the last needs duplicating + memset(&hashes[0], 0, sizeof(hashes[0])); // Gen tx gets a null entry + *witness_needed = false; + for (unsigned long i = 0; i < tmpl->txncount; ++i) { + struct blktxn_t * const txn = &tmpl->txns[i]; + if (txn->txid && memcmp(txn->hash_, txn->txid, sizeof(*txn->txid))) { + *witness_needed = true; + } + memcpy(&hashes[i + 1], txn->hash_, sizeof(*hashes)); + } + if (!*witness_needed) + return true; + + // Step 2: Reduce it to a merkle root + for ( ; hashcount > 1 ; hashcount /= 2) { + if (hashcount % 1 == 1) { + // Odd number, duplicate the last + memcpy(&hashes[hashcount], &hashes[hashcount - 1], sizeof(*hashes)); + ++hashcount; + } + for (size_t i = 0; i < hashcount; i += 2) { + // We overlap input and output here, on the first pair + if (!dblsha256(&hashes[i / 2], &hashes[i], sizeof(*hashes) * 2)) { + return false; + } + } + } + + memcpy(out, hashes, sizeof(*out)); + return true; +} + +static +bool _blkmk_witness_mrklroot(blktemplate_t * const tmpl) { + if (tmpl->_calculated_witness) { + // Already calculated + return true; + } + tmpl->_witnessmrklroot = malloc(sizeof(libblkmaker_hash_t)); + if (!tmpl->_witnessmrklroot) { + return false; + } + bool witness_needed; + if (!_blkmk_calculate_witness_mrklroot(tmpl, tmpl->_witnessmrklroot, &witness_needed)) { + free(tmpl->_witnessmrklroot); + tmpl->_witnessmrklroot = NULL; + return false; + } + if (!witness_needed) { + free(tmpl->_witnessmrklroot); + tmpl->_witnessmrklroot = NULL; + } + tmpl->_calculated_witness = true; + return true; +} + static const int cbScriptSigLen = 4 + 1 + 36; static @@ -386,6 +455,57 @@ bool _blkmk_extranonce(blktemplate_t *tmpl, void *vout, unsigned int workid, siz return true; } +static const unsigned char witness_magic[] = { 0x6a /* OP_RETURN */, /* FIXME */ }; +#define commitment_spk_size (sizeof(witness_magic) + sizeof(libblkmaker_hash_t) /* witness mrklroot */) +#define commitment_txout_size (8 /* value */ + 1 /* scriptPubKey length */ + commitment_spk_size) +static const size_t max_witness_commitment_insert = max_varint_size + commitment_txout_size - 1; + +static +bool _blkmk_insert_witness_commitment(blktemplate_t * const tmpl, unsigned char * const gentxdata, size_t * const gentxsize) { + if (!_blkmk_witness_mrklroot(tmpl)) { + return false; + } + if (!tmpl->_witnessmrklroot) { + // No commitment needed + return true; + } + + if (cbScriptSigLen >= *gentxsize) { + return false; + } + const uint8_t coinbasesz = gentxdata[cbScriptSigLen]; + const size_t offset_of_txout_count = cbScriptSigLen + coinbasesz + 4 /* nSequence */; + if (offset_of_txout_count >= *gentxsize) { + return false; + } + uint64_t txout_count; + const size_t in_txout_count_size = varintDecode(&gentxdata[offset_of_txout_count], *gentxsize - offset_of_txout_count, &txout_count); + if (!in_txout_count_size) { + return false; + } + ++txout_count; + unsigned char insertbuf[max_varint_size + commitment_txout_size]; + const size_t out_txout_count_size = varintEncode(insertbuf, txout_count); + unsigned char * const commitment_txout = &insertbuf[out_txout_count_size]; + memset(commitment_txout, 0, 8); // value + commitment_txout[8] = commitment_spk_size; + memcpy(&commitment_txout[9], witness_magic, sizeof(witness_magic)); + memcpy(&commitment_txout[9 + sizeof(witness_magic)], tmpl->_witnessmrklroot, sizeof(*tmpl->_witnessmrklroot)); + + // TODO: Put the new txout at the end to reduce movement + const size_t offset_of_txout_data = (offset_of_txout_count + in_txout_count_size); + const size_t new_offset_of_preexisting_txout_data = (offset_of_txout_count + out_txout_count_size + commitment_txout_size); + const size_t length_of_preexisting_txout_data_to_end_of_gentx = *gentxsize - offset_of_txout_data; + memmove(&gentxdata[new_offset_of_preexisting_txout_data], &gentxdata[offset_of_txout_data], length_of_preexisting_txout_data_to_end_of_gentx); + const size_t movement_delta = new_offset_of_preexisting_txout_data - offset_of_txout_data; + *gentxsize += movement_delta; + + const size_t insertbuf_len = out_txout_count_size + commitment_txout_size; + memcpy(&gentxdata[offset_of_txout_data], insertbuf, insertbuf_len); + + return true; +} + static void blkmk_set_times(blktemplate_t *tmpl, void * const out_hdrbuf, const time_t usetime, int16_t * const out_expire, const bool can_roll_ntime) { @@ -412,10 +532,13 @@ bool blkmk_sample_data_(blktemplate_t * const tmpl, uint8_t * const cbuf, const my_htole32(&cbuf[0], tmpl->version); memcpy(&cbuf[4], &tmpl->prevblk, 32); - unsigned char cbtxndata[tmpl->cbtxn->datasz + sizeof(dataid)]; + unsigned char cbtxndata[tmpl->cbtxn->datasz + sizeof(dataid) + max_witness_commitment_insert]; size_t cbtxndatasz = 0; if (!_blkmk_extranonce(tmpl, cbtxndata, dataid, &cbtxndatasz)) return false; + if (!_blkmk_insert_witness_commitment(tmpl, cbtxndata, &cbtxndatasz)) { + return false; + } if (!build_merkle_root(&cbuf[36], tmpl, cbtxndata, cbtxndatasz)) return false; @@ -463,7 +586,7 @@ bool blkmk_get_mdata(blktemplate_t * const tmpl, void * const buf, const size_t memcpy(&cbuf[4], &tmpl->prevblk, 32); *out_cbtxnsz = tmpl->cbtxn->datasz + extranoncesz; - *out_cbtxn = malloc(*out_cbtxnsz); + *out_cbtxn = malloc(*out_cbtxnsz + max_witness_commitment_insert); if (!*out_cbtxn) return false; unsigned char dummy[extranoncesz]; @@ -473,6 +596,10 @@ bool blkmk_get_mdata(blktemplate_t * const tmpl, void * const buf, const size_t free(*out_cbtxn); return false; } + if (!_blkmk_insert_witness_commitment(tmpl, *out_cbtxn, out_cbtxnsz)) { + free(*out_cbtxn); + return false; + } blkmk_set_times(tmpl, &cbuf[68], usetime, out_expire, can_roll_ntime); memcpy(&cbuf[72], &tmpl->diffbits, 4); @@ -518,8 +645,13 @@ char *blkmk_assemble_submission_(blktemplate_t * const tmpl, const unsigned char { offs += varintEncode(&blk[offs], 1 + tmpl->txncount); - if (!_blkmk_extranonce(tmpl, &blk[offs], dataid, &offs)) + size_t cbtxnlen = 0; + if (!_blkmk_extranonce(tmpl, &blk[offs], dataid, &cbtxnlen)) return NULL; + if (!_blkmk_insert_witness_commitment(tmpl, &blk[offs], &cbtxnlen)) { + return NULL; + } + offs += cbtxnlen; if (foreign || !(tmpl->mutations & BMAb_COINBASE)) for (unsigned long i = 0; i < tmpl->txncount; ++i) diff --git a/blkmaker_jansson.c b/blkmaker_jansson.c index fcf803f..397b8f0 100644 --- a/blkmaker_jansson.c +++ b/blkmaker_jansson.c @@ -152,6 +152,16 @@ const char *parse_txn(struct blktxn_t *txn, json_t *txnj) { my_flip(*txn->hash_, sizeof(*txn->hash_)); } + if ((vv = json_object_get(txnj, "txid")) && json_is_string(vv)) { + hexdata = json_string_value(vv); + txn->txid = malloc(sizeof(*txn->txid)); + if (!my_hex2bin(*txn->txid, hexdata, sizeof(*txn->txid))) { + return "Error decoding txid field"; + } else { + my_flip(*txn->txid, sizeof(*txn->txid)); + } + } + // TODO: dependcount/depends, fee, required, sigops return NULL; diff --git a/blktemplate.c b/blktemplate.c index 32875c2..0212628 100644 --- a/blktemplate.c +++ b/blktemplate.c @@ -100,6 +100,7 @@ void _blktxn_free(struct blktxn_t *bt) { free(bt->hash); free(bt->hash_); free(bt->depends); + free(bt->txid); } #define blktxn_free _blktxn_free @@ -119,6 +120,7 @@ void blktmpl_free(blktemplate_t *tmpl) { free(tmpl->cbtxn); } free(tmpl->_mrklbranch); + free(tmpl->_witnessmrklroot); for (unsigned i = 0; i < tmpl->aux_count; ++i) blkaux_clean(&tmpl->auxs[i]); free(tmpl->auxs); diff --git a/blktemplate.h b/blktemplate.h index 7bed8ec..4f3bb76 100644 --- a/blktemplate.h +++ b/blktemplate.h @@ -38,6 +38,7 @@ struct blktxn_t { int16_t sigops; txnhash_t *hash_; + txnhash_t *txid; }; struct blkaux_t { @@ -134,6 +135,9 @@ typedef struct { unsigned aux_count; struct blkaux_t *auxs; + + bool _calculated_witness; + libblkmaker_hash_t *_witnessmrklroot; } blktemplate_t; extern blktemplate_t *blktmpl_create(); From c70cc4f1168c68787beadf7f5148ec2e8609c4ff Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 20 Jan 2016 01:45:23 +0000 Subject: [PATCH 03/19] Segnet support (witness magic, address versions, and block version bump) --- base58.c | 2 ++ blkmaker.c | 2 +- blkmaker.h | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/base58.c b/base58.c index ea3343f..ef67dae 100644 --- a/base58.c +++ b/base58.c @@ -46,6 +46,7 @@ size_t blkmk_address_to_script(void *out, size_t outsz, const char *addr) { addrver = b58check(addrbin, sizeof(addrbin), addr, b58sz); switch (addrver) { case 0: // Bitcoin pubkey hash + case 30: // Segnet pubkey hash case 111: // Testnet pubkey hash if (outsz < (rv = 25)) return rv; @@ -57,6 +58,7 @@ size_t blkmk_address_to_script(void *out, size_t outsz, const char *addr) { cout[24] = 0xac; // OP_CHECKSIG return rv; case 5: // Bitcoin script hash + case 50: // Segnet script hash case 196: // Testnet script hash if (outsz < (rv = 23)) return rv; diff --git a/blkmaker.c b/blkmaker.c index 417b95b..954693e 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -455,7 +455,7 @@ bool _blkmk_extranonce(blktemplate_t *tmpl, void *vout, unsigned int workid, siz return true; } -static const unsigned char witness_magic[] = { 0x6a /* OP_RETURN */, /* FIXME */ }; +static const unsigned char witness_magic[] = { 0x6a /* OP_RETURN */, 0x24, 0xaa, 0x21, 0xa9, 0xed }; #define commitment_spk_size (sizeof(witness_magic) + sizeof(libblkmaker_hash_t) /* witness mrklroot */) #define commitment_txout_size (8 /* value */ + 1 /* scriptPubKey length */ + commitment_spk_size) static const size_t max_witness_commitment_insert = max_varint_size + commitment_txout_size - 1; diff --git a/blkmaker.h b/blkmaker.h index 9759da2..6523caa 100644 --- a/blkmaker.h +++ b/blkmaker.h @@ -12,7 +12,7 @@ extern "C" { #endif #define BLKMAKER_VERSION (6L) -#define BLKMAKER_MAX_BLOCK_VERSION (4) +#define BLKMAKER_MAX_BLOCK_VERSION (5) extern bool (*blkmk_sha256_impl)(void *hash_out, const void *data, size_t datasz); From 22f6e42844aa14ed0037ebf12a734f07e63533d7 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Sat, 23 Jan 2016 22:33:24 -0500 Subject: [PATCH 04/19] segwit: fix commitment offsets --- blkmaker.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blkmaker.c b/blkmaker.c index 954693e..2b57a5b 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -474,7 +474,7 @@ bool _blkmk_insert_witness_commitment(blktemplate_t * const tmpl, unsigned char return false; } const uint8_t coinbasesz = gentxdata[cbScriptSigLen]; - const size_t offset_of_txout_count = cbScriptSigLen + coinbasesz + 4 /* nSequence */; + const size_t offset_of_txout_count = cbScriptSigLen + coinbasesz + sizeof(coinbasesz) + 4 /* nSequence */; if (offset_of_txout_count >= *gentxsize) { return false; } @@ -501,7 +501,7 @@ bool _blkmk_insert_witness_commitment(blktemplate_t * const tmpl, unsigned char *gentxsize += movement_delta; const size_t insertbuf_len = out_txout_count_size + commitment_txout_size; - memcpy(&gentxdata[offset_of_txout_data], insertbuf, insertbuf_len); + memcpy(&gentxdata[offset_of_txout_count], insertbuf, insertbuf_len); return true; } From 15e2c35bf69c997488e37147cf062dfa925b4912 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Sat, 23 Jan 2016 22:48:40 -0500 Subject: [PATCH 05/19] segwit: hash with witness nonce, null for now --- blkmaker.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/blkmaker.c b/blkmaker.c index 2b57a5b..719a92e 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -459,6 +459,7 @@ static const unsigned char witness_magic[] = { 0x6a /* OP_RETURN */, 0x24, 0xaa, #define commitment_spk_size (sizeof(witness_magic) + sizeof(libblkmaker_hash_t) /* witness mrklroot */) #define commitment_txout_size (8 /* value */ + 1 /* scriptPubKey length */ + commitment_spk_size) static const size_t max_witness_commitment_insert = max_varint_size + commitment_txout_size - 1; +static const libblkmaker_hash_t witness_nonce = { 0 }; static bool _blkmk_insert_witness_commitment(blktemplate_t * const tmpl, unsigned char * const gentxdata, size_t * const gentxsize) { @@ -469,6 +470,13 @@ bool _blkmk_insert_witness_commitment(blktemplate_t * const tmpl, unsigned char // No commitment needed return true; } + + libblkmaker_hash_t merkle_with_nonce[2]; + libblkmaker_hash_t commitment; + memcpy(&merkle_with_nonce[0], tmpl->_witnessmrklroot, sizeof(*tmpl->_witnessmrklroot)); + memcpy(&merkle_with_nonce[1], &witness_nonce, sizeof(witness_nonce)); + if(!dblsha256(&commitment, &merkle_with_nonce[0], sizeof(merkle_with_nonce))) + return false; if (cbScriptSigLen >= *gentxsize) { return false; @@ -490,7 +498,7 @@ bool _blkmk_insert_witness_commitment(blktemplate_t * const tmpl, unsigned char memset(commitment_txout, 0, 8); // value commitment_txout[8] = commitment_spk_size; memcpy(&commitment_txout[9], witness_magic, sizeof(witness_magic)); - memcpy(&commitment_txout[9 + sizeof(witness_magic)], tmpl->_witnessmrklroot, sizeof(*tmpl->_witnessmrklroot)); + memcpy(&commitment_txout[9 + sizeof(witness_magic)], &commitment, sizeof(commitment)); // TODO: Put the new txout at the end to reduce movement const size_t offset_of_txout_data = (offset_of_txout_count + in_txout_count_size); From 9a5799891e0f3590779b8e5a993a7b306088e2fa Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Sun, 24 Jan 2016 22:03:20 -0500 Subject: [PATCH 06/19] segwit: fix witness merkle root creation --- blkmaker.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blkmaker.c b/blkmaker.c index 719a92e..c86c9a6 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -329,7 +329,7 @@ bool _blkmk_calculate_witness_mrklroot(blktemplate_t * const tmpl, libblkmaker_h // Step 2: Reduce it to a merkle root for ( ; hashcount > 1 ; hashcount /= 2) { - if (hashcount % 1 == 1) { + if (hashcount % 2 == 1) { // Odd number, duplicate the last memcpy(&hashes[hashcount], &hashes[hashcount - 1], sizeof(*hashes)); ++hashcount; From 3be2fadacac300b9ec03bd17101d4f01e94c917a Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Sat, 23 Jul 2016 21:08:17 +0000 Subject: [PATCH 07/19] AUTHORS: Add Cory Fields --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index 8bfab83..d5a9d3d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,3 +1,4 @@ Luke Dashjr Andy Alness Huang Le <4tarhl@gmail.com> +Cory Fields From 5016f8d86a8f8d481a9331c4a394cb3a97660a0c Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Sat, 23 Jul 2016 21:24:29 +0000 Subject: [PATCH 08/19] Parse transaction weights into blktxn_t structure ABI break: sizeof(blktxn_t) has been increased, so accesses to blktmpl_t->txns[>0] use a different offset (aside, hash_ and txid are moved) New ABI supports up to 512 MB transactions (with a max weight-per-bytes of 4), and library gracefully interprets larger weight values as -1 (unknown) --- blkmaker_jansson.c | 9 +++++++++ blktemplate.h | 1 + 2 files changed, 10 insertions(+) diff --git a/blkmaker_jansson.c b/blkmaker_jansson.c index 709b7a8..8865683 100644 --- a/blkmaker_jansson.c +++ b/blkmaker_jansson.c @@ -163,6 +163,15 @@ const char *parse_txn(struct blktxn_t *txn, json_t *txnj) { } } + txn->weight = -1; + if ((vv = json_object_get(txnj, "weight")) && json_is_number(vv)) { + const double f = json_number_value(txnj); + const int32_t i32 = f; + if (f == i32) { + txn->weight = i32; + } + } + // TODO: dependcount/depends, fee, required, sigops return NULL; diff --git a/blktemplate.h b/blktemplate.h index d3a80c6..f048356 100644 --- a/blktemplate.h +++ b/blktemplate.h @@ -39,6 +39,7 @@ struct blktxn_t { uint64_t fee; bool required; int16_t sigops; + int32_t weight; txnhash_t *hash_; txnhash_t *txid; From 048483d97c94f948e6e444ec2ae0c4e99c69c0f7 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 26 Jul 2016 04:14:53 +0000 Subject: [PATCH 09/19] Parse template block version, rules, and mutations before time limits, transactions, and aux data --- blkmaker_jansson.c | 144 ++++++++++++++++++++++----------------------- 1 file changed, 72 insertions(+), 72 deletions(-) diff --git a/blkmaker_jansson.c b/blkmaker_jansson.c index 05f4186..092836a 100644 --- a/blkmaker_jansson.c +++ b/blkmaker_jansson.c @@ -308,78 +308,6 @@ const char *blktmpl_add_jansson(blktemplate_t *tmpl, const json_t *json, time_t GETNUM_O(sizelimit, unsigned long); GETNUM(version, uint32_t); - GETNUM_O2(cbvalue, coinbasevalue, uint64_t); - - GETSTR(workid, workid); - - GETNUM_O(expires, int16_t); - GETNUM_O(maxtime, blktime_t); - GETNUM_O(maxtimeoff, blktime_diff_t); - GETNUM_O(mintime, blktime_t); - GETNUM_O(mintimeoff, blktime_diff_t); - - GETSTR(longpollid, lp.id); - GETSTR(longpolluri, lp.uri); - GETBOOL(submitold, submitold, true); - - 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; - tmpl->txns_sigops = 0; - for (size_t i = 0; i < txns; ++i) - { - struct blktxn_t * const txn = &tmpl->txns[i]; - if ((s = parse_txn(txn, json_array_get(v, i), i + 1))) { - return s; - } - tmpl->txns_datasz += txn->datasz; - if (tmpl->txns_sigops == -1) { - ; // Impossible to tally the unknown - } else if (txn->sigops_ == -1) { - tmpl->txns_sigops = -1; - } else { - tmpl->txns_sigops += txn->sigops_; - } - } - - if ((v = json_object_get(json, "coinbasetxn")) && json_is_object(v)) - { - tmpl->cbtxn = calloc(1, sizeof(*tmpl->cbtxn)); - if ((s = parse_txn(tmpl->cbtxn, v, 0))) - return s; - } - - if ((v = json_object_get(json, "coinbaseaux")) && json_is_object(v)) - { - tmpl->aux_count = json_object_size(v); - tmpl->auxs = calloc(tmpl->aux_count, sizeof(*tmpl->auxs)); - unsigned i = 0; - for (void *iter = json_object_iter(v); iter; (iter = json_object_iter_next(v, iter)), ++i) - { - v2 = json_object_iter_value(iter); - s = json_string_value(v2); - if (!s) - continue; - size_t sz = strlen(s) / 2; - tmpl->auxs[i] = (struct blkaux_t){ - .auxname = strdup(json_object_iter_key(iter)), - .data = malloc(sz), - .datasz = sz, - }; - if (!my_hex2bin(tmpl->auxs[i].data, s, sz)) { - return "Error decoding 'coinbaseaux' data"; - } - } - } - - if ((v = json_object_get(json, "target")) && json_is_string(v)) - { - tmpl->target = malloc(sizeof(*tmpl->target)); - if (!my_hex2bin(tmpl->target, json_string_value(v), sizeof(*tmpl->target))) - return "Error decoding 'target'"; - } - if ((v = json_object_get(json, "mutable")) && json_is_array(v)) { for (size_t i = json_array_size(v); i--; ) @@ -458,6 +386,78 @@ const char *blktmpl_add_jansson(blktemplate_t *tmpl, const json_t *json, time_t return "Unrecognized block version, and not allowed to reduce or force it"; } + GETNUM_O2(cbvalue, coinbasevalue, uint64_t); + + GETSTR(workid, workid); + + GETNUM_O(expires, int16_t); + GETNUM_O(maxtime, blktime_t); + GETNUM_O(maxtimeoff, blktime_diff_t); + GETNUM_O(mintime, blktime_t); + GETNUM_O(mintimeoff, blktime_diff_t); + + GETSTR(longpollid, lp.id); + GETSTR(longpolluri, lp.uri); + GETBOOL(submitold, submitold, true); + + 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; + tmpl->txns_sigops = 0; + for (size_t i = 0; i < txns; ++i) + { + struct blktxn_t * const txn = &tmpl->txns[i]; + if ((s = parse_txn(txn, json_array_get(v, i), i + 1))) { + return s; + } + tmpl->txns_datasz += txn->datasz; + if (tmpl->txns_sigops == -1) { + ; // Impossible to tally the unknown + } else if (txn->sigops_ == -1) { + tmpl->txns_sigops = -1; + } else { + tmpl->txns_sigops += txn->sigops_; + } + } + + if ((v = json_object_get(json, "coinbasetxn")) && json_is_object(v)) + { + tmpl->cbtxn = calloc(1, sizeof(*tmpl->cbtxn)); + if ((s = parse_txn(tmpl->cbtxn, v, 0))) + return s; + } + + if ((v = json_object_get(json, "coinbaseaux")) && json_is_object(v)) + { + tmpl->aux_count = json_object_size(v); + tmpl->auxs = calloc(tmpl->aux_count, sizeof(*tmpl->auxs)); + unsigned i = 0; + for (void *iter = json_object_iter(v); iter; (iter = json_object_iter_next(v, iter)), ++i) + { + v2 = json_object_iter_value(iter); + s = json_string_value(v2); + if (!s) + continue; + size_t sz = strlen(s) / 2; + tmpl->auxs[i] = (struct blkaux_t){ + .auxname = strdup(json_object_iter_key(iter)), + .data = malloc(sz), + .datasz = sz, + }; + if (!my_hex2bin(tmpl->auxs[i].data, s, sz)) { + return "Error decoding 'coinbaseaux' data"; + } + } + } + + if ((v = json_object_get(json, "target")) && json_is_string(v)) + { + tmpl->target = malloc(sizeof(*tmpl->target)); + if (!my_hex2bin(tmpl->target, json_string_value(v), sizeof(*tmpl->target))) + return "Error decoding 'target'"; + } + tmpl->_time_rcvd = time_rcvd; return NULL; From b5c6d97be750bb0046a10156befb7abfecc051c3 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 26 Jul 2016 04:18:10 +0000 Subject: [PATCH 10/19] Use new sigop counting (ie, quadrupled) when "segwit" in rules list --- blkmaker.c | 11 +++++++---- blkmaker_jansson.c | 3 +++ blktemplate.h | 1 + 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/blkmaker.c b/blkmaker.c index caa2684..315ff7b 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -119,7 +119,7 @@ char varintEncode(unsigned char *out, uint64_t n) { } static -int16_t blkmk_count_sigops(const uint8_t * const script, const size_t scriptsz) { +int16_t blkmk_count_sigops(const uint8_t * const script, const size_t scriptsz, const bool bip141) { int16_t sigops = 0; for (size_t i = 0; i < scriptsz; ++i) { if (script[i] <= 0x4c /* OP_PUSHDATA1 */) { @@ -146,6 +146,9 @@ int16_t blkmk_count_sigops(const uint8_t * const script, const size_t scriptsz) sigops += 20; } } + if (bip141) { + sigops *= 4; + } return sigops; } @@ -220,7 +223,7 @@ uint64_t blkmk_init_generation3(blktemplate_t * const tmpl, const void * const s memset(&data[off], 0, 4); // lock time off += 4; - const int16_t sigops_counted = blkmk_count_sigops(script, scriptsz); + const int16_t sigops_counted = blkmk_count_sigops(script, scriptsz, tmpl->_bip141_sigops); if (tmpl->txns_datasz + off > tmpl->sizelimit || (tmpl->txns_sigops >= 0 && tmpl->txns_sigops + sigops_counted > tmpl->sigoplimit)) { free(data); @@ -439,7 +442,7 @@ bool _blkmk_append_cb(blktemplate_t * const tmpl, void * const vout, const void return false; } - const int16_t orig_scriptSig_sigops = blkmk_count_sigops(&in[cbScriptSigLen + 1], in[cbScriptSigLen]); + const int16_t orig_scriptSig_sigops = blkmk_count_sigops(&in[cbScriptSigLen + 1], in[cbScriptSigLen], tmpl->_bip141_sigops); int cbPostScriptSig = cbScriptSigLen + 1 + in[cbScriptSigLen]; if (appended_at_offset) *appended_at_offset = cbPostScriptSig; @@ -458,7 +461,7 @@ bool _blkmk_append_cb(blktemplate_t * const tmpl, void * const vout, const void out[cbScriptSigLen] += appendsz; memcpy(outExtranonce, append, appendsz); - const int16_t sigops_counted = (tmpl->cbtxn->sigops_ - orig_scriptSig_sigops) + blkmk_count_sigops(&out[cbScriptSigLen + 1], out[cbScriptSigLen]); + const int16_t sigops_counted = (tmpl->cbtxn->sigops_ - orig_scriptSig_sigops) + blkmk_count_sigops(&out[cbScriptSigLen + 1], out[cbScriptSigLen], tmpl->_bip141_sigops); if (tmpl->txns_sigops >= 0 && tmpl->txns_sigops + sigops_counted > tmpl->sigoplimit) { // Overflowed :( if (out == in) { diff --git a/blkmaker_jansson.c b/blkmaker_jansson.c index 092836a..b24a7f8 100644 --- a/blkmaker_jansson.c +++ b/blkmaker_jansson.c @@ -343,6 +343,9 @@ const char *blktmpl_add_jansson(blktemplate_t *tmpl, const json_t *json, time_t if (!tmpl->rules[i]) { return "Memory allocation error parsing rules"; } + if (!strcmp(s, "segwit")) { + tmpl->_bip141_sigops = true; + } } v = json_object_get(json, "vbavailable"); diff --git a/blktemplate.h b/blktemplate.h index 18ad43a..563ae7f 100644 --- a/blktemplate.h +++ b/blktemplate.h @@ -153,6 +153,7 @@ typedef struct { struct blktmpl_vbassoc **vbavailable; uint32_t vbrequired; + bool _bip141_sigops; bool _calculated_witness; libblkmaker_hash_t *_witnessmrklroot; } blktemplate_t; From 5307b027f616601b3ee3f7effd0897499ef9a47e Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 26 Jul 2016 04:36:22 +0000 Subject: [PATCH 11/19] Implement weightlimit --- blkmaker.c | 18 ++++++++++++++++++ blkmaker_jansson.c | 9 +++++++++ blktemplate.h | 2 ++ 3 files changed, 29 insertions(+) diff --git a/blkmaker.c b/blkmaker.c index 315ff7b..97f8e5a 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -224,7 +224,9 @@ uint64_t blkmk_init_generation3(blktemplate_t * const tmpl, const void * const s off += 4; const int16_t sigops_counted = blkmk_count_sigops(script, scriptsz, tmpl->_bip141_sigops); + const int64_t gentx_weight = (off * 4) + 2 /* marker & flag */ + 1 /* witness stack count */ + 1 /* stack item size */ + 32 /* stack item: nonce */ ; if (tmpl->txns_datasz + off > tmpl->sizelimit + || (tmpl->txns_weight >= 0 && tmpl->txns_weight + gentx_weight > tmpl->weightlimit) || (tmpl->txns_sigops >= 0 && tmpl->txns_sigops + sigops_counted > tmpl->sigoplimit)) { free(data); return 0; @@ -241,6 +243,7 @@ uint64_t blkmk_init_generation3(blktemplate_t * const tmpl, const void * const s txn->data = data; txn->datasz = off; txn->sigops_ = sigops_counted; + txn->weight = gentx_weight; if (tmpl->cbtxn) { @@ -442,6 +445,10 @@ bool _blkmk_append_cb(blktemplate_t * const tmpl, void * const vout, const void return false; } + if (tmpl->cbtxn->weight + tmpl->txns_weight + (appendsz * 4) > tmpl->weightlimit) { + return false; + } + const int16_t orig_scriptSig_sigops = blkmk_count_sigops(&in[cbScriptSigLen + 1], in[cbScriptSigLen], tmpl->_bip141_sigops); int cbPostScriptSig = cbScriptSigLen + 1 + in[cbScriptSigLen]; if (appended_at_offset) @@ -504,6 +511,16 @@ ssize_t blkmk_append_coinbase_safe2(blktemplate_t * const tmpl, const void * con availsz = availsz2; } } + { + const size_t current_blockweight = tmpl->cbtxn->weight + tmpl->txns_weight; + if (current_blockweight > tmpl->weightlimit) { + return false; + } + const size_t availsz2 = (tmpl->weightlimit - current_blockweight) / 4; + if (availsz2 < availsz) { + availsz = availsz2; + } + } if (appendsz > availsz) return availsz; @@ -515,6 +532,7 @@ ssize_t blkmk_append_coinbase_safe2(blktemplate_t * const tmpl, const void * con if (!_blkmk_append_cb(tmpl, newp, append, appendsz, NULL, &tmpl->cbtxn->sigops_)) return -3; tmpl->cbtxn->datasz += appendsz; + tmpl->cbtxn->weight += appendsz * 4; return availsz; } diff --git a/blkmaker_jansson.c b/blkmaker_jansson.c index b24a7f8..ceedca1 100644 --- a/blkmaker_jansson.c +++ b/blkmaker_jansson.c @@ -306,6 +306,7 @@ const char *blktmpl_add_jansson(blktemplate_t *tmpl, const json_t *json, time_t my_flip(tmpl->prevblk, 32); GETNUM_O(sigoplimit, unsigned short); GETNUM_O(sizelimit, unsigned long); + GETNUM_O(weightlimit, int64_t); GETNUM(version, uint32_t); if ((v = json_object_get(json, "mutable")) && json_is_array(v)) @@ -408,6 +409,7 @@ const char *blktmpl_add_jansson(blktemplate_t *tmpl, const json_t *json, time_t tmpl->txns = calloc(txns, sizeof(*tmpl->txns)); tmpl->txns_datasz = 0; tmpl->txns_sigops = 0; + tmpl->txns_weight = 0; for (size_t i = 0; i < txns; ++i) { struct blktxn_t * const txn = &tmpl->txns[i]; @@ -422,6 +424,13 @@ const char *blktmpl_add_jansson(blktemplate_t *tmpl, const json_t *json, time_t } else { tmpl->txns_sigops += txn->sigops_; } + if (tmpl->txns_weight == -1) { + ; // Impossible to tally the unknown + } else if (txn->weight == -1) { + tmpl->txns_weight = -1; + } else { + tmpl->txns_weight += txn->weight; + } } if ((v = json_object_get(json, "coinbasetxn")) && json_is_object(v)) diff --git a/blktemplate.h b/blktemplate.h index 563ae7f..5c19fc0 100644 --- a/blktemplate.h +++ b/blktemplate.h @@ -156,6 +156,8 @@ typedef struct { bool _bip141_sigops; bool _calculated_witness; libblkmaker_hash_t *_witnessmrklroot; + int64_t weightlimit; + int64_t txns_weight; } blktemplate_t; extern void blktxn_init(struct blktxn_t *); From 28a2bb7f6b225da344bb07b7e5ece362cf7f03cd Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 26 Jul 2016 17:20:55 +0000 Subject: [PATCH 12/19] Add segwit commitment at the end, rather than the start of the output list --- blkmaker.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/blkmaker.c b/blkmaker.c index 97f8e5a..f506228 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -605,16 +605,21 @@ bool _blkmk_insert_witness_commitment(blktemplate_t * const tmpl, unsigned char memcpy(&commitment_txout[9], witness_magic, sizeof(witness_magic)); memcpy(&commitment_txout[9 + sizeof(witness_magic)], &commitment, sizeof(commitment)); - // TODO: Put the new txout at the end to reduce movement const size_t offset_of_txout_data = (offset_of_txout_count + in_txout_count_size); - const size_t new_offset_of_preexisting_txout_data = (offset_of_txout_count + out_txout_count_size + commitment_txout_size); - const size_t length_of_preexisting_txout_data_to_end_of_gentx = *gentxsize - offset_of_txout_data; - memmove(&gentxdata[new_offset_of_preexisting_txout_data], &gentxdata[offset_of_txout_data], length_of_preexisting_txout_data_to_end_of_gentx); - const size_t movement_delta = new_offset_of_preexisting_txout_data - offset_of_txout_data; - *gentxsize += movement_delta; + const size_t new_offset_of_preexisting_txout_data = (offset_of_txout_count + out_txout_count_size); + const size_t length_of_txtail = 4; + const size_t length_of_preexisting_txout_data = (*gentxsize - length_of_txtail) - offset_of_txout_data; + const size_t offset_of_txtail_i = *gentxsize - length_of_txtail; // just the lock time + const size_t offset_of_txtail_o = offset_of_txtail_i + (out_txout_count_size - in_txout_count_size) + commitment_txout_size; + memmove(&gentxdata[offset_of_txtail_o], &gentxdata[offset_of_txtail_i], length_of_txtail); + if (offset_of_txout_data != new_offset_of_preexisting_txout_data) { + memmove(&gentxdata[new_offset_of_preexisting_txout_data], &gentxdata[offset_of_txout_data], length_of_preexisting_txout_data); + } + memcpy(&gentxdata[offset_of_txout_count], insertbuf, out_txout_count_size); + const size_t offset_of_commitment_txout_o = new_offset_of_preexisting_txout_data + length_of_preexisting_txout_data; + memcpy(&gentxdata[offset_of_commitment_txout_o], commitment_txout, commitment_txout_size); - const size_t insertbuf_len = out_txout_count_size + commitment_txout_size; - memcpy(&gentxdata[offset_of_txout_count], insertbuf, insertbuf_len); + *gentxsize = offset_of_txtail_o + length_of_txtail; return true; } From 2e0cc834feddc49eaa00c323ef1a1cbe4b2e0789 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 26 Jul 2016 23:30:31 +0000 Subject: [PATCH 13/19] Bugfix: blktxn_init: Initialise txid and weight --- blktemplate.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/blktemplate.c b/blktemplate.c index 0c39949..77dd3f2 100644 --- a/blktemplate.c +++ b/blktemplate.c @@ -63,6 +63,7 @@ void blktxn_init(struct blktxn_t * const txn) { txn->datasz = 0; txn->hash = NULL; txn->hash_ = NULL; + txn->txid = NULL; txn->dependscount = -1; txn->depends = NULL; @@ -70,6 +71,7 @@ void blktxn_init(struct blktxn_t * const txn) { txn->fee_ = -1; txn->required = false; txn->sigops_ = -1; + txn->weight = -1; } blktemplate_t *blktmpl_create() { From 86c6f760bfb499a6a2280aded8b7ea77802425d1 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 26 Jul 2016 23:54:14 +0000 Subject: [PATCH 14/19] Bugfix: assemble_submission: Enlarge block buffer for witness commitment --- blkmaker.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blkmaker.c b/blkmaker.c index f01b54f..79e34fc 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -759,7 +759,7 @@ static char *blkmk_assemble_submission2_internal(blktemplate_t * const tmpl, con size_t blkbuf_sz = libblkmaker_blkheader_size; if (incl_gentxn) { blkbuf_sz += max_varint_size /* tx count */; - blkbuf_sz += tmpl->cbtxn->datasz + extranoncesz; + blkbuf_sz += tmpl->cbtxn->datasz + extranoncesz + (max_varint_size - 1) /* possible enlargement to txout count when adding commitment output */ + commitment_txout_size; if (incl_alltxn) { blkbuf_sz += tmpl->txns_datasz; } From 3ff360493923c04061d1ee08b45d5efcfd556861 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 26 Jul 2016 23:54:37 +0000 Subject: [PATCH 15/19] Add "segwit" to supported rule list --- blkmaker.c | 1 + 1 file changed, 1 insertion(+) diff --git a/blkmaker.c b/blkmaker.c index 79e34fc..8553200 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -26,6 +26,7 @@ const char *blkmk_supported_rules[] = { "csv", + "segwit", NULL }; From c9030312dc29a2e04d98b30c740687ee93f848ce Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 28 Jul 2016 03:51:06 +0000 Subject: [PATCH 16/19] Revert Segnet support --- base58.c | 2 -- blkmaker.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/base58.c b/base58.c index ef67dae..ea3343f 100644 --- a/base58.c +++ b/base58.c @@ -46,7 +46,6 @@ size_t blkmk_address_to_script(void *out, size_t outsz, const char *addr) { addrver = b58check(addrbin, sizeof(addrbin), addr, b58sz); switch (addrver) { case 0: // Bitcoin pubkey hash - case 30: // Segnet pubkey hash case 111: // Testnet pubkey hash if (outsz < (rv = 25)) return rv; @@ -58,7 +57,6 @@ size_t blkmk_address_to_script(void *out, size_t outsz, const char *addr) { cout[24] = 0xac; // OP_CHECKSIG return rv; case 5: // Bitcoin script hash - case 50: // Segnet script hash case 196: // Testnet script hash if (outsz < (rv = 23)) return rv; diff --git a/blkmaker.h b/blkmaker.h index 9de20b2..0a0895c 100644 --- a/blkmaker.h +++ b/blkmaker.h @@ -13,7 +13,7 @@ extern "C" { #define BLKMAKER_VERSION (7L) #define BLKMAKER_MAX_BLOCK_VERSION (0x3fffffff) -#define BLKMAKER_MAX_PRERULES_BLOCK_VERSION (5) +#define BLKMAKER_MAX_PRERULES_BLOCK_VERSION (4) extern const char *blkmk_supported_rules[]; extern bool blkmk_supports_rule(const char *rulename); From 28f39f440c5116bc4d92d9a6b19a5b0e8684c130 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 11 Aug 2016 22:10:44 +0000 Subject: [PATCH 17/19] Bugfix: Initialise weightlimit to INT64_MAX --- blktemplate.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/blktemplate.c b/blktemplate.c index 77dd3f2..db10f00 100644 --- a/blktemplate.c +++ b/blktemplate.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -82,6 +83,7 @@ blktemplate_t *blktmpl_create() { tmpl->sigoplimit = USHRT_MAX; tmpl->sizelimit = ULONG_MAX; + tmpl->weightlimit = INT64_MAX; tmpl->maxtime = 0xffffffff; tmpl->maxtimeoff = 0x7fff; From aa74130c596279e689360b412fdd0160b3994024 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 11 Aug 2016 22:10:13 +0000 Subject: [PATCH 18/19] Bugfix: Handle unknown transaction weight by either calculating it (generation only) or ignoring the weightlimit --- blkmaker.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/blkmaker.c b/blkmaker.c index 8553200..f2c0b14 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -153,6 +153,17 @@ int16_t blkmk_count_sigops(const uint8_t * const script, const size_t scriptsz, return sigops; } +static int64_t blkmk_calc_gentx_weight(const void * const data, const size_t datasz) { + return (datasz * 4) + 2 /* marker & flag */ + 1 /* witness stack count */ + 1 /* stack item size */ + 32 /* stack item: nonce */; +} + +static int64_t blktxn_set_gentx_weight(struct blktxn_t * const gentx) { + if (gentx->weight < 0) { + gentx->weight = blkmk_calc_gentx_weight(gentx->data, gentx->datasz); + } + return gentx->weight; +} + 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))) { @@ -225,7 +236,7 @@ uint64_t blkmk_init_generation3(blktemplate_t * const tmpl, const void * const s off += 4; const int16_t sigops_counted = blkmk_count_sigops(script, scriptsz, tmpl->_bip141_sigops); - const int64_t gentx_weight = (off * 4) + 2 /* marker & flag */ + 1 /* witness stack count */ + 1 /* stack item size */ + 32 /* stack item: nonce */ ; + const int64_t gentx_weight = blkmk_calc_gentx_weight(data, off); if (tmpl->txns_datasz + off > tmpl->sizelimit || (tmpl->txns_weight >= 0 && tmpl->txns_weight + gentx_weight > tmpl->weightlimit) || (tmpl->txns_sigops >= 0 && tmpl->txns_sigops + sigops_counted > tmpl->sigoplimit)) { @@ -446,7 +457,7 @@ bool _blkmk_append_cb(blktemplate_t * const tmpl, void * const vout, const void return false; } - if (tmpl->cbtxn->weight + tmpl->txns_weight + (appendsz * 4) > tmpl->weightlimit) { + if (tmpl->txns_weight >= 0 && (blktxn_set_gentx_weight(tmpl->cbtxn) + tmpl->txns_weight + (appendsz * 4) > tmpl->weightlimit)) { return false; } @@ -512,8 +523,8 @@ ssize_t blkmk_append_coinbase_safe2(blktemplate_t * const tmpl, const void * con availsz = availsz2; } } - { - const size_t current_blockweight = tmpl->cbtxn->weight + tmpl->txns_weight; + if (tmpl->txns_weight >= 0) { + const size_t current_blockweight = blktxn_set_gentx_weight(tmpl->cbtxn) + tmpl->txns_weight; if (current_blockweight > tmpl->weightlimit) { return false; } From 963262af084aad543769e01c6bd728c2c3e2368b Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 12 Aug 2016 01:20:46 +0000 Subject: [PATCH 19/19] _blkmk_calculate_witness_mrklroot: Allocate heap space for hashes, rather than use the (potentially too small) stack --- blkmaker.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/blkmaker.c b/blkmaker.c index 9d2e151..3d43efc 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -402,7 +402,10 @@ bool _blkmk_calculate_witness_mrklroot(blktemplate_t * const tmpl, libblkmaker_h // Step 1: Populate hashes with the witness hashes for all transactions size_t hashcount = tmpl->txncount + 1; - libblkmaker_hash_t hashes[hashcount + 1]; // +1 for when the last needs duplicating + libblkmaker_hash_t * const hashes = malloc((hashcount + 1) * sizeof(*hashes)); // +1 for when the last needs duplicating + if (!hashes) { + return false; + } memset(&hashes[0], 0, sizeof(hashes[0])); // Gen tx gets a null entry *witness_needed = false; for (unsigned long i = 0; i < tmpl->txncount; ++i) { @@ -412,8 +415,10 @@ bool _blkmk_calculate_witness_mrklroot(blktemplate_t * const tmpl, libblkmaker_h } memcpy(&hashes[i + 1], txn->hash_, sizeof(*hashes)); } - if (!*witness_needed) + if (!*witness_needed) { + free(hashes); return true; + } // Step 2: Reduce it to a merkle root for ( ; hashcount > 1 ; hashcount /= 2) { @@ -425,12 +430,14 @@ bool _blkmk_calculate_witness_mrklroot(blktemplate_t * const tmpl, libblkmaker_h for (size_t i = 0; i < hashcount; i += 2) { // We overlap input and output here, on the first pair if (!dblsha256(&hashes[i / 2], &hashes[i], sizeof(*hashes) * 2)) { + free(hashes); return false; } } } memcpy(out, hashes, sizeof(*out)); + free(hashes); return true; }