drop old caching mechanism.
This commit is contained in:
parent
5fd44dbed8
commit
4d937e642a
@ -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();
|
||||
});
|
||||
});
|
||||
|
||||
@ -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();
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user