diff --git a/lib/bcoin/chain.js b/lib/bcoin/chain.js index fc812373..d04b66e2 100644 --- a/lib/bcoin/chain.js +++ b/lib/bcoin/chain.js @@ -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 */ diff --git a/lib/bcoin/wallet.js b/lib/bcoin/wallet.js index a0691ffc..c94b9d09 100644 --- a/lib/bcoin/wallet.js +++ b/lib/bcoin/wallet.js @@ -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 {