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

View File

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