drop old caching mechanism.

This commit is contained in:
Christopher Jeffrey 2016-05-05 19:48:59 -07:00
parent 5fd44dbed8
commit 4d937e642a
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
2 changed files with 52 additions and 99 deletions

View File

@ -468,42 +468,45 @@ Chain.prototype._verify = function _verify(block, prev, callback) {
var ret = {};
var height, ts, i, tx, medianTime, commitmentHash;
function done(err, result) {
prev.free();
callback(err, result);
}
if (!block.verify(ret))
return done(new VerifyError(block, 'invalid', ret.reason, ret.score));
return callback(new VerifyError(block, 'invalid', ret.reason, ret.score));
if (this.options.spv || block.type !== 'block')
return done(null, constants.flags.MANDATORY_VERIFY_FLAGS);
return callback(null, constants.flags.MANDATORY_VERIFY_FLAGS);
// Skip the genesis block
if (block.isGenesis())
return done(null, constants.flags.MANDATORY_VERIFY_FLAGS);
return callback(null, constants.flags.MANDATORY_VERIFY_FLAGS);
// Ensure it's not an orphan
if (!prev)
return done(new VerifyError(block, 'invalid', 'bad-prevblk', 0));
return callback(new VerifyError(block, 'invalid', 'bad-prevblk', 0));
prev.ensureAncestors(function(err) {
prev.getRetargetAncestors(function(err, ancestors) {
if (err)
return done(err);
return callback(err);
height = prev.height + 1;
medianTime = prev.getMedianTime();
// Ensure the timestamp is correct
if (block.ts <= medianTime)
return done(new VerifyError(block, 'invalid', 'time-too-old', 0));
if (block.ts <= medianTime) {
return callback(new VerifyError(block,
'invalid',
'time-too-old',
0));
}
if (block.bits !== self.getTarget(prev, block))
return done(new VerifyError(block, 'invalid', 'bad-diffbits', 100));
if (block.bits !== self.getTarget(prev, block, ancestors)) {
return callback(new VerifyError(block,
'invalid',
'bad-diffbits',
100));
}
self._checkDeployments(block, prev, function(err, state) {
self._checkDeployments(block, prev, ancestors, function(err, state) {
if (err)
return done(err);
return callback(err);
// Expose the state of csv and segwit globally.
self.csvActive = state.csv;
@ -511,12 +514,16 @@ Chain.prototype._verify = function _verify(block, prev, callback) {
// Can't verify any further when merkleblock or headers.
if (block.type !== 'block')
return done(null, state.flags);
return callback(null, state.flags);
// Make sure the height contained in the coinbase is correct.
if (state.coinbaseHeight) {
if (block.getCoinbaseHeight() !== height)
return done(new VerifyError(block, 'invalid', 'bad-cb-height', 100));
if (block.getCoinbaseHeight() !== height) {
return callback(new VerifyError(block,
'invalid',
'bad-cb-height',
100));
}
}
// Check the commitment hash for segwit.
@ -524,13 +531,13 @@ Chain.prototype._verify = function _verify(block, prev, callback) {
commitmentHash = block.commitmentHash;
if (commitmentHash) {
if (!block.witnessNonce) {
return done(new VerifyError(block,
return callback(new VerifyError(block,
'invalid',
'bad-witness-merkle-size',
100));
}
if (commitmentHash !== block.getCommitmentHash('hex')) {
return done(new VerifyError(block,
return callback(new VerifyError(block,
'invalid',
'bad-witness-merkle-match',
100));
@ -542,7 +549,7 @@ Chain.prototype._verify = function _verify(block, prev, callback) {
// witness data data cannot contain it.
if (!commitmentHash) {
if (block.hasWitness()) {
return done(new VerifyError(block,
return callback(new VerifyError(block,
'invalid',
'unexpected-witness',
100));
@ -552,7 +559,7 @@ Chain.prototype._verify = function _verify(block, prev, callback) {
// Check block cost (different from block size
// check in non-contextual verification).
if (block.getCost() > constants.block.MAX_COST) {
return done(new VerifyError(block,
return callback(new VerifyError(block,
'invalid',
'bad-blk-cost',
100));
@ -570,14 +577,14 @@ Chain.prototype._verify = function _verify(block, prev, callback) {
// Transactions must be finalized with
// regards to nSequence and nLockTime.
if (!tx.isFinal(height, ts)) {
return done(new VerifyError(block,
return callback(new VerifyError(block,
'invalid',
'bad-txns-nonfinal',
10));
}
}
return done(null, state);
return callback(null, state);
});
});
};
@ -587,11 +594,12 @@ Chain.prototype._verify = function _verify(block, prev, callback) {
* @private
* @param {Block} block
* @param {ChainBlock} prev
* @param {ChainBlock[]} ancestors
* @param {Function} callback - Returns
* [{@link VerifyError}, {@link DeploymentState}].
*/
Chain.prototype._checkDeployments = function _checkDeployments(block, prev, callback) {
Chain.prototype._checkDeployments = function _checkDeployments(block, prev, ancestors, callback) {
var self = this;
var height = prev.height + 1;
var state = {
@ -615,41 +623,41 @@ Chain.prototype._checkDeployments = function _checkDeployments(block, prev, call
// Only allow version 2 blocks (coinbase height)
// once the majority of blocks are using it.
if (block.version < 2 && prev.isOutdated(2))
if (block.version < 2 && prev.isOutdated(2, ancestors))
return callback(new VerifyError(block, 'obsolete', 'bad-version', 0));
// Only allow version 3 blocks (sig validation)
// once the majority of blocks are using it.
if (block.version < 3 && prev.isOutdated(3))
if (block.version < 3 && prev.isOutdated(3, ancestors))
return callback(new VerifyError(block, 'obsolete', 'bad-version', 0));
// Only allow version 4 blocks (checklocktimeverify)
// once the majority of blocks are using it.
if (block.version < 4 && prev.isOutdated(4))
if (block.version < 4 && prev.isOutdated(4, ancestors))
return callback(new VerifyError(block, 'obsolete', 'bad-version', 0));
// Only allow version 5 blocks (bip141 - segnet3)
// once the majority of blocks are using it.
if (network.segwitHeight !== -1 && height >= network.segwitHeight) {
if (block.version < 5 && prev.isOutdated(5))
if (block.version < 5 && prev.isOutdated(5, ancestors))
return callback(new VerifyError(block, 'obsolete', 'bad-version', 0));
}
// Make sure the height contained in the coinbase is correct.
if (block.version >= 2 && prev.isUpgraded(2))
if (block.version >= 2 && prev.isUpgraded(2, ancestors))
state.coinbaseHeight = true;
// Signature validation is now enforced (bip66)
if (block.version >= 3 && prev.isUpgraded(3))
if (block.version >= 3 && prev.isUpgraded(3, ancestors))
state.flags |= constants.flags.VERIFY_DERSIG;
// CHECKLOCKTIMEVERIFY is now usable (bip65)
if (block.version >= 4 && prev.isUpgraded(4))
if (block.version >= 4 && prev.isUpgraded(4, ancestors))
state.flags |= constants.flags.VERIFY_CHECKLOCKTIMEVERIFY;
// Segregrated witness is now usable (bip141 - segnet3)
if (network.segwitHeight !== -1 && height >= network.segwitHeight) {
if (block.version >= 5 && prev.isUpgraded(5)) {
if (block.version >= 5 && prev.isUpgraded(5, ancestors)) {
state.flags |= constants.flags.VERIFY_WITNESS;
state.segwit = true;
}
@ -2046,7 +2054,6 @@ Chain.prototype.getTargetAsync = function getTargetAsync(last, block, callback)
/**
* Calculate the target synchronously. _Must_
* have ancestors pre-allocated.
* @see ChainBlock#ensureAncestors.
* @param {ChainBlock} last - Previous entry.
* @param {Block|MerkleBlock|null} - Current block.
* @param {Function} callback - returns [Error, Number]
@ -2061,9 +2068,6 @@ Chain.prototype.getTarget = function getTarget(last, block, ancestors) {
if (!last)
return powLimit;
if (!ancestors)
ancestors = last.ancestors;
// Do not retarget
if ((last.height + 1) % network.pow.retargetInterval !== 0) {
if (network.pow.allowMinDifficultyBlocks) {
@ -2391,21 +2395,17 @@ Chain.prototype._getInitialState = function _getInitialState(callback) {
return callback();
}
prev.ensureAncestors(function(err) {
if (err) {
prev.free();
prev.getRetargetAncestors(function(err, ancestors) {
if (err)
return callback(err);
}
self._checkDeployments(self.tip, prev, function(err, state) {
if (err) {
prev.free();
self._checkDeployments(self.tip, prev, ancestors, function(err, state) {
if (err)
return callback(err);
}
self.csvActive = state.csv;
self.segwitActive = state.segwit;
prev.free();
return callback();
});
});

View File

@ -57,7 +57,6 @@ function ChainBlock(chain, data, prev) {
this.nonce = data.nonce;
this.height = data.height;
this.chainwork = data.chainwork || this.getChainwork(prev);
this.ancestors = [];
}
/**
@ -99,7 +98,7 @@ ChainBlock.prototype.isGenesis = function isGenesis() {
* @param {Function} callback
*/
ChainBlock.prototype.ensureAncestors = function ensureAncestors(callback) {
ChainBlock.prototype.getRetargetAncestors = function getRetargetAncestors(callback) {
var majorityWindow = network.block.majorityWindow;
var medianTimespan = constants.block.MEDIAN_TIMESPAN;
var powDiffInterval = network.pow.retargetInterval;
@ -107,33 +106,7 @@ ChainBlock.prototype.ensureAncestors = function ensureAncestors(callback) {
var max = Math.max(majorityWindow, medianTimespan);
if ((this.height + 1) % powDiffInterval === 0 || allowMinDiff)
max = Math.max(max, powDiffInterval);
assert(this.ancestors.length === 0);
return this.alloc(max, callback);
};
/**
* Allocate ancestors.
* @param {Number} max - Number of ancestors.
* @param {Function} callback
*/
ChainBlock.prototype.alloc = function alloc(max, callback) {
var self = this;
var i;
return this.getAncestors(max, function(err, ancestors) {
if (err)
return callback(err);
assert(ancestors);
self.ancestors.length = 0;
for (i = 0; i < ancestors.length; i++)
self.ancestors.push(ancestors[i]);
return callback();
});
return this.getAncestors(max, callback);
};
/**
@ -144,14 +117,11 @@ ChainBlock.prototype.alloc = function alloc(max, callback) {
ChainBlock.prototype.getAncestors = function getAncestors(max, callback) {
var entry = this;
var ancestors = this.ancestors.slice();
var ancestors = [];
if (max === 0)
return callback(null, []);
if (ancestors.length)
entry = ancestors.pop();
assert(utils.isNumber(max));
// Try to do this iteratively and synchronously
@ -186,15 +156,6 @@ ChainBlock.prototype.getAncestors = function getAncestors(max, callback) {
})(null, entry);
};
/**
* Free up ancestors. This is very important because
* chain entries are cached in the ChainDB's LRU cache.
*/
ChainBlock.prototype.free = function free() {
this.ancestors.length = 0;
};
/**
* Test whether the entry is in the main chain.
* @param {Function} callback - Return [Error, Boolean].
@ -291,9 +252,6 @@ ChainBlock.prototype.getMedianTime = function getMedianTime(ancestors) {
var timeSpan = constants.block.MEDIAN_TIMESPAN;
var i;
if (!ancestors)
ancestors = this.ancestors;
for (i = 0; i < timeSpan && entry; i++, entry = ancestors[i])
median.push(entry.ts);
@ -382,9 +340,6 @@ ChainBlock.prototype.isSuperMajority = function isSuperMajority(version, require
var majorityWindow = network.block.majorityWindow;
var i;
if (!ancestors)
ancestors = this.ancestors;
for (i = 0; i < majorityWindow && found < required && entry; i++) {
if (entry.version >= version)
found++;
@ -502,9 +457,7 @@ ChainBlock.fromJSON = function fromJSON(chain, json) {
*/
ChainBlock.prototype.inspect = function inspect() {
var json = this.toJSON();
json.ancestors = this.ancestors.length;
return json;
return this.toJSON();
};
/**