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);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var fast = process.argv.indexOf('--fast') !== -1;
|
||||||
|
|
||||||
var node = new bcoin.fullnode({
|
var node = new bcoin.fullnode({
|
||||||
logLevel: 'debug',
|
logLevel: 'debug',
|
||||||
logFile: true,
|
logFile: true,
|
||||||
db: 'leveldb',
|
db: 'leveldb',
|
||||||
prune: process.argv.indexOf('--prune') !== -1,
|
prune: process.argv.indexOf('--prune') !== -1,
|
||||||
compact: process.argv.indexOf('--compact') !== -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,
|
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
|
parallel: process.argv.indexOf('--parallel') !== -1
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -112,7 +112,7 @@ Chain.prototype._init = function _init() {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
self.logger.info('Block %s (%d) added to chain.',
|
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) {
|
this.on('competitor', function(block, entry) {
|
||||||
@ -124,8 +124,8 @@ Chain.prototype._init = function _init() {
|
|||||||
entry.height,
|
entry.height,
|
||||||
self.tip.height,
|
self.tip.height,
|
||||||
entry.height,
|
entry.height,
|
||||||
utils.revHex(self.tip.hash),
|
self.tip.rhash,
|
||||||
utils.revHex(entry.hash),
|
entry.rhash,
|
||||||
self.tip.chainwork.toString(),
|
self.tip.chainwork.toString(),
|
||||||
entry.chainwork.toString(),
|
entry.chainwork.toString(),
|
||||||
self.tip.chainwork.sub(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.');
|
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) {
|
this.db.open(function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
@ -467,7 +473,7 @@ Chain.prototype.isGenesis = function isGenesis(block) {
|
|||||||
Chain.prototype.verify = function verify(block, prev, callback) {
|
Chain.prototype.verify = function verify(block, prev, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var ret = {};
|
var ret = {};
|
||||||
var height, ts, i, tx, medianTime, commitmentHash;
|
var i, height, ts, tx, medianTime, commitmentHash;
|
||||||
|
|
||||||
if (!block.verify(ret)) {
|
if (!block.verify(ret)) {
|
||||||
return callback(new VerifyError(block,
|
return callback(new VerifyError(block,
|
||||||
@ -488,6 +494,9 @@ Chain.prototype.verify = function verify(block, prev, callback) {
|
|||||||
0));
|
0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (prev.isHistorical())
|
||||||
|
return callback(null, this.state);
|
||||||
|
|
||||||
prev.getRetargetAncestors(function(err, ancestors) {
|
prev.getRetargetAncestors(function(err, ancestors) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
@ -732,6 +741,9 @@ Chain.prototype.checkDuplicates = function checkDuplicates(block, prev, callback
|
|||||||
if (this.isGenesis(block))
|
if (this.isGenesis(block))
|
||||||
return callback();
|
return callback();
|
||||||
|
|
||||||
|
if (prev.isHistorical())
|
||||||
|
return callback();
|
||||||
|
|
||||||
if (this.network.block.bip34height === -1
|
if (this.network.block.bip34height === -1
|
||||||
|| height <= this.network.block.bip34height) {
|
|| height <= this.network.block.bip34height) {
|
||||||
return this.findDuplicates(block, prev, callback);
|
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) {
|
Chain.prototype.checkInputs = function checkInputs(block, prev, state, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var height = prev.height + 1;
|
var height = prev.height + 1;
|
||||||
var scriptCheck = true;
|
var historical = prev.isHistorical();
|
||||||
var historical = false;
|
|
||||||
var sigops = 0;
|
var sigops = 0;
|
||||||
var ret = {};
|
var ret = {};
|
||||||
|
|
||||||
@ -820,14 +831,6 @@ Chain.prototype.checkInputs = function checkInputs(block, prev, state, callback)
|
|||||||
if (this.isGenesis(block))
|
if (this.isGenesis(block))
|
||||||
return callback();
|
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) {
|
this.db.getCoinView(block, function(err, view) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(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.
|
// Verify sequence locks.
|
||||||
self.checkLocks(prev, tx, state.lockFlags, function(err, valid) {
|
self.checkLocks(prev, tx, state.lockFlags, function(err, valid) {
|
||||||
if (err)
|
if (err)
|
||||||
@ -886,18 +896,17 @@ Chain.prototype.checkInputs = function checkInputs(block, prev, state, callback)
|
|||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
|
if (historical)
|
||||||
|
return callback(null, view);
|
||||||
|
|
||||||
// Verify all txs in parallel.
|
// Verify all txs in parallel.
|
||||||
utils.every(block.txs, function(tx, next) {
|
utils.every(block.txs, function(tx, next) {
|
||||||
if (!scriptCheck)
|
|
||||||
return next(null, true);
|
|
||||||
|
|
||||||
tx.verifyAsync(state.flags, next);
|
tx.verifyAsync(state.flags, next);
|
||||||
}, function(err, verified) {
|
}, function(err, verified) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
if (!verified) {
|
if (!verified) {
|
||||||
assert(!historical, 'BUG: Invalid inputs in historical data!');
|
|
||||||
return callback(new VerifyError(block,
|
return callback(new VerifyError(block,
|
||||||
'invalid',
|
'invalid',
|
||||||
'mandatory-script-verify-flag-failed',
|
'mandatory-script-verify-flag-failed',
|
||||||
@ -2067,8 +2076,7 @@ Chain.prototype.findLocator = function findLocator(locator, callback) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Chain.prototype.isActive = function isActive(prev, id, callback) {
|
Chain.prototype.isActive = function isActive(prev, id, callback) {
|
||||||
// Optimization for main
|
if (prev.isHistorical())
|
||||||
if (this.network.type === 'main' && prev.height < 400000)
|
|
||||||
return callback(null, false);
|
return callback(null, false);
|
||||||
|
|
||||||
this.getState(prev, id, function(err, state) {
|
this.getState(prev, id, function(err, state) {
|
||||||
@ -2346,7 +2354,7 @@ Chain.prototype.getLocks = function getLocks(prev, tx, flags, callback) {
|
|||||||
var coinHeight;
|
var coinHeight;
|
||||||
|
|
||||||
if (tx.isCoinbase() || tx.version < 2 || !hasFlag)
|
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) {
|
utils.forEachSerial(tx.inputs, function(input, next) {
|
||||||
if (input.sequence & disableFlag)
|
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) {
|
Chain.prototype.evalLocks = function evalLocks(prev, minHeight, minTime, callback) {
|
||||||
if (minHeight >= prev.height + 1)
|
if (minHeight >= prev.height + 1)
|
||||||
return utils.asyncify(callback)(null, false);
|
return callback(null, false);
|
||||||
|
|
||||||
if (minTime === -1)
|
if (minTime === -1)
|
||||||
return utils.asyncify(callback)(null, true);
|
return callback(null, true);
|
||||||
|
|
||||||
prev.getMedianTimeAsync(function(err, medianTime) {
|
prev.getMedianTimeAsync(function(err, medianTime) {
|
||||||
if (err)
|
if (err)
|
||||||
|
|||||||
@ -209,9 +209,12 @@ function ChainDB(chain, options) {
|
|||||||
// Key size: 66b (* 2)
|
// Key size: 66b (* 2)
|
||||||
this.coinWindow = ((165 * 1024 + 2300 * 4) + (2300 * 66 * 2)) * 5;
|
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.cacheHash = new bcoin.lru(this.cacheWindow, 1);
|
||||||
this.cacheHeight = 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);
|
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() {
|
ChainEntry.prototype.__defineGetter__('rhash', function() {
|
||||||
return utils.revHex(this.hash);
|
return utils.revHex(this.hash);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -62,7 +62,8 @@ function Fullnode(options) {
|
|||||||
preload: false,
|
preload: false,
|
||||||
spv: false,
|
spv: false,
|
||||||
prune: this.options.prune,
|
prune: this.options.prune,
|
||||||
useCheckpoints: this.options.useCheckpoints
|
useCheckpoints: this.options.useCheckpoints,
|
||||||
|
coinCache: this.options.coinCache
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fee estimation.
|
// Fee estimation.
|
||||||
@ -120,6 +121,7 @@ function Fullnode(options) {
|
|||||||
fees: this.fees,
|
fees: this.fees,
|
||||||
db: this.db,
|
db: this.db,
|
||||||
location: this.location('walletdb'),
|
location: this.location('walletdb'),
|
||||||
|
useCheckpoints: this.options.useCheckpoints,
|
||||||
verify: false
|
verify: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -252,6 +252,8 @@ Peer.prototype._onConnect = function _onConnect() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._onAck = function _onAck(err) {
|
Peer.prototype._onAck = function _onAck(err) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
this._error(err);
|
this._error(err);
|
||||||
this.destroy();
|
this.destroy();
|
||||||
|
|||||||
@ -112,13 +112,16 @@ main.checkpoints = {
|
|||||||
225430: '32595730b165f097e7b806a679cf7f3e439040f750433808c101000000000000',
|
225430: '32595730b165f097e7b806a679cf7f3e439040f750433808c101000000000000',
|
||||||
250000: '14d2f24d29bed75354f3f88a5fb50022fc064b02291fdf873800000000000000',
|
250000: '14d2f24d29bed75354f3f88a5fb50022fc064b02291fdf873800000000000000',
|
||||||
279000: '407ebde958e44190fa9e810ea1fc3a7ef601c3b0a0728cae0100000000000000',
|
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.lastHeight = 382320;
|
||||||
main.checkpoints.txsLastCheckpoint = 36544669;
|
|
||||||
main.checkpoints.txsPerDay = 60000.0;
|
|
||||||
main.checkpoints.lastHeight = 295000;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @const {Number}
|
* @const {Number}
|
||||||
@ -474,9 +477,6 @@ testnet.checkpoints = {
|
|||||||
546: '70cb6af7ebbcb1315d3414029c556c55f3e2fc353c4c9063a76c932a00000000'
|
546: '70cb6af7ebbcb1315d3414029c556c55f3e2fc353c4c9063a76c932a00000000'
|
||||||
};
|
};
|
||||||
|
|
||||||
testnet.checkpoints.tsLastCheckpoint = 1338180505;
|
|
||||||
testnet.checkpoints.txsLastCheckpoint = 16341;
|
|
||||||
testnet.checkpoints.txsPerDay = 300;
|
|
||||||
testnet.checkpoints.lastHeight = 546;
|
testnet.checkpoints.lastHeight = 546;
|
||||||
|
|
||||||
testnet.halvingInterval = 210000;
|
testnet.halvingInterval = 210000;
|
||||||
@ -618,9 +618,6 @@ regtest.alertKey = new Buffer(
|
|||||||
'hex');
|
'hex');
|
||||||
|
|
||||||
regtest.checkpoints = {};
|
regtest.checkpoints = {};
|
||||||
regtest.checkpoints.tsLastCheckpoint = 0;
|
|
||||||
regtest.checkpoints.txsLastCheckpoint = 0;
|
|
||||||
regtest.checkpoints.txsPerDay = 300;
|
|
||||||
regtest.checkpoints.lastHeight = 0;
|
regtest.checkpoints.lastHeight = 0;
|
||||||
|
|
||||||
regtest.halvingInterval = 150;
|
regtest.halvingInterval = 150;
|
||||||
@ -760,9 +757,6 @@ segnet3.alertKey = new Buffer(
|
|||||||
'hex');
|
'hex');
|
||||||
|
|
||||||
segnet3.checkpoints = {};
|
segnet3.checkpoints = {};
|
||||||
segnet3.checkpoints.tsLastCheckpoint = 0;
|
|
||||||
segnet3.checkpoints.txsLastCheckpoint = 0;
|
|
||||||
segnet3.checkpoints.txsPerDay = 300;
|
|
||||||
segnet3.checkpoints.lastHeight = 0;
|
segnet3.checkpoints.lastHeight = 0;
|
||||||
|
|
||||||
segnet3.halvingInterval = 210000;
|
segnet3.halvingInterval = 210000;
|
||||||
@ -880,9 +874,6 @@ segnet4.alertKey = new Buffer(
|
|||||||
'hex');
|
'hex');
|
||||||
|
|
||||||
segnet4.checkpoints = {};
|
segnet4.checkpoints = {};
|
||||||
segnet4.checkpoints.tsLastCheckpoint = 0;
|
|
||||||
segnet4.checkpoints.txsLastCheckpoint = 0;
|
|
||||||
segnet4.checkpoints.txsPerDay = 300;
|
|
||||||
segnet4.checkpoints.lastHeight = 0;
|
segnet4.checkpoints.lastHeight = 0;
|
||||||
|
|
||||||
segnet4.halvingInterval = 210000;
|
segnet4.halvingInterval = 210000;
|
||||||
|
|||||||
@ -349,6 +349,11 @@ TXDB.prototype.addBlock = function addBlock(block, txs, callback, force) {
|
|||||||
|
|
||||||
callback = utils.wrap(callback, unlock);
|
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))
|
if (!Array.isArray(txs))
|
||||||
txs = [txs];
|
txs = [txs];
|
||||||
|
|
||||||
|
|||||||
@ -71,7 +71,8 @@ function WalletDB(options) {
|
|||||||
|
|
||||||
this.tx = new bcoin.txdb(this, {
|
this.tx = new bcoin.txdb(this, {
|
||||||
verify: this.options.verify,
|
verify: this.options.verify,
|
||||||
useFilter: true
|
useCheckpoints: this.options.useCheckpoints,
|
||||||
|
useFilter: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (bcoin.useWorkers)
|
if (bcoin.useWorkers)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user