chain deployment state.

This commit is contained in:
Christopher Jeffrey 2016-06-30 10:58:00 -07:00
parent eb4f16f2b7
commit 4b7d4a3c8d
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
2 changed files with 90 additions and 31 deletions

View File

@ -498,14 +498,8 @@ Chain.prototype._verify = function _verify(block, prev, callback) {
return callback(new VerifyError(block, 'invalid', ret.reason, ret.score));
// Skip the genesis block. Skip all blocks in spv mode.
if (this.options.spv || this.isGenesis(block)) {
return callback(null, {
flags: constants.flags.MANDATORY_VERIFY_FLAGS,
lockFlags: constants.flags.MANDATORY_LOCKTIME_FLAGS,
segwit: false,
csv: false
});
}
if (this.options.spv || this.isGenesis(block))
return callback(null, new DeploymentState());
// Ensure it's not an orphan
if (!prev) {
@ -542,15 +536,15 @@ Chain.prototype._verify = function _verify(block, prev, callback) {
return callback(err);
// Expose the state of csv and segwit globally.
self.csvActive = state.csv;
self.segwitActive = state.segwit;
self.csvActive = state.hasCSV();
self.segwitActive = state.hasWitness();
// Can't verify any further when merkleblock or headers.
if (self.options.spv)
return callback(null, state);
// Make sure the height contained in the coinbase is correct.
if (state.coinbaseHeight) {
if (state.hasBIP34()) {
if (block.getCoinbaseHeight() !== height) {
return callback(new VerifyError(block,
'invalid',
@ -560,7 +554,7 @@ Chain.prototype._verify = function _verify(block, prev, callback) {
}
// Check the commitment hash for segwit.
if (state.segwit) {
if (state.hasWitness()) {
commitmentHash = block.commitmentHash;
if (commitmentHash) {
if (!block.witnessNonce) {
@ -635,13 +629,7 @@ Chain.prototype._verify = function _verify(block, prev, callback) {
Chain.prototype._checkDeployments = function _checkDeployments(block, prev, ancestors, callback) {
var self = this;
var height = prev.height + 1;
var state = {
flags: constants.flags.MANDATORY_VERIFY_FLAGS,
lockFlags: constants.flags.MANDATORY_LOCKTIME_FLAGS,
coinbaseHeight: false,
segwit: false,
csv: false
};
var state = new DeploymentState();
// For some reason bitcoind has p2sh in the
// mandatory flags by default, when in reality
@ -651,8 +639,8 @@ Chain.prototype._checkDeployments = function _checkDeployments(block, prev, ance
// not have a signature. See:
// 6a26d2ecb67f27d1fa5524763b49029d7106e91e3cc05743073461a719776192
// 9c08a4d78931342b37fd5f72900fb9983087e6f46c4a097d8a1f52c74e28eaf6
if (block.ts < constants.block.BIP16_TIME)
state.flags &= ~constants.flags.VERIFY_P2SH;
if (block.ts >= constants.block.BIP16_TIME)
state.flags |= constants.flags.VERIFY_P2SH;
// Only allow version 2 blocks (coinbase height)
// once the majority of blocks are using it.
@ -678,7 +666,7 @@ Chain.prototype._checkDeployments = function _checkDeployments(block, prev, ance
// Make sure the height contained in the coinbase is correct.
if (block.version >= 2 && prev.isUpgraded(2, ancestors))
state.coinbaseHeight = true;
state.bip34 = true;
// Signature validation is now enforced (bip66)
if (block.version >= 3 && prev.isUpgraded(3, ancestors))
@ -690,10 +678,8 @@ Chain.prototype._checkDeployments = function _checkDeployments(block, prev, ance
// Segregrated witness is now usable (bip141 - segnet3)
if (this.network.segwitHeight !== -1 && height >= this.network.segwitHeight) {
if (block.version >= 5 && prev.isUpgraded(5, ancestors)) {
if (block.version >= 5 && prev.isUpgraded(5, ancestors))
state.flags |= constants.flags.VERIFY_WITNESS;
state.segwit = true;
}
}
utils.serial([
@ -708,7 +694,6 @@ Chain.prototype._checkDeployments = function _checkDeployments(block, prev, ance
state.flags |= constants.flags.VERIFY_CHECKSEQUENCEVERIFY;
state.lockFlags |= constants.flags.VERIFY_SEQUENCE;
state.lockFlags |= constants.flags.MEDIAN_TIME_PAST;
state.csv = true;
}
return next();
@ -720,10 +705,8 @@ Chain.prototype._checkDeployments = function _checkDeployments(block, prev, ance
if (err)
return next(err);
if (active) {
if (active)
state.flags |= constants.flags.VERIFY_WITNESS;
state.segwit = true;
}
return next();
});
@ -2366,8 +2349,8 @@ Chain.prototype._getInitialState = function _getInitialState(callback) {
if (err)
return callback(err);
self.csvActive = state.csv;
self.segwitActive = state.segwit;
self.csvActive = state.hasCSV();
self.segwitActive = state.hasWitness();
return callback();
});
@ -2509,6 +2492,78 @@ Chain.prototype.checkLocks = function checkLocks(prev, tx, flags, callback) {
});
};
/**
* Represents the deployment state of the chain.
* @constructor
* @property {VerifyFlags} flags
* @property {LockFlags} lockFlags
* @property {Boolean} bip34
*/
function DeploymentState() {
if (!(this instanceof DeploymentState))
return new DeploymentState();
this.flags = constants.flags.MANDATORY_VERIFY_FLAGS;
this.flags &= ~constants.flags.VERIFY_P2SH;
this.lockFlags = constants.flags.MANDATORY_LOCKTIME_FLAGS;
this.bip34 = false;
}
/**
* Test whether p2sh is active.
* @returns {Boolean}
*/
DeploymentState.prototype.hasP2SH = function hasP2SH() {
return (this.flags & constants.flags.VERIFY_P2SH) !== 0;
};
/**
* Test whether bip34 (coinbase height) is active.
* @returns {Boolean}
*/
DeploymentState.prototype.hasBIP34 = function hasBIP34() {
return this.bip34;
};
/**
* Test whether bip66 (VERIFY_DERSIG) is active.
* @returns {Boolean}
*/
DeploymentState.prototype.hasBIP66 = function hasBIP66() {
return (this.flags & constants.flags.VERIFY_DERSIG) !== 0;
};
/**
* Test whether cltv is active.
* @returns {Boolean}
*/
DeploymentState.prototype.hasCLTV = function hasCLTV() {
return (this.flags & constants.flags.VERIFY_CHECKLOCKTIMEVERIFY) !== 0;
};
/**
* Test whether csv is active.
* @returns {Boolean}
*/
DeploymentState.prototype.hasCSV = function hasCSV() {
return (this.flags & constants.flags.VERIFY_CHECKSEQUENCEVERIFY) !== 0;
};
/**
* Test whether segwit is active.
* @returns {Boolean}
*/
DeploymentState.prototype.hasWitness = function hasWitness() {
return (this.flags & constants.flags.VERIFY_WITNESS) !== 0;
};
/*
* Expose
*/

View File

@ -2719,9 +2719,13 @@ MasterKey.prototype.toJSON = function toJSON() {
*/
MasterKey.prototype.fromJSON = function fromJSON(json) {
assert(typeof json.encrypted === 'boolean');
this.encrypted = json.encrypted;
if (json.encrypted) {
assert(typeof json.iv === 'string');
assert(typeof json.ciphertext === 'string');
this.iv = new Buffer(json.iv, 'hex');
this.ciphertext = new Buffer(json.ciphertext, 'hex');
} else {