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