Merge branch 'bip9' into 0.5.x
This commit is contained in:
14
blkmaker.c
14
blkmaker.c
@@ -24,6 +24,20 @@
|
|||||||
|
|
||||||
#include "private.h"
|
#include "private.h"
|
||||||
|
|
||||||
|
const char *blkmk_supported_rules[] = {
|
||||||
|
"csv",
|
||||||
|
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
|
static inline
|
||||||
void my_htole32(unsigned char *buf, uint32_t n) {
|
void my_htole32(unsigned char *buf, uint32_t n) {
|
||||||
buf[0] = (n >> 0) % 256;
|
buf[0] = (n >> 0) % 256;
|
||||||
|
|||||||
@@ -12,7 +12,11 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define BLKMAKER_VERSION (7L)
|
#define BLKMAKER_VERSION (7L)
|
||||||
#define BLKMAKER_MAX_BLOCK_VERSION (4)
|
#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 bool (*blkmk_sha256_impl)(void *hash_out, const void *data, size_t datasz);
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
# error "Jansson 2.0 with long long support required!"
|
# error "Jansson 2.0 with long long support required!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
json_t *blktmpl_request_jansson(const uint32_t caps, const char * const lpid) {
|
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;
|
json_t *req, *jcaps, *jstr, *reqf, *reqa;
|
||||||
if (!(req = json_object()))
|
if (!(req = json_object()))
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -62,6 +62,26 @@ json_t *blktmpl_request_jansson(const uint32_t caps, const char * const lpid) {
|
|||||||
if (json_object_set_new(req, "longpollid", jstr))
|
if (json_object_set_new(req, "longpollid", jstr))
|
||||||
goto err;
|
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")))
|
if (!(jstr = json_string("getblocktemplate")))
|
||||||
goto err;
|
goto err;
|
||||||
if (json_object_set_new(reqf, "method", jstr))
|
if (json_object_set_new(reqf, "method", jstr))
|
||||||
@@ -84,6 +104,10 @@ err:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
json_t *blktmpl_request_jansson(const uint32_t caps, const char * const lpid) {
|
||||||
|
return blktmpl_request_jansson2(caps, lpid, blkmk_supported_rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define my_hex2bin _blkmk_hex2bin
|
#define my_hex2bin _blkmk_hex2bin
|
||||||
|
|
||||||
@@ -283,10 +307,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)
|
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
|
else
|
||||||
if (!(tmpl->mutations & BMM_VERFORCE))
|
if (!(tmpl->mutations & BMM_VERFORCE))
|
||||||
return "Unrecognized block version, and not allowed to reduce or force it";
|
return "Unrecognized block version, and not allowed to reduce or force it";
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern json_t *blktmpl_request_jansson(uint32_t extracaps, const char *lpid);
|
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 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 *blktmpl_propose_jansson(blktemplate_t *, uint32_t caps, bool foreign);
|
||||||
extern json_t *blkmk_submit_jansson(blktemplate_t *, const unsigned char *data, unsigned int dataid, blknonce_t);
|
extern json_t *blkmk_submit_jansson(blktemplate_t *, const unsigned char *data, unsigned int dataid, blknonce_t);
|
||||||
|
|||||||
@@ -125,5 +125,20 @@ void blktmpl_free(blktemplate_t *tmpl) {
|
|||||||
free(tmpl->target);
|
free(tmpl->target);
|
||||||
free(tmpl->lp.id);
|
free(tmpl->lp.id);
|
||||||
free(tmpl->lp.uri);
|
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);
|
free(tmpl);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,6 +93,11 @@ extern gbt_capabilities_t blktmpl_getcapability(const char *);
|
|||||||
|
|
||||||
typedef gbt_capabilities_t blkmutations_t;
|
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)
|
// WARNING: Do not allocate this (ABI is not guaranteed to remain fixed-size)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
@@ -139,6 +144,11 @@ typedef struct {
|
|||||||
struct blkaux_t *auxs;
|
struct blkaux_t *auxs;
|
||||||
|
|
||||||
unsigned long txns_datasz;
|
unsigned long txns_datasz;
|
||||||
|
|
||||||
|
char **rules;
|
||||||
|
bool unsupported_rule;
|
||||||
|
struct blktmpl_vbassoc **vbavailable;
|
||||||
|
uint32_t vbrequired;
|
||||||
} blktemplate_t;
|
} blktemplate_t;
|
||||||
|
|
||||||
extern blktemplate_t *blktmpl_create();
|
extern blktemplate_t *blktmpl_create();
|
||||||
|
|||||||
Reference in New Issue
Block a user