merkleblock/utils: optimize merkle root calculation.

This commit is contained in:
Christopher Jeffrey 2016-07-27 06:28:28 -07:00
parent 868512e054
commit 4e977810ce
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
3 changed files with 47 additions and 17 deletions

View File

@ -25,8 +25,11 @@ node.open(function(err) {
if (process.argv.indexOf('--test') !== -1) { if (process.argv.indexOf('--test') !== -1) {
node.pool.watchAddress('1VayNert3x1KzbpzMGt2qdqrAThiRovi8'); node.pool.watchAddress('1VayNert3x1KzbpzMGt2qdqrAThiRovi8');
node.on('tx', function(tx) { node.pool.watch(bcoin.outpoint().toRaw());
utils.log(tx); node.on('block', function(block) {
assert(block.txs.length >= 1);
if (block.txs.length > 1)
utils.log(block.txs[1]);
}); });
} }

View File

@ -429,17 +429,26 @@ crypto.ccmp = function ccmp(a, b) {
crypto.buildMerkleTree = function buildMerkleTree(leaves) { crypto.buildMerkleTree = function buildMerkleTree(leaves) {
var tree = leaves.slice(); var tree = leaves.slice();
var size = leaves.length; var size = leaves.length;
var i, j, i2, hash; var i, j, i2, hash, left, right, buf;
if (size > 1)
buf = new Buffer(64);
for (j = 0; size > 1; size = ((size + 1) / 2) | 0) { for (j = 0; size > 1; size = ((size + 1) / 2) | 0) {
for (i = 0; i < size; i += 2) { for (i = 0; i < size; i += 2) {
i2 = Math.min(i + 1, size - 1); i2 = Math.min(i + 1, size - 1);
left = tree[j + i];
right = tree[j + i2];
if (i2 === i + 1 && i2 + 1 === size if (i2 === i + 1 && i2 + 1 === size
&& tree[j + i].compare(tree[j + i2]) === 0) { && left.compare(right) === 0) {
return; return;
} }
hash = Buffer.concat([tree[j + i], tree[j + i2]]);
hash = crypto.hash256(hash); left.copy(buf, 0);
right.copy(buf, 32);
hash = crypto.hash256(buf);
tree.push(hash); tree.push(hash);
} }
j += size; j += size;
@ -498,19 +507,25 @@ crypto.getMerkleBranch = function getMerkleBranch(index, leaves) {
*/ */
crypto.checkMerkleBranch = function checkMerkleBranch(hash, branch, index) { crypto.checkMerkleBranch = function checkMerkleBranch(hash, branch, index) {
var otherside, i; var i, otherside, buf;
if (index === -1) if (branch.length === 0)
return false; return hash;
buf = new Buffer(64);
for (i = 0; i < branch.length; i++) { for (i = 0; i < branch.length; i++) {
otherside = branch[i]; otherside = branch[i];
if (index & 1) if (index & 1) {
hash = crypto.hash256(Buffer.concat([otherside, hash])); otherside.copy(buf, 0);
else hash.copy(buf, 32);
hash = crypto.hash256(Buffer.concat([hash, otherside])); } else {
hash.copy(buf, 0);
otherside.copy(buf, 32);
}
hash = crypto.hash256(buf);
index >>>= 1; index >>>= 1;
} }

View File

@ -162,7 +162,7 @@ MerkleBlock.prototype.extractTree = function extractTree() {
var flags = this.flags; var flags = this.flags;
var totalTX = this.totalTX; var totalTX = this.totalTX;
var height = 0; var height = 0;
var root, p; var root, p, buf;
function width(height) { function width(height) {
return (totalTX + (1 << height) - 1) >>> height; return (totalTX + (1 << height) - 1) >>> height;
@ -203,7 +203,10 @@ MerkleBlock.prototype.extractTree = function extractTree() {
right = left; right = left;
} }
return utils.hash256(Buffer.concat([left, right])); left.copy(buf, 0);
right.copy(buf, 32);
return utils.hash256(buf);
} }
for (p = 0; p < this.hashes.length; p++) for (p = 0; p < this.hashes.length; p++)
@ -225,6 +228,9 @@ MerkleBlock.prototype.extractTree = function extractTree() {
while (width(height) > 1) while (width(height) > 1)
height++; height++;
if (height > 0)
buf = new Buffer(64);
root = traverse(height, 0); root = traverse(height, 0);
if (failed) if (failed)
@ -446,7 +452,7 @@ MerkleBlock.fromBlock = function fromBlock(block, filter) {
var leaves = []; var leaves = [];
var bits = []; var bits = [];
var hashes = []; var hashes = [];
var i, tx, totalTX, height, flags, p, merkle; var i, tx, totalTX, height, flags, p, merkle, buf;
for (i = 0; i < block.txs.length; i++) { for (i = 0; i < block.txs.length; i++) {
tx = block.txs[i]; tx = block.txs[i];
@ -478,7 +484,10 @@ MerkleBlock.fromBlock = function fromBlock(block, filter) {
else else
right = left; right = left;
return utils.hash256(Buffer.concat([left, right])); left.copy(buf, 0);
right.copy(buf, 32);
return utils.hash256(buf);
} }
function traverse(height, pos, leaves, matches) { function traverse(height, pos, leaves, matches) {
@ -505,6 +514,9 @@ MerkleBlock.fromBlock = function fromBlock(block, filter) {
while (width(height) > 1) while (width(height) > 1)
height++; height++;
if (height > 0)
buf = new Buffer(64);
traverse(height, 0, leaves, matches); traverse(height, 0, leaves, matches);
flags = new Buffer((bits.length + 7) / 8 | 0); flags = new Buffer((bits.length + 7) / 8 | 0);