From 65b9f2dcd0e0ce55c40834167e3780f644819602 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 12 Aug 2016 03:37:55 +0000 Subject: [PATCH 01/28] Document uselessness and future removal of blktemplate_t.{min,max}nonce --- blktemplate.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/blktemplate.h b/blktemplate.h index fcad752..ed5765d 100644 --- a/blktemplate.h +++ b/blktemplate.h @@ -123,6 +123,8 @@ typedef struct { blktime_diff_t maxtimeoff; blktime_t mintime; blktime_diff_t mintimeoff; + + // Note these never were and are NOT supported, but retained merely for ABI compatibility; they will be removed without an API version bump in 0.6! blknonce_t minnonce; blknonce_t maxnonce; From 711b938fb81be3a89720fe5d51d690479489d338 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 12 Aug 2016 04:18:00 +0000 Subject: [PATCH 02/28] gitignore: Various development-related files --- .gitignore | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitignore b/.gitignore index 6200e5f..a4bcac9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,10 @@ +*.gcov +*.gcda +*.gcno +vgcore* +core* +*.orig +*.rej *~ *.so *.o From 130cfbdb3ef57c4bf946bd1ac213da775bcc3c61 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Sat, 13 Aug 2016 07:23:14 +0000 Subject: [PATCH 03/28] Bugfix: example: Deal with build and portability issues --- Makefile.am | 6 +++--- example.c | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index 209262f..daee8b5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -54,10 +54,10 @@ dist_noinst_DATA = \ if CAN_COMPILE_EXAMPLE EXTRA_PROGRAMS = example example_SOURCES = example.c -example_LDADD = libblkmaker-$(LIBBLKMAKER_API_VERSION).la libblkmaker_jansson-$(LIBBLKMAKER_API_VERSION).la $(LIBGCRYPT_LIBS) -example_CFLAGS = $(LIBGCRYPT_CFLAGS) +example_CFLAGS = $(libbase58_CFLAGS) $(JANSSON_CFLAGS) $(LIBGCRYPT_CFLAGS) +example_LDADD = $(libbase58_LIBS) libblkmaker-@LIBBLKMAKER_API_VERSION@.la libblkmaker_jansson-@LIBBLKMAKER_API_VERSION@.la $(JANSSON_LIBS) $(LIBGCRYPT_LIBS) else example: - @echo "libgcrypt is required to build the example, but was not found" + @echo "libgcrypt is required to build the example, but was not found" .PHONY: example endif diff --git a/example.c b/example.c index 595922c..f4c8c44 100644 --- a/example.c +++ b/example.c @@ -9,7 +9,11 @@ #include #include +#ifndef WIN32 #include +#else +#include +#endif #include #include @@ -127,4 +131,5 @@ int main(int argc, char**argv) { send_json(req); } blktmpl_free(tmpl); + return 0; } From 9cfdca809c7d63c1294097095e7979e52177c264 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Sat, 13 Aug 2016 08:17:25 +0000 Subject: [PATCH 04/28] Bugfix: blkmk_append_coinbase_safe2: Check for unexpected larger values before subtracting --- blkmaker.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/blkmaker.c b/blkmaker.c index 3c46754..96abc05 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -257,8 +257,9 @@ 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 (appendsz > 100 || in[cbScriptSigLen] > 100 - appendsz) { return false; + } int cbPostScriptSig = cbScriptSigLen + 1 + in[cbScriptSigLen]; if (appended_at_offset) @@ -295,6 +296,9 @@ ssize_t blkmk_append_coinbase_safe2(blktemplate_t * const tmpl, const void * con if (extranoncesz == sizeof(unsigned int)) ++extranoncesz; } + if (extranoncesz > 100 || tmpl->cbtxn->data[cbScriptSigLen] > 100 || extranoncesz + tmpl->cbtxn->data[cbScriptSigLen] > 100) { + return -5; + } size_t availsz = 100 - extranoncesz - tmpl->cbtxn->data[cbScriptSigLen]; if (appendsz > availsz) return availsz; From 6c56da6a04d0ea2e75e9ceedebb1ef30743d3458 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Sat, 13 Aug 2016 08:17:25 +0000 Subject: [PATCH 05/28] Bugfix: blkmk_append_coinbase_safe2: Check for unexpected larger values before subtracting (in sigop checks) --- blkmaker.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blkmaker.c b/blkmaker.c index 7099451..cbcb44b 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -385,7 +385,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_ + blkmk_count_sigops(&out[cbScriptSigLen + 1], out[cbScriptSigLen]) - orig_scriptSig_sigops; if (tmpl->txns_sigops >= 0 && tmpl->txns_sigops + sigops_counted > tmpl->sigoplimit) { // Overflowed :( if (out == in) { From 5a6bc0caecf3c3237d5d5ac1f0180985299737c9 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 10 Aug 2016 22:31:31 +0000 Subject: [PATCH 06/28] Initial unit tests covering template and parsing --- .gitignore | 5 + Makefile.am | 6 + test.c | 451 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 462 insertions(+) create mode 100644 test.c diff --git a/.gitignore b/.gitignore index a4bcac9..e908649 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,8 @@ config.* ii ar-lib compile +test-driver +test +test-suite.log +test.log +test.trs diff --git a/Makefile.am b/Makefile.am index daee8b5..ff4c9ec 100644 --- a/Makefile.am +++ b/Makefile.am @@ -50,6 +50,12 @@ dist_noinst_DATA = \ AUTHORS COPYING README \ example.c \ testinput.c + +noinst_PROGRAMS = test +test_SOURCES = test.c +test_CFLAGS = $(libbase58_CFLAGS) $(JANSSON_CFLAGS) +test_LDADD = $(libbase58_LIBS) libblkmaker-@LIBBLKMAKER_API_VERSION@.la libblkmaker_jansson-@LIBBLKMAKER_API_VERSION@.la $(JANSSON_LIBS) +TESTS = test if CAN_COMPILE_EXAMPLE EXTRA_PROGRAMS = example diff --git a/test.c b/test.c new file mode 100644 index 0000000..5c786e9 --- /dev/null +++ b/test.c @@ -0,0 +1,451 @@ +/* + * Copyright 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. + */ + +#include +#include +#include +#include + +#include "blktemplate.h" +#include "blkmaker.h" +#include "blkmaker_jansson.h" + +static void capabilityname_test() { + for (unsigned int i = 0; i < GBT_CAPABILITY_COUNT; ++i) { + const gbt_capabilities_t capid = (1 << i); + const char * const capname = blktmpl_capabilityname(capid); + if (!capname) { + continue; + } + const size_t strlen_capname = strlen(capname); + assert(strlen_capname > 0); + assert(strlen_capname <= BLKTMPL_LONGEST_CAPABILITY_NAME); + assert(blktmpl_getcapability(capname) == capid); + } +} + +static void blktxn_test(const int c) { + struct blktxn_t * const txn = malloc(sizeof(*txn)); + memset(txn, c, sizeof(*txn)); + blktxn_init(txn); + blktxn_clean(txn); + free(txn); +} + +static bool caps_includes(const uint32_t caps, const uint32_t expected_caps) { + return (caps & expected_caps) == expected_caps; +} + +static void blktmpl_test() { + blktemplate_t * const tmpl = blktmpl_create(); + + { + static const uint32_t expected_fresh_caps = GBT_CBTXN | GBT_WORKID | BMM_TIMEINC | BMM_CBAPPEND | BMM_VERFORCE | BMM_VERDROP | BMAb_COINBASE | BMAb_TRUNCATE; + assert(caps_includes(blktmpl_addcaps(tmpl), expected_fresh_caps)); + } + + assert(!tmpl->version); + assert(!blktmpl_get_longpoll(tmpl)); + assert(!blktmpl_get_submitold(tmpl)); + + blktmpl_free(tmpl); +} + +static bool json_are_equal(json_t * const ja, json_t * const jb) { + char *sa, *sb; + sa = json_dumps(ja, JSON_COMPACT | JSON_SORT_KEYS); + sb = json_dumps(jb, JSON_COMPACT | JSON_SORT_KEYS); + const bool rv = !strcmp(sa, sb); + free(sa); + free(sb); + return rv; +} + +static void rulecompare(json_t * const jb, const char * const * const rulelist) { + const size_t z = json_array_size(jb); + const char *sa; + json_t *jc; + + for (size_t i = 0; i < z; ++i) { + assert((jc = json_array_get(jb, i))); + assert((sa = json_string_value(jc))); + assert(!strcmp(sa, rulelist[i])); + } + assert(!rulelist[z]); +} + +static void check_request(json_t * const ja, const char * const * const rulelist, uint32_t * const out_caps) { + const char *sa; + json_t *jb, *jc; + + assert(json_object_get(ja, "id")); + assert((jb = json_object_get(ja, "method"))); + assert((sa = json_string_value(jb))); + assert(!strcmp(sa, "getblocktemplate")); + assert((jb = json_object_get(ja, "params"))); + assert(json_is_array(jb)); + assert(json_array_size(jb) >= 1); + jc = json_array_get(jb, 0); + assert(json_is_object(jc)); + assert((jb = json_object_get(jc, "maxversion"))); + assert(json_number_value(jb) == BLKMAKER_MAX_BLOCK_VERSION); + assert((jb = json_object_get(jc, "rules"))); + assert(json_is_array(jb)); + rulecompare(jb, rulelist); + if (out_caps) { + *out_caps = 0; + if ((jb = json_object_get(jc, "capabilities")) && json_is_array(jb)) { + const size_t z = json_array_size(jb); + for (size_t i = 0; i < z; ++i) { + assert((jc = json_array_get(jb, i))); + assert((sa = json_string_value(jc))); + uint32_t capid = blktmpl_getcapability(sa); + assert(capid); + *out_caps |= capid; + } + } + } +} + +static void blktmpl_request_jansson_test_old() { + blktemplate_t * const tmpl = blktmpl_create(); + json_t *ja, *jb; + + ja = blktmpl_request_jansson2(0, NULL, blkmk_supported_rules); + jb = blktmpl_request_jansson(0, NULL); + assert(json_are_equal(ja, jb)); + json_decref(jb); + + check_request(ja, blkmk_supported_rules, NULL); + + json_decref(ja); + blktmpl_free(tmpl); +} + +static void blktmpl_request_jansson_test_custom_rulelist() { + blktemplate_t * const tmpl = blktmpl_create(); + json_t *ja; + const char *custom_rulelist[] = { + "abc", + "xyz", + NULL + }; + + ja = blktmpl_request_jansson2(0, NULL, custom_rulelist); + check_request(ja, custom_rulelist, NULL); + + json_decref(ja); + blktmpl_free(tmpl); +} + +static void blktmpl_request_jansson_test_custom_caps_i(json_t * const ja, const uint32_t test_caps) { + uint32_t caps; + check_request(ja, blkmk_supported_rules, &caps); + assert(caps == test_caps); + json_decref(ja); +} + +static void blktmpl_request_jansson_test_custom_caps() { + blktemplate_t * const tmpl = blktmpl_create(); + json_t *ja; + uint32_t test_caps = GBT_SERVICE | GBT_LONGPOLL; + + ja = blktmpl_request_jansson2(test_caps, NULL, blkmk_supported_rules); + blktmpl_request_jansson_test_custom_caps_i(ja, test_caps); + + test_caps |= blktmpl_addcaps(tmpl); + ja = blktmpl_request_jansson2(test_caps, NULL, blkmk_supported_rules); + blktmpl_request_jansson_test_custom_caps_i(ja, test_caps); + + blktmpl_free(tmpl); +} + +static void blktmpl_request_jansson_test_longpoll() { + blktemplate_t * const tmpl = blktmpl_create(); + static const char * const lpid = "mylpid00"; + const char *sa; + json_t *ja, *jb, *jc; + + ja = blktmpl_request_jansson2(0, lpid, blkmk_supported_rules); + check_request(ja, blkmk_supported_rules, NULL); + + jb = json_array_get(json_object_get(ja, "params"), 0); + assert((jc = json_object_get(jb, "longpollid"))); + assert((sa = json_string_value(jc))); + assert(!strcmp(sa, lpid)); + + json_decref(ja); + blktmpl_free(tmpl); +} + +static const char *blktmpl_add_jansson_str(blktemplate_t * const tmpl, const char * const s, const time_t time_rcvd) { + json_t * const j = json_loads(s, 0, NULL); + assert(j); + const char * const rv = blktmpl_add_jansson(tmpl, j, time_rcvd); + json_decref(j); + return rv; +} + +static const time_t simple_time_rcvd = 0x777; + +static void blktmpl_jansson_simple() { + blktemplate_t * const tmpl = blktmpl_create(); + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":2,\"height\":3,\"bits\":\"1d00ffff\",\"curtime\":777,\"previousblockhash\":\"0000000077777777777777777777777777777777777777777777777777777777\",\"coinbasevalue\":512}", simple_time_rcvd)); + assert(tmpl->version == 2); + assert(tmpl->height == 3); + assert(!memcmp(tmpl->diffbits, "\xff\xff\0\x1d", 4)); + assert(tmpl->curtime == 777); + for (int i = 0; i < 7; ++i) { + assert(tmpl->prevblk[i] == 0x77777777); + } + assert(!tmpl->prevblk[7]); + assert(tmpl->cbvalue == 512); + + // Check clear values + assert(tmpl->txncount == 0); + assert(tmpl->txns_datasz == 0); + assert(tmpl->txns_sigops == 0); + assert(!tmpl->cbtxn); + assert(!tmpl->workid); + assert(!blktmpl_get_longpoll(tmpl)); + assert(blktmpl_get_submitold(tmpl)); + assert(!tmpl->target); + assert(!tmpl->mutations); + assert(tmpl->aux_count == 0); + assert(!tmpl->rules); + assert(!tmpl->unsupported_rule); + assert(!tmpl->vbavailable); + assert(!tmpl->vbrequired); + + // Check reasonable default ranges + assert(tmpl->sigoplimit >= 20000); + assert(tmpl->sizelimit >= 1000000); + assert(tmpl->expires >= 60); + assert(tmpl->maxtime >= tmpl->curtime + 60); + assert(tmpl->maxtimeoff >= 60); + assert(tmpl->mintime <= tmpl->curtime - 60); + assert(tmpl->mintimeoff <= -60); + + blktmpl_free(tmpl); +} + +static void blktmpl_jansson_bip22_required() { + blktemplate_t * const tmpl = blktmpl_create(); + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"sigoplimit\":100,\"sizelimit\":1000,\"transactions\":[{\"data\":\"01000000019999999999999999999999999999999999999999999999999999999999999999aaaaaaaa00222222220100100000015100000000\",\"required\":true},{\"hash\":\"8eda1a8b67996401a89af8de4edd6715c23a7fb213f9866e18ab9d4367017e8d\",\"data\":\"01000000011c69f212e62f2cdd80937c9c0857cedec005b11d3b902d21007c932c1c7cd20f0000000000444444440100100000015100000000\",\"depends\":[1],\"fee\":12,\"required\":false,\"sigops\":4},{\"data\":\"01000000010099999999999999999999999999999999999999999999999999999999999999aaaaaaaa00555555550100100000015100000000\"}],\"coinbaseaux\":{\"dummy\":\"deadbeef\"},\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000\"},\"workid\":\"mywork\"}", simple_time_rcvd)); + assert(tmpl->version == 3); + assert(tmpl->height == 4); + assert(!memcmp(tmpl->diffbits, "\xff\x7f\0\x1d", 4)); + assert(tmpl->curtime == 877); + for (int i = 0; i < 7; ++i) { + assert(tmpl->prevblk[i] == 0xa7777777); + } + assert(!tmpl->prevblk[7]); + assert(tmpl->cbvalue == 640); + assert(tmpl->sigoplimit == 100); + assert(tmpl->sizelimit == 1000); + assert(tmpl->txncount == 3); + assert(tmpl->txns); + assert(tmpl->txns[0].data); + assert(tmpl->txns[0].datasz == 57); + assert(!memcmp(tmpl->txns[0].data, "\x01\0\0\0\x01\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\xaa\xaa\xaa\xaa\0\x22\x22\x22\x22\x01\0\x10\0\0\x01\x51\0\0\0\0", 57)); + assert(tmpl->txns[0].dependscount == -1); + assert(tmpl->txns[0].fee_ == -1); + assert(tmpl->txns[0].required); + assert(tmpl->txns[0].sigops_ == -1); + assert(tmpl->txns[1].data); + assert(tmpl->txns[1].datasz == 57); + assert(!memcmp(tmpl->txns[1].data, "\x01\0\0\0\x01\x1c\x69\xf2\x12\xe6\x2f\x2c\xdd\x80\x93\x7c\x9c\x08\x57\xce\xde\xc0\x05\xb1\x1d\x3b\x90\x2d\x21\0\x7c\x93\x2c\x1c\x7c\xd2\x0f\0\0\0\0\0\x44\x44\x44\x44\x01\0\x10\0\0\x01\x51\0\0\0\0", 57)); + assert(tmpl->txns[1].dependscount == 1); + assert(tmpl->txns[1].depends); + assert(tmpl->txns[1].depends[0] == 1); + assert(tmpl->txns[1].fee_ == 12); + assert(!tmpl->txns[1].required); + assert(tmpl->txns[1].sigops_ == 4); + assert(!memcmp(tmpl->txns[1].hash_, "\x8d\x7e\x01\x67\x43\x9d\xab\x18\x6e\x86\xf9\x13\xb2\x7f\x3a\xc2\x15\x67\xdd\x4e\xde\xf8\x9a\xa8\x01\x64\x99\x67\x8b\x1a\xda\x8e", 32)); + assert(tmpl->txns[2].data); + assert(tmpl->txns[2].datasz == 57); + assert(!memcmp(tmpl->txns[2].data, "\x01\0\0\0\x01\0\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\xaa\xaa\xaa\xaa\0\x55\x55\x55\x55\x01\0\x10\0\0\x01\x51\0\0\0\0", 57)); + assert(tmpl->txns[2].dependscount == -1); + assert(tmpl->txns[2].fee_ == -1); + assert(!tmpl->txns[2].required); + assert(tmpl->txns[2].sigops_ == -1); + assert(tmpl->cbtxn->data); + assert(tmpl->cbtxn->datasz == 64); + assert(!memcmp(tmpl->cbtxn->data, "\x01\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xff\xff\xff\xff\x07\x01\x04\x04\xde\xad\xbe\xef\x33\x33\x33\x33\x01\0\x10\0\0\x01\x51\0\0\0\0", 64)); + assert(tmpl->aux_count == 1); + assert(tmpl->auxs); + assert(tmpl->auxs[0].auxname); + assert(!strcmp(tmpl->auxs[0].auxname, "dummy")); + assert(tmpl->auxs[0].datasz == 4); + assert(!memcmp(tmpl->auxs[0].data, "\xde\xad\xbe\xef", 4)); + assert(tmpl->workid); + assert(!strcmp(tmpl->workid, "mywork")); + assert(blktmpl_get_submitold(tmpl)); + + blktmpl_free(tmpl); +} + +static void blktmpl_jansson_bip22_longpoll() { + blktemplate_t *tmpl = blktmpl_create(); + const struct blktmpl_longpoll_req *lp; + + assert(!blktmpl_get_longpoll(tmpl)); + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"longpollid\":\"mylpid\"}", simple_time_rcvd)); + lp = blktmpl_get_longpoll(tmpl); + assert(lp->id); + assert(!strcmp(lp->id, "mylpid")); + assert(!lp->uri); + assert(blktmpl_get_submitold(tmpl)); + + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"longpollid\":\"myLPid\",\"longpolluri\":\"/LP\",\"submitold\":false}", simple_time_rcvd)); + lp = blktmpl_get_longpoll(tmpl); + assert(lp->id); + assert(!strcmp(lp->id, "myLPid")); + assert(lp->uri); + assert(!strcmp(lp->uri, "/LP")); + assert(!blktmpl_get_submitold(tmpl)); + + blktmpl_free(tmpl); +} + +static void blktmpl_jansson_bip23_bpe() { + blktemplate_t *tmpl = blktmpl_create(); + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"expires\":99,\"target\":\"0000000077777777777777777777777777777777777777777777777777777777\"}", simple_time_rcvd)); + assert(tmpl->expires == 99); + assert(!(*tmpl->target)[0]); + for (int i = 1; i < 8; ++i) { + assert((*tmpl->target)[i] == 0x77777777); + } + + blktmpl_free(tmpl); +} + +static void blktmpl_jansson_bip23_mutations() { + blktemplate_t *tmpl = blktmpl_create(); + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"maxtime\":2113929216,\"maxtimeoff\":50,\"mintime\":800,\"mintimeoff\":-50,\"mutable\":[\"prevblock\",\"version/force\"],\"noncerange\":\"01000000f0000000\"}", simple_time_rcvd)); + assert(tmpl->maxtime == 2113929216); + assert(tmpl->maxtimeoff == 50); + assert(tmpl->mintime == 800); + assert(tmpl->mintimeoff == -50); + // As of right now, implied mutations are not included in the value + // assert(tmpl->mutations == (BMM_CBAPPEND | BMM_CBSET | BMM_GENERATE | BMM_TIMEINC | BMM_TIMEDEC | BMM_TXNADD | BMM_PREVBLK | BMM_VERFORCE)); + assert(caps_includes(tmpl->mutations, BMM_PREVBLK | BMM_VERFORCE)); + + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"mutable\":[\"version/reduce\",\"coinbase/append\",\"generation\",\"time\",\"transactions\"],\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000\"},\"transactions\":[]}", simple_time_rcvd)); + assert(tmpl->mutations == (BMM_CBAPPEND | BMM_GENERATE | BMM_TIMEINC | BMM_TIMEDEC | BMM_TXNADD | BMM_VERDROP)); + + blktmpl_free(tmpl); +} + +static void blktmpl_jansson_bip23_abbrev() { + blktemplate_t * const tmpl = blktmpl_create(); + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"mutable\":[\"submit/hash\",\"submit/coinbase\",\"submit/truncate\"]}", simple_time_rcvd)); + assert(tmpl->mutations == (BMA_TXNHASH | BMAb_COINBASE | BMAb_TRUNCATE)); + + blktmpl_free(tmpl); +} + +static void blktmpl_jansson_bip9() { + blktemplate_t *tmpl; + + tmpl = blktmpl_create(); + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":536871040,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"rules\":[\"csv\"],\"vbavailable\":{\"!segwit\":7}}", simple_time_rcvd)); + assert(tmpl->version == 0x20000080); + assert(tmpl->rules); + assert(tmpl->rules[0]); + assert(!strcmp(tmpl->rules[0], "csv")); + assert(!tmpl->rules[1]); + assert(!tmpl->unsupported_rule); + assert(tmpl->vbavailable); + assert(tmpl->vbavailable[0]); + assert(tmpl->vbavailable[0]->name); + assert(!strcmp(tmpl->vbavailable[0]->name, "!segwit")); + assert(tmpl->vbavailable[0]->bitnum == 7); + assert(!tmpl->vbavailable[1]); + assert(!tmpl->vbrequired); + + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":536871040,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"rules\":[\"csv\"],\"vbavailable\":{\"!segwit\":7},\"vbrequired\":128}", simple_time_rcvd)); + assert(tmpl->version == 0x20000080); + assert(tmpl->rules); + assert(tmpl->rules[0]); + assert(!strcmp(tmpl->rules[0], "csv")); + assert(!tmpl->rules[1]); + assert(!tmpl->unsupported_rule); + assert(tmpl->vbavailable); + assert(tmpl->vbavailable[0]); + assert(tmpl->vbavailable[0]->name); + assert(!strcmp(tmpl->vbavailable[0]->name, "!segwit")); + assert(tmpl->vbavailable[0]->bitnum == 7); + assert(!tmpl->vbavailable[1]); + assert(tmpl->vbrequired == 0x80); + + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":536871040,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"rules\":[\"csv\",\"foo\"],\"vbavailable\":{}}", simple_time_rcvd)); + assert(tmpl->version == 0x20000080); + assert(tmpl->rules); + assert(tmpl->rules[0]); + assert(!strcmp(tmpl->rules[0], "csv")); + assert(tmpl->rules[1]); + assert(!strcmp(tmpl->rules[1], "foo")); + assert(!tmpl->rules[2]); + assert(tmpl->unsupported_rule); + assert(tmpl->vbavailable); + assert(!tmpl->vbavailable[0]); + assert(!tmpl->vbrequired); + + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + + assert(blktmpl_add_jansson_str(tmpl, "{\"version\":536871040,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"rules\":[\"csv\",\"!foo\"],\"vbavailable\":{}}", simple_time_rcvd)); + + blktmpl_free(tmpl); +} + +int main() { + puts("capabilityname"); + capabilityname_test(); + + puts("blktxn"); + blktxn_test('\0'); + blktxn_test('\xa5'); + blktxn_test('\xff'); + + puts("blktmpl"); + blktmpl_test(); + + puts("blktmpl_request_jansson"); + blktmpl_request_jansson_test_old(); + blktmpl_request_jansson_test_custom_rulelist(); + blktmpl_request_jansson_test_custom_caps(); + blktmpl_request_jansson_test_longpoll(); + + puts("blktmpl_jansson"); + blktmpl_jansson_simple(); + blktmpl_jansson_bip22_required(); + blktmpl_jansson_bip22_longpoll(); + blktmpl_jansson_bip23_bpe(); + blktmpl_jansson_bip23_mutations(); + blktmpl_jansson_bip23_abbrev(); + blktmpl_jansson_bip9(); +} From bfd7d9469af00bc1756d45bce6c6059b764b0a23 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 11 Aug 2016 00:46:34 +0000 Subject: [PATCH 07/28] Travis: Initial CI spec YML --- .travis.yml | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..3d2e49b --- /dev/null +++ b/.travis.yml @@ -0,0 +1,44 @@ +os: linux +language: c +compiler: gcc +sudo: false +matrix: + include: +# Normal build + - addons: + apt: + packages: + - build-essential + - libjansson-dev + - libgcrypt11-dev +# clang + - compiler: clang + addons: + apt: + packages: + - build-essential + - libjansson-dev + - libgcrypt11-dev +# w/o libgcrypt + - addons: + apt: + packages: + - build-essential + - libjansson-dev + exclude: + - compiler: gcc +# TODO: Linux32 (or 64) & OS X & Win32/64 (needs libs cross-compiled) +install: + - git clone git://github.com/bitcoin/libbase58 -b v0.1.4 --depth 1 + - pushd libbase58 + - ./autogen.sh + - ./configure --prefix="$HOME" $TARGET_OPTS + - make + - make check + - make install + - popd +script: + - ./autogen.sh + - ./configure PKG_CONFIG_PATH="$HOME/lib/pkgconfig" $TARGET_OPTS $CONFIGURE_OPTS || tail -n 1000 config.log + - make + - make check From cdb5841c8847a01181af1880901d1d6de8e5e4c5 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Sat, 13 Aug 2016 07:27:54 +0000 Subject: [PATCH 08/28] Travis: Run tests with -fsanitize={address,memory,undefined} -Wall -Werror --- .travis.yml | 60 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3d2e49b..f298790 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,10 @@ os: linux language: c compiler: gcc sudo: false +env: + global: + - PKG_CONFIG_LIBDIR="$HOME/lib/pkgconfig" + - OPTS="--prefix=$HOME" matrix: include: # Normal build @@ -11,6 +15,7 @@ matrix: - build-essential - libjansson-dev - libgcrypt11-dev + env: CFLAGS="-Wall" AM_CFLAGS='-Werror' # clang - compiler: clang addons: @@ -19,6 +24,18 @@ matrix: - build-essential - libjansson-dev - libgcrypt11-dev + env: CFLAGS="-Wall -fsanitize=undefined -fno-sanitize-recover -fsanitize=address" +# clang + - compiler: clang + addons: + apt: + packages: + - build-essential + env: + - BUILD_LIBS=1 + JANSSON_VERSION=v2.1 + CFLAGS="-O0 -ggdb -Wall -fsanitize=undefined -fno-sanitize-recover -fsanitize=memory -fPIE -pie" + LDFLAGS="-fsanitize=memory -fPIE -pie -L$HOME/lib" # w/o libgcrypt - addons: apt: @@ -28,17 +45,48 @@ matrix: exclude: - compiler: gcc # TODO: Linux32 (or 64) & OS X & Win32/64 (needs libs cross-compiled) -install: +script: + - if [ -n "$BUILD_LIBS" ]; then + OPTS="$OPTS --with-gpg-error-prefix=$HOME"; + git clone git://git.gnupg.org/libgpg-error.git -b libgpg-error-1.13 --depth 1; + pushd libgpg-error; + ./autogen.sh; + ./configure $TARGET_OPTS $OPTS $GPGERROR_OPTS --disable-languages --disable-doc; + make; + LD_LIBRARY_PATH="$HOME/lib" make check; + make install; + popd; + OPTS="$OPTS --with-libgcrypt-prefix=$HOME"; + git clone git://git.gnupg.org/libgcrypt.git -b libgcrypt-1.5.4 --depth 1; + pushd libgcrypt; + ./autogen.sh; + ./configure $TARGET_OPTS $OPTS --disable-ciphers --disable-pubkey-ciphers --disable-random --disable-asm; + make; + LD_LIBRARY_PATH="$HOME/lib" make check; + make install; + popd; + + git clone https://github.com/akheron/jansson.git -b "$JANSSON_VERSION" --depth 1; + pushd jansson; + autoreconf -f -i; + ./configure $TARGET_OPTS $OPTS; + make AM_CFLAGS= ; + LD_LIBRARY_PATH="$HOME/lib" make check; + make install; + popd; + fi - git clone git://github.com/bitcoin/libbase58 -b v0.1.4 --depth 1 - pushd libbase58 - ./autogen.sh - - ./configure --prefix="$HOME" $TARGET_OPTS + - ./configure $TARGET_OPTS $OPTS - make - - make check + - LD_LIBRARY_PATH="$HOME/lib" make check; - make install - popd -script: + - - ./autogen.sh - - ./configure PKG_CONFIG_PATH="$HOME/lib/pkgconfig" $TARGET_OPTS $CONFIGURE_OPTS || tail -n 1000 config.log + - ./configure $TARGET_OPTS $OPTS $CONFIGURE_OPTS || { tail -n 1000 config.log; false; }; - make - - make check + - make example$EXEEXT + - LSAN_OPTIONS=1 LD_LIBRARY_PATH="$HOME/lib" make check; + - make install From 18ece76f7776217cc3d41a7f2a665770828ef066 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Sat, 13 Aug 2016 07:29:42 +0000 Subject: [PATCH 09/28] Travis: Build for Windows and test in WINE --- .travis.yml | 61 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index f298790..5df1ac3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -42,18 +42,54 @@ matrix: packages: - build-essential - libjansson-dev +# Win32 + - addons: + apt: + packages: + - gcc-mingw-w64-i686 + - binutils-mingw-w64-i686 + - mingw-w64-dev + - wine + env: + - CROSS_TARGET=i686-w64-mingw32 + EXEEXT=.exe + BUILD_LIBS=1 + WINE_TESTS=1 + OPTS="$OPTS --disable-static" + JANSSON_VERSION=v2.4 +# Win64 + - addons: + apt: + packages: + - gcc-mingw-w64-x86-64 + - binutils-mingw-w64-x86-64 + - mingw-w64-dev + - wine + env: + - CROSS_TARGET=x86_64-w64-mingw32 + EXEEXT=.exe + BUILD_LIBS=1 + WINE_TESTS=1 + OPTS="$OPTS --disable-static" + JANSSON_VERSION=v2.4 exclude: - compiler: gcc -# TODO: Linux32 (or 64) & OS X & Win32/64 (needs libs cross-compiled) +# TODO: Linux32 (or 64) & OS X script: + - if [ -n "$CROSS_TARGET" ]; then + unset CC; + TARGET_OPTS="$TARGET_OPTS --host=$CROSS_TARGET"; + fi - if [ -n "$BUILD_LIBS" ]; then OPTS="$OPTS --with-gpg-error-prefix=$HOME"; git clone git://git.gnupg.org/libgpg-error.git -b libgpg-error-1.13 --depth 1; pushd libgpg-error; ./autogen.sh; - ./configure $TARGET_OPTS $OPTS $GPGERROR_OPTS --disable-languages --disable-doc; + ./configure $TARGET_OPTS $OPTS --disable-languages --disable-doc; make; - LD_LIBRARY_PATH="$HOME/lib" make check; + if [ -z "$WINE_TESTS" ]; then + LD_LIBRARY_PATH="$HOME/lib" make check; + fi; make install; popd; OPTS="$OPTS --with-libgcrypt-prefix=$HOME"; @@ -62,7 +98,9 @@ script: ./autogen.sh; ./configure $TARGET_OPTS $OPTS --disable-ciphers --disable-pubkey-ciphers --disable-random --disable-asm; make; - LD_LIBRARY_PATH="$HOME/lib" make check; + if [ -z "$WINE_TESTS" ]; then + LD_LIBRARY_PATH="$HOME/lib" make check; + fi; make install; popd; @@ -71,7 +109,9 @@ script: autoreconf -f -i; ./configure $TARGET_OPTS $OPTS; make AM_CFLAGS= ; - LD_LIBRARY_PATH="$HOME/lib" make check; + if [ -z "$WINE_TESTS" ]; then + LD_LIBRARY_PATH="$HOME/lib" make check; + fi; make install; popd; fi @@ -80,7 +120,9 @@ script: - ./autogen.sh - ./configure $TARGET_OPTS $OPTS - make - - LD_LIBRARY_PATH="$HOME/lib" make check; + - if [ -z "$WINE_TESTS" ]; then + LD_LIBRARY_PATH="$HOME/lib" make check; + fi - make install - popd - @@ -88,5 +130,10 @@ script: - ./configure $TARGET_OPTS $OPTS $CONFIGURE_OPTS || { tail -n 1000 config.log; false; }; - make - make example$EXEEXT - - LSAN_OPTIONS=1 LD_LIBRARY_PATH="$HOME/lib" make check; + - if [ -z "$WINE_TESTS" ]; then + LSAN_OPTIONS=1 LD_LIBRARY_PATH="$HOME/lib" make check; + else + ln -s $HOME/bin/*.dll .libs/; + LSAN_OPTIONS=1 WINEDLLPATH="$PWD/.libs" wine .libs/test.exe; + fi - make install From 0dcc8d8697b5dc72c1a53f02419ae5ecf1127756 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 10 Aug 2016 22:45:00 +0000 Subject: [PATCH 10/28] test: Use libgcrypt for SHA256 --- Makefile.am | 6 +++--- configure.ac | 10 +++++----- test.c | 9 +++++++++ 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/Makefile.am b/Makefile.am index ff4c9ec..b7a95a2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -51,13 +51,13 @@ dist_noinst_DATA = \ example.c \ testinput.c +if HAVE_LIBGCRYPT noinst_PROGRAMS = test test_SOURCES = test.c -test_CFLAGS = $(libbase58_CFLAGS) $(JANSSON_CFLAGS) -test_LDADD = $(libbase58_LIBS) libblkmaker-@LIBBLKMAKER_API_VERSION@.la libblkmaker_jansson-@LIBBLKMAKER_API_VERSION@.la $(JANSSON_LIBS) +test_CFLAGS = $(libbase58_CFLAGS) $(JANSSON_CFLAGS) $(LIBGCRYPT_CFLAGS) +test_LDADD = $(libbase58_LIBS) libblkmaker-@LIBBLKMAKER_API_VERSION@.la libblkmaker_jansson-@LIBBLKMAKER_API_VERSION@.la $(JANSSON_LIBS) $(LIBGCRYPT_LIBS) TESTS = test -if CAN_COMPILE_EXAMPLE EXTRA_PROGRAMS = example example_SOURCES = example.c example_CFLAGS = $(libbase58_CFLAGS) $(JANSSON_CFLAGS) $(LIBGCRYPT_CFLAGS) diff --git a/configure.ac b/configure.ac index 4671ca7..8072702 100644 --- a/configure.ac +++ b/configure.ac @@ -51,18 +51,18 @@ PKG_CHECK_MODULES([libbase58],[libbase58]) AC_CHECK_LIB([ws2_32], [strchr]) -dnl libgcrypt necessary to build example.c with "make example" +dnl libgcrypt necessary to build tests and example dnl check for libgcrypt: m4_ifdef([AM_PATH_LIBGCRYPT], [ AM_PATH_LIBGCRYPT([], [ - can_compile_example=yes + have_libgcrypt=yes ],[ - can_compile_example=no + have_libgcrypt=no ]) ],[ - m4_warn([syntax], [AM_PATH_LIBGCRYPT missing; example will not be available]) + m4_warn([syntax], [AM_PATH_LIBGCRYPT missing; example and tests will not be available]) ]) -AM_CONDITIONAL([CAN_COMPILE_EXAMPLE], [test x$can_compile_example = xyes]) +AM_CONDITIONAL([HAVE_LIBGCRYPT], [test x$have_libgcrypt = xyes]) AC_OUTPUT diff --git a/test.c b/test.c index 5c786e9..191d9c9 100644 --- a/test.c +++ b/test.c @@ -10,10 +10,17 @@ #include #include +#include + #include "blktemplate.h" #include "blkmaker.h" #include "blkmaker_jansson.h" +static bool my_sha256(void *digest, const void *buffer, size_t length) { + gcry_md_hash_buffer(GCRY_MD_SHA256, digest, buffer, length); + return true; +} + static void capabilityname_test() { for (unsigned int i = 0; i < GBT_CAPABILITY_COUNT; ++i) { const gbt_capabilities_t capid = (1 << i); @@ -423,6 +430,8 @@ static void blktmpl_jansson_bip9() { } int main() { + blkmk_sha256_impl = my_sha256; + puts("capabilityname"); capabilityname_test(); From 70a022e944060333a62bb0f6bdf8e32df753f78b Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 10 Aug 2016 22:51:04 +0000 Subject: [PATCH 11/28] test: Check out block proposals --- test.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/test.c b/test.c index 191d9c9..26246ee 100644 --- a/test.c +++ b/test.c @@ -429,6 +429,64 @@ static void blktmpl_jansson_bip9() { blktmpl_free(tmpl); } +static void blktmpl_jansson_propose_check(json_t *j, const int level) { + const char *sa; + + j = json_array_get(json_object_get(j, "params"), 0); + assert((j = json_object_get(j, "data"))); + assert((sa = json_string_value(j))); + assert(strlen(sa) >= 160); + assert(!memcmp(sa, "03000000777777a7777777a7777777a7777777a7777777a7777777a7777777a700000000", 72)); + // Don't check merkle root + assert(!memcmp(&sa[136], "6d030000ff7f001d", 16)); + // Don't check nonce + size_t pos = 160; + if (level > 0) { + assert(!strncmp(&sa[pos], "0401000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000", 130)); + pos += 130; + if (level > 1) { + assert(!strcmp(&sa[pos], "01000000019999999999999999999999999999999999999999999999999999999999999999aaaaaaaa0022222222010010000001510000000001000000011c69f212e62f2cdd80937c9c0857cedec005b11d3b902d21007c932c1c7cd20f000000000044444444010010000001510000000001000000010099999999999999999999999999999999999999999999999999999999999999aaaaaaaa00555555550100100000015100000000")); + pos += strlen(&sa[pos]); + } + } + assert(sa[pos] == '\0'); +} + +static void blktmpl_jansson_propose() { + blktemplate_t * const tmpl = blktmpl_create(); + const char *sa; + json_t *j, *ja, *jb; + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"sigoplimit\":100,\"sizelimit\":1000,\"transactions\":[{\"data\":\"01000000019999999999999999999999999999999999999999999999999999999999999999aaaaaaaa00222222220100100000015100000000\",\"required\":true},{\"hash\":\"8eda1a8b67996401a89af8de4edd6715c23a7fb213f9866e18ab9d4367017e8d\",\"data\":\"01000000011c69f212e62f2cdd80937c9c0857cedec005b11d3b902d21007c932c1c7cd20f0000000000444444440100100000015100000000\",\"depends\":[1],\"fee\":12,\"required\":false,\"sigops\":4},{\"data\":\"01000000010099999999999999999999999999999999999999999999999999999999999999aaaaaaaa00555555550100100000015100000000\"}],\"coinbaseaux\":{\"dummy\":\"deadbeef\"},\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000\"},\"workid\":\"mywork\"}", simple_time_rcvd)); + + assert((j = blktmpl_propose_jansson(tmpl, 0, false))); + check_request(j, blkmk_supported_rules, NULL); + + ja = json_array_get(json_object_get(j, "params"), 0); + assert((jb = json_object_get(ja, "mode"))); + assert((sa = json_string_value(jb))); + assert(!strcmp(sa, "proposal")); + assert((jb = json_object_get(ja, "workid"))); + assert((sa = json_string_value(jb))); + assert(!strcmp(sa, "mywork")); + blktmpl_jansson_propose_check(j, 2); + json_decref(j); + + tmpl->mutations |= BMAb_COINBASE; + assert((j = blktmpl_propose_jansson(tmpl, 0, false))); + check_request(j, blkmk_supported_rules, NULL); + blktmpl_jansson_propose_check(j, 1); + json_decref(j); + + tmpl->mutations |= BMAb_TRUNCATE; + assert((j = blktmpl_propose_jansson(tmpl, 0, false))); + check_request(j, blkmk_supported_rules, NULL); + blktmpl_jansson_propose_check(j, 0); + json_decref(j); + + blktmpl_free(tmpl); +} + int main() { blkmk_sha256_impl = my_sha256; @@ -457,4 +515,5 @@ int main() { blktmpl_jansson_bip23_mutations(); blktmpl_jansson_bip23_abbrev(); blktmpl_jansson_bip9(); + blktmpl_jansson_propose(); } From c0f590e8890c5f006a6d64146ad8b0f013ccb9f3 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 11 Aug 2016 00:01:20 +0000 Subject: [PATCH 12/28] test: Check out submissions --- test.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 7 deletions(-) diff --git a/test.c b/test.c index 26246ee..862c61e 100644 --- a/test.c +++ b/test.c @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -429,12 +430,7 @@ static void blktmpl_jansson_bip9() { blktmpl_free(tmpl); } -static void blktmpl_jansson_propose_check(json_t *j, const int level) { - const char *sa; - - j = json_array_get(json_object_get(j, "params"), 0); - assert((j = json_object_get(j, "data"))); - assert((sa = json_string_value(j))); +static void blktmpl_jansson_submit_data_check(const char * const sa, const int level) { assert(strlen(sa) >= 160); assert(!memcmp(sa, "03000000777777a7777777a7777777a7777777a7777777a7777777a7777777a700000000", 72)); // Don't check merkle root @@ -449,7 +445,18 @@ static void blktmpl_jansson_propose_check(json_t *j, const int level) { pos += strlen(&sa[pos]); } } - assert(sa[pos] == '\0'); + if (level >= 0) { + assert(sa[pos] == '\0'); + } +} + +static void blktmpl_jansson_propose_check(json_t *j, const int level) { + const char *sa; + + j = json_array_get(json_object_get(j, "params"), 0); + assert((j = json_object_get(j, "data"))); + assert((sa = json_string_value(j))); + return blktmpl_jansson_submit_data_check(sa, level); } static void blktmpl_jansson_propose() { @@ -487,6 +494,66 @@ static void blktmpl_jansson_propose() { blktmpl_free(tmpl); } +static void blktmpl_jansson_submit() { + blktemplate_t * const tmpl = blktmpl_create(); + const char *sa; + uint8_t data[76]; + int16_t i16; + unsigned int dataid; + json_t *j, *ja, *jb, *jc; + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"sigoplimit\":100,\"sizelimit\":1000,\"transactions\":[{\"data\":\"01000000019999999999999999999999999999999999999999999999999999999999999999aaaaaaaa00222222220100100000015100000000\",\"required\":true},{\"hash\":\"8eda1a8b67996401a89af8de4edd6715c23a7fb213f9866e18ab9d4367017e8d\",\"data\":\"01000000011c69f212e62f2cdd80937c9c0857cedec005b11d3b902d21007c932c1c7cd20f0000000000444444440100100000015100000000\",\"depends\":[1],\"fee\":12,\"required\":false,\"sigops\":4},{\"data\":\"01000000010099999999999999999999999999999999999999999999999999999999999999aaaaaaaa00555555550100100000015100000000\"}],\"coinbaseaux\":{\"dummy\":\"deadbeef\"},\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000\"},\"workid\":\"mywork\",\"mutable\":[\"submit/coinbase\",\"submit/truncate\",\"coinbase/append\"]}", simple_time_rcvd)); + + assert(76 == blkmk_get_data(tmpl, data, sizeof(data), simple_time_rcvd, &i16, &dataid)); + + assert((j = blkmk_submit_foreign_jansson(tmpl, data, 0, 0x12345678))); + assert((ja = json_object_get(j, "params"))); + assert(json_is_array(ja)); + assert(json_array_size(ja) >= 1); + assert((sa = json_string_value(json_array_get(ja, 0)))); + blktmpl_jansson_submit_data_check(sa, 2); + if (json_array_size(ja) >= 2) { + assert(json_is_object((jb = json_array_get(ja, 1)))); + assert(!json_object_get(jb, "workid")); + } + json_decref(j); + + assert((j = blkmk_submit_jansson(tmpl, data, 0, 0x12345678))); + assert(json_object_get(j, "id")); + assert((ja = json_object_get(j, "method"))); + assert((sa = json_string_value(ja))); + assert(!strcmp(sa, "submitblock")); + assert((ja = json_object_get(j, "params"))); + assert(json_is_array(ja)); + assert(json_array_size(ja) >= 2); + assert((sa = json_string_value(json_array_get(ja, 0)))); + blktmpl_jansson_submit_data_check(sa, 0); + assert(!memcmp(&sa[72], "512a63f45f96f0269a2d23ccd96bcf0322ee4f60254748e30b89e2b59431aba16d030000ff7f001d12345678", 64)); // merkle root + assert(!memcmp(&sa[152], "12345678", 8)); // nonce + assert(json_is_object((jb = json_array_get(ja, 1)))); + assert((jc = json_object_get(jb, "workid"))); + assert((sa = json_string_value(jc))); + assert(!strcmp(sa, "mywork")); + json_decref(j); + + assert(76 == blkmk_get_data(tmpl, data, sizeof(data), simple_time_rcvd, &i16, &dataid)); + + assert((j = blkmk_submit_jansson(tmpl, data, dataid, 0x12345678))); + assert((ja = json_object_get(j, "params"))); + assert(json_is_array(ja)); + assert(json_array_size(ja) >= 2); + assert((sa = json_string_value(json_array_get(ja, 0)))); + blktmpl_jansson_submit_data_check(sa, -1); + // TODO: Check inserted dataid + assert(json_is_object((jb = json_array_get(ja, 1)))); + assert((jc = json_object_get(jb, "workid"))); + assert((sa = json_string_value(jc))); + assert(!strcmp(sa, "mywork")); + json_decref(j); + + blktmpl_free(tmpl); +} + int main() { blkmk_sha256_impl = my_sha256; @@ -516,4 +583,5 @@ int main() { blktmpl_jansson_bip23_abbrev(); blktmpl_jansson_bip9(); blktmpl_jansson_propose(); + blktmpl_jansson_submit(); } From 5c471cb3fe769c36f1f882045a00c33efc0a7b28 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 11 Aug 2016 00:23:02 +0000 Subject: [PATCH 13/28] test: Check out mdata submissions --- test.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/test.c b/test.c index 862c61e..8b5d079 100644 --- a/test.c +++ b/test.c @@ -554,6 +554,79 @@ static void blktmpl_jansson_submit() { blktmpl_free(tmpl); } +static void blktmpl_jansson_submitm() { + blktemplate_t * const tmpl = blktmpl_create(); + const char *sa; + uint8_t data[76], *cbtxn, *branches, extranonce[10]; + size_t cbextranonceoffset, cbtxnsize; + int branchcount; + int16_t i16; + json_t *j, *ja, *jb, *jc; + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"sigoplimit\":100,\"sizelimit\":1000,\"transactions\":[{\"data\":\"01000000019999999999999999999999999999999999999999999999999999999999999999aaaaaaaa00222222220100100000015100000000\",\"required\":true},{\"hash\":\"8eda1a8b67996401a89af8de4edd6715c23a7fb213f9866e18ab9d4367017e8d\",\"data\":\"01000000011c69f212e62f2cdd80937c9c0857cedec005b11d3b902d21007c932c1c7cd20f0000000000444444440100100000015100000000\",\"depends\":[1],\"fee\":12,\"required\":false,\"sigops\":4},{\"data\":\"01000000010099999999999999999999999999999999999999999999999999999999999999aaaaaaaa00555555550100100000015100000000\"}],\"coinbaseaux\":{\"dummy\":\"deadbeef\"},\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000\"},\"workid\":\"mywork\",\"mutable\":[\"submit/coinbase\",\"submit/truncate\",\"coinbase/append\"]}", simple_time_rcvd)); + + assert(blkmk_get_mdata(tmpl, data, sizeof(data), simple_time_rcvd, &i16, &cbtxn, &cbtxnsize, &cbextranonceoffset, &branchcount, &branches, 1, false)); + free(cbtxn); + free(branches); + memset(&data[36], '\xee', 32); // merkle root, must be provided by caller + + extranonce[0] = 11; + assert((j = blkmk_submitm_jansson(tmpl, data, extranonce, 1, 0x12345678, false))); + assert(json_object_get(j, "id")); + assert((ja = json_object_get(j, "method"))); + assert((sa = json_string_value(ja))); + assert(!strcmp(sa, "submitblock")); + assert((ja = json_object_get(j, "params"))); + assert(json_is_array(ja)); + assert(json_array_size(ja) >= 2); + assert((sa = json_string_value(json_array_get(ja, 0)))); + blktmpl_jansson_submit_data_check(sa, -1); + assert(!strcmp(&sa[160], "0401000000010000000000000000000000000000000000000000000000000000000000000000ffffffff08010404deadbeef0b333333330100100000015100000000")); + assert(json_is_object((jb = json_array_get(ja, 1)))); + assert((jc = json_object_get(jb, "workid"))); + assert((sa = json_string_value(jc))); + assert(!strcmp(sa, "mywork")); + json_decref(j); + + extranonce[0] = 22; + assert((j = blkmk_submitm_jansson(tmpl, data, extranonce, 1, 0x12345678, true))); + assert((ja = json_object_get(j, "params"))); + assert(json_is_array(ja)); + assert(json_array_size(ja) >= 2); + assert((sa = json_string_value(json_array_get(ja, 0)))); + blktmpl_jansson_submit_data_check(sa, -1); + assert(!strcmp(&sa[160], "0401000000010000000000000000000000000000000000000000000000000000000000000000ffffffff08010404deadbeef1633333333010010000001510000000001000000019999999999999999999999999999999999999999999999999999999999999999aaaaaaaa0022222222010010000001510000000001000000011c69f212e62f2cdd80937c9c0857cedec005b11d3b902d21007c932c1c7cd20f000000000044444444010010000001510000000001000000010099999999999999999999999999999999999999999999999999999999999999aaaaaaaa00555555550100100000015100000000")); + json_decref(j); + + assert(blkmk_get_mdata(tmpl, data, sizeof(data), simple_time_rcvd, &i16, &cbtxn, &cbtxnsize, &cbextranonceoffset, &branchcount, &branches, 3, false)); + free(cbtxn); + free(branches); + + extranonce[0] = 0x11; + extranonce[1] = 0x22; + extranonce[2] = 0x33; + assert((j = blkmk_submitm_jansson(tmpl, data, extranonce, 3, 0x12345678, false))); + assert((ja = json_object_get(j, "params"))); + assert(json_is_array(ja)); + assert(json_array_size(ja) >= 2); + assert((sa = json_string_value(json_array_get(ja, 0)))); + blktmpl_jansson_submit_data_check(sa, -1); + assert(!strcmp(&sa[160], "0401000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0a010404deadbeef112233333333330100100000015100000000")); + json_decref(j); + + extranonce[2] = 0xed; + assert((j = blkmk_submitm_jansson(tmpl, data, extranonce, 3, 0x12345678, true))); + assert((ja = json_object_get(j, "params"))); + assert(json_is_array(ja)); + assert(json_array_size(ja) >= 2); + assert((sa = json_string_value(json_array_get(ja, 0)))); + blktmpl_jansson_submit_data_check(sa, -1); + assert(!strcmp(&sa[160], "0401000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0a010404deadbeef1122ed33333333010010000001510000000001000000019999999999999999999999999999999999999999999999999999999999999999aaaaaaaa0022222222010010000001510000000001000000011c69f212e62f2cdd80937c9c0857cedec005b11d3b902d21007c932c1c7cd20f000000000044444444010010000001510000000001000000010099999999999999999999999999999999999999999999999999999999999999aaaaaaaa00555555550100100000015100000000")); + json_decref(j); + + blktmpl_free(tmpl); +} + int main() { blkmk_sha256_impl = my_sha256; @@ -584,4 +657,5 @@ int main() { blktmpl_jansson_bip9(); blktmpl_jansson_propose(); blktmpl_jansson_submit(); + blktmpl_jansson_submitm(); } From 136f2b5457053e9bcdecada3694a8c0c50644240 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 11 Aug 2016 00:29:18 +0000 Subject: [PATCH 14/28] test: Check blkmk_supports_rule --- test.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test.c b/test.c index 8b5d079..8e9e77c 100644 --- a/test.c +++ b/test.c @@ -627,6 +627,18 @@ static void blktmpl_jansson_submitm() { blktmpl_free(tmpl); } +static void test_blkmk_supports_rule() { + for (const char **rule = blkmk_supported_rules; *rule; ++rule) { + assert(blkmk_supports_rule(*rule)); + char important_rule[strlen(*rule) + 2]; + important_rule[0] = '!'; + strcpy(&important_rule[1], *rule); + assert(!blkmk_supports_rule(important_rule)); + } + assert(!blkmk_supports_rule("foo")); + assert(!blkmk_supports_rule("")); +} + int main() { blkmk_sha256_impl = my_sha256; @@ -658,4 +670,7 @@ int main() { blktmpl_jansson_propose(); blktmpl_jansson_submit(); blktmpl_jansson_submitm(); + + puts("blkmk_supports_rule"); + test_blkmk_supports_rule(); } From 0d940766718a0930cc253af5c06807cab5411259 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 11 Aug 2016 03:32:18 +0000 Subject: [PATCH 15/28] test: Check blkmk_address_to_script --- test.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test.c b/test.c index 8e9e77c..a05c00e 100644 --- a/test.c +++ b/test.c @@ -639,6 +639,19 @@ static void test_blkmk_supports_rule() { assert(!blkmk_supports_rule("")); } +static void test_blkmk_address_to_script() { + uint8_t script[0x100]; + + assert(blkmk_address_to_script(script, sizeof(script), "1QATWksNFGeUJCWBrN4g6hGM178Lovm7Wh") == 25); + assert(!memcmp(script, "\x76\xa9\x14\xfe\x14\xc4\xc6\x8d\x83\xda\x61\xfc\x57\x7b\x04\xcb\x6e\xcb\x6d\x31\xba\x1d\x52\x88\xac", 25)); + + assert(blkmk_address_to_script(script, sizeof(script), "3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy") == 23); + assert(!memcmp(script, "\xa9\x14\xb4\x72\xa2\x66\xd0\xbd\x89\xc1\x37\x06\xa4\x13\x2c\xcf\xb1\x6f\x7c\x3b\x9f\xcb\x87", 23)); + + assert(blkmk_address_to_script(script, sizeof(script), "1BitcoinEaterAddressDontSendf59kuE") == 25); + assert(!memcmp(script, "\x76\xa9\x14\x75\x9d\x66\x77\x09\x1e\x97\x3b\x9e\x9d\x99\xf1\x9c\x68\xfb\xf4\x3e\x3f\x05\xf9\x88\xac", 25)); +} + int main() { blkmk_sha256_impl = my_sha256; @@ -673,4 +686,7 @@ int main() { puts("blkmk_supports_rule"); test_blkmk_supports_rule(); + + puts("blkmk_address_to_script"); + test_blkmk_address_to_script(); } From cf8d325b30ea2acd39782b6494401c39a83d478a Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 11 Aug 2016 03:52:23 +0000 Subject: [PATCH 16/28] test: Check blkmk_{time,work}_left --- test.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test.c b/test.c index a05c00e..3306a1f 100644 --- a/test.c +++ b/test.c @@ -652,6 +652,38 @@ static void test_blkmk_address_to_script() { assert(!memcmp(script, "\x76\xa9\x14\x75\x9d\x66\x77\x09\x1e\x97\x3b\x9e\x9d\x99\xf1\x9c\x68\xfb\xf4\x3e\x3f\x05\xf9\x88\xac", 25)); } +static void test_blkmk_x_left() { + blktemplate_t *tmpl = blktmpl_create(); + uint8_t data[76]; + int16_t i16; + unsigned int dataid, orig_work_left; + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"transactions\":[],\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000\"},\"expires\":44}", simple_time_rcvd)); + + assert(blkmk_work_left(tmpl) == 1); + assert(76 == blkmk_get_data(tmpl, data, sizeof(data), simple_time_rcvd, &i16, &dataid)); + assert(blkmk_work_left(tmpl) == 0); + + assert(blkmk_time_left(tmpl, simple_time_rcvd) == 44); + assert(blkmk_time_left(tmpl, simple_time_rcvd + 1) == 43); + assert(blkmk_time_left(tmpl, simple_time_rcvd + 43) == 1); + assert(blkmk_time_left(tmpl, simple_time_rcvd + 50) == 0); + + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"transactions\":[],\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000\"},\"mutable\":[\"coinbase/append\"]}", simple_time_rcvd)); + + orig_work_left = blkmk_work_left(tmpl); + assert(orig_work_left > 0xf0); + assert(76 == blkmk_get_data(tmpl, data, sizeof(data), simple_time_rcvd, &i16, &dataid)); + assert(blkmk_work_left(tmpl) == orig_work_left - 1); + assert(76 == blkmk_get_data(tmpl, data, sizeof(data), simple_time_rcvd, &i16, &dataid)); + assert(blkmk_work_left(tmpl) == orig_work_left - 2); + + blktmpl_free(tmpl); +} + int main() { blkmk_sha256_impl = my_sha256; @@ -689,4 +721,7 @@ int main() { puts("blkmk_address_to_script"); test_blkmk_address_to_script(); + + puts("blkmk_*_left"); + test_blkmk_x_left(); } From bdb9519f1b5a7b5d56b5703656387fc43242615b Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 11 Aug 2016 04:13:49 +0000 Subject: [PATCH 17/28] test: Check blkmk_get_data --- test.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/test.c b/test.c index 3306a1f..eb46a24 100644 --- a/test.c +++ b/test.c @@ -22,6 +22,10 @@ static bool my_sha256(void *digest, const void *buffer, size_t length) { return true; } +static bool bad_sha256(void *digest, const void *buffer, size_t length) { + return false; +} + static void capabilityname_test() { for (unsigned int i = 0; i < GBT_CAPABILITY_COUNT; ++i) { const gbt_capabilities_t capid = (1 << i); @@ -684,6 +688,58 @@ static void test_blkmk_x_left() { blktmpl_free(tmpl); } +static void test_blkmk_get_data() { + blktemplate_t *tmpl = blktmpl_create(); + uint8_t data[76]; + int16_t i16; + unsigned int dataid, first_dataid; + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"sigoplimit\":100,\"sizelimit\":1000,\"transactions\":[{\"data\":\"01000000019999999999999999999999999999999999999999999999999999999999999999aaaaaaaa00222222220100100000015100000000\",\"required\":true},{\"hash\":\"8eda1a8b67996401a89af8de4edd6715c23a7fb213f9866e18ab9d4367017e8d\",\"data\":\"01000000011c69f212e62f2cdd80937c9c0857cedec005b11d3b902d21007c932c1c7cd20f0000000000444444440100100000015100000000\",\"depends\":[1],\"fee\":12,\"required\":false,\"sigops\":4},{\"data\":\"01000000010099999999999999999999999999999999999999999999999999999999999999aaaaaaaa00555555550100100000015100000000\"}],\"coinbaseaux\":{\"dummy\":\"deadbeef\"},\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000\"},\"workid\":\"mywork\",\"mutable\":[\"submit/coinbase\",\"submit/truncate\",\"coinbase/append\"],\"expires\":32}", simple_time_rcvd)); + + assert(blkmk_work_left(tmpl) > 0xf0); + assert(76 == blkmk_get_data(tmpl, data, sizeof(data), simple_time_rcvd, &i16, &first_dataid)); + assert(first_dataid == 0); + assert(i16 == 31 || i16 == 32); + assert(!memcmp(data, "\x03\0\0\0\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\0\0\0\0\x51\x2a\x63\xf4\x5f\x96\xf0\x26\x9a\x2d\x23\xcc\xd9\x6b\xcf\x03\x22\xee\x4f\x60\x25\x47\x48\xe3\x0b\x89\xe2\xb5\x94\x31\xab\xa1\x6d\x03\0\0\xff\x7f\0\x1d", 76)); + + assert(76 == blkmk_get_data(tmpl, data, sizeof(data), simple_time_rcvd + 4, &i16, &dataid)); + assert(dataid == first_dataid + 1); + assert(i16 == 27 || i16 == 28); + assert(!memcmp(data, "\x03\0\0\0\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\0\0\0\0\x2a\x73\x99\xbc\x0a\x19\xa1\x11\x03\xfc\x3b\x8f\x4b\xe4\0\x68\x18\xea\x3f\x2a\0\xcf\x42\x8b\xd7\x09\x1c\x8d\xe2\xea\xe7\x38\x71\x03\0\0\xff\x7f\0\x1d", 76)); + + assert(76 == blkmk_get_data(tmpl, data, sizeof(data) + 1, simple_time_rcvd + 8, &i16, &dataid)); + assert(dataid == first_dataid + 2); + assert(i16 == 23 || i16 == 24); + assert(!memcmp(data, "\x03\0\0\0\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\0\0\0\0\xe2\xe4\xbc\x8e\x65\x8b\x52\x2e\xe5\xeb\x69\xd5\xe5\xd4\xa6\x25\xfd\x8f\x32\x2d\x71\x0f\xc0\xb2\x38\xe1\x71\x01\x61\x56\x2c\x2e\x75\x03\0\0\xff\x7f\0\x1d", 76)); + + // Too-small buffer fails with desired buffer size + assert(76 == blkmk_get_data(tmpl, data, sizeof(data) - 1, simple_time_rcvd + 8, &i16, &dataid)); + // Make sure dataid wasn't incremented for the failure + assert(76 == blkmk_get_data(tmpl, data, sizeof(data), simple_time_rcvd + 8, &i16, &dataid)); + assert(dataid == first_dataid + 3); + + // Bad hash function should fail + blkmk_sha256_impl = bad_sha256; + assert(0 == blkmk_get_data(tmpl, data, sizeof(data), simple_time_rcvd + 8, &i16, &dataid)); + blkmk_sha256_impl = my_sha256; + + // No more time, fail + assert(0 == blkmk_get_data(tmpl, data, sizeof(data), simple_time_rcvd + 35, &i16, &dataid)); + + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"sigoplimit\":100,\"sizelimit\":1000,\"transactions\":[{\"data\":\"01000000019999999999999999999999999999999999999999999999999999999999999999aaaaaaaa00222222220100100000015100000000\",\"required\":true},{\"hash\":\"8eda1a8b67996401a89af8de4edd6715c23a7fb213f9866e18ab9d4367017e8d\",\"data\":\"01000000011c69f212e62f2cdd80937c9c0857cedec005b11d3b902d21007c932c1c7cd20f0000000000444444440100100000015100000000\",\"depends\":[1],\"fee\":12,\"required\":false,\"sigops\":4},{\"data\":\"01000000010099999999999999999999999999999999999999999999999999999999999999aaaaaaaa00555555550100100000015100000000\"}],\"coinbaseaux\":{\"dummy\":\"deadbeef\"},\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000\"},\"workid\":\"mywork\",\"expires\":32}", simple_time_rcvd)); + // Make sure a non-appendable fails the second get_data + assert(76 == blkmk_get_data(tmpl, data, sizeof(data), simple_time_rcvd, &i16, &first_dataid)); + assert(first_dataid == 0); + assert(0 == blkmk_get_data(tmpl, data, sizeof(data), simple_time_rcvd, &i16, &first_dataid)); + + // TODO: ensure a scriptsig with <4 bytes cannot be produced through to get_data; but this requires a platform where sizeof(unsigned int) < 4 and no height-in-coinbase... + + blktmpl_free(tmpl); +} + int main() { blkmk_sha256_impl = my_sha256; @@ -724,4 +780,7 @@ int main() { puts("blkmk_*_left"); test_blkmk_x_left(); + + puts("blkmk_get_data"); + test_blkmk_get_data(); } From 04753c725751516e81ecc1a27b9f36138353e502 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 11 Aug 2016 04:16:54 +0000 Subject: [PATCH 18/28] test: Check blkmk_get_mdata --- test.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/test.c b/test.c index eb46a24..65dce72 100644 --- a/test.c +++ b/test.c @@ -740,6 +740,100 @@ static void test_blkmk_get_data() { blktmpl_free(tmpl); } +static void test_blkmk_get_mdata() { + blktemplate_t *tmpl = blktmpl_create(); + uint8_t data[76], *cbtxn, *branches; + size_t cbextranonceoffset, cbtxnsize; + int branchcount; + int16_t i16; + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"sigoplimit\":100,\"sizelimit\":1000,\"transactions\":[{\"data\":\"01000000019999999999999999999999999999999999999999999999999999999999999999aaaaaaaa00222222220100100000015100000000\",\"required\":true},{\"hash\":\"8eda1a8b67996401a89af8de4edd6715c23a7fb213f9866e18ab9d4367017e8d\",\"data\":\"01000000011c69f212e62f2cdd80937c9c0857cedec005b11d3b902d21007c932c1c7cd20f0000000000444444440100100000015100000000\",\"depends\":[1],\"fee\":12,\"required\":false,\"sigops\":4},{\"data\":\"01000000010099999999999999999999999999999999999999999999999999999999999999aaaaaaaa00555555550100100000015100000000\"}],\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000\"},\"workid\":\"mywork\",\"mutable\":[\"submit/coinbase\",\"submit/truncate\",\"coinbase/append\"],\"expires\":99}", simple_time_rcvd)); + + assert(blkmk_get_mdata(tmpl, data, sizeof(data), simple_time_rcvd, &i16, &cbtxn, &cbtxnsize, &cbextranonceoffset, &branchcount, &branches, 1, false)); + assert(!memcmp(data, "\x03\0\0\0\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\0\0\0\0", 36)); + // Skip merkle root + assert(!memcmp(&data[68], "\x6d\x03\0\0\xff\x7f\0\x1d", 8)); + assert(i16 == 98 || i16 == 99); + assert(cbtxnsize == 65); + assert(cbextranonceoffset == 49); + assert(!memcmp(cbtxn, "\x01\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xff\xff\xff\xff\x08\x01\x04\x04\xde\xad\xbe\xef", 49)); + assert(!memcmp(&cbtxn[50], "\x33\x33\x33\x33\x01\0\x10\0\0\x01\x51\0\0\0\0", 65-50)); + assert(branchcount == 2); + assert(!memcmp(branches, "\x0f\xd2\x7c\x1c\x2c\x93\x7c\0\x21\x2d\x90\x3b\x1d\xb1\x05\xc0\xde\xce\x57\x08\x9c\x7c\x93\x80\xdd\x2c\x2f\xe6\x12\xf2\x69\x1c\x2b\x07\x3c\xb8\x85\xbf\x62\x3b\x1c\xd5\xac\xda\x81\xce\xe8\x9f\xe9\x19\x0e\x10\x85\xff\x54\x98\xc3\x33\x4c\x2c\x63\xf8\xdd\x4d", 64)); + free(cbtxn); + free(branches); + + assert(blkmk_get_mdata(tmpl, data, sizeof(data), simple_time_rcvd + 4, &i16, &cbtxn, &cbtxnsize, &cbextranonceoffset, &branchcount, &branches, 3, false)); + assert(!memcmp(data, "\x03\0\0\0\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\0\0\0\0", 36)); + // Skip merkle root + assert(!memcmp(&data[68], "\x71\x03\0\0\xff\x7f\0\x1d", 8)); + assert(i16 == 94 || i16 == 95); + assert(cbtxnsize == 67); + assert(cbextranonceoffset == 49); + assert(!memcmp(cbtxn, "\x01\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xff\xff\xff\xff\x0a\x01\x04\x04\xde\xad\xbe\xef", 49)); + assert(!memcmp(&cbtxn[52], "\x33\x33\x33\x33\x01\0\x10\0\0\x01\x51\0\0\0\0", 67-52)); + assert(branchcount == 2); + assert(!memcmp(branches, "\x0f\xd2\x7c\x1c\x2c\x93\x7c\0\x21\x2d\x90\x3b\x1d\xb1\x05\xc0\xde\xce\x57\x08\x9c\x7c\x93\x80\xdd\x2c\x2f\xe6\x12\xf2\x69\x1c\x2b\x07\x3c\xb8\x85\xbf\x62\x3b\x1c\xd5\xac\xda\x81\xce\xe8\x9f\xe9\x19\x0e\x10\x85\xff\x54\x98\xc3\x33\x4c\x2c\x63\xf8\xdd\x4d", 64)); + free(cbtxn); + free(branches); + + size_t sizeof_dataid = sizeof(unsigned int); + size_t expected_space = sizeof_dataid + 1; + assert(blkmk_get_mdata(tmpl, data, sizeof(data), simple_time_rcvd + 8, &i16, &cbtxn, &cbtxnsize, &cbextranonceoffset, &branchcount, &branches, sizeof_dataid, false)); + assert(!memcmp(data, "\x03\0\0\0\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\x77\x77\x77\xa7\0\0\0\0", 36)); + // Skip merkle root + assert(!memcmp(&data[68], "\x75\x03\0\0\xff\x7f\0\x1d", 8)); + assert(i16 == 90 || i16 == 91); + assert(cbtxnsize == 64 + expected_space); + assert(cbextranonceoffset == 49); + assert(!memcmp(cbtxn, "\x01\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xff\xff\xff\xff", 41)); + assert(cbtxn[41] == 7 + expected_space); + assert(!memcmp(&cbtxn[42], "\x01\x04\x04\xde\xad\xbe\xef", 7)); + assert(!memcmp(&cbtxn[49 + expected_space], "\x33\x33\x33\x33\x01\0\x10\0\0\x01\x51\0\0\0\0", 15)); + assert(branchcount == 2); + assert(!memcmp(branches, "\x0f\xd2\x7c\x1c\x2c\x93\x7c\0\x21\x2d\x90\x3b\x1d\xb1\x05\xc0\xde\xce\x57\x08\x9c\x7c\x93\x80\xdd\x2c\x2f\xe6\x12\xf2\x69\x1c\x2b\x07\x3c\xb8\x85\xbf\x62\x3b\x1c\xd5\xac\xda\x81\xce\xe8\x9f\xe9\x19\x0e\x10\x85\xff\x54\x98\xc3\x33\x4c\x2c\x63\xf8\xdd\x4d", 64)); + free(cbtxn); + free(branches); + + // If hashing fails, so must get_mdata + blkmk_sha256_impl = bad_sha256; + assert(!blkmk_get_mdata(tmpl, data, sizeof(data) - 1, simple_time_rcvd + 8, &i16, &cbtxn, &cbtxnsize, &cbextranonceoffset, &branchcount, &branches, sizeof_dataid, false)); + blkmk_sha256_impl = my_sha256; + + // Buffer too small must fail + assert(!blkmk_get_mdata(tmpl, data, sizeof(data) - 1, simple_time_rcvd + 8, &i16, &cbtxn, &cbtxnsize, &cbextranonceoffset, &branchcount, &branches, sizeof_dataid, false)); + + // Without cb append/set mutations, we must fail too + tmpl->mutations &= ~(BMM_CBAPPEND | BMM_CBSET); + assert(!blkmk_get_mdata(tmpl, data, sizeof(data), simple_time_rcvd + 8, &i16, &cbtxn, &cbtxnsize, &cbextranonceoffset, &branchcount, &branches, sizeof_dataid, false)); + // ... but only one or the other should be sufficient + tmpl->mutations |= BMM_CBAPPEND; + assert(blkmk_get_mdata(tmpl, data, sizeof(data), simple_time_rcvd + 8, &i16, &cbtxn, &cbtxnsize, &cbextranonceoffset, &branchcount, &branches, sizeof_dataid, false)); + free(cbtxn); + free(branches); + tmpl->mutations = (tmpl->mutations & ~BMM_CBAPPEND) | BMM_CBSET; + assert(blkmk_get_mdata(tmpl, data, sizeof(data), simple_time_rcvd + 8, &i16, &cbtxn, &cbtxnsize, &cbextranonceoffset, &branchcount, &branches, sizeof_dataid, false)); + free(cbtxn); + free(branches); + + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"sigoplimit\":100,\"sizelimit\":1000,\"transactions\":[{\"data\":\"01000000019999999999999999999999999999999999999999999999999999999999999999aaaaaaaa00222222220100100000015100000000\",\"required\":true},{\"hash\":\"8eda1a8b67996401a89af8de4edd6715c23a7fb213f9866e18ab9d4367017e8d\",\"data\":\"01000000011c69f212e62f2cdd80937c9c0857cedec005b11d3b902d21007c932c1c7cd20f0000000000444444440100100000015100000000\",\"depends\":[1],\"fee\":12,\"required\":false,\"sigops\":4},{\"data\":\"01000000010099999999999999999999999999999999999999999999999999999999999999aaaaaaaa00555555550100100000015100000000\"}],\"mutable\":[\"coinbase/append\"]}", simple_time_rcvd)); + + // No generation transaction, fail + assert(!blkmk_get_mdata(tmpl, data, sizeof(data), simple_time_rcvd, &i16, &cbtxn, &cbtxnsize, &cbextranonceoffset, &branchcount, &branches, 1, false)); + + // Initialising it should make us work though + assert(blkmk_init_generation(tmpl, NULL, 0) == 640); + assert(blkmk_get_mdata(tmpl, data, sizeof(data), simple_time_rcvd, &i16, &cbtxn, &cbtxnsize, &cbextranonceoffset, &branchcount, &branches, 1, false)); + assert(cbtxn[41] >= 4 /* libblkmaker_coinbase_size_minimum */); + free(cbtxn); + free(branches); + + blktmpl_free(tmpl); +} + int main() { blkmk_sha256_impl = my_sha256; @@ -783,4 +877,7 @@ int main() { puts("blkmk_get_data"); test_blkmk_get_data(); + + puts("blkmk_get_mdata"); + test_blkmk_get_mdata(); } From 07ce01f57a2b810ccc1fb3d4bb5f317e13496c72 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 11 Aug 2016 05:33:56 +0000 Subject: [PATCH 19/28] test: Check blkmk_init_generation --- blkmaker.c | 6 ++++++ test.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/blkmaker.c b/blkmaker.c index cbcb44b..071227b 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -135,6 +135,12 @@ uint64_t blkmk_init_generation3(blktemplate_t * const tmpl, const void * const s return 0; } + if (!tmpl->cbvalue) { + // TODO: Figure it out from the existing cbtxn + *inout_newcb = false; + return 0; + } + *inout_newcb = true; if (scriptsz >= 0xfd) diff --git a/test.c b/test.c index 65dce72..dff9351 100644 --- a/test.c +++ b/test.c @@ -834,6 +834,63 @@ static void test_blkmk_get_mdata() { blktmpl_free(tmpl); } +static void test_blkmk_init_generation() { + blktemplate_t *tmpl; + bool newcb; + + tmpl = blktmpl_create(); + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640}", simple_time_rcvd)); + assert(!tmpl->cbtxn); + assert(blkmk_init_generation(tmpl, NULL, 0) == 640); + assert(tmpl->cbtxn); + assert(tmpl->cbtxn->datasz == 62); + assert(!memcmp(tmpl->cbtxn->data, "\x01\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xff\xff\xff\xff\x02\x01\x04\xff\xff\xff\xff\x01\x80\x02\0\0\0\0\0\0\0\0\0\0\0", tmpl->cbtxn->datasz)); + + newcb = false; + assert(!blkmk_init_generation3(tmpl, "\0", 1, &newcb)); + + newcb = true; + assert(blkmk_init_generation3(tmpl, "\x04" "test", 5, &newcb)); + assert(newcb); + assert(tmpl->cbtxn); + assert(tmpl->cbtxn->datasz == 67); + assert(!memcmp(tmpl->cbtxn->data, "\x01\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xff\xff\xff\xff\x02\x01\x04\xff\xff\xff\xff\x01\x80\x02\0\0\0\0\0\0\x05\x04" "test\0\0\0\0", tmpl->cbtxn->datasz)); + + assert(!blkmk_init_generation2(tmpl, "\0", 1, &newcb)); + assert(!newcb); + + tmpl->mutations &= ~BMM_GENERATE; + newcb = true; + assert(!blkmk_init_generation3(tmpl, "\0", 1, &newcb)); + + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":40000000,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":10000000000}", simple_time_rcvd)); + newcb = false; + assert(blkmk_init_generation3(tmpl, "\x04" "test", 5, &newcb)); + assert(newcb); + assert(tmpl->cbtxn); + assert(tmpl->cbtxn->datasz == 70); + assert(!memcmp(tmpl->cbtxn->data, "\x01\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xff\xff\xff\xff\x05\x04\0\x5a\x62\x02\xff\xff\xff\xff\x01\0\xe4\x0b\x54\x02\0\0\0\x05\x04" "test\0\0\0\0", tmpl->cbtxn->datasz)); + + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":40000000,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000000000\"},\"mutable\":[\"generation\"],\"coinbasevalue\":89064736821248}", simple_time_rcvd)); + newcb = false; + assert(!blkmk_init_generation3(tmpl, "\x04" "test", 5, &newcb)); + assert(!newcb); + newcb = true; + assert(blkmk_init_generation3(tmpl, "\x04" "test", 5, &newcb)); + assert(newcb); + assert(tmpl->cbtxn); + assert(tmpl->cbtxn->datasz == 70); + assert(!memcmp(tmpl->cbtxn->data, "\x01\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xff\xff\xff\xff\x05\x04\0\x5a\x62\x02\xff\xff\xff\xff\x01\0\x10\0\0\x01\x51\0\0\x05\x04" "test\0\0\0\0", tmpl->cbtxn->datasz)); + + blktmpl_free(tmpl); +} + int main() { blkmk_sha256_impl = my_sha256; @@ -880,4 +937,7 @@ int main() { puts("blkmk_get_mdata"); test_blkmk_get_mdata(); + + puts("blkmk_init_generation"); + test_blkmk_init_generation(); } From 4572fcb97be1f08feb11f32423899d9bd59bdf79 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 11 Aug 2016 06:58:50 +0000 Subject: [PATCH 20/28] test: Check acceptance of float-looking numbers, and rejection of JSON missing fields --- test.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 155 insertions(+), 2 deletions(-) diff --git a/test.c b/test.c index dff9351..6382d8d 100644 --- a/test.c +++ b/test.c @@ -205,7 +205,7 @@ static const char *blktmpl_add_jansson_str(blktemplate_t * const tmpl, const cha static const time_t simple_time_rcvd = 0x777; static void blktmpl_jansson_simple() { - blktemplate_t * const tmpl = blktmpl_create(); + blktemplate_t *tmpl = blktmpl_create(); assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":2,\"height\":3,\"bits\":\"1d00ffff\",\"curtime\":777,\"previousblockhash\":\"0000000077777777777777777777777777777777777777777777777777777777\",\"coinbasevalue\":512}", simple_time_rcvd)); assert(tmpl->version == 2); @@ -243,6 +243,26 @@ static void blktmpl_jansson_simple() { assert(tmpl->mintime <= tmpl->curtime - 60); assert(tmpl->mintimeoff <= -60); + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + + assert(blktmpl_add_jansson_str(tmpl, "{\"height\":3,\"bits\":\"1d00ffff\",\"curtime\":777,\"previousblockhash\":\"0000000077777777777777777777777777777777777777777777777777777777\",\"coinbasevalue\":512}", simple_time_rcvd)); + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + assert(blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"bits\":\"1d00ffff\",\"curtime\":777,\"previousblockhash\":\"0000000077777777777777777777777777777777777777777777777777777777\",\"coinbasevalue\":512}", simple_time_rcvd)); + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + assert(blktmpl_add_jansson_str(tmpl, "{\"version\":2,\"height\":3,\"curtime\":777,\"previousblockhash\":\"0000000077777777777777777777777777777777777777777777777777777777\",\"coinbasevalue\":512}", simple_time_rcvd)); + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + assert(blktmpl_add_jansson_str(tmpl, "{\"version\":2,\"height\":3,\"bits\":\"1d00ffff\",\"previousblockhash\":\"0000000077777777777777777777777777777777777777777777777777777777\",\"coinbasevalue\":512}", simple_time_rcvd)); + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + assert(blktmpl_add_jansson_str(tmpl, "{\"version\":2,\"height\":3,\"bits\":\"1d00ffff\",\"curtime\":777,\"coinbasevalue\":512}", simple_time_rcvd)); + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + assert(blktmpl_add_jansson_str(tmpl, "{\"version\":2,\"height\":3,\"bits\":\"1d00ffff\",\"curtime\":777,\"previousblockhash\":\"0000000077777777777777777777777777777777777777777777777777777777\"}", simple_time_rcvd)); + blktmpl_free(tmpl); } @@ -434,6 +454,138 @@ static void blktmpl_jansson_bip9() { blktmpl_free(tmpl); } +static void test_blktmpl_jansson_floaty() { + blktemplate_t *tmpl = blktmpl_create(); + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":536871040.0,\"height\":3.0,\"bits\":\"1d00ffff\",\"curtime\":777.0,\"previousblockhash\":\"0000000077777777777777777777777777777777777777777777777777777777\",\"coinbasevalue\":512.000,\"sigoplimit\":1000.0,\"sizelimit\":10000.0,\"transactions\":[{\"data\":\"01000000019999999999999999999999999999999999999999999999999999999999999999aaaaaaaa00222222220100100000015100000000\"},{\"hash\":\"8eda1a8b67996401a89af8de4edd6715c23a7fb213f9866e18ab9d4367017e8d\",\"data\":\"01000000011c69f212e62f2cdd80937c9c0857cedec005b11d3b902d21007c932c1c7cd20f0000000000444444440100100000015100000000\",\"depends\":[1.0],\"fee\":12.0,\"sigops\":4.0}],\"expires\":33.0,\"maxtime\":2113929216.0,\"maxtimeoff\":50.0,\"mintime\":800.0,\"mintimeoff\":-50.0,\"rules\":[\"csv\"],\"vbavailable\":{\"!segwit\":7.0},\"vbrequired\":128.0}", simple_time_rcvd)); + assert(tmpl->version == 536871040); + assert(tmpl->height == 3); + assert(!memcmp(tmpl->diffbits, "\xff\xff\0\x1d", 4)); + assert(tmpl->curtime == 777); + for (int i = 0; i < 7; ++i) { + assert(tmpl->prevblk[i] == 0x77777777); + } + assert(!tmpl->prevblk[7]); + assert(tmpl->cbvalue == 512); + + assert(tmpl->txncount == 2); + assert(tmpl->txns_datasz == 114); + assert(tmpl->txns_sigops == -1); + assert(tmpl->txns); + assert(tmpl->txns[0].data); + assert(tmpl->txns[0].datasz == 57); + assert(!memcmp(tmpl->txns[0].data, "\x01\0\0\0\x01\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\xaa\xaa\xaa\xaa\0\x22\x22\x22\x22\x01\0\x10\0\0\x01\x51\0\0\0\0", 57)); + assert(tmpl->txns[0].dependscount == -1); + assert(tmpl->txns[0].fee_ == -1); + assert(tmpl->txns[0].sigops_ == -1); + assert(tmpl->txns[1].data); + assert(tmpl->txns[1].datasz == 57); + assert(!memcmp(tmpl->txns[1].data, "\x01\0\0\0\x01\x1c\x69\xf2\x12\xe6\x2f\x2c\xdd\x80\x93\x7c\x9c\x08\x57\xce\xde\xc0\x05\xb1\x1d\x3b\x90\x2d\x21\0\x7c\x93\x2c\x1c\x7c\xd2\x0f\0\0\0\0\0\x44\x44\x44\x44\x01\0\x10\0\0\x01\x51\0\0\0\0", 57)); + assert(tmpl->txns[1].dependscount == 1); + assert(tmpl->txns[1].depends); + assert(tmpl->txns[1].depends[0] == 1); + assert(tmpl->txns[1].fee_ == 12); + assert(!tmpl->txns[1].required); + assert(tmpl->txns[1].sigops_ == 4); + assert(!memcmp(tmpl->txns[1].hash_, "\x8d\x7e\x01\x67\x43\x9d\xab\x18\x6e\x86\xf9\x13\xb2\x7f\x3a\xc2\x15\x67\xdd\x4e\xde\xf8\x9a\xa8\x01\x64\x99\x67\x8b\x1a\xda\x8e", 32)); + + assert(tmpl->rules); + assert(tmpl->rules[0]); + assert(!strcmp(tmpl->rules[0], "csv")); + assert(!tmpl->rules[1]); + assert(!tmpl->unsupported_rule); + assert(tmpl->vbavailable); + assert(tmpl->vbavailable[0]); + assert(tmpl->vbavailable[0]->name); + assert(!strcmp(tmpl->vbavailable[0]->name, "!segwit")); + assert(tmpl->vbavailable[0]->bitnum == 7); + assert(!tmpl->vbavailable[1]); + assert(tmpl->vbrequired == 0x80); + + assert(tmpl->sigoplimit == 1000); + assert(tmpl->sizelimit == 10000); + assert(tmpl->expires == 33); + assert(tmpl->maxtime == 2113929216); + assert(tmpl->maxtimeoff == 50); + assert(tmpl->mintime == 800); + assert(tmpl->mintimeoff == -50); + + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + + // Truncate times (curtime perhaps ought to pull limits closer to it, but it's a fraction of a second anyway, so don't bother) + // Ignore coinbasevalue problems if we have coinbasetxn + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":2.0,\"height\":3.0,\"bits\":\"1d00ffff\",\"curtime\":777.5,\"previousblockhash\":\"0000000077777777777777777777777777777777777777777777777777777777\",\"coinbasevalue\":512.333,\"expires\":33.4,\"maxtime\":2113929216.6,\"maxtimeoff\":50.3,\"mintime\":800.4,\"mintimeoff\":-50.5,\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000000000\"}}", simple_time_rcvd)); + + assert(tmpl->version == 2); + assert(tmpl->height == 3); + assert(!memcmp(tmpl->diffbits, "\xff\xff\0\x1d", 4)); + assert(tmpl->curtime == 777); + for (int i = 0; i < 7; ++i) { + assert(tmpl->prevblk[i] == 0x77777777); + } + assert(!tmpl->prevblk[7]); + assert(!tmpl->cbvalue); + + assert(tmpl->expires == 33); + assert(tmpl->maxtime == 2113929216); + assert(tmpl->maxtimeoff == 50); + assert(tmpl->mintime == 800); + assert(tmpl->mintimeoff == -50); + + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + + // Most values with a fraction should fail + assert(blktmpl_add_jansson_str(tmpl, "{\"version\":2.3,\"height\":3.0,\"bits\":\"1d00ffff\",\"curtime\":777.0,\"previousblockhash\":\"0000000077777777777777777777777777777777777777777777777777777777\",\"coinbasevalue\":512.000}", simple_time_rcvd)); + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + assert(blktmpl_add_jansson_str(tmpl, "{\"version\":2.0,\"height\":3.5,\"bits\":\"1d00ffff\",\"curtime\":777.0,\"previousblockhash\":\"0000000077777777777777777777777777777777777777777777777777777777\",\"coinbasevalue\":512.000}", simple_time_rcvd)); + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + assert(blktmpl_add_jansson_str(tmpl, "{\"version\":2.0,\"height\":3.0,\"bits\":\"1d00ffff\",\"curtime\":777.0,\"previousblockhash\":\"0000000077777777777777777777777777777777777777777777777777777777\",\"coinbasevalue\":512.5}", simple_time_rcvd)); + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + assert(blktmpl_add_jansson_str(tmpl, "{\"version\":536871040.0,\"height\":3.0,\"bits\":\"1d00ffff\",\"curtime\":777.0,\"previousblockhash\":\"0000000077777777777777777777777777777777777777777777777777777777\",\"coinbasevalue\":512.000,\"rules\":[\"csv\"],\"vbavailable\":{\"!segwit\":7.2},\"vbrequired\":128.0}", simple_time_rcvd)); + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + assert(blktmpl_add_jansson_str(tmpl, "{\"version\":536871040.0,\"height\":3.0,\"bits\":\"1d00ffff\",\"curtime\":777.0,\"previousblockhash\":\"0000000077777777777777777777777777777777777777777777777777777777\",\"coinbasevalue\":512.000,\"rules\":[\"csv\"],\"vbavailable\":{\"!segwit\":7.0},\"vbrequired\":128.6}", simple_time_rcvd)); + + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + + // Transaction-related values are optional, so it's safe to ignore them + // Even though they could indicate varying rules, we have BIP9 to deal with that, and don't enforce the limits when missing tx info anyway + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3.0,\"height\":3.0,\"bits\":\"1d00ffff\",\"curtime\":777.0,\"previousblockhash\":\"0000000077777777777777777777777777777777777777777777777777777777\",\"coinbasevalue\":512.000,\"transactions\":[{\"data\":\"01000000019999999999999999999999999999999999999999999999999999999999999999aaaaaaaa00222222220100100000015100000000\"},{\"hash\":\"8eda1a8b67996401a89af8de4edd6715c23a7fb213f9866e18ab9d4367017e8d\",\"data\":\"01000000011c69f212e62f2cdd80937c9c0857cedec005b11d3b902d21007c932c1c7cd20f0000000000444444440100100000015100000000\",\"depends\":[1.5],\"fee\":12.3,\"sigops\":4.6}],\"sigoplimit\":4444.4,\"sizelimit\":323333.3}", simple_time_rcvd)); + + assert(tmpl->version == 3); + assert(tmpl->height == 3); + + // These should be defaults + assert(tmpl->sigoplimit >= 20000); + assert(tmpl->sizelimit >= 1000000); + + assert(tmpl->txncount == 2); + assert(tmpl->txns_datasz == 114); + assert(tmpl->txns_sigops == -1); + assert(tmpl->txns); + assert(tmpl->txns[0].data); + assert(tmpl->txns[0].datasz == 57); + assert(!memcmp(tmpl->txns[0].data, "\x01\0\0\0\x01\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\xaa\xaa\xaa\xaa\0\x22\x22\x22\x22\x01\0\x10\0\0\x01\x51\0\0\0\0", 57)); + assert(tmpl->txns[0].dependscount == -1); + assert(tmpl->txns[0].fee_ == -1); + assert(tmpl->txns[0].sigops_ == -1); + assert(tmpl->txns[1].data); + assert(tmpl->txns[1].datasz == 57); + assert(!memcmp(tmpl->txns[1].data, "\x01\0\0\0\x01\x1c\x69\xf2\x12\xe6\x2f\x2c\xdd\x80\x93\x7c\x9c\x08\x57\xce\xde\xc0\x05\xb1\x1d\x3b\x90\x2d\x21\0\x7c\x93\x2c\x1c\x7c\xd2\x0f\0\0\0\0\0\x44\x44\x44\x44\x01\0\x10\0\0\x01\x51\0\0\0\0", 57)); + assert(tmpl->txns[1].dependscount == -1); + assert(tmpl->txns[1].fee_ == -1); + assert(tmpl->txns[1].sigops_ == -1); + assert(!memcmp(tmpl->txns[1].hash_, "\x8d\x7e\x01\x67\x43\x9d\xab\x18\x6e\x86\xf9\x13\xb2\x7f\x3a\xc2\x15\x67\xdd\x4e\xde\xf8\x9a\xa8\x01\x64\x99\x67\x8b\x1a\xda\x8e", 32)); + + blktmpl_free(tmpl); +} + static void blktmpl_jansson_submit_data_check(const char * const sa, const int level) { assert(strlen(sa) >= 160); assert(!memcmp(sa, "03000000777777a7777777a7777777a7777777a7777777a7777777a7777777a700000000", 72)); @@ -468,7 +620,7 @@ static void blktmpl_jansson_propose() { const char *sa; json_t *j, *ja, *jb; - assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"sigoplimit\":100,\"sizelimit\":1000,\"transactions\":[{\"data\":\"01000000019999999999999999999999999999999999999999999999999999999999999999aaaaaaaa00222222220100100000015100000000\",\"required\":true},{\"hash\":\"8eda1a8b67996401a89af8de4edd6715c23a7fb213f9866e18ab9d4367017e8d\",\"data\":\"01000000011c69f212e62f2cdd80937c9c0857cedec005b11d3b902d21007c932c1c7cd20f0000000000444444440100100000015100000000\",\"depends\":[1],\"fee\":12,\"required\":false,\"sigops\":4},{\"data\":\"01000000010099999999999999999999999999999999999999999999999999999999999999aaaaaaaa00555555550100100000015100000000\"}],\"coinbaseaux\":{\"dummy\":\"deadbeef\"},\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000\"},\"workid\":\"mywork\"}", simple_time_rcvd)); + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"sigoplimit\":100,\"sizelimit\":1000,\"transactions\":[{\"data\":\"01000000019999999999999999999999999999999999999999999999999999999999999999aaaaaaaa00222222220100100000015100000000\",\"required\":true},{\"hash\":\"8eda1a8b67996401a89af8de4edd6715c23a7fb213f9866e18ab9d4367017e8d\",\"data\":\"01000000011c69f212e62f2cdd80937c9c0857cedec005b11d3b902d21007c932c1c7cd20f0000000000444444440100100000015100000000\",\"depends\":[1],\"fee\":12,\"required\":false,\"sigops\":4},{\"data\":\"01000000010099999999999999999999999999999999999999999999999999999999999999aaaaaaaa00555555550100100000015100000000\"}],\"coinbaseaux\":{\"dummy\":\"deadbeef\"},\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000\"},\"workid\":\"mywork\"}", simple_time_rcvd)); assert((j = blktmpl_propose_jansson(tmpl, 0, false))); check_request(j, blkmk_supported_rules, NULL); @@ -919,6 +1071,7 @@ int main() { blktmpl_jansson_bip23_mutations(); blktmpl_jansson_bip23_abbrev(); blktmpl_jansson_bip9(); + test_blktmpl_jansson_floaty(); blktmpl_jansson_propose(); blktmpl_jansson_submit(); blktmpl_jansson_submitm(); From c1a159d4179d5b54b9bcd602a42d93082da738df Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 11 Aug 2016 07:23:08 +0000 Subject: [PATCH 21/28] test: Check blkmk_append_coinbase_safe --- test.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/test.c b/test.c index 6382d8d..bbba7b4 100644 --- a/test.c +++ b/test.c @@ -1043,6 +1043,60 @@ static void test_blkmk_init_generation() { blktmpl_free(tmpl); } +static void test_blkmk_append_coinbase_safe() { + blktemplate_t *tmpl; + static const uint8_t lots_of_zero[100] = {0}; + + tmpl = blktmpl_create(); + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000000000\"}}", simple_time_rcvd)); + // Should fail because we lack coinbase/append mutability + assert(blkmk_append_coinbase_safe(tmpl, "", 1) <= 0); + + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000000000\"},\"mutable\":[\"coinbase/append\"]}", simple_time_rcvd)); + assert(blkmk_append_coinbase_safe(tmpl, "", 1) >= 1); + assert(tmpl->cbtxn); + assert(tmpl->cbtxn->datasz == 68); + assert(!memcmp(tmpl->cbtxn->data, "\x01\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xff\xff\xff\xff\x08\x01\x04\x04\xde\xad\xbe\xef\0\x33\x33\x33\x33\x01\0\x10\0\0\x01\x51\0\0\0\0\0\0\0", tmpl->cbtxn->datasz)); + + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"sigoplimit\":21}", simple_time_rcvd)); + assert(blkmk_init_generation(tmpl, NULL, 0) == 640); + assert(blkmk_append_coinbase_safe(tmpl, "", 1) >= 1); + assert(tmpl->cbtxn); + assert(tmpl->cbtxn->datasz == 63); + assert(!memcmp(tmpl->cbtxn->data, "\x01\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xff\xff\xff\xff\x03\x01\x04\0\xff\xff\xff\xff\x01\x80\x02\0\0\0\0\0\0\0\0\0\0\0", tmpl->cbtxn->datasz)); + + // With 99-byte extranonce, we're already beyond the limit + assert(blkmk_append_coinbase_safe2(tmpl, "", 1, 99, true) <= 0); + // This should just barely break the limit + assert(blkmk_append_coinbase_safe2(tmpl, "", 1, 100 - tmpl->cbtxn->data[41], true) <= 0); + // This should be okay + assert(blkmk_append_coinbase_safe2(tmpl, "", 1, 100 - tmpl->cbtxn->data[41] - 1, true) >= 1); + // Up to 21 sigops is okay + assert(blkmk_append_coinbase_safe2(tmpl, "\xae", 1, 3, true) >= 1); + assert(blkmk_append_coinbase_safe2(tmpl, "\xac", 1, 3, true) >= 1); + // But 22 should hit the limit + assert(blkmk_append_coinbase_safe2(tmpl, "\xac", 1, 3, true) <= 0); + // Non-sigop stuff is fine to continue + assert(blkmk_append_coinbase_safe2(tmpl, "", 1, 3, true) >= 1); + const uint8_t padsz = 100 - tmpl->cbtxn->data[41] - 3; + assert(blkmk_append_coinbase_safe2(tmpl, lots_of_zero, padsz, 3, true) >= padsz); + // One too many + assert(blkmk_append_coinbase_safe2(tmpl, "", 1, 3, true) <= 0); + // Becomes okay if we reduce extranonce size + assert(blkmk_append_coinbase_safe2(tmpl, "", 1, 2, true) >= 1); + assert(blkmk_append_coinbase_safe2(tmpl, lots_of_zero, 2, 0, true) >= 2); + // Totally full now + assert(blkmk_append_coinbase_safe2(tmpl, "", 1, 0, true) <= 0); + + blktmpl_free(tmpl); +} + int main() { blkmk_sha256_impl = my_sha256; @@ -1093,4 +1147,7 @@ int main() { puts("blkmk_init_generation"); test_blkmk_init_generation(); + + puts("blkmk_append_coinbase_safe"); + test_blkmk_append_coinbase_safe(); } From 9bb03c6cf3a0b0155f39d726741d6f15338d5987 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 11 Aug 2016 23:31:02 +0000 Subject: [PATCH 22/28] test: Check against sizelimit and sigoplimit for init_generation and append_coinbase_safe --- test.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/test.c b/test.c index bbba7b4..3686dad 100644 --- a/test.c +++ b/test.c @@ -1040,11 +1040,25 @@ static void test_blkmk_init_generation() { assert(tmpl->cbtxn->datasz == 70); assert(!memcmp(tmpl->cbtxn->data, "\x01\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xff\xff\xff\xff\x05\x04\0\x5a\x62\x02\xff\xff\xff\xff\x01\0\x10\0\0\x01\x51\0\0\x05\x04" "test\0\0\0\0", tmpl->cbtxn->datasz)); + tmpl->sizelimit = 151; + assert(blkmk_init_generation3(tmpl, "\x04" "test", 5, &newcb)); + assert(!blkmk_init_generation3(tmpl, "\x05" "testx", 6, &newcb)); + tmpl->sizelimit = 10000; + tmpl->sigoplimit = 1; + assert(blkmk_init_generation3(tmpl, "\x05" "testx", 6, &newcb)); + assert(blkmk_init_generation3(tmpl, "\x05" "testx\xac", 7, &newcb)); + assert(!blkmk_init_generation3(tmpl, "\x05" "testx\xac\xac", 8, &newcb)); + tmpl->sigoplimit = 21; + assert(blkmk_init_generation3(tmpl, "\x05" "testx\xac\xac", 8, &newcb)); + assert(blkmk_init_generation3(tmpl, "\x05" "testx\xac\xae", 8, &newcb)); + assert(!blkmk_init_generation3(tmpl, "\x05" "testx\xac\xae\xac", 9, &newcb)); + blktmpl_free(tmpl); } static void test_blkmk_append_coinbase_safe() { blktemplate_t *tmpl; + bool newcb; static const uint8_t lots_of_zero[100] = {0}; tmpl = blktmpl_create(); @@ -1074,25 +1088,32 @@ static void test_blkmk_append_coinbase_safe() { // With 99-byte extranonce, we're already beyond the limit assert(blkmk_append_coinbase_safe2(tmpl, "", 1, 99, true) <= 0); // This should just barely break the limit - assert(blkmk_append_coinbase_safe2(tmpl, "", 1, 100 - tmpl->cbtxn->data[41], true) <= 0); + assert(blkmk_append_coinbase_safe2(tmpl, "", 1, 100 - tmpl->cbtxn->data[41], true) == 0); // This should be okay - assert(blkmk_append_coinbase_safe2(tmpl, "", 1, 100 - tmpl->cbtxn->data[41] - 1, true) >= 1); + assert(blkmk_append_coinbase_safe2(tmpl, "", 1, 100 - tmpl->cbtxn->data[41] - 1, true) == 1); // Up to 21 sigops is okay assert(blkmk_append_coinbase_safe2(tmpl, "\xae", 1, 3, true) >= 1); assert(blkmk_append_coinbase_safe2(tmpl, "\xac", 1, 3, true) >= 1); // But 22 should hit the limit - assert(blkmk_append_coinbase_safe2(tmpl, "\xac", 1, 3, true) <= 0); + assert(blkmk_append_coinbase_safe2(tmpl, "\xac", 1, 3, true) < 0); // Non-sigop stuff is fine to continue assert(blkmk_append_coinbase_safe2(tmpl, "", 1, 3, true) >= 1); const uint8_t padsz = 100 - tmpl->cbtxn->data[41] - 3; - assert(blkmk_append_coinbase_safe2(tmpl, lots_of_zero, padsz, 3, true) >= padsz); + assert(blkmk_append_coinbase_safe2(tmpl, lots_of_zero, padsz, 3, true) == padsz); // One too many - assert(blkmk_append_coinbase_safe2(tmpl, "", 1, 3, true) <= 0); + assert(blkmk_append_coinbase_safe2(tmpl, "", 1, 3, true) == 0); // Becomes okay if we reduce extranonce size - assert(blkmk_append_coinbase_safe2(tmpl, "", 1, 2, true) >= 1); - assert(blkmk_append_coinbase_safe2(tmpl, lots_of_zero, 2, 0, true) >= 2); + assert(blkmk_append_coinbase_safe2(tmpl, "", 1, 2, true) == 1); + assert(blkmk_append_coinbase_safe2(tmpl, lots_of_zero, 2, 0, true) == 2); // Totally full now - assert(blkmk_append_coinbase_safe2(tmpl, "", 1, 0, true) <= 0); + assert(blkmk_append_coinbase_safe2(tmpl, "", 1, 0, true) == 0); + + newcb = true; + assert(blkmk_init_generation3(tmpl, NULL, 0, &newcb)); + tmpl->sizelimit = tmpl->cbtxn->datasz + 81 + 5; + assert(blkmk_append_coinbase_safe2(tmpl, "\x04" "test", 5, 0, true) == 5); + assert(blkmk_init_generation3(tmpl, NULL, 0, &newcb)); + assert(blkmk_append_coinbase_safe2(tmpl, "\x05" "testx", 6, 0, true) == 5); blktmpl_free(tmpl); } From fd04e03c5d7afcb6c8e83e8745f64dfba97516bf Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 12 Aug 2016 00:06:38 +0000 Subject: [PATCH 23/28] test: Check varint encoding within reason --- test.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/test.c b/test.c index 3686dad..05e0064 100644 --- a/test.c +++ b/test.c @@ -783,6 +783,48 @@ static void blktmpl_jansson_submitm() { blktmpl_free(tmpl); } +static void test_blkmk_varint_encode_internal(const unsigned long txncount, const char * const expected, const size_t expectedsz) { + blktemplate_t * const tmpl = blktmpl_create(); + const char *sa; + uint8_t data[76]; + int16_t i16; + unsigned int dataid; + json_t *j, *ja, *jb; + + j = json_loads("{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"transactions\":[{\"data\":\"01\"}],\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000\"},\"mutable\":[\"submit/coinbase\"]}", 0, NULL); + assert(j); + assert((ja = json_object_get(j, "transactions"))); + assert((jb = json_array_get(ja, 0))); + for (unsigned int i = 2; i < txncount; ++i) { + assert(!json_array_append(ja, jb)); + } + assert(json_array_size(ja) == txncount - 1); + assert(!blktmpl_add_jansson(tmpl, j, simple_time_rcvd)); + json_decref(j); + + assert(76 == blkmk_get_data(tmpl, data, sizeof(data), simple_time_rcvd, &i16, &dataid)); + + assert((j = blkmk_submit_jansson(tmpl, data, 0, 0x12345678))); + assert((ja = json_object_get(j, "params"))); + assert(json_is_array(ja)); + assert(json_array_size(ja) >= 1); + assert((sa = json_string_value(json_array_get(ja, 0)))); + blktmpl_jansson_submit_data_check(sa, -1); + assert(!memcmp(&sa[160], expected, expectedsz)); // tx count + gentx version + json_decref(j); + + blktmpl_free(tmpl); +} + +static void test_blkmk_varint_encode() { + test_blkmk_varint_encode_internal(4, "0401000000", 10); + test_blkmk_varint_encode_internal(0xfc, "fc01000000", 10); + test_blkmk_varint_encode_internal(0xfd, "fdfd0001000000", 14); + test_blkmk_varint_encode_internal(0xffff, "fdffff01000000", 14); + test_blkmk_varint_encode_internal(0x10000, "fe0000010001000000", 18); + // TODO: Find a way to test 64-bit and upper 32-bit +} + static void test_blkmk_supports_rule() { for (const char **rule = blkmk_supported_rules; *rule; ++rule) { assert(blkmk_supports_rule(*rule)); @@ -1151,6 +1193,9 @@ int main() { blktmpl_jansson_submit(); blktmpl_jansson_submitm(); + puts("blkmk_varint_encode"); + test_blkmk_varint_encode(); + puts("blkmk_supports_rule"); test_blkmk_supports_rule(); From 793d18084772c663b4bcca2eca07b1dd43ab75fc Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 12 Aug 2016 04:16:55 +0000 Subject: [PATCH 24/28] test: Increase coverage of blkmk_address_to_script --- test.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test.c b/test.c index 05e0064..67521ed 100644 --- a/test.c +++ b/test.c @@ -848,6 +848,35 @@ static void test_blkmk_address_to_script() { assert(blkmk_address_to_script(script, sizeof(script), "1BitcoinEaterAddressDontSendf59kuE") == 25); assert(!memcmp(script, "\x76\xa9\x14\x75\x9d\x66\x77\x09\x1e\x97\x3b\x9e\x9d\x99\xf1\x9c\x68\xfb\xf4\x3e\x3f\x05\xf9\x88\xac", 25)); + + assert(blkmk_address_to_script(script, 25, "1QATWksNFGeUJCWBrN4g6hGM178Lovm7Wh") == 25); + assert(!memcmp(script, "\x76\xa9\x14\xfe\x14\xc4\xc6\x8d\x83\xda\x61\xfc\x57\x7b\x04\xcb\x6e\xcb\x6d\x31\xba\x1d\x52\x88\xac", 25)); + + assert(blkmk_address_to_script(script, 23, "3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy") == 23); + assert(!memcmp(script, "\xa9\x14\xb4\x72\xa2\x66\xd0\xbd\x89\xc1\x37\x06\xa4\x13\x2c\xcf\xb1\x6f\x7c\x3b\x9f\xcb\x87", 23)); + + assert(blkmk_address_to_script(script, 25, "1BitcoinEaterAddressDontSendf59kuE") == 25); + assert(!memcmp(script, "\x76\xa9\x14\x75\x9d\x66\x77\x09\x1e\x97\x3b\x9e\x9d\x99\xf1\x9c\x68\xfb\xf4\x3e\x3f\x05\xf9\x88\xac", 25)); + + // Missing last letter + assert(!blkmk_address_to_script(script, sizeof(script), "1QATWksNFGeUJCWBrN4g6hGM178Lovm7W")); + // Extra letters/symbols + assert(!blkmk_address_to_script(script, sizeof(script), "1QATWksNFGeUJCWBrN4g6hGM178Lovm7Whz")); + assert(!blkmk_address_to_script(script, sizeof(script), "1QATWksNFGeUJCWBrN4g6hGM178Lovm7Wh\xff")); + assert(!blkmk_address_to_script(script, sizeof(script), "1QATWksNFGeUJCWBrN4g6hGM178Lovm7Wh\x01")); + assert(!blkmk_address_to_script(script, sizeof(script), "1QATWksNFGeUJCWBrN4g6hGM178Lovm7Wh/")); + // Missing last byte (decoded) + assert(!blkmk_address_to_script(script, sizeof(script), "16FNsF1zNp3bjQuNwgfSdBUwq4CdfGoh")); + // Extra byte (decoded) + assert(!blkmk_address_to_script(script, sizeof(script), "12mEk2LdJmz4PUumptsyDa8ijHU3QS8Hhh1")); + assert(!blkmk_address_to_script(script, sizeof(script), "")); + assert(!blkmk_address_to_script(script, sizeof(script), "\x01")); + assert(!blkmk_address_to_script(script, sizeof(script), "\xff")); + + // Too little buffer space + assert(blkmk_address_to_script(script, 20, "1QATWksNFGeUJCWBrN4g6hGM178Lovm7Wh") == 25); + assert(blkmk_address_to_script(script, 0, "3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy") == 23); + assert(blkmk_address_to_script(script, 24, "1BitcoinEaterAddressDontSendf59kuE") == 25); } static void test_blkmk_x_left() { From 970017ab38f13ae3bfafb4bce1ea4a36069232d6 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 12 Aug 2016 04:25:44 +0000 Subject: [PATCH 25/28] test: Increase coverage of blkmk_count_sigops --- test.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test.c b/test.c index 67521ed..cd4b11c 100644 --- a/test.c +++ b/test.c @@ -1119,10 +1119,20 @@ static void test_blkmk_init_generation() { assert(blkmk_init_generation3(tmpl, "\x05" "testx", 6, &newcb)); assert(blkmk_init_generation3(tmpl, "\x05" "testx\xac", 7, &newcb)); assert(!blkmk_init_generation3(tmpl, "\x05" "testx\xac\xac", 8, &newcb)); + assert(blkmk_init_generation3(tmpl, "\x05" "testx\xac\x4c\0", 9, &newcb)); + assert(blkmk_init_generation3(tmpl, "\x05" "testx\xac\x4c", 8, &newcb)); + assert(blkmk_init_generation3(tmpl, "\x05" "testx\xac\x4d\x01", 9, &newcb)); + assert(blkmk_init_generation3(tmpl, "\x05" "testx\xac\x4e\x01", 9, &newcb)); + assert(blkmk_init_generation3(tmpl, "\x05" "testx\xac\x4e\0\0\0\0", 12, &newcb)); + assert(blkmk_init_generation3(tmpl, "\x4c\x04" "estx\xad", 7, &newcb)); + assert(!blkmk_init_generation3(tmpl, "\x4c\x04" "estx\xad\xad", 8, &newcb)); + assert(!blkmk_init_generation3(tmpl, "\x4c\x04" "estx\xac\xad", 8, &newcb)); tmpl->sigoplimit = 21; assert(blkmk_init_generation3(tmpl, "\x05" "testx\xac\xac", 8, &newcb)); assert(blkmk_init_generation3(tmpl, "\x05" "testx\xac\xae", 8, &newcb)); assert(!blkmk_init_generation3(tmpl, "\x05" "testx\xac\xae\xac", 9, &newcb)); + assert(blkmk_init_generation3(tmpl, "\x4d\x03\0" "stx\xac\xaf", 8, &newcb)); + assert(!blkmk_init_generation3(tmpl, "\x4d\x03\0" "stx\xac\xaf\xac", 9, &newcb)); blktmpl_free(tmpl); } From 31c1d2c1682859f19c8275ff486c399ab914a294 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 12 Aug 2016 04:47:43 +0000 Subject: [PATCH 26/28] test: Increase coverage of blkmk_init_generation --- test.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/test.c b/test.c index cd4b11c..7e9ec80 100644 --- a/test.c +++ b/test.c @@ -1057,6 +1057,19 @@ static void test_blkmk_get_mdata() { blktmpl_free(tmpl); } +static const void *my_memmemr(const void * const haystack_p, const size_t haystacklen, const void * const needle, const size_t needlelen) { + if (needlelen > haystacklen) + return NULL; + const uint8_t * const haystack = haystack_p, *p; + for (ssize_t i = haystacklen - needlelen; i >= 0; --i) { + p = &haystack[i]; + if (!memcmp(p, needle, needlelen)) { + return p; + } + } + return NULL; +} + static void test_blkmk_init_generation() { blktemplate_t *tmpl; bool newcb; @@ -1089,6 +1102,25 @@ static void test_blkmk_init_generation() { blktmpl_free(tmpl); tmpl = blktmpl_create(); + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":40000000,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"coinbaseaux\":{\"dummy\":\"aabbccddeeff0011\"}}", simple_time_rcvd)); + assert(blkmk_init_generation(tmpl, NULL, 0) == 640); + assert(my_memmemr(&tmpl->cbtxn->data[42], tmpl->cbtxn->data[41], "\xaa\xbb\xcc\xdd\xee\xff\0\x11", 8)); + + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":128,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"coinbaseaux\":{\"dummy\":\"aabbccddeeff0011aabbccddeeff0011aabbccddeeff0011aabbccddeeff0011aabbccddeeff0011aabbccddeeff0011aabbccddeeff0011aabbccddeeff0011aabbccddeeff0011aabbccddeeff0011aabbccddeeff0011aabbccddeeff001199\"}}", simple_time_rcvd)); + assert(!blkmk_init_generation(tmpl, NULL, 0)); + tmpl->height = 4; + assert(blkmk_init_generation(tmpl, NULL, 0) == 640); + tmpl->cbvalue = 0; + newcb = true; + // Unknown cbvalue needs to either fail, or figure it out from an existing cbtxn (which we don't support yet) + assert(!blkmk_init_generation3(tmpl, NULL, 0, &newcb)); + + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":40000000,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":10000000000}", simple_time_rcvd)); newcb = false; assert(blkmk_init_generation3(tmpl, "\x04" "test", 5, &newcb)); From 30ba82f339395dfee852507b9a10bfced16a48f6 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 12 Aug 2016 04:51:34 +0000 Subject: [PATCH 27/28] test: Increase coverage of capabilities functions --- test.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test.c b/test.c index 7e9ec80..c12c624 100644 --- a/test.c +++ b/test.c @@ -38,6 +38,8 @@ static void capabilityname_test() { assert(strlen_capname <= BLKTMPL_LONGEST_CAPABILITY_NAME); assert(blktmpl_getcapability(capname) == capid); } + assert(!blktmpl_getcapability("foo")); + assert(!blktmpl_capabilityname((uint32_t)1 << GBT_CAPABILITY_COUNT)); } static void blktxn_test(const int c) { @@ -208,6 +210,7 @@ static void blktmpl_jansson_simple() { blktemplate_t *tmpl = blktmpl_create(); assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":2,\"height\":3,\"bits\":\"1d00ffff\",\"curtime\":777,\"previousblockhash\":\"0000000077777777777777777777777777777777777777777777777777777777\",\"coinbasevalue\":512}", simple_time_rcvd)); + assert(blktmpl_addcaps(tmpl) == 0); // Until we support merging templates assert(tmpl->version == 2); assert(tmpl->height == 3); assert(!memcmp(tmpl->diffbits, "\xff\xff\0\x1d", 4)); From f3659638d7f1fdbff51494aa01b8b7fad39e3116 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 12 Aug 2016 04:54:24 +0000 Subject: [PATCH 28/28] test: Check invalid and uppercase hex data --- test.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test.c b/test.c index c12c624..9096c37 100644 --- a/test.c +++ b/test.c @@ -265,6 +265,12 @@ static void blktmpl_jansson_simple() { blktmpl_free(tmpl); tmpl = blktmpl_create(); assert(blktmpl_add_jansson_str(tmpl, "{\"version\":2,\"height\":3,\"bits\":\"1d00ffff\",\"curtime\":777,\"previousblockhash\":\"0000000077777777777777777777777777777777777777777777777777777777\"}", simple_time_rcvd)); + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + assert(blktmpl_add_jansson_str(tmpl, "{\"version\":2,\"height\":3,\"bits\":\"1d00ffff\",\"curtime\":777,\"previousblockhash\":\"0??0000077777777777777777777777777777777777777777777777777777777\",\"coinbasevalue\":512}", simple_time_rcvd)); + blktmpl_free(tmpl); + tmpl = blktmpl_create(); + assert(blktmpl_add_jansson_str(tmpl, "{\"version\":2,\"height\":3,\"bits\":\"1d00ffff\",\"curtime\":777,\"previousblockhash\":\"00000077777777777777777777777777777777777777777777777777777777\",\"coinbasevalue\":512}", simple_time_rcvd)); blktmpl_free(tmpl); } @@ -272,7 +278,7 @@ static void blktmpl_jansson_simple() { static void blktmpl_jansson_bip22_required() { blktemplate_t * const tmpl = blktmpl_create(); - assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"sigoplimit\":100,\"sizelimit\":1000,\"transactions\":[{\"data\":\"01000000019999999999999999999999999999999999999999999999999999999999999999aaaaaaaa00222222220100100000015100000000\",\"required\":true},{\"hash\":\"8eda1a8b67996401a89af8de4edd6715c23a7fb213f9866e18ab9d4367017e8d\",\"data\":\"01000000011c69f212e62f2cdd80937c9c0857cedec005b11d3b902d21007c932c1c7cd20f0000000000444444440100100000015100000000\",\"depends\":[1],\"fee\":12,\"required\":false,\"sigops\":4},{\"data\":\"01000000010099999999999999999999999999999999999999999999999999999999999999aaaaaaaa00555555550100100000015100000000\"}],\"coinbaseaux\":{\"dummy\":\"deadbeef\"},\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000\"},\"workid\":\"mywork\"}", simple_time_rcvd)); + assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"sigoplimit\":100,\"sizelimit\":1000,\"transactions\":[{\"data\":\"01000000019999999999999999999999999999999999999999999999999999999999999999aaaAaaaa00222222220100100000015100000000\",\"required\":true},{\"hash\":\"8eda1a8b67996401a89af8de4edd6715c23a7fb213f9866e18ab9d4367017e8d\",\"data\":\"01000000011c69f212e62F2cdd80937c9c0857cEDeC005b11d3B902d21007c932c1c7cd20f0000000000444444440100100000015100000000\",\"depends\":[1],\"fee\":12,\"required\":false,\"sigops\":4},{\"data\":\"01000000010099999999999999999999999999999999999999999999999999999999999999aaaaaaaa00555555550100100000015100000000\"}],\"coinbaseaux\":{\"dummy\":\"deadbeef\"},\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000\"},\"workid\":\"mywork\"}", simple_time_rcvd)); assert(tmpl->version == 3); assert(tmpl->height == 4); assert(!memcmp(tmpl->diffbits, "\xff\x7f\0\x1d", 4));