if we're going to have checkpoints, might as well optimize the hell out of them.
This commit is contained in:
parent
04565cfadb
commit
27684e9661
7
bin/node
7
bin/node
@ -12,15 +12,18 @@ process.on('uncaughtException', function(err) {
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
var fast = process.argv.indexOf('--fast') !== -1;
|
||||
|
||||
var node = new bcoin.fullnode({
|
||||
logLevel: 'debug',
|
||||
logFile: true,
|
||||
db: 'leveldb',
|
||||
prune: process.argv.indexOf('--prune') !== -1,
|
||||
compact: process.argv.indexOf('--compact') !== -1,
|
||||
useCheckpoints: process.argv.indexOf('--checkpoints') !== -1,
|
||||
useCheckpoints: fast || process.argv.indexOf('--checkpoints') !== -1,
|
||||
coinCache: fast || process.argv.indexOf('--coin-cache') !== -1,
|
||||
selfish: process.argv.indexOf('--selfish') !== -1,
|
||||
headers: process.argv.indexOf('--headers') !== -1,
|
||||
headers: fast || process.argv.indexOf('--headers') !== -1,
|
||||
parallel: process.argv.indexOf('--parallel') !== -1
|
||||
});
|
||||
|
||||
|
||||
@ -112,7 +112,7 @@ Chain.prototype._init = function _init() {
|
||||
return;
|
||||
|
||||
self.logger.info('Block %s (%d) added to chain.',
|
||||
utils.revHex(entry.hash), entry.height);
|
||||
entry.rhash, entry.height);
|
||||
});
|
||||
|
||||
this.on('competitor', function(block, entry) {
|
||||
@ -124,8 +124,8 @@ Chain.prototype._init = function _init() {
|
||||
entry.height,
|
||||
self.tip.height,
|
||||
entry.height,
|
||||
utils.revHex(self.tip.hash),
|
||||
utils.revHex(entry.hash),
|
||||
self.tip.rhash,
|
||||
entry.rhash,
|
||||
self.tip.chainwork.toString(),
|
||||
entry.chainwork.toString(),
|
||||
self.tip.chainwork.sub(entry.chainwork).toString());
|
||||
@ -189,6 +189,12 @@ Chain.prototype._open = function open(callback) {
|
||||
|
||||
this.logger.info('Chain is loading.');
|
||||
|
||||
if (this.options.useCheckpoints)
|
||||
this.logger.info('Checkpoints are enabled.');
|
||||
|
||||
if (this.options.coinCache)
|
||||
this.logger.info('Coin cache is enabled.');
|
||||
|
||||
this.db.open(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
@ -467,7 +473,7 @@ Chain.prototype.isGenesis = function isGenesis(block) {
|
||||
Chain.prototype.verify = function verify(block, prev, callback) {
|
||||
var self = this;
|
||||
var ret = {};
|
||||
var height, ts, i, tx, medianTime, commitmentHash;
|
||||
var i, height, ts, tx, medianTime, commitmentHash;
|
||||
|
||||
if (!block.verify(ret)) {
|
||||
return callback(new VerifyError(block,
|
||||
@ -488,6 +494,9 @@ Chain.prototype.verify = function verify(block, prev, callback) {
|
||||
0));
|
||||
}
|
||||
|
||||
if (prev.isHistorical())
|
||||
return callback(null, this.state);
|
||||
|
||||
prev.getRetargetAncestors(function(err, ancestors) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
@ -732,6 +741,9 @@ Chain.prototype.checkDuplicates = function checkDuplicates(block, prev, callback
|
||||
if (this.isGenesis(block))
|
||||
return callback();
|
||||
|
||||
if (prev.isHistorical())
|
||||
return callback();
|
||||
|
||||
if (this.network.block.bip34height === -1
|
||||
|| height <= this.network.block.bip34height) {
|
||||
return this.findDuplicates(block, prev, callback);
|
||||
@ -809,8 +821,7 @@ Chain.prototype.findDuplicates = function findDuplicates(block, prev, callback)
|
||||
Chain.prototype.checkInputs = function checkInputs(block, prev, state, callback) {
|
||||
var self = this;
|
||||
var height = prev.height + 1;
|
||||
var scriptCheck = true;
|
||||
var historical = false;
|
||||
var historical = prev.isHistorical();
|
||||
var sigops = 0;
|
||||
var ret = {};
|
||||
|
||||
@ -820,14 +831,6 @@ Chain.prototype.checkInputs = function checkInputs(block, prev, state, callback)
|
||||
if (this.isGenesis(block))
|
||||
return callback();
|
||||
|
||||
// If we are an ancestor of a checkpoint, we can
|
||||
// skip the input verification.
|
||||
if (height <= this.network.checkpoints.lastHeight) {
|
||||
if (this.options.useCheckpoints)
|
||||
scriptCheck = false;
|
||||
historical = true;
|
||||
}
|
||||
|
||||
this.db.getCoinView(block, function(err, view) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
@ -845,6 +848,13 @@ Chain.prototype.checkInputs = function checkInputs(block, prev, state, callback)
|
||||
}
|
||||
}
|
||||
|
||||
// Skip everything if we're
|
||||
// using checkpoints.
|
||||
if (historical) {
|
||||
view.addTX(tx);
|
||||
return next();
|
||||
}
|
||||
|
||||
// Verify sequence locks.
|
||||
self.checkLocks(prev, tx, state.lockFlags, function(err, valid) {
|
||||
if (err)
|
||||
@ -886,18 +896,17 @@ Chain.prototype.checkInputs = function checkInputs(block, prev, state, callback)
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (historical)
|
||||
return callback(null, view);
|
||||
|
||||
// Verify all txs in parallel.
|
||||
utils.every(block.txs, function(tx, next) {
|
||||
if (!scriptCheck)
|
||||
return next(null, true);
|
||||
|
||||
tx.verifyAsync(state.flags, next);
|
||||
}, function(err, verified) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!verified) {
|
||||
assert(!historical, 'BUG: Invalid inputs in historical data!');
|
||||
return callback(new VerifyError(block,
|
||||
'invalid',
|
||||
'mandatory-script-verify-flag-failed',
|
||||
@ -2067,8 +2076,7 @@ Chain.prototype.findLocator = function findLocator(locator, callback) {
|
||||
*/
|
||||
|
||||
Chain.prototype.isActive = function isActive(prev, id, callback) {
|
||||
// Optimization for main
|
||||
if (this.network.type === 'main' && prev.height < 400000)
|
||||
if (prev.isHistorical())
|
||||
return callback(null, false);
|
||||
|
||||
this.getState(prev, id, function(err, state) {
|
||||
@ -2346,7 +2354,7 @@ Chain.prototype.getLocks = function getLocks(prev, tx, flags, callback) {
|
||||
var coinHeight;
|
||||
|
||||
if (tx.isCoinbase() || tx.version < 2 || !hasFlag)
|
||||
return utils.asyncify(callback)(null, minHeight, minTime);
|
||||
return callback(null, minHeight, minTime);
|
||||
|
||||
utils.forEachSerial(tx.inputs, function(input, next) {
|
||||
if (input.sequence & disableFlag)
|
||||
@ -2395,10 +2403,10 @@ Chain.prototype.getLocks = function getLocks(prev, tx, flags, callback) {
|
||||
|
||||
Chain.prototype.evalLocks = function evalLocks(prev, minHeight, minTime, callback) {
|
||||
if (minHeight >= prev.height + 1)
|
||||
return utils.asyncify(callback)(null, false);
|
||||
return callback(null, false);
|
||||
|
||||
if (minTime === -1)
|
||||
return utils.asyncify(callback)(null, true);
|
||||
return callback(null, true);
|
||||
|
||||
prev.getMedianTimeAsync(function(err, medianTime) {
|
||||
if (err)
|
||||
|
||||
@ -209,9 +209,12 @@ function ChainDB(chain, options) {
|
||||
// Key size: 66b (* 2)
|
||||
this.coinWindow = ((165 * 1024 + 2300 * 4) + (2300 * 66 * 2)) * 5;
|
||||
|
||||
this.coinCache = new bcoin.lru.nil(this.coinWindow);
|
||||
this.coinCache = new bcoin.lru.nil();
|
||||
this.cacheHash = new bcoin.lru(this.cacheWindow, 1);
|
||||
this.cacheHeight = new bcoin.lru(this.cacheWindow, 1);
|
||||
|
||||
if (this.options.coinCache)
|
||||
this.coinCache = new bcoin.lru(this.coinWindow);
|
||||
}
|
||||
|
||||
utils.inherits(ChainDB, AsyncObject);
|
||||
|
||||
@ -446,6 +446,19 @@ ChainEntry.prototype.isSuperMajorityAsync = function isSuperMajorityAsync(versio
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether the entry is potentially an ancestor of a checkpoint.
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
ChainEntry.prototype.isHistorical = function isHistorical() {
|
||||
if (this.chain.options.useCheckpoints) {
|
||||
if (this.height + 1 <= this.network.checkpoints.lastHeight)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
ChainEntry.prototype.__defineGetter__('rhash', function() {
|
||||
return utils.revHex(this.hash);
|
||||
});
|
||||
|
||||
@ -62,7 +62,8 @@ function Fullnode(options) {
|
||||
preload: false,
|
||||
spv: false,
|
||||
prune: this.options.prune,
|
||||
useCheckpoints: this.options.useCheckpoints
|
||||
useCheckpoints: this.options.useCheckpoints,
|
||||
coinCache: this.options.coinCache
|
||||
});
|
||||
|
||||
// Fee estimation.
|
||||
@ -120,6 +121,7 @@ function Fullnode(options) {
|
||||
fees: this.fees,
|
||||
db: this.db,
|
||||
location: this.location('walletdb'),
|
||||
useCheckpoints: this.options.useCheckpoints,
|
||||
verify: false
|
||||
});
|
||||
|
||||
|
||||
@ -252,6 +252,8 @@ Peer.prototype._onConnect = function _onConnect() {
|
||||
*/
|
||||
|
||||
Peer.prototype._onAck = function _onAck(err) {
|
||||
var self = this;
|
||||
|
||||
if (err) {
|
||||
this._error(err);
|
||||
this.destroy();
|
||||
|
||||
@ -112,13 +112,16 @@ main.checkpoints = {
|
||||
225430: '32595730b165f097e7b806a679cf7f3e439040f750433808c101000000000000',
|
||||
250000: '14d2f24d29bed75354f3f88a5fb50022fc064b02291fdf873800000000000000',
|
||||
279000: '407ebde958e44190fa9e810ea1fc3a7ef601c3b0a0728cae0100000000000000',
|
||||
295000: '83a93246c67003105af33ae0b29dd66f689d0f0ff54e9b4d0000000000000000'
|
||||
295000: '83a93246c67003105af33ae0b29dd66f689d0f0ff54e9b4d0000000000000000',
|
||||
// Checkpoints from btcd:
|
||||
300255: 'b2f3a0f0de4120c1089d5f5280a263059f9b6e7c520428160000000000000000',
|
||||
319400: '3bf115fd057391587ca39a531c5d4989e1adec9b2e05c6210000000000000000',
|
||||
343185: '548536d48e7678fcfa034202dd45d4a76b1ad061f38b2b070000000000000000',
|
||||
352940: 'ffc9520143e41c94b6e03c2fa3e62bb76b55ba2df45d75100000000000000000',
|
||||
382320: 'b28afdde92b0899715e40362f56afdb20e3d135bedc68d0a0000000000000000'
|
||||
};
|
||||
|
||||
main.checkpoints.tsLastCheckpoint = 1397080064;
|
||||
main.checkpoints.txsLastCheckpoint = 36544669;
|
||||
main.checkpoints.txsPerDay = 60000.0;
|
||||
main.checkpoints.lastHeight = 295000;
|
||||
main.checkpoints.lastHeight = 382320;
|
||||
|
||||
/**
|
||||
* @const {Number}
|
||||
@ -474,9 +477,6 @@ testnet.checkpoints = {
|
||||
546: '70cb6af7ebbcb1315d3414029c556c55f3e2fc353c4c9063a76c932a00000000'
|
||||
};
|
||||
|
||||
testnet.checkpoints.tsLastCheckpoint = 1338180505;
|
||||
testnet.checkpoints.txsLastCheckpoint = 16341;
|
||||
testnet.checkpoints.txsPerDay = 300;
|
||||
testnet.checkpoints.lastHeight = 546;
|
||||
|
||||
testnet.halvingInterval = 210000;
|
||||
@ -618,9 +618,6 @@ regtest.alertKey = new Buffer(
|
||||
'hex');
|
||||
|
||||
regtest.checkpoints = {};
|
||||
regtest.checkpoints.tsLastCheckpoint = 0;
|
||||
regtest.checkpoints.txsLastCheckpoint = 0;
|
||||
regtest.checkpoints.txsPerDay = 300;
|
||||
regtest.checkpoints.lastHeight = 0;
|
||||
|
||||
regtest.halvingInterval = 150;
|
||||
@ -760,9 +757,6 @@ segnet3.alertKey = new Buffer(
|
||||
'hex');
|
||||
|
||||
segnet3.checkpoints = {};
|
||||
segnet3.checkpoints.tsLastCheckpoint = 0;
|
||||
segnet3.checkpoints.txsLastCheckpoint = 0;
|
||||
segnet3.checkpoints.txsPerDay = 300;
|
||||
segnet3.checkpoints.lastHeight = 0;
|
||||
|
||||
segnet3.halvingInterval = 210000;
|
||||
@ -880,9 +874,6 @@ segnet4.alertKey = new Buffer(
|
||||
'hex');
|
||||
|
||||
segnet4.checkpoints = {};
|
||||
segnet4.checkpoints.tsLastCheckpoint = 0;
|
||||
segnet4.checkpoints.txsLastCheckpoint = 0;
|
||||
segnet4.checkpoints.txsPerDay = 300;
|
||||
segnet4.checkpoints.lastHeight = 0;
|
||||
|
||||
segnet4.halvingInterval = 210000;
|
||||
|
||||
@ -349,6 +349,11 @@ TXDB.prototype.addBlock = function addBlock(block, txs, callback, force) {
|
||||
|
||||
callback = utils.wrap(callback, unlock);
|
||||
|
||||
if (this.options.useCheckpoints) {
|
||||
if (block.height < this.network.checkpoints.lastHeight)
|
||||
return this.writeTip(block.hash, callback);
|
||||
}
|
||||
|
||||
if (!Array.isArray(txs))
|
||||
txs = [txs];
|
||||
|
||||
|
||||
@ -71,7 +71,8 @@ function WalletDB(options) {
|
||||
|
||||
this.tx = new bcoin.txdb(this, {
|
||||
verify: this.options.verify,
|
||||
useFilter: true
|
||||
useCheckpoints: this.options.useCheckpoints,
|
||||
useFilter: true,
|
||||
});
|
||||
|
||||
if (bcoin.useWorkers)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user