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;
|
this.flags = data.flags;
|
||||||
|
|
||||||
|
// List of matched TXs
|
||||||
|
this.tx = [];
|
||||||
|
this.invalid = false;
|
||||||
|
|
||||||
this._hash = null;
|
this._hash = null;
|
||||||
|
|
||||||
|
// Verify partial merkle tree and fill `ts` array
|
||||||
|
this._verifyMerkle();
|
||||||
}
|
}
|
||||||
module.exports = Block;
|
module.exports = Block;
|
||||||
|
|
||||||
@ -42,13 +49,60 @@ Block.prototype.abbr = function abbr() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Block.prototype.verify = function verify() {
|
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) {
|
Block.prototype.render = function render(framer) {
|
||||||
return [];
|
return [];
|
||||||
};
|
};
|
||||||
|
|
||||||
Block.prototype.hasMerkle = function hasMerkle(hash) {
|
Block.prototype.hasTX = function hasTX(hash) {
|
||||||
return this.hashes.indexOf(hash) !== -1;
|
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);
|
}, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data.ts && block && block.hasMerkle(this.hash('hex')))
|
if (!data.ts && block && block.hasTX(this.hash('hex')))
|
||||||
this.ts = block.ts;
|
this.ts = block.ts;
|
||||||
}
|
}
|
||||||
module.exports = TX;
|
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