diff --git a/lib/bcoin/chain.js b/lib/bcoin/chain.js index 7f093ff8..8fad723e 100644 --- a/lib/bcoin/chain.js +++ b/lib/bcoin/chain.js @@ -154,21 +154,24 @@ Chain.prototype._init = function _init() { if (err) return self.emit('error', err); - self.isSegwitActive(function(err) { + self.db.getTip(function(err, tip) { if (err) return self.emit('error', err); - self.db.getTip(function(err, tip) { + assert(tip); + + self.tip = tip; + self.height = tip.height; + + if (self.bestHeight === -1) + network.height = tip.height; + + self.isSegwitActive(function(err, result) { if (err) return self.emit('error', err); - assert(tip); - - self.tip = tip; - self.height = tip.height; - - if (self.bestHeight === -1) - network.height = tip.height; + if (result) + utils.debug('Segwit is active.'); self.loaded = true; self.emit('open'); @@ -1906,6 +1909,7 @@ Chain.prototype.computeBlockVersion = function computeBlockVersion(prev, callbac }; Chain.prototype.isSegwitActive = function isSegwitActive(callback) { + var self = this; var tip = this.tip; var unlock; @@ -1915,7 +1919,7 @@ Chain.prototype.isSegwitActive = function isSegwitActive(callback) { if (!tip) return utils.asyncify(callback)(null, false); - if (!(network.segwitHeight !== -1 && height >= network.segwitHeight)) + if (!(network.segwitHeight !== -1 && tip.height >= network.segwitHeight)) return utils.asyncify(callback)(null, false); unlock = this._lock(isSegwitActive, [callback]); diff --git a/lib/bcoin/coin.js b/lib/bcoin/coin.js index cde997ff..d1788056 100644 --- a/lib/bcoin/coin.js +++ b/lib/bcoin/coin.js @@ -22,12 +22,12 @@ var network = bcoin.protocol.network; function Coin(tx, index) { var options; - if (!(this instanceof Coin)) - return new Coin(tx, index); - if (tx instanceof Coin) return tx; + if (!(this instanceof Coin)) + return new Coin(tx, index); + if (tx instanceof bcoin.tx) { this.version = tx.version; this.height = tx.height; @@ -117,7 +117,7 @@ Coin.prototype.toJSON = function toJSON() { version: this.version, height: this.height, value: utils.btc(this.value), - script: utils.toHex(bcoin.protocol.framer(this.script)), + script: utils.toHex(bcoin.protocol.framer.script(this.script)), coinbase: this.coinbase, hash: this.hash ? utils.revHex(this.hash) : null, index: this.index diff --git a/lib/bcoin/mempool.js b/lib/bcoin/mempool.js index f291f6f5..48de5b75 100644 --- a/lib/bcoin/mempool.js +++ b/lib/bcoin/mempool.js @@ -360,6 +360,7 @@ Mempool.prototype.addTX = function addTX(tx, peer, callback, force) { 'mempool full', 0)); } + utils.debug('Added orphan %s to mempool.', tx.rhash); return self.storeOrphan(tx, callback); } @@ -412,6 +413,7 @@ Mempool.prototype.addUnchecked = function addUnchecked(tx, peer, callback) { self.addUnchecked(tx, peer, function(err) { if (err) self.emit('error', err); + utils.debug('Resolved orphan %s in mempool.', tx.rhash); next(); }, true); }, callback); @@ -872,9 +874,9 @@ Mempool.prototype.getLocks = function getLocks(tx, flags, entry, callback) { if (input.sequence & disableFlag) return next(); - coinHeight = coin.height === -1 + coinHeight = input.coin.height === -1 ? self.chain.tip + 1 - : coin.height; + : input.coin.height; if ((input.sequence & typeFlag) === 0) { coinHeight += (input.sequence & mask) - 1; @@ -921,7 +923,7 @@ Mempool.prototype.evalLocks = function evalLocks(entry, minHeight, minTime, call return callback(null, true); }); -} +}; Mempool.prototype.checkLocks = function checkLocks(tx, flags, entry, callback) { var self = this; @@ -931,7 +933,7 @@ Mempool.prototype.checkLocks = function checkLocks(tx, flags, entry, callback) { self.evalLocks(entry, minHeight, minTime, callback); }); -} +}; Mempool.prototype.checkMempoolLocks = function checkMempoolLocks(tx, flags, callback) { var self = this; @@ -950,7 +952,7 @@ Mempool.prototype.checkMempoolLocks = function checkMempoolLocks(tx, flags, call }); this.checkLocks(tx, flags, index, callback); -} +}; /** * VerifyError diff --git a/lib/bcoin/peer.js b/lib/bcoin/peer.js index 1bade9ee..c3ec7bef 100644 --- a/lib/bcoin/peer.js +++ b/lib/bcoin/peer.js @@ -42,6 +42,8 @@ function Peer(pool, options) { this.ack = false; this.connected = false; this.ts = this.options.ts || 0; + this.sendHeaders = false; + this.haveWitness = false; this.challenge = null; this.lastPong = 0; @@ -147,6 +149,11 @@ Peer.prototype._init = function init() { this.challenge = utils.nonce(); this._ping.timer = setInterval(function() { + if (self.options.witness && !self.haveWitness) { + self._error('Peer does not support segregated witness.'); + self.setMisbehavior(100); + return; + } self._write(self.framer.ping({ nonce: self.challenge })); @@ -163,12 +170,20 @@ Peer.prototype._init = function init() { self.emit('ack'); self.ts = utils.now(); - self._write(self.framer.packet('getaddr', new Buffer([]))); + self._write(self.framer.packet('getaddr')); - if (self.pool.options.headers) { + if (self.options.headers) { if (self.version && self.version.version > 70012) - self._write(self.framer.packet('sendheaders', new Buffer([]))); + self._write(self.framer.packet('sendheaders')); } + + if (self.options.witness) { + if (self.version && self.version.version >= 70012) + self._write(self.framer.packet('havewitness')); + } + + if (self.pool.chain.isFull()) + self.getMempool(); }); // Send hello @@ -454,6 +469,16 @@ Peer.prototype._onPacket = function onPacket(packet) { } } + if (cmd === 'sendheaders') { + this.sendHeaders = true; + return; + } + + if (cmd === 'havewitness') { + this.haveWitness = true; + return; + } + if (this._res(cmd, payload)) return; @@ -469,14 +494,14 @@ Peer.prototype._emitMerkle = function _emitMerkle(payload) { Peer.prototype._handleVersion = function handleVersion(payload) { if (payload.version < constants.minVersion) { this._error('Peer doesn\'t support required protocol version.'); - this.pool.setMisbehavior(this, 100); + this.setMisbehavior(100); return; } if (this.options.headers) { if (payload.version < 31800) { this._error('Peer doesn\'t support getheaders.'); - this.pool.setMisbehavior(this, 100); + this.setMisbehavior(100); return; } } @@ -484,7 +509,7 @@ Peer.prototype._handleVersion = function handleVersion(payload) { if (this.options.network) { if (!payload.network) { this._error('Peer does not support network services.'); - this.pool.setMisbehavior(this, 100); + this.setMisbehavior(100); return; } } @@ -492,19 +517,22 @@ Peer.prototype._handleVersion = function handleVersion(payload) { if (this.options.spv) { if (!payload.bloom && payload.version < 70011) { this._error('Peer does not support bip37.'); - this.pool.setMisbehavior(this, 100); + this.setMisbehavior(100); return; } } if (this.options.witness) { if (!payload.witness) { - this._error('Peer does not support segregated witness.'); - this.pool.setMisbehavior(this, 100); - return; + // this._error('Peer does not support segregated witness service.'); + // this.setMisbehavior(100); + // return; } } + if (payload.witness) + this.haveWitness = true; + // ACK this._write(this.framer.verack()); this.version = payload; @@ -734,8 +762,8 @@ Peer.prototype.isMisbehaving = function isMisbehaving() { return this.pool.isMisbehaving(this.host); }; -Peer.prototype.setMisbehavior = function setMisbehavior(dos) { - return this.pool.setMisbehavior(this, dos); +Peer.prototype.setMisbehavior = function setMisbehavior(score) { + return this.pool.setMisbehavior(this, score); }; Peer.prototype.sendReject = function sendReject(obj, code, reason, score) { diff --git a/lib/bcoin/protocol/constants.js b/lib/bcoin/protocol/constants.js index 176c500d..5154d435 100644 --- a/lib/bcoin/protocol/constants.js +++ b/lib/bcoin/protocol/constants.js @@ -7,10 +7,9 @@ var bn = require('bn.js'); exports.minVersion = 70001; -exports.version = 70002; +exports.version = 70012; // exports.maxMessage = 2 * 1024 * 1024; // main exports.maxMessage = 4 * 1000 * 1000; // segwit -exports.bcoinServices = 0; exports.services = { network: (1 << 0), @@ -19,6 +18,9 @@ exports.services = { witness: (1 << 3) }; +exports.localServices = exports.services.network + | exports.services.witness; + exports.inv = { error: 0, tx: 1, diff --git a/lib/bcoin/protocol/framer.js b/lib/bcoin/protocol/framer.js index c7d1ea86..cac9611a 100644 --- a/lib/bcoin/protocol/framer.js +++ b/lib/bcoin/protocol/framer.js @@ -10,6 +10,7 @@ var constants = require('./constants'); var utils = require('../utils'); var assert = utils.assert; var BufferWriter = require('../writer'); +var DUMMY = new Buffer([]); /** * Framer @@ -53,8 +54,14 @@ Framer.prototype.header = function header(cmd, payload) { }; Framer.prototype.packet = function packet(cmd, payload) { - var h = this.header(cmd, payload); - return Buffer.concat([h, payload]); + var header; + + if (!payload) + payload = DUMMY; + + header = this.header(cmd, payload); + + return Buffer.concat([header, payload]); }; Framer.prototype.version = function version(options) { @@ -205,10 +212,10 @@ Framer.version = function version(options, writer) { options.local = {}; if (options.local.services == null) - options.local.services = constants.bcoinServices; + options.local.services = constants.localServices; p.write32(constants.version); - p.writeU64(constants.bcoinServices); + p.writeU64(constants.localServices); p.write64(utils.now()); Framer.address(options.remote, false, p); Framer.address(options.local, false, p); diff --git a/lib/bcoin/protocol/parser.js b/lib/bcoin/protocol/parser.js index eadf26b7..d671f8bf 100644 --- a/lib/bcoin/protocol/parser.js +++ b/lib/bcoin/protocol/parser.js @@ -153,6 +153,9 @@ Parser.prototype.parsePayload = function parsePayload(cmd, p) { if (cmd === 'alert') return Parser.parseAlert(p); + if (cmd === 'utxo') + return Parser.parseUTXO(p); + return p; }; @@ -436,7 +439,7 @@ Parser.parseOutput = function parseOutput(p) { }; Parser.parseUTXO = function parseUTXO(p) { - var version, height, value, script, hash, index, coinbase; + var version, height, value, script; p = new BufferReader(p); p.start(); diff --git a/lib/bcoin/script.js b/lib/bcoin/script.js index 949d5922..751e0e89 100644 --- a/lib/bcoin/script.js +++ b/lib/bcoin/script.js @@ -2234,7 +2234,7 @@ Script.format = function format(code) { assert(typeof chunk === 'number'); - if (constants.opcodeByVal[chunk]) + if (constants.opcodesByVal[chunk]) return constants.opcodesByVal[chunk]; chunk = chunk.toString(16); diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index 19621fdb..1272d303 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -852,7 +852,7 @@ TX.prototype.isStandardInputs = function isStandardInputs(flags) { return false; if ((flags & constants.flags.VERIFY_WITNESS) - && input.coin.isWitnessProgram()) { + && input.coin.script.isWitnessProgram()) { hadWitness = true; // Input script must be empty. @@ -1266,8 +1266,7 @@ TX._fromExtended = function _fromExtended(buf, saveCoins) { coin = bcoin.protocol.parser.parseCoin(coin, false); coin.hash = tx.inputs[i].prevout.hash; coin.index = tx.inputs[i].prevout.index; - coin.coinbase = false; - tx.inputs[i].coin = new bcoin.coin(coin); + tx.inputs[i].coin = coin; } }