Review Fixes
This commit is contained in:
parent
a67084d176
commit
a478e39524
|
@ -57,10 +57,12 @@ function MerkleBlock(arg) {
|
|||
flags: arg.flags
|
||||
};
|
||||
} else {
|
||||
throw new TypeError('Unrecognized argument for Block');
|
||||
throw new TypeError('Unrecognized argument for MerkleBlock');
|
||||
}
|
||||
_.extend(this,info);
|
||||
this._validMerkleTree = null;
|
||||
this._flagBitsUsed = 0;
|
||||
this._hashesUsed = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -140,13 +142,10 @@ MerkleBlock.prototype.toJSON = function toJSON() {
|
|||
* @returns {Bool} - True/False whether this MerkleBlock is Valid
|
||||
*/
|
||||
MerkleBlock.prototype.validMerkleTree = function validMerkleTree() {
|
||||
$.checkState(this.flags instanceof Array, 'MerkleBlock flags is not an array');
|
||||
$.checkState(this.hashes instanceof Array, 'MerkleBlock flags is not an array');
|
||||
var self = this;
|
||||
if(this._validMerkleTree === true) {
|
||||
return true;
|
||||
} else if (this._validMerkleTree === false) {
|
||||
return false;
|
||||
$.checkState(_.isArray(this.flags), 'MerkleBlock flags is not an array');
|
||||
$.checkState(_.isArray(this.hashes), 'MerkleBlock hashes is not an array');
|
||||
if(_.isBoolean(this._validMerkleTree)) {
|
||||
return this._validMerkleTree;
|
||||
}
|
||||
|
||||
// Can't have more hashes than numTransactions
|
||||
|
@ -159,50 +158,58 @@ MerkleBlock.prototype.validMerkleTree = function validMerkleTree() {
|
|||
return this._setValidMerkleTree(false);
|
||||
}
|
||||
|
||||
// Calculate height of tree
|
||||
// From Bitcoin Core merkleblock.h CalcTreeWidth() + CPartialMerkleTree
|
||||
var height = 0;
|
||||
while (calcTreeWidth(height) > 1) {
|
||||
while (this._calcTreeWidth(height) > 1) {
|
||||
height++;
|
||||
}
|
||||
|
||||
var flagBitsUsed = 0;
|
||||
var hashesUsed = 0;
|
||||
|
||||
// Modeled after Bitcoin Core merkleblock.h CalcTreeWidth()
|
||||
function calcTreeWidth(height) {
|
||||
return (self.numTransactions + (1 << height) - 1) >> height;
|
||||
this._flagBitsUsed = 0;
|
||||
this._hashesUsed = 0;
|
||||
var root = this._traverseMerkleTree(height, 0);
|
||||
if(this._hashesUsed !== this.hashes.length) {
|
||||
return this._setValidMerkleTree(false);
|
||||
}
|
||||
return this._setValidMerkleTree(BufferUtil.equals(root, this.header.merkleRoot));
|
||||
}
|
||||
|
||||
// Modeled after Bitcoin Core merkleblock.cpp TraverseAndExtract()
|
||||
function traverse(depth, pos) {
|
||||
if(flagBitsUsed > self.flags.length * 8) {
|
||||
/** Traverse a the tree in this MerkleBlock, validating it along the way
|
||||
* Modeled after Bitcoin Core merkleblock.cpp TraverseAndExtract()
|
||||
* @param {Number} - Current height
|
||||
* @param {Number} - Current position in the tree
|
||||
* @returns {Buffer|null} - Buffer containing the Merkle Hash far that height
|
||||
* @private
|
||||
*/
|
||||
MerkleBlock.prototype._traverseMerkleTree = function traverseMerkleTree(depth, pos) {
|
||||
if(this._flagBitsUsed > this.flags.length * 8) {
|
||||
return null;
|
||||
}
|
||||
var isParentOfMatch = (self.flags[flagBitsUsed >> 3] >>> (flagBitsUsed++ & 7)) & 1;
|
||||
var isParentOfMatch = (this.flags[this._flagBitsUsed >> 3] >>> (this._flagBitsUsed++ & 7)) & 1;
|
||||
if(depth === 0 || !isParentOfMatch) {
|
||||
if(hashesUsed >= self.hashes.length) {
|
||||
if(this._hashesUsed >= this.hashes.length) {
|
||||
return null;
|
||||
}
|
||||
var hash = self.hashes[hashesUsed++];
|
||||
var hash = this.hashes[this._hashesUsed++];
|
||||
return new Buffer(hash, 'hex');
|
||||
} else {
|
||||
var left = traverse(depth-1, pos*2);
|
||||
var left = this._traverseMerkleTree(depth-1, pos*2);
|
||||
var right;
|
||||
if(pos*2+1 < calcTreeWidth(depth-1)) {
|
||||
right = traverse(depth-1, pos*2+1);
|
||||
if(pos*2+1 < this._calcTreeWidth(depth-1)) {
|
||||
right = this._traverseMerkleTree(depth-1, pos*2+1);
|
||||
} else {
|
||||
right = left;
|
||||
}
|
||||
return Hash.sha256sha256(new Buffer.concat([left, right]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var root = traverse(height, 0);
|
||||
if(hashesUsed !== this.hashes.length) {
|
||||
return this._setValidMerkleTree(false);
|
||||
}
|
||||
return this._setValidMerkleTree(BufferUtil.equals(root, this.header.merkleRoot));
|
||||
/** Calculates the width of a merkle tree at a given height.
|
||||
* Modeled after Bitcoin Core merkleblock.h CalcTreeWidth()
|
||||
* @param {Number} - Height at which we want the tree width
|
||||
* @returns {Number} - Width of the tree at a given height
|
||||
* @private
|
||||
*/
|
||||
MerkleBlock.prototype._calcTreeWidth = function calcTreeWidth(height) {
|
||||
return (this.numTransactions + (1 << height) - 1) >> height;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -211,14 +218,11 @@ MerkleBlock.prototype.validMerkleTree = function validMerkleTree() {
|
|||
* @private
|
||||
*/
|
||||
MerkleBlock.prototype.hasTransaction = function hasTransaction(tx) {
|
||||
$.checkArgument(!_.isUndefined(tx), 'No transaction given');
|
||||
$.checkArgument(tx instanceof Transaction
|
||||
|| typeof tx === 'string', 'No transaction given');
|
||||
$.checkArgument(!_.isUndefined(tx), 'tx cannot be undefined');
|
||||
$.checkArgument(tx instanceof Transaction || typeof tx === 'string',
|
||||
'Invalid tx given, tx must be a "string" or "Transaction"');
|
||||
|
||||
var hash = tx;
|
||||
if(tx instanceof Transaction) {
|
||||
hash = tx.id;
|
||||
}
|
||||
var hash = tx.id || tx;
|
||||
var revHash = BufferUtil.reverse(new Buffer(hash,'hex')).toString('hex');
|
||||
|
||||
return (this.hashes.indexOf(hash) !== -1
|
||||
|
|
|
@ -34,7 +34,7 @@ describe('MerkleBlock', function() {
|
|||
it('should not make an empty block', function() {
|
||||
(function() {
|
||||
return new MerkleBlock();
|
||||
}).should.throw('Unrecognized argument for Block');
|
||||
}).should.throw('Unrecognized argument for MerkleBlock');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue