diff --git a/bin/node b/bin/node index 4241e49b..676bd213 100755 --- a/bin/node +++ b/bin/node @@ -34,6 +34,8 @@ node.open(function(err) { if (bcoin.network.get().type !== 'regtest') node.pool.connect(); node.miner.start(); + if (node.chain.isFull()) + node.startSync(); return; } diff --git a/lib/bcoin/abstractblock.js b/lib/bcoin/abstractblock.js index e41883db..7cf30215 100644 --- a/lib/bcoin/abstractblock.js +++ b/lib/bcoin/abstractblock.js @@ -166,7 +166,7 @@ AbstractBlock.prototype.__defineGetter__('rhash', function() { AbstractBlock.prototype.toInv = function toInv() { return { type: constants.inv.BLOCK, - hash: this.hash() + hash: this.hash('hex') }; }; diff --git a/lib/bcoin/fullnode.js b/lib/bcoin/fullnode.js index 5cf19a57..ac742c1a 100644 --- a/lib/bcoin/fullnode.js +++ b/lib/bcoin/fullnode.js @@ -177,7 +177,7 @@ Fullnode.prototype._init = function _init() { }); this.miner.on('block', function(block) { - self.pool.announce(block); + self.pool.broadcast(block.toInv()); }); function load(err) { @@ -259,9 +259,12 @@ Fullnode.prototype.sendTX = function sendTX(item, wait, callback) { if (err) return callback(err); - self.pool.announce(item); + if (!wait) { + self.pool.broadcast(item.toInv()); + return callback(); + } - return callback(); + return self.pool.broadcast(item.toInv(), callback); }); }; diff --git a/lib/bcoin/miner.js b/lib/bcoin/miner.js index 77388fda..6ea7c1d1 100644 --- a/lib/bcoin/miner.js +++ b/lib/bcoin/miner.js @@ -125,7 +125,7 @@ Miner.prototype._init = function _init() { bcoin.debug( 'Found block: %d (%s)', block.height, - block.hash('hex')); + block.rhash); // Emit the block hex as a failsafe (in case we can't send it) bcoin.debug('Raw: %s', block.render().toString('hex')); }); @@ -534,7 +534,7 @@ MinerBlock.prototype.findNonce = function findNonce() { data.writeUInt32LE(block.nonce, 76, true); // Send progress report every so often - if (block.nonce % 100000 === 0) + if (block.nonce % 500000 === 0) this.sendStatus(); } @@ -571,15 +571,10 @@ MinerBlock.prototype.findNonce = function findNonce() { }; MinerBlock.prototype.__defineGetter__('hashes', function() { - return new bn(this.iterations) - .mul(utils.U32) - .addn(this.block.nonce | 0); + return this.iterations * 0xffffffff + this.block.nonce; }); MinerBlock.prototype.__defineGetter__('rate', function() { - if (!this.block.nonce) - return 0; - // Calculate our terrible hashrate return (this.block.nonce / (utils.now() - this.begin)) | 0; }); @@ -591,7 +586,7 @@ MinerBlock.prototype.sendStatus = function sendStatus() { this.emit('status', { block: this.block, target: this.block.bits, - hashes: this.hashes.toString(10), + hashes: this.hashes, hashrate: this.rate, height: this.height, best: utils.revHex(this.tip.hash) diff --git a/lib/bcoin/peer.js b/lib/bcoin/peer.js index a6a5fbdd..9b420ab1 100644 --- a/lib/bcoin/peer.js +++ b/lib/bcoin/peer.js @@ -1085,13 +1085,14 @@ Peer.prototype._handleGetData = function handleGetData(items) { } bcoin.debug( - 'Peer requested %s:%s as a %s packet (%s).', - entry.packetType, + 'Peer requested %s %s as a %s packet (%s).', + entry.type === constants.inv.TX ? 'tx' : 'block', utils.revHex(entry.hash), witness ? 'witness' : 'normal', this.hostname); - entry.sendTo(peer, witness); + if (!entry.send(this, witness)) + check.push(item); } if (this.pool.options.selfish) diff --git a/lib/bcoin/pool.js b/lib/bcoin/pool.js index 26bebf47..aabf71c2 100644 --- a/lib/bcoin/pool.js +++ b/lib/bcoin/pool.js @@ -1685,25 +1685,34 @@ Pool.prototype.fulfill = function fulfill(hash) { /** * Broadcast a transaction or block. - * @param {TX|Block} msg + * @param {TX|Block|InvItem} msg * @param {Function} callback - Returns [Error]. Executes on request, reject, * or timeout. * @returns {BroadcastItem} */ Pool.prototype.broadcast = function broadcast(msg, callback) { - var hash = msg.hash('hex'); - var item = this.inv.map[hash]; + var hash = msg.hash; + var item; + + if (msg.toInv) + hash = msg.toInv().hash; + + item = this.inv.map[hash]; if (item) { item.refresh(); + item.announce(); item.addCallback(callback); return item; } item = new BroadcastItem(this, msg, callback); - return item.start(); + item.start(); + item.announce(); + + return item; }; /** @@ -2187,7 +2196,7 @@ LoadRequest.prototype.inspect = function inspect() { * @constructor * @private * @param {Pool} pool - * @param {TX|Block} item + * @param {TX|Block|InvItem} item * @param {Function?} callback * @emits BroadcastItem#ack * @emits BroadcastItem#reject @@ -2198,20 +2207,30 @@ function BroadcastItem(pool, item, callback) { if (!(this instanceof BroadcastItem)) return new BroadcastItem(pool, item); + this.pool = pool; + this.callback = []; + + this.id = this.pool.uid++; + this.msg = null; + if (item instanceof bcoin.tx) { if (item.mutable) item = item.toTX(); } - this.pool = pool; - this.callback = []; + if (item.toInv) { + this.msg = item; + item = item.toInv(); + } - this.id = this.pool.uid++; - this.hash = item.hash('hex'); - this.type = (item instanceof bcoin.tx) - ? constants.inv.TX - : constants.inv.BLOCK; - this.msg = item; + this.hash = item.hash; + this.type = item.type; + + if (typeof this.type === 'string') + this.type = constants.inv[this.type.toUpperCase()]; + + assert(this.type != null); + assert(typeof this.hash === 'string'); // INV does not set the witness // mask (only GETDATA does this). @@ -2267,7 +2286,13 @@ BroadcastItem.prototype.refresh = function refresh() { self.emit('timeout'); self.finish(new Error('Timed out.')); }, this.pool.inv.timeout); +}; +/** + * Announce the item. + */ + +BroadcastItem.prototype.announce = function announce() { this.pool.announce(this); }; @@ -2298,12 +2323,18 @@ BroadcastItem.prototype.finish = function finish(err) { * Send the item to a peer. * @param {Peer} peer * @param {Boolean} witness - Whether to use the witness serialization. + * @returns {Boolean} Whether the data is available to be sent. */ -BroadcastItem.prototype.sendTo = function sendTo(peer, witness) { +BroadcastItem.prototype.send = function send(peer, witness) { var self = this; var i, data; + if (!this.msg) { + this.ack(peer); + return false; + } + if (this.type === constants.inv.TX) { data = witness ? peer.framer.witnessTX(this.msg) @@ -2316,10 +2347,23 @@ BroadcastItem.prototype.sendTo = function sendTo(peer, witness) { peer.write(value); + this.ack(peer); + + return true; +}; + +/** + * Handle an ack from a peer. + * @param {Peer} peer + */ + +BroadcastItem.prototype.ack = function ack(peer) { + var self = this; + setTimeout(function() { self.emit('ack', peer); - for (i = 0; i < this.callback.length; i++) + for (i = 0; i < self.callback.length; i++) self.callback[i](); self.callback.length = 0; @@ -2344,15 +2388,6 @@ BroadcastItem.prototype.reject = function reject(peer) { this.callback.length = 0; }; -/** - * Convert to an InvItem. - * @returns {InvItem} - */ - -BroadcastItem.prototype.toInv = function toInv() { - return this; -}; - /** * Inspect the broadcast item. */ diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index e8a9a3be..986364e7 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -1710,7 +1710,7 @@ TX.prototype.__defineGetter__('wtxid', function() { TX.prototype.toInv = function toInv() { return { type: constants.inv.TX, - hash: this.hash() + hash: this.hash('hex') }; }; diff --git a/lib/bcoin/workers.js b/lib/bcoin/workers.js index c3fa10fd..b5409df0 100644 --- a/lib/bcoin/workers.js +++ b/lib/bcoin/workers.js @@ -35,7 +35,7 @@ function Workers(options) { EventEmitter.call(this); this.uid = 0; - this.size = Math.max(2, options.size || Workers.CORES); + this.size = Math.max(1, options.size || Workers.CORES); this.timeout = options.timeout || 60000; this.network = bcoin.network.get(options.network); this.children = [];