diff --git a/blkmaker.c b/blkmaker.c index 98bc7cc..85a17ab 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -125,19 +125,20 @@ uint64_t blkmk_init_generation3(blktemplate_t * const tmpl, const void * const s return 0; } - struct blktxn_t *txn = calloc(1, sizeof(*tmpl->cbtxn)); + struct blktxn_t *txn = malloc(sizeof(*tmpl->cbtxn)); if (!txn) { free(data); return 0; } + blktxn_init(txn); txn->data = data; txn->datasz = off; if (tmpl->cbtxn) { - _blktxn_free(tmpl->cbtxn); + blktxn_clean(tmpl->cbtxn); free(tmpl->cbtxn); } tmpl->cbtxn = txn; diff --git a/blkmaker_jansson.c b/blkmaker_jansson.c index e5322fa..390b08a 100644 --- a/blkmaker_jansson.c +++ b/blkmaker_jansson.c @@ -8,6 +8,7 @@ #define _BSD_SOURCE #define _DEFAULT_SOURCE +#include #include #include #include @@ -139,9 +140,11 @@ err: static void my_flip(void *, size_t); static -const char *parse_txn(struct blktxn_t *txn, json_t *txnj) { +const char *parse_txn(struct blktxn_t *txn, json_t *txnj, size_t my_tx_index) { json_t *vv; + blktxn_init(txn); + if (!((vv = json_object_get(txnj, "data")) && json_is_string(vv))) return "Missing or invalid type for transaction data"; const char *hexdata = json_string_value(vv); @@ -164,7 +167,61 @@ const char *parse_txn(struct blktxn_t *txn, json_t *txnj) { my_flip(*txn->hash_, sizeof(*txn->hash_)); } - // TODO: dependcount/depends, fee, required, sigops + if ((vv = json_object_get(txnj, "depends")) && json_is_array(vv)) { + size_t depcount = json_array_size(vv); + if (depcount <= LONG_MAX) { + json_t *v; + long i; + double f; + unsigned long ul; + + txn->depends = malloc(sizeof(*txn->depends) * depcount); + for (i = 0; i < depcount; ++i) { + v = json_array_get(vv, i); + if (!json_is_number(v)) { + break; + } + f = json_number_value(v); + ul = f; + if (f != ul || ul >= my_tx_index) { + // Out of range for storage type, fractional number, forward dependency, etc + break; + } + txn->depends[i] = ul; + } + if (i != depcount) { + // We failed somewhere + free(txn->depends); + txn->depends = NULL; + } else { + // Success, finish up with storing the count + txn->dependscount = depcount; + } + } + } + + if ((vv = json_object_get(txnj, "fee")) && json_is_number(vv)) { + double f; + int64_t i64; + + f = json_number_value(vv); + i64 = f; + if (i64 == f && i64 >= 0) { + txn->fee_ = i64; + } + } + + if ((vv = json_object_get(txnj, "required")) && json_is_true(vv)) { + txn->required = true; + } + + if ((vv = json_object_get(txnj, "sigops")) && json_is_number(vv)) { + const double f = json_number_value(vv); + int16_t i16 = f; + if (i16 == f && i16 >= 0) { + txn->sigops_ = i16; + } + } return NULL; } @@ -224,12 +281,12 @@ const char *blktmpl_add_jansson(blktemplate_t *tmpl, const json_t *json, time_t v = json_object_get(json, "transactions"); size_t txns = tmpl->txncount = json_array_size(v); - tmpl->txns = calloc(txns, sizeof(*tmpl->txns)); + tmpl->txns = malloc(txns * sizeof(*tmpl->txns)); tmpl->txns_datasz = 0; for (size_t i = 0; i < txns; ++i) { struct blktxn_t * const txn = &tmpl->txns[i]; - if ((s = parse_txn(txn, json_array_get(v, i)))) { + if ((s = parse_txn(txn, json_array_get(v, i), i + 1))) { return s; } tmpl->txns_datasz += txn->datasz; @@ -237,8 +294,8 @@ const char *blktmpl_add_jansson(blktemplate_t *tmpl, const json_t *json, time_t if ((v = json_object_get(json, "coinbasetxn")) && json_is_object(v)) { - tmpl->cbtxn = calloc(1, sizeof(*tmpl->cbtxn)); - if ((s = parse_txn(tmpl->cbtxn, v))) + tmpl->cbtxn = malloc(sizeof(*tmpl->cbtxn)); + if ((s = parse_txn(tmpl->cbtxn, v, 0))) return s; } diff --git a/blktemplate.c b/blktemplate.c index 055cc69..d39bd74 100644 --- a/blktemplate.c +++ b/blktemplate.c @@ -58,6 +58,20 @@ gbt_capabilities_t blktmpl_getcapability(const char *n) { return 0; } +void blktxn_init(struct blktxn_t * const txn) { + txn->data = NULL; + txn->datasz = 0; + txn->hash = NULL; + txn->hash_ = NULL; + + txn->dependscount = -1; + txn->depends = NULL; + + txn->fee_ = -1; + txn->required = false; + txn->sigops_ = -1; +} + blktemplate_t *blktmpl_create() { blktemplate_t *tmpl; tmpl = calloc(1, sizeof(*tmpl)); @@ -94,13 +108,12 @@ bool blktmpl_get_submitold(blktemplate_t *tmpl) { return tmpl->submitold; } -void _blktxn_free(struct blktxn_t *bt) { +void blktxn_clean(struct blktxn_t * const bt) { free(bt->data); free(bt->hash); free(bt->hash_); free(bt->depends); } -#define blktxn_free _blktxn_free static void blkaux_clean(struct blkaux_t * const aux) { @@ -110,11 +123,11 @@ void blkaux_clean(struct blkaux_t * const aux) { void blktmpl_free(blktemplate_t *tmpl) { for (unsigned long i = 0; i < tmpl->txncount; ++i) - blktxn_free(&tmpl->txns[i]); + blktxn_clean(&tmpl->txns[i]); free(tmpl->txns); if (tmpl->cbtxn) { - blktxn_free(tmpl->cbtxn); + blktxn_clean(tmpl->cbtxn); free(tmpl->cbtxn); } free(tmpl->_mrklbranch); diff --git a/blktemplate.h b/blktemplate.h index c7a3abf..e675bee 100644 --- a/blktemplate.h +++ b/blktemplate.h @@ -33,12 +33,12 @@ struct blktxn_t { // NOTE: The byte order of hash is backward; use hash_ instead txnhash_t *hash; - signed long dependcount; + signed long dependscount; unsigned long *depends; - uint64_t fee; + int64_t fee_; bool required; - int16_t sigops; + int16_t sigops_; txnhash_t *hash_; }; @@ -141,6 +141,9 @@ typedef struct { unsigned long txns_datasz; } blktemplate_t; +extern void blktxn_init(struct blktxn_t *); +extern void blktxn_clean(struct blktxn_t *); + extern blktemplate_t *blktmpl_create(); extern uint32_t blktmpl_addcaps(const blktemplate_t *); extern const struct blktmpl_longpoll_req *blktmpl_get_longpoll(blktemplate_t *); diff --git a/private.h b/private.h index 550c35d..6080ec2 100644 --- a/private.h +++ b/private.h @@ -11,9 +11,6 @@ extern bool _blkmk_dblsha256(void *hash, const void *data, size_t datasz); extern bool blkmk_sample_data_(blktemplate_t *, uint8_t *, unsigned int dataid); extern char *blkmk_assemble_submission2_(blktemplate_t *, const unsigned char *data, const void *extranonce, size_t extranoncesz, unsigned int dataid, blknonce_t nonce, bool foreign); -// blktemplate.c -extern void _blktxn_free(struct blktxn_t *); - // hex.c extern void _blkmk_bin2hex(char *out, const void *data, size_t datasz); extern bool _blkmk_hex2bin(void *o, const char *x, size_t len);