diff --git a/lib/bcoin/chain.js b/lib/bcoin/chain.js index ba60c3f2..9025f4e9 100644 --- a/lib/bcoin/chain.js +++ b/lib/bcoin/chain.js @@ -42,6 +42,7 @@ function Chain(node, options) { this.lastUpdate = utils.now(); this.tip = null; this.height = -1; + this.segwitActive = null; this.orphan = { map: {}, @@ -153,20 +154,25 @@ Chain.prototype._init = function _init() { if (err) return self.emit('error', err); - self.db.getTip(function(err, tip) { + self.isSegwitActive(function(err) { if (err) return self.emit('error', err); - assert(tip); + self.db.getTip(function(err, tip) { + if (err) + return self.emit('error', err); - self.tip = tip; - self.height = tip.height; + assert(tip); - self.loaded = true; - self.emit('open'); + self.tip = tip; + self.height = tip.height; - if (self.isFull()) - self.emit('full'); + self.loaded = true; + self.emit('open'); + + if (self.isFull()) + self.emit('full'); + }); }); }); }); @@ -489,6 +495,9 @@ Chain.prototype._verify = function _verify(block, prev, peer, callback) { if (block.version >= 5 && prev.isUpgraded(5)) { flags |= constants.flags.VERIFY_WITNESS; segwit = true; + self.segwitActive = true; + } else if (block.version >= 5) { + self.segwitActive = false; } } @@ -1878,6 +1887,41 @@ Chain.prototype.computeBlockVersion = function computeBlockVersion(prev, callbac }); }; +Chain.prototype.isSegwitActive = function isSegwitActive(callback) { + var tip = this.tip; + var unlock; + + if (this.segwitActive != null) + return utils.asyncify(callback)(null, this.segwitActive); + + if (!tip) + return utils.asyncify(callback)(null, false); + + if (!(network.segwitHeight !== -1 && height >= network.segwitHeight)) + return utils.asyncify(callback)(null, false); + + unlock = this._lock(isSegwitActive, [callback]); + if (!unlock) + return; + + callback = utils.wrap(callback, unlock); + + tip.ensureAncestors(function(err) { + if (err) + return callback(err); + + if (!tip.isUpgraded(5)) { + tip.free(); + self.segwitActive = false; + return callback(null, false); + } + + tip.free(); + self.segwitActive = true; + return callback(null, true); + }); +}; + /** * Expose */ diff --git a/lib/bcoin/mempool.js b/lib/bcoin/mempool.js index 757a51c0..88403141 100644 --- a/lib/bcoin/mempool.js +++ b/lib/bcoin/mempool.js @@ -339,8 +339,8 @@ Mempool.prototype.addTX = function addTX(tx, peer, callback, force) { if (!tx.hasPrevout()) { if (self.size > Mempool.MAX_MEMPOOL_SIZE) { - return callback( - new VerifyError('insufficientfee', + return callback(new VerifyError( + 'insufficientfee', 'mempool full', 0)); } @@ -359,8 +359,8 @@ Mempool.prototype.addTX = function addTX(tx, peer, callback, force) { return callback(err); if (!result) { - return callback( - new VerifyError('insufficientfee', + return callback(new VerifyError( + 'insufficientfee', 'mempool full', 0)); } @@ -415,13 +415,18 @@ Mempool.prototype.verify = function verify(tx, callback) { var self = this; var height = this.chain.height + 1; var total, input, coin, i, fee, now, free, minFee; + var flags = Mempool.flags; + var mandatory = Mempool.mandatory; - if (network.type !== 'segwit') { + if (this.chain.segwitActive) { + flags |= constants.flags.VERIFY_WITNESS; + mandatory |= constants.flags.VERIFY_WITNESS; + } else { if (tx.hasWitness()) return callback(new VerifyError('nonstandard', 'no-witness-yet', 0)); } - if (this.requireStandard && !tx.isStandardInputs(Mempool.flags)) { + if (this.requireStandard && !tx.isStandardInputs(flags)) { return callback(new VerifyError( 'nonstandard', 'bad-txns-nonstandard-inputs', @@ -529,12 +534,12 @@ Mempool.prototype.verify = function verify(tx, callback) { } // Do this in the worker pool. - tx.verifyAsync(null, true, Mempool.flags, function(err, result) { + tx.verifyAsync(null, true, flags, function(err, result) { if (err) return callback(err); if (!result) { - return tx.verifyAsync(null, true, Mempool.mandatory, function(err, result) { + return tx.verifyAsync(null, true, mandatory, function(err, result) { if (err) return callback(err); @@ -545,8 +550,8 @@ Mempool.prototype.verify = function verify(tx, callback) { 0)); } - return callback( - new VerifyError('nonstandard', + return callback(new VerifyError( + 'nonstandard', 'non-mandatory-script-verify-flag', 0)); });