block: validate partial merkle tree
This commit is contained in:
parent
0a90240879
commit
d49b04158f
@ -18,7 +18,14 @@ function Block(data) {
|
||||
});
|
||||
this.flags = data.flags;
|
||||
|
||||
// List of matched TXs
|
||||
this.tx = [];
|
||||
this.invalid = false;
|
||||
|
||||
this._hash = null;
|
||||
|
||||
// Verify partial merkle tree and fill `ts` array
|
||||
this._verifyMerkle();
|
||||
}
|
||||
module.exports = Block;
|
||||
|
||||
@ -42,13 +49,60 @@ Block.prototype.abbr = function abbr() {
|
||||
};
|
||||
|
||||
Block.prototype.verify = function verify() {
|
||||
return utils.testTarget(this.bits, this.hash());
|
||||
return !this.invalid && utils.testTarget(this.bits, this.hash());
|
||||
};
|
||||
|
||||
Block.prototype.render = function render(framer) {
|
||||
return [];
|
||||
};
|
||||
|
||||
Block.prototype.hasMerkle = function hasMerkle(hash) {
|
||||
return this.hashes.indexOf(hash) !== -1;
|
||||
Block.prototype.hasTX = function hasTX(hash) {
|
||||
return this.tx.indexOf(hash) !== -1;
|
||||
};
|
||||
|
||||
Block.prototype._verifyMerkle = function verifyMerkle() {
|
||||
var height = 0;
|
||||
|
||||
// Count leafs
|
||||
for (var i = this.totalTX; i > 0; i >>= 1)
|
||||
height++;
|
||||
if (this.totalTX > (1 << (height - 1)))
|
||||
height++;
|
||||
|
||||
var tx = [];
|
||||
var i = 0;
|
||||
var j = 0;
|
||||
var hashes = this.hashes;
|
||||
var flags = this.flags;
|
||||
|
||||
var root = visit(1);
|
||||
if (!root || root !== this.merkleRoot) {
|
||||
this.invalid = true;
|
||||
return;
|
||||
}
|
||||
this.tx = tx;
|
||||
function visit(depth) {
|
||||
if (i === flags.length * 8 || j === hashes.length)
|
||||
return null;
|
||||
|
||||
var flag = (flags[i >> 3] >>> (i & 7)) & 1;
|
||||
i++;
|
||||
|
||||
if (flag === 0 || depth === height) {
|
||||
if (depth === height)
|
||||
tx.push(hashes[j]);
|
||||
return hashes[j++];
|
||||
}
|
||||
|
||||
// Go deeper
|
||||
var left = visit(depth + 1);
|
||||
if (!left)
|
||||
return null;
|
||||
var right = visit(depth + 1);
|
||||
if (right === left)
|
||||
return null;
|
||||
if (!right)
|
||||
right = left;
|
||||
return utils.toHex(utils.dsha256(left + right, 'hex'));
|
||||
}
|
||||
};
|
||||
|
||||
@ -33,7 +33,7 @@ function TX(data, block) {
|
||||
}, this);
|
||||
}
|
||||
|
||||
if (!data.ts && block && block.hasMerkle(this.hash('hex')))
|
||||
if (!data.ts && block && block.hasTX(this.hash('hex')))
|
||||
this.ts = block.ts;
|
||||
}
|
||||
module.exports = TX;
|
||||
|
||||
39
test/block-test.js
Normal file
39
test/block-test.js
Normal file
@ -0,0 +1,39 @@
|
||||
var assert = require('assert');
|
||||
var bn = require('bn.js');
|
||||
var bcoin = require('../');
|
||||
|
||||
describe('Block', function() {
|
||||
it('should parse partial merkle tree', function() {
|
||||
var block = bcoin.block({
|
||||
type: 'block',
|
||||
version: 2,
|
||||
prevBlock: 'd1831d4411bdfda89d9d8c842b541beafd1437fc560dbe5c0000000000000000',
|
||||
merkleRoot: '28bec1d35af480ba3884553d72694f6ba6c163a5c081d7e6edaec15f373f19af',
|
||||
ts: 1399713634,
|
||||
bits: 419465580,
|
||||
nonce: 1186968784,
|
||||
totalTX: 461,
|
||||
hashes:[
|
||||
'7d22e53bce1bbb3294d1a396c5acc45bdcc8f192cb492f0d9f55421fd4c62de1',
|
||||
'9d6d585fdaf3737b9a54aaee1dd003f498328d699b7dfb42dd2b44b6ebde2333',
|
||||
'8b61da3053d6f382f2145bdd856bc5dcf052c3a11c1784d3d51b2cbe0f6d0923',
|
||||
'd7bbaae4716cb0d329d755b707cee588cddc68601f99bc05fef1fabeb8dfe4a0',
|
||||
'7393f84cd04ca8931975c66282ebf1847c78d8de6c2578d4f9bae23bc6f30857',
|
||||
'ec8c51de3170301430ec56f6703533d9ea5b05c6fa7068954bcb90eed8c2ee5c',
|
||||
'c7c152869db09a5ae2291fa03142912d9d7aba75be7d491a8ac4230ee9a920cb',
|
||||
'5adbf04583354515a225f2c418de7c5cdac4cef211820c79717cd2c50412153f',
|
||||
'1f5e46b9da3a8b1241f4a1501741d3453bafddf6135b600b926e3f4056c6d564',
|
||||
'33825657ba32afe269819f01993bd77baba86379043168c94845d32370e53562' ],
|
||||
flags: [ 245, 90, 0 ]
|
||||
});
|
||||
|
||||
assert(block.verify());
|
||||
assert.equal(block.tx.length, 2);
|
||||
assert.equal(
|
||||
block.tx[0],
|
||||
'7393f84cd04ca8931975c66282ebf1847c78d8de6c2578d4f9bae23bc6f30857');
|
||||
assert.equal(
|
||||
block.tx[1],
|
||||
'ec8c51de3170301430ec56f6703533d9ea5b05c6fa7068954bcb90eed8c2ee5c');
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user