Optimise merkle root creation by reusing a merkle branch
This commit is contained in:
73
blkmaker.c
73
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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
12
private.h
12
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
|
||||
|
||||
Reference in New Issue
Block a user