better preload. misc fixes.
This commit is contained in:
parent
05d4eab0d8
commit
17e25804de
@ -304,9 +304,6 @@ Block.prototype.verifyContext = function verifyContext() {
|
||||
var sigops = 0;
|
||||
var prev, height, ts, i, j, tx, cb, input;
|
||||
|
||||
if (this.subtype !== 'block')
|
||||
return true;
|
||||
|
||||
if (this.isGenesis())
|
||||
return true;
|
||||
|
||||
@ -363,6 +360,10 @@ Block.prototype.verifyContext = function verifyContext() {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// Can't verify any further when merkleblock or headers.
|
||||
if (this.subtype !== 'block')
|
||||
return true;
|
||||
|
||||
// Make sure the height contained in the coinbase is correct.
|
||||
if (this.version >= 2 && prev.isUpgraded(2)) {
|
||||
cb = bcoin.script.getCoinbaseData(this.txs[0].inputs[0].script);
|
||||
|
||||
@ -96,7 +96,7 @@ Chain.prototype._init = function _init() {
|
||||
|
||||
utils.debug('Chain is loading.');
|
||||
|
||||
this.preload(function(err, start) {
|
||||
this._preload(function(err, start) {
|
||||
if (err) {
|
||||
utils.debug('Preloading chain failed.');
|
||||
utils.debug('Reason: %s', err.message);
|
||||
@ -143,7 +143,12 @@ Chain.prototype._init = function _init() {
|
||||
});
|
||||
};
|
||||
|
||||
Chain.prototype.preload = function preload(callback) {
|
||||
// Stream headers from electrum.org for quickly
|
||||
// preloading the chain. Electrum.org stores
|
||||
// headers in the standard block header format,
|
||||
// but they do not store chainwork, so we have
|
||||
// to calculate it ourselves.
|
||||
Chain.prototype._preload = function _preload(callback) {
|
||||
var self = this;
|
||||
var url = 'https://headers.electrum.org/blockchain_headers';
|
||||
var chainHeight, buf, height, stream;
|
||||
@ -202,6 +207,7 @@ Chain.prototype.preload = function preload(callback) {
|
||||
|
||||
blocks.forEach(function(data) {
|
||||
var entry = bcoin.chainblock.fromRaw(self, height, data);
|
||||
var block = bcoin.block(entry, 'headers');
|
||||
var start;
|
||||
|
||||
// Do some paranoid checks.
|
||||
@ -212,18 +218,34 @@ Chain.prototype.preload = function preload(callback) {
|
||||
return callback(new Error('Corrupt headers.'), start + 1);
|
||||
}
|
||||
|
||||
// Verify the block headers. We don't want to
|
||||
// trust an external centralized source completely.
|
||||
// For very paranoid but slower validation:
|
||||
// if (!block.verify() || !block.verifyContext()) {
|
||||
if (!block.verify()) {
|
||||
start = Math.max(0, height - 2);
|
||||
stream.destroy();
|
||||
self.resetHeight(start);
|
||||
return callback(new Error('Bad headers.'), start + 1);
|
||||
}
|
||||
|
||||
lastEntry = entry;
|
||||
|
||||
delete entry.chainwork;
|
||||
entry.chainwork = entry.getChainwork();
|
||||
|
||||
// Skip the genesis block in case it ends up being corrupt
|
||||
// Skip the genesis block in case
|
||||
// it ends up being corrupt.
|
||||
if (height === 0) {
|
||||
height++;
|
||||
return;
|
||||
}
|
||||
|
||||
self._saveEntry(entry, height > chainHeight);
|
||||
// Don't write blocks we already have
|
||||
// (bad for calculating chainwork).
|
||||
// self._saveEntry(entry, height > chainHeight);
|
||||
|
||||
self._saveEntry(entry, true);
|
||||
|
||||
height++;
|
||||
|
||||
@ -630,7 +652,7 @@ Chain.prototype.fillPercent = function fillPercent() {
|
||||
};
|
||||
|
||||
Chain.prototype.hashRange = function hashRange(start, end) {
|
||||
var hashes;
|
||||
var hashes = [];
|
||||
|
||||
start = this.byTime(start);
|
||||
end = this.byTime(end);
|
||||
@ -694,13 +716,15 @@ Chain.prototype.getLocator = function getLocator(start) {
|
||||
|
||||
Chain.prototype.getOrphanRoot = function getOrphanRoot(hash) {
|
||||
var self = this;
|
||||
var root = hash;
|
||||
var root;
|
||||
|
||||
if (utils.isBuffer(hash))
|
||||
hash = utils.toHex(hash);
|
||||
else if (hash.hash)
|
||||
hash = hash.hash('hex');
|
||||
|
||||
root = hash;
|
||||
|
||||
while (this.orphan.bmap[hash]) {
|
||||
root = hash;
|
||||
hash = this.orphan.bmap[hash].prevBlock;
|
||||
|
||||
@ -1163,7 +1163,10 @@ TX.prototype.sortMembers = function sortMembers() {
|
||||
}
|
||||
|
||||
this.inputs = this.inputs.slice().sort(function(a, b) {
|
||||
var res = new bn(a.prevout.hash, 'hex').cmp(new bn(b.prevout.hash, 'hex'));
|
||||
var h1 = utils.toArray(a.prevout.hash, 'hex');
|
||||
var h2 = utils.toArray(b.prevout.hash, 'hex');
|
||||
|
||||
var res = utils.cmp(h1, h2);
|
||||
if (res !== 0)
|
||||
return res;
|
||||
|
||||
@ -1178,7 +1181,7 @@ TX.prototype.sortMembers = function sortMembers() {
|
||||
a = bcoin.script.encode(a.script);
|
||||
b = bcoin.script.encode(b.script);
|
||||
|
||||
return new bn(a).cmp(b);
|
||||
return utils.cmp(a, b);
|
||||
});
|
||||
|
||||
if (this.changeIndex !== -1) {
|
||||
|
||||
@ -787,13 +787,13 @@ utils.hidden = function hidden(obj, prop, value) {
|
||||
|
||||
utils.sortKeys = function sortKeys(keys) {
|
||||
return keys.slice().sort(function(a, b) {
|
||||
return new bn(a).cmp(new bn(b)) > 0;
|
||||
return utils.cmp(a, b);
|
||||
});
|
||||
};
|
||||
|
||||
utils.sortHDKeys = function sortHDKeys(keys) {
|
||||
return keys.slice().sort(function(a, b) {
|
||||
return new bn(a.publicKey).cmp(new bn(b.publicKey)) > 0;
|
||||
return utils.cmp(a.publicKey, b.publicKey);
|
||||
});
|
||||
};
|
||||
|
||||
@ -1381,16 +1381,18 @@ utils.cmp = function(a, b) {
|
||||
return 0;
|
||||
};
|
||||
|
||||
// https://cryptocoding.net/index.php/Coding_rules
|
||||
// memcmp in constant time (can only return true or false)
|
||||
// https://cryptocoding.net/index.php/Coding_rules
|
||||
// $ man 3 memcmp (see NetBSD's consttime_memequal)
|
||||
// This protects us against timing attacks when
|
||||
// comparing an input against a secret string.
|
||||
utils.ccmp = function(a, b) {
|
||||
var res, i;
|
||||
|
||||
assert(a.length === b.length);
|
||||
|
||||
for (i = 0; i < a.length; i++)
|
||||
res = a[i] ^ b[i];
|
||||
res |= a[i] ^ b[i];
|
||||
|
||||
return res === 0;
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user