diff --git a/etc/sample.conf b/etc/sample.conf index a1ffbeda..e63997e1 100644 --- a/etc/sample.conf +++ b/etc/sample.conf @@ -32,7 +32,6 @@ log-file: true # Chain # -witness: true prune: false checkpoints: true coin-cache: 40 diff --git a/lib/blockchain/chain.js b/lib/blockchain/chain.js index f895817d..2aa1ac1e 100644 --- a/lib/blockchain/chain.js +++ b/lib/blockchain/chain.js @@ -287,18 +287,6 @@ Chain.prototype.verify = co(function* verify(block, prev) { if (this.options.spv) return this.state; - // Skip any blocks below the - // last checkpoint. - if (!this.options.witness) { - // We can't skip this with segwit - // enabled since the block may have - // been malleated: we don't know - // until we verify the witness - // merkle root. - if (prev.isHistorical()) - return this.state; - } - ancestors = yield prev.getRetargetAncestors(); // Ensure the POW is what we expect. @@ -480,8 +468,7 @@ Chain.prototype.getDeployments = co(function* getDeployments(block, prev) { // Segregrated witness is now usable (bip141 - segnet4) active = yield this.isActive(prev, deployments.segwit); if (active) { - if (this.options.witness) - state.flags |= Script.flags.VERIFY_WITNESS; + state.flags |= Script.flags.VERIFY_WITNESS; // BIP147 state.flags |= Script.flags.VERIFY_NULLDUMMY; } @@ -1995,15 +1982,7 @@ Chain.prototype.findLocator = co(function* findLocator(locator) { */ Chain.prototype.isActive = co(function* isActive(prev, deployment) { - var state; - - if (!this.options.witness) { - if (prev.isHistorical()) - return false; - } - - state = yield this.getState(prev, deployment); - + var state = yield this.getState(prev, deployment); return state === common.thresholdStates.ACTIVE; }); @@ -2296,7 +2275,6 @@ function ChainOptions(options) { this.bufferKeys = !util.isBrowser; this.spv = false; - this.witness = true; this.prune = false; this.indexTX = false; this.indexAddress = false; @@ -2357,11 +2335,6 @@ ChainOptions.prototype.fromOptions = function fromOptions(options) { this.spv = options.spv; } - if (options.witness != null) { - assert(typeof options.witness === 'boolean'); - this.witness = options.witness; - } - if (options.prune != null) { assert(typeof options.prune === 'boolean'); this.prune = options.prune; diff --git a/lib/blockchain/chaindb.js b/lib/blockchain/chaindb.js index 5a240edb..39ae4fde 100644 --- a/lib/blockchain/chaindb.js +++ b/lib/blockchain/chaindb.js @@ -1867,7 +1867,7 @@ function ChainFlags(options) { this.network = Network.primary; this.spv = false; - this.witness = false; + this.witness = true; this.prune = false; this.indexTX = false; this.indexAddress = false; @@ -1884,11 +1884,6 @@ ChainFlags.prototype.fromOptions = function fromOptions(options) { this.spv = options.spv; } - if (options.witness != null) { - assert(typeof options.witness === 'boolean'); - this.witness = options.witness; - } - if (options.prune != null) { assert(typeof options.prune === 'boolean'); this.prune = options.prune; @@ -1922,11 +1917,8 @@ ChainFlags.prototype.verify = function verify(options) { throw new Error('Cannot retroactively disable SPV.'); if (!options.forceWitness) { - if (options.witness && !this.witness) + if (!this.witness) throw new Error('Cannot retroactively enable witness.'); - - if (!options.witness && this.witness) - throw new Error('Cannot retroactively disable witness.'); } if (options.prune && !this.prune) diff --git a/lib/net/common.js b/lib/net/common.js index 5cbfe0a8..b86e188d 100644 --- a/lib/net/common.js +++ b/lib/net/common.js @@ -115,8 +115,7 @@ exports.LOCAL_SERVICES = 0 */ exports.REQUIRED_SERVICES = 0 - | exports.services.NETWORK - | exports.services.WITNESS; + | exports.services.NETWORK; /** * Default user agent: `/bcoin:[version]/`. diff --git a/lib/net/peer.js b/lib/net/peer.js index e60566c9..2d17dac8 100644 --- a/lib/net/peer.js +++ b/lib/net/peer.js @@ -1407,7 +1407,7 @@ Peer.prototype.blockType = function blockType() { return invTypes.CMPCT_BLOCK; } - if (this.options.witness && this.hasWitness()) + if (this.hasWitness()) return invTypes.WITNESS_BLOCK; return invTypes.BLOCK; @@ -1419,7 +1419,7 @@ Peer.prototype.blockType = function blockType() { */ Peer.prototype.txType = function txType() { - if (this.options.witness && this.hasWitness()) + if (this.hasWitness()) return invTypes.WITNESS_TX; return invTypes.TX; @@ -1645,7 +1645,7 @@ Peer.prototype.handleVersion = co(function* handleVersion(packet) { throw new Error('Peer does not support BIP37.'); } - if (this.options.witness) { + if (this.options.hasWitness()) { if (!(this.services & services.WITNESS)) throw new Error('Peer does not support segregated witness.'); } @@ -1815,12 +1815,6 @@ Peer.prototype.handleFeeFilter = co(function* handleFeeFilter(packet) { */ Peer.prototype.handleSendCmpct = co(function* handleSendCmpct(packet) { - var max = this.options.witness ? 2 : 1; - - // Core witness nodes send this twice - // with both version 1 and 2 (why - // would you even _want_ non-witness - // blocks if you use segwit??). if (this.compactMode !== -1) { this.logger.debug( 'Peer sent a duplicate sendcmpct (%s).', @@ -1828,7 +1822,7 @@ Peer.prototype.handleSendCmpct = co(function* handleSendCmpct(packet) { return; } - if (packet.version > max) { + if (packet.version > 2) { // Ignore this.logger.info( 'Peer request compact blocks version %d (%s).', @@ -2041,9 +2035,16 @@ Peer.prototype.sendReject = function sendReject(code, reason, msg) { */ Peer.prototype.sendCompact = function sendCompact(mode) { - var version = this.options.witness ? 2 : 1; this.logger.info('Initializing compact blocks (%s).', this.hostname()); - this.send(new packets.SendCmpctPacket(mode, version)); + + if (this.services & common.services.WITNESS) { + if (this.version >= common.COMPACT_WITNESS_VERSION) { + this.send(new packets.SendCmpctPacket(mode, 2)); + return; + } + } + + this.send(new packets.SendCmpctPacket(mode, 1)); }; /** @@ -2115,7 +2116,7 @@ Peer.prototype.hasCompact = function hasCompact() { if (this.version < common.COMPACT_VERSION) return false; - if (!this.options.witness) + if (!this.options.hasWitness()) return true; if (!(this.services & services.WITNESS)) @@ -2159,12 +2160,12 @@ function PeerOptions(options) { this.noRelay = false; this.spv = false; this.compact = false; - this.witness = true; this.headers = false; this.banScore = common.BAN_SCORE; this.getHeight = PeerOptions.getHeight; this.isFull = PeerOptions.isFull; + this.hasWitness = PeerOptions.hasWitness; this.createNonce = PeerOptions.createNonce; this.hasNonce = PeerOptions.hasNonce; this.getRate = PeerOptions.getRate; @@ -2236,11 +2237,6 @@ PeerOptions.prototype.fromOptions = function fromOptions(options) { this.compact = options.compact; } - if (options.witness != null) { - assert(typeof options.witness === 'boolean'); - this.witness = options.witness; - } - if (options.headers != null) { assert(typeof options.headers === 'boolean'); this.headers = options.headers; @@ -2261,6 +2257,11 @@ PeerOptions.prototype.fromOptions = function fromOptions(options) { this.isFull = options.isFull; } + if (options.hasWitness != null) { + assert(typeof options.hasWitness === 'function'); + this.hasWitness = options.hasWitness; + } + if (options.createNonce != null) { assert(typeof options.createNonce === 'function'); this.createNonce = options.createNonce; @@ -2309,6 +2310,16 @@ PeerOptions.isFull = function isFull() { return false; }; +/** + * Whether segwit is enabled. + * @private + * @returns {Boolean} + */ + +PeerOptions.hasWitness = function hasWitness() { + return true; +}; + /** * Create a version packet nonce. * @private diff --git a/lib/net/pool.js b/lib/net/pool.js index 7c47e0d5..d305de5a 100644 --- a/lib/net/pool.js +++ b/lib/net/pool.js @@ -602,7 +602,7 @@ Pool.prototype.sendSync = co(function* sendSync(peer) { if (!(peer.services & services.NETWORK)) return false; - if (this.options.witness && !peer.hasWitness()) + if (this.options.hasWitness() && !peer.hasWitness()) return false; if (!peer.loader) { @@ -826,7 +826,7 @@ Pool.prototype.sendBlock = co(function* sendBlock(peer, item, witness) { // If we have the same serialization, we // can write the raw binary to the socket. - if (witness === this.chain.options.witness) { + if (witness || !this.options.hasWitness()) { block = yield this.chain.db.getRawBlock(item.hash); if (block) { @@ -1278,7 +1278,7 @@ Pool.prototype.handleGetAddr = co(function* handleGetAddr(peer, packet) { Pool.prototype.handleAddr = co(function* handleAddr(peer, packet) { var addrs = packet.items; var now = this.network.now(); - var services = this.options.requiredServices; + var services = this.options.getRequiredServices(); var i, addr; for (i = 0; i < addrs.length; i++) { @@ -1395,7 +1395,7 @@ Pool.prototype.handleBlockInv = co(function* handleBlockInv(peer, hashes) { if (!this.chain.synced && !peer.loader) return; - if (this.options.witness && !peer.hasWitness()) + if (this.options.hasWitness() && !peer.hasWitness()) return; // Request headers instead. @@ -2341,7 +2341,7 @@ Pool.prototype.handleSendCmpct = co(function* handleSendCmpct(peer, packet) { Pool.prototype.handleCmpctBlock = co(function* handleCmpctBlock(peer, packet) { var block = packet.block; var hash = block.hash('hex'); - var witness = this.options.witness; + var witness = peer.hasWitness(); var result; if (!this.syncing) @@ -2603,7 +2603,7 @@ Pool.prototype.addInbound = function addInbound(socket) { */ Pool.prototype.getHost = function getHost() { - var services = this.options.requiredServices; + var services = this.options.getRequiredServices(); var now = this.network.now(); var i, entry, addr; @@ -3192,7 +3192,6 @@ function PoolOptions(options) { this.address = new NetAddress(); this.address.port = this.network.port; - this.witness = true; this.checkpoints = true; this.spv = false; this.listen = false; @@ -3257,14 +3256,6 @@ PoolOptions.prototype.fromOptions = function fromOptions(options) { this.mempool = options.mempool; } - if (options.witness != null) { - assert(typeof options.witness === 'boolean'); - assert(options.witness === this.chain.options.witness); - this.witness = options.witness; - } else { - this.witness = this.chain.options.witness; - } - if (options.checkpoints != null) { assert(typeof options.checkpoints === 'boolean'); assert(options.checkpoints === this.chain.options.checkpoints); @@ -3430,11 +3421,6 @@ PoolOptions.prototype.fromOptions = function fromOptions(options) { this.blockMode = options.blockMode; } - if (!this.witness) { - this.services &= ~common.services.WITNESS; - this.requiredServices &= ~common.services.WITNESS; - } - if (this.spv) { this.requiredServices |= common.services.BLOOM; this.services &= ~common.services.NETWORK; @@ -3491,6 +3477,29 @@ PoolOptions.prototype.isFull = function isFull() { return this.chain.synced; }; +/** + * Get required services for outbound peers. + * @private + * @returns {Number} + */ + +PoolOptions.prototype.getRequiredServices = function getRequiredServices() { + var services = this.options.requiredServices; + if (this.hasWitness()) + services |= common.services.WITNESS; + return services; +}; + +/** + * Whether segwit is enabled. + * @private + * @returns {Boolean} + */ + +PoolOptions.prototype.hasWitness = function hasWitness() { + return this.chain.state.hasWitness(); +}; + /** * Create a version packet nonce. * @private diff --git a/lib/node/config.js b/lib/node/config.js index 3943a4cc..d0082747 100644 --- a/lib/node/config.js +++ b/lib/node/config.js @@ -171,7 +171,6 @@ config.parseData = function parseData(data, prefix, dirname) { options.logFile = boolpath(data.logfile, prefix, dirname); // Chain - options.witness = bool(data.witness); options.forceWitness = bool(data.forcewitness); options.prune = bool(data.prune); options.checkpoints = bool(data.checkpoints); diff --git a/lib/node/fullnode.js b/lib/node/fullnode.js index 88f5d9c8..8daffe3a 100644 --- a/lib/node/fullnode.js +++ b/lib/node/fullnode.js @@ -66,7 +66,6 @@ function FullNode(options) { location: this.location('chain'), maxFiles: this.options.maxFiles, cacheSize: this.options.cacheSize, - witness: this.options.witness, forceWitness: this.options.forceWitness, prune: this.options.prune, checkpoints: this.options.checkpoints, diff --git a/lib/node/spvnode.js b/lib/node/spvnode.js index 0f159212..d89a614d 100644 --- a/lib/node/spvnode.js +++ b/lib/node/spvnode.js @@ -51,7 +51,6 @@ function SPVNode(options) { location: this.location('spvchain'), maxFiles: this.options.maxFiles, cacheSize: this.options.cacheSize, - witness: this.options.witness, forceWitness: this.options.forceWitness, checkpoints: this.options.checkpoints, spv: true @@ -61,7 +60,6 @@ function SPVNode(options) { network: this.network, logger: this.logger, chain: this.chain, - witness: this.options.witness, proxyServer: this.options.proxyServer, seeds: this.options.seeds, nodes: this.options.nodes, diff --git a/migrate/chaindb1to2.js b/migrate/chaindb1to2.js index 6a7225a7..96f2f015 100644 --- a/migrate/chaindb1to2.js +++ b/migrate/chaindb1to2.js @@ -30,7 +30,6 @@ db = LDB({ options = {}; options.spv = process.argv.indexOf('--spv') !== -1; -options.witness = process.argv.indexOf('--witness') !== -1; options.prune = process.argv.indexOf('--prune') !== -1; options.indexTX = process.argv.indexOf('--index-tx') !== -1; options.indexAddress = process.argv.indexOf('--index-address') !== -1;