From 1e495560780fc411dffece51542695e35a5642cb Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 27 Apr 2016 05:53:37 +0000 Subject: [PATCH 1/4] Implement BIP 9 template request "rules" parameter --- blkmaker.c | 4 ++++ blkmaker_jansson.c | 27 ++++++++++++++++++++++++++- private.h | 1 + 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/blkmaker.c b/blkmaker.c index d7bfcaa..f7d325c 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -18,6 +18,10 @@ #include "private.h" +const char *blkmk_supported_rules[] = { + NULL +}; + static inline void my_htole32(unsigned char *buf, uint32_t n) { buf[0] = (n >> 0) % 256; diff --git a/blkmaker_jansson.c b/blkmaker_jansson.c index 6588978..ecbc52d 100644 --- a/blkmaker_jansson.c +++ b/blkmaker_jansson.c @@ -28,7 +28,8 @@ # error "Jansson 2.0 with long long support required!" #endif -json_t *blktmpl_request_jansson(gbt_capabilities_t caps, const char *lpid) { +static +json_t *blktmpl_request_jansson2(const uint32_t caps, const char * const lpid, const char * const * const rulelist) { json_t *req, *jcaps, *jstr, *reqf, *reqa; if (!(req = json_object())) return NULL; @@ -67,6 +68,26 @@ json_t *blktmpl_request_jansson(gbt_capabilities_t caps, const char *lpid) { if (json_object_set_new(req, "longpollid", jstr)) goto err; } + jstr = NULL; + + // Add rules list + if (!(jcaps = json_array())) { + goto err; + } + for (const char * const *currule = rulelist; *currule; ++currule) { + if (!(jstr = json_string(*currule))) { + goto err; + } + if (json_array_append_new(jcaps, jstr)) { + goto err; + } + } + jstr = NULL; + if (json_object_set_new(req, "rules", jcaps)) + goto err; + jcaps = NULL; + + // Put together main JSON-RPC request Object if (!(jstr = json_string("getblocktemplate"))) goto err; if (json_object_set_new(reqf, "method", jstr)) @@ -89,6 +110,10 @@ err: return NULL; } +json_t *blktmpl_request_jansson(gbt_capabilities_t caps, const char *lpid) { + return blktmpl_request_jansson2(caps, lpid, blkmk_supported_rules); +} + #define my_hex2bin _blkmk_hex2bin diff --git a/private.h b/private.h index 7908739..14eacf1 100644 --- a/private.h +++ b/private.h @@ -5,6 +5,7 @@ #include // blkmaker.c +extern const char *blkmk_supported_rules[]; extern bool _blkmk_dblsha256(void *hash, const void *data, size_t datasz); // blktemplate.c From ae7055df8bbb72dd42dcb6a8d1440ca87da6b0f3 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Sun, 22 May 2016 13:33:34 +0000 Subject: [PATCH 2/4] Parse BIP 9 template fields, and implement handling of unrecognised rules --- blkmaker.c | 9 +++++++ blkmaker.h | 3 ++- blkmaker_jansson.c | 62 ++++++++++++++++++++++++++++++++++++++++++++-- blktemplate.c | 15 +++++++++++ blktemplate.h | 10 ++++++++ private.h | 1 + 6 files changed, 97 insertions(+), 3 deletions(-) diff --git a/blkmaker.c b/blkmaker.c index f7d325c..e1acd6d 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -22,6 +22,15 @@ const char *blkmk_supported_rules[] = { NULL }; +bool blkmk_supports_rule(const char * const rulename) { + for (const char **r = blkmk_supported_rules; *r; ++r) { + if (!strcmp(rulename, *r)) { + return true; + } + } + return false; +} + static inline void my_htole32(unsigned char *buf, uint32_t n) { buf[0] = (n >> 0) % 256; diff --git a/blkmaker.h b/blkmaker.h index 4c2a7d6..809ec6b 100644 --- a/blkmaker.h +++ b/blkmaker.h @@ -8,7 +8,8 @@ #include #define BLKMAKER_VERSION (5L) -#define BLKMAKER_MAX_BLOCK_VERSION (4) +#define BLKMAKER_MAX_BLOCK_VERSION (0x3fffffff) +#define BLKMAKER_MAX_PRERULES_BLOCK_VERSION (4) extern bool (*blkmk_sha256_impl)(void *hash_out, const void *data, size_t datasz); diff --git a/blkmaker_jansson.c b/blkmaker_jansson.c index ecbc52d..cbce12f 100644 --- a/blkmaker_jansson.c +++ b/blkmaker_jansson.c @@ -251,10 +251,68 @@ const char *blktmpl_add_jansson(blktemplate_t *tmpl, const json_t *json, time_t } } - if (tmpl->version > BLKMAKER_MAX_BLOCK_VERSION || (tmpl->version >= 2 && !tmpl->height)) + if ((tmpl->version & 0xe0000000) == 0x20000000 && (v = json_object_get(json, "vbavailable")) && json_is_object(v) && (v = json_object_get(json, "rules")) && json_is_array(v)) { + // calloc so that a failure doesn't result in freeing a random pointer + size_t n = json_array_size(v); + tmpl->rules = calloc(n + 1, sizeof(*tmpl->rules)); + for (size_t i = 0; i < n; ++i) { + v2 = json_array_get(v, i); + if (!json_is_string(v2)) { + return "Non-String data in template rules list"; + } + s = json_string_value(v2); + if (s[0] == '!') { + ++s; + if (!blkmk_supports_rule(s)) { + return "Unsupported rule strictly required by template"; + } + } else { + if (!blkmk_supports_rule(s)) { + tmpl->unsupported_rule = true; + } + } + tmpl->rules[i] = strdup(s); + if (!tmpl->rules[i]) { + return "Memory allocation error parsing rules"; + } + } + + v = json_object_get(json, "vbavailable"); + n = json_object_size(v); + tmpl->vbavailable = calloc(n + 1, sizeof(*tmpl->vbavailable)); + struct blktmpl_vbassoc **cur_vbassoc = tmpl->vbavailable; + for (void *iter = json_object_iter(v); iter; (iter = json_object_iter_next(v, iter)), ++cur_vbassoc) { + v2 = json_object_iter_value(iter); + if (!json_is_number(v2)) { + return "Invalid type for vbavailable bit"; + } + double bitnum = json_number_value(v2); + if (bitnum < 0 || bitnum > 28 || (unsigned)bitnum != bitnum) { + return "Invalid bit number in vbavailable"; + } + *cur_vbassoc = malloc(sizeof(**cur_vbassoc)); + if (!*cur_vbassoc) { + return "Memory allocation error for struct blktmpl_vbassoc"; + } + **cur_vbassoc = (struct blktmpl_vbassoc){ + .name = strdup(json_object_iter_key(iter)), + .bitnum = bitnum, + }; + if (!(*cur_vbassoc)->name) { + return "Memory allocation error for vbavailable name"; + } + } + + v = json_object_get(json, "vbrequired"); + if (v && json_is_number(v)) { + tmpl->vbrequired = json_number_value(v); + } + } + else + if (tmpl->version > BLKMAKER_MAX_PRERULES_BLOCK_VERSION || (tmpl->version >= 2 && !tmpl->height)) { if (tmpl->mutations & BMM_VERDROP) - tmpl->version = tmpl->height ? BLKMAKER_MAX_BLOCK_VERSION : 1; + tmpl->version = tmpl->height ? BLKMAKER_MAX_PRERULES_BLOCK_VERSION : 1; else if (!(tmpl->mutations & BMM_VERFORCE)) return "Unrecognized block version, and not allowed to reduce or force it"; diff --git a/blktemplate.c b/blktemplate.c index f70f30f..fd990b7 100644 --- a/blktemplate.c +++ b/blktemplate.c @@ -117,5 +117,20 @@ void blktmpl_free(blktemplate_t *tmpl) { free(tmpl->workid); free(tmpl->lp.id); free(tmpl->lp.uri); + + if (tmpl->rules) { + for (char **currule = tmpl->rules; *currule; ++currule) { + free(*currule); + } + free(tmpl->rules); + } + if (tmpl->vbavailable) { + for (struct blktmpl_vbassoc **curvb = tmpl->vbavailable; *curvb; ++curvb) { + free((*curvb)->name); + free(*curvb); + } + free(tmpl->vbavailable); + } + free(tmpl); } diff --git a/blktemplate.h b/blktemplate.h index 263976a..83b92ee 100644 --- a/blktemplate.h +++ b/blktemplate.h @@ -78,6 +78,11 @@ extern gbt_capabilities_t blktmpl_getcapability(const char *); typedef gbt_capabilities_t blkmutations_t; +struct blktmpl_vbassoc { + char *name; + uint8_t bitnum; +}; + // WARNING: Do not allocate this (ABI is not guaranteed to remain fixed-size) typedef struct { uint32_t version; @@ -123,6 +128,11 @@ typedef struct { int _mrklbranchcount; libblkmaker_hash_t _mrklroot; unsigned int next_dataid; + + char **rules; + bool unsupported_rule; + struct blktmpl_vbassoc **vbavailable; + uint32_t vbrequired; } blktemplate_t; extern blktemplate_t *blktmpl_create(); diff --git a/private.h b/private.h index 14eacf1..055061b 100644 --- a/private.h +++ b/private.h @@ -7,6 +7,7 @@ // blkmaker.c extern const char *blkmk_supported_rules[]; extern bool _blkmk_dblsha256(void *hash, const void *data, size_t datasz); +extern bool blkmk_supports_rule(const char *rulename); // blktemplate.c extern void _blktxn_free(struct blktxn_t *); From f658eabf5ed466f49cae2cdf675be4a6867c8b44 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Sun, 22 May 2016 16:45:03 +0000 Subject: [PATCH 3/4] "csv" deployment requires no particular changes, so add it to supported rules --- blkmaker.c | 1 + 1 file changed, 1 insertion(+) diff --git a/blkmaker.c b/blkmaker.c index e1acd6d..a59d6c4 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -19,6 +19,7 @@ #include "private.h" const char *blkmk_supported_rules[] = { + "csv", NULL }; From 0d8212c1dcf9dab28d749c08bd107ce0f06d45e3 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 25 May 2016 03:55:31 +0000 Subject: [PATCH 4/4] Make new BIP 9 features public --- blkmaker.h | 3 +++ blkmaker_jansson.c | 1 - blkmaker_jansson.h | 1 + private.h | 2 -- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/blkmaker.h b/blkmaker.h index 9d95634..0a0895c 100644 --- a/blkmaker.h +++ b/blkmaker.h @@ -15,6 +15,9 @@ extern "C" { #define BLKMAKER_MAX_BLOCK_VERSION (0x3fffffff) #define BLKMAKER_MAX_PRERULES_BLOCK_VERSION (4) +extern const char *blkmk_supported_rules[]; +extern bool blkmk_supports_rule(const char *rulename); + extern bool (*blkmk_sha256_impl)(void *hash_out, const void *data, size_t datasz); extern uint64_t blkmk_init_generation(blktemplate_t *, void *script, size_t scriptsz); diff --git a/blkmaker_jansson.c b/blkmaker_jansson.c index f154e34..c3f436d 100644 --- a/blkmaker_jansson.c +++ b/blkmaker_jansson.c @@ -22,7 +22,6 @@ # error "Jansson 2.0 with long long support required!" #endif -static json_t *blktmpl_request_jansson2(const uint32_t caps, const char * const lpid, const char * const * const rulelist) { json_t *req, *jcaps, *jstr, *reqf, *reqa; if (!(req = json_object())) diff --git a/blkmaker_jansson.h b/blkmaker_jansson.h index 6308488..8c9ad1d 100644 --- a/blkmaker_jansson.h +++ b/blkmaker_jansson.h @@ -10,6 +10,7 @@ extern "C" { #endif extern json_t *blktmpl_request_jansson(uint32_t extracaps, const char *lpid); +extern json_t *blktmpl_request_jansson2(uint32_t extracaps, const char *lpid, const char * const *rulelist); extern const char *blktmpl_add_jansson(blktemplate_t *, const json_t *, time_t time_rcvd); extern json_t *blktmpl_propose_jansson(blktemplate_t *, uint32_t caps, bool foreign); extern json_t *blkmk_submit_jansson(blktemplate_t *, const unsigned char *data, unsigned int dataid, blknonce_t); diff --git a/private.h b/private.h index 60ca9c3..550c35d 100644 --- a/private.h +++ b/private.h @@ -7,9 +7,7 @@ #include // blkmaker.c -extern const char *blkmk_supported_rules[]; extern bool _blkmk_dblsha256(void *hash, const void *data, size_t datasz); -extern bool blkmk_supports_rule(const char *rulename); extern bool blkmk_sample_data_(blktemplate_t *, uint8_t *, unsigned int dataid); extern char *blkmk_assemble_submission2_(blktemplate_t *, const unsigned char *data, const void *extranonce, size_t extranoncesz, unsigned int dataid, blknonce_t nonce, bool foreign);