block: validate partial merkle tree

This commit is contained in:
Fedor Indutny 2014-05-10 19:45:03 +04:00
parent 0a90240879
commit d49b04158f
3 changed files with 97 additions and 4 deletions

View File

@ -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'));
}
};

View File

@ -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
View 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');
});
});