diff --git a/blkmaker.c b/blkmaker.c index db48a80..b1e1c2e 100644 --- a/blkmaker.c +++ b/blkmaker.c @@ -124,30 +124,87 @@ uint64_t blkmk_init_generation(blktemplate_t *tmpl, void *script, size_t scripts } static -bool build_merkle_root(unsigned char *mrklroot_out, blktemplate_t *tmpl, unsigned char *cbtxndata, size_t cbtxndatasz) { +bool blkmk_hash_transactions(blktemplate_t * const tmpl) +{ + for (unsigned long i = 0; i < tmpl->txncount; ++i) + { + struct blktxn_t * const txn = &tmpl->txns[i]; + if (txn->hash_) + continue; + txn->hash_ = malloc(sizeof(*txn->hash_)); + if (!dblsha256(txn->hash_, txn->data, txn->datasz)) + { + free(txn->hash_); + return false; + } + } + return true; +} + +static +bool blkmk_build_merkle_branches(blktemplate_t * const tmpl) +{ + int branchcount, i; + libblkmaker_hash_t *branches; + + if (tmpl->_mrklbranch) + return true; + + if (!blkmk_hash_transactions(tmpl)) + return false; + + branchcount = blkmk_flsl(tmpl->txncount); + branches = malloc(branchcount * sizeof(*branches)); + size_t hashcount = tmpl->txncount + 1; unsigned char hashes[(hashcount + 1) * 32]; - if (!dblsha256(&hashes[0], cbtxndata, cbtxndatasz)) - return false; - for (unsigned long i = 0; i < tmpl->txncount; ++i) - if (!dblsha256(&hashes[32 * (i + 1)], tmpl->txns[i].data, tmpl->txns[i].datasz)) - return false; + for (i = 0; i < tmpl->txncount; ++i) + memcpy(&hashes[0x20 * (i + 1)], tmpl->txns[i].hash_, 0x20); - while (hashcount > 1) + for (i = 0; i < branchcount; ++i) { + memcpy(&branches[i], &hashes[0x20], 0x20); if (hashcount % 2) { memcpy(&hashes[32 * hashcount], &hashes[32 * (hashcount - 1)], 32); ++hashcount; } - for (size_t i = 0; i < hashcount; i += 2) + for (size_t i = 2; i < hashcount; i += 2) // This is where we overlap input and output, on the first pair if (!dblsha256(&hashes[i / 2 * 32], &hashes[32 * i], 64)) + { + free(branches); return false; + } hashcount /= 2; } + tmpl->_mrklbranch = branches; + tmpl->_mrklbranchcount = branchcount; + + return true; +} + +static +bool build_merkle_root(unsigned char *mrklroot_out, blktemplate_t *tmpl, unsigned char *cbtxndata, size_t cbtxndatasz) { + int i; + libblkmaker_hash_t hashes[0x40]; + + if (!blkmk_build_merkle_branches(tmpl)) + return false; + + if (!dblsha256(&hashes[0], cbtxndata, cbtxndatasz)) + return false; + + for (i = 0; i < tmpl->_mrklbranchcount; ++i) + { + memcpy(&hashes[1], tmpl->_mrklbranch[i], 0x20); + // This is where we overlap input and output, on the first pair + if (!dblsha256(&hashes[0], &hashes[0], 0x40)) + return false; + } + memcpy(mrklroot_out, &hashes[0], 32); return true; diff --git a/blktemplate.c b/blktemplate.c index a368be0..83d8292 100644 --- a/blktemplate.c +++ b/blktemplate.c @@ -110,6 +110,7 @@ void blktmpl_free(blktemplate_t *tmpl) { blktxn_free(tmpl->cbtxn); free(tmpl->cbtxn); } + free(tmpl->_mrklbranch); // TODO: maybe free auxnames[0..n]? auxdata too free(tmpl->auxnames); free(tmpl->auxdata); diff --git a/blktemplate.h b/blktemplate.h index 9239778..8b832c5 100644 --- a/blktemplate.h +++ b/blktemplate.h @@ -120,6 +120,8 @@ typedef struct { blknonce_t maxnonce; // TEMPORARY HACK + libblkmaker_hash_t *_mrklbranch; + int _mrklbranchcount; libblkmaker_hash_t _mrklroot; unsigned int next_dataid; } blktemplate_t; diff --git a/private.h b/private.h index 33e4c7f..f0e437a 100644 --- a/private.h +++ b/private.h @@ -18,4 +18,16 @@ extern bool _blkmk_hex2bin(void *o, const char *x, size_t len); extern bool _blkmk_b58tobin(void *bin, size_t binsz, const char *b58, size_t b58sz); extern int _blkmk_b58check(void *bin, size_t binsz, const char *b58); +// inline + +// NOTE: This must return 0 for 0 +static inline +int blkmk_flsl(unsigned long n) +{ + int i; + for (i = 0; n; ++i) + n >>= 1; + return i; +} + #endif