From d78a727de83b9b078b2638bb44d708abdfaab2a5 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Sat, 5 Mar 2016 07:28:45 -0800 Subject: [PATCH] leveldb stuff. --- lib/bcoin/block.js | 2 +- lib/bcoin/blockdb.js | 729 +++++------------------------------ lib/bcoin/pool.js | 10 +- lib/bcoin/protocol/framer.js | 17 +- 4 files changed, 123 insertions(+), 635 deletions(-) diff --git a/lib/bcoin/block.js b/lib/bcoin/block.js index 86221361..1d536add 100644 --- a/lib/bcoin/block.js +++ b/lib/bcoin/block.js @@ -386,7 +386,7 @@ Block.fromRaw = function fromRaw(data, enc, type) { Block.prototype.toSmall = function toSmall() { var block = this.abbr(); - var buf = new Buffer(block.length + 4 + this.txs.length * 32); + var buf = new Buffer(block.length + 4 + utils.sizeIntv(this.txs.length) + this.txs.length * 32); var height = this.height; var off = 0; diff --git a/lib/bcoin/blockdb.js b/lib/bcoin/blockdb.js index 7d0dce08..7a7e72ae 100644 --- a/lib/bcoin/blockdb.js +++ b/lib/bcoin/blockdb.js @@ -9,7 +9,7 @@ var utils = bcoin.utils; var assert = utils.assert; var EventEmitter = require('events').EventEmitter; var network = bcoin.protocol.network; -var fs = bcoin.fs; +var DUMMY = new Buffer([]); /** * BlockDB @@ -40,7 +40,6 @@ function BlockDB(node, options) { this.options = options; this.node = node; - this.data = new BlockData(node, this, options); this.cache = { unspent: new bcoin.lru(32 * 1024 * 1024), @@ -50,7 +49,7 @@ function BlockDB(node, options) { if (+process.env.BCOIN_FRESH === 1 && bcoin.cp) bcoin.cp.execFileSync('rm', ['-rf', this.file], { stdio: 'ignore' }); - this.index = new levelup(this.file, { + this.db = new levelup(this.file, { keyEncoding: 'ascii', valueEncoding: 'binary', createIfMissing: true, @@ -71,16 +70,11 @@ utils.inherits(BlockDB, EventEmitter); BlockDB.prototype.close = function close(callback) { var self = this; - this.index.close(function(err) { + this.db.close(function(err) { if (err) return callback(err); - self.data.closeAsync(function(err) { - if (err) - return callback(err); - - return callback(); - }); + return callback(); }); }; @@ -88,7 +82,7 @@ BlockDB.prototype.migrate = function migrate(blockSize, compression, callback) { var options, db, pending, stream, total, done; callback = utils.once(callback); - options = utils.merge({}, this.index.options); + options = utils.merge({}, this.db.options); if (blockSize != null) options.blockSize = blockSize; @@ -103,7 +97,7 @@ BlockDB.prototype.migrate = function migrate(blockSize, compression, callback) { db = levelup(this.file + '.migrated', options); - stream = this.index.createReadStream(); + stream = this.db.createReadStream(); pending = 0; total = 0; @@ -137,34 +131,16 @@ BlockDB.prototype.migrate = function migrate(blockSize, compression, callback) { }); }; -BlockDB.prototype.createOffset = function createOffset(size, offset, height) { - var buf = new Buffer(16); - utils.writeU32(buf, size, 0); - utils.writeU64(buf, offset, 4); - utils.writeU32(buf, height, 12); - return buf; -}; - -BlockDB.prototype.parseOffset = function parseOffset(data) { - // Avoid using bignumbers here to increase performance. - // This is safe because this number will never exceed - // 53 bits (up to 8.3 petabytes). - var hi = utils.readU32(data, 8); - var lo = utils.readU32(data, 4); - return { - size: utils.readU32(data, 0), - offset: (hi * 0x100000000) + lo, - height: utils.readU32(data, 12) - }; -}; - BlockDB.prototype.saveBlock = function saveBlock(block, callback) { var self = this; - - var batch = self.index.batch(); + var batch = this.db.batch(); batch.put('b/b/' + block.hash('hex'), block.toSmall()); + block.txs.forEach(function(tx, i) { + batch.put('t/t/' + tx.hash('hex'), tx.toExtended()); + }); + self.connectBlock(block, callback, batch); }; @@ -180,29 +156,26 @@ BlockDB.prototype.removeBlock = function removeBlock(hash, callback) { if (!block) return callback(); - batch = self.index.batch(); - - batch.del('b/b/' + block.hash('hex')); + batch = self.db.batch(); function cb(err) { if (err) return callback(err); - return callback(null, block); + batch.del('b/b/' + block.hash('hex')); - // XXX This seems to be truncating too much right now - self.data.truncateAsync(block._fileOffset, function(err) { - if (err) - return callback(err); - return callback(null, block); + block.txs.forEach(function(tx, i) { + batch.del('t/t/' + tx.hash('hex')); }); + + return callback(null, block); } self.disconnectBlock(hash, cb, batch); }); }; -BlockDB.prototype.connectBlock = function connectBlock(block, callback, batch, blockOffset) { +BlockDB.prototype.connectBlock = function connectBlock(block, callback, batch) { var self = this; this._getCoinBlock(block, function(err, block) { @@ -215,16 +188,13 @@ BlockDB.prototype.connectBlock = function connectBlock(block, callback, batch, b } if (!batch) - batch = self.index.batch(); + batch = self.db.batch(); batch.put('b/h/' + block.height, block.hash()); block.txs.forEach(function(tx, i) { var hash = tx.hash('hex'); var uniq = {}; - var txOffset; - - batch.put('t/t/' + hash, tx.toExtended()); tx.inputs.forEach(function(input) { var type = input.getType(); @@ -247,7 +217,7 @@ BlockDB.prototype.connectBlock = function connectBlock(block, callback, batch, b } if (uaddr) - batch.put('t/a/' + uaddr + '/' + hash, new Buffer([])); + batch.put('t/a/' + uaddr + '/' + hash, DUMMY); if (address) { batch.del( @@ -265,7 +235,7 @@ BlockDB.prototype.connectBlock = function connectBlock(block, callback, batch, b tx.outputs.forEach(function(output, i) { var type = output.getType(); var address = output.getAddress(); - var uaddr, coinOffset; + var uaddr; if (type === 'pubkey' || type === 'multisig') address = null; @@ -280,10 +250,10 @@ BlockDB.prototype.connectBlock = function connectBlock(block, callback, batch, b } if (uaddr) - batch.put('t/a/' + uaddr + '/' + hash, new Buffer([])); + batch.put('t/a/' + uaddr + '/' + hash, DUMMY); if (address) - batch.put('u/a/' + address + '/' + hash + '/' + i, new Buffer([])); + batch.put('u/a/' + address + '/' + hash + '/' + i, DUMMY); batch.put('u/t/' + hash + '/' + i, bcoin.coin(tx, i).toRaw()); }); @@ -313,7 +283,7 @@ BlockDB.prototype.disconnectBlock = function disconnectBlock(hash, callback, bat } if (!batch) - batch = self.index.batch(); + batch = self.db.batch(); if (typeof hash === 'string') assert(block.hash('hex') === hash); @@ -327,12 +297,10 @@ BlockDB.prototype.disconnectBlock = function disconnectBlock(hash, callback, bat if (self.options.cache) self.cache.tx.remove(hash); - batch.del('t/t/' + hash); - tx.inputs.forEach(function(input) { var type = input.getType(); var address = input.getAddress(); - var uaddr, coinOffset; + var uaddr, coin; if (input.isCoinbase()) return; @@ -349,13 +317,7 @@ BlockDB.prototype.disconnectBlock = function disconnectBlock(hash, callback, bat uaddr = null; } - assert(input.output._fileOffset >= 0); - - coinOffset = self.createOffset( - input.output._size, - input.output._fileOffset, - input.output.height - ); + assert(input.output); if (uaddr) batch.del('t/a/' + uaddr + '/' + hash); @@ -364,13 +326,13 @@ BlockDB.prototype.disconnectBlock = function disconnectBlock(hash, callback, bat batch.put('u/a/' + address + '/' + input.prevout.hash + '/' + input.prevout.index, - coinOffset); + DUMMY); } batch.put('u/t/' + input.prevout.hash + '/' + input.prevout.index, - coinOffset); + input.output.toRaw()); }); tx.outputs.forEach(function(output, i) { @@ -514,8 +476,8 @@ BlockDB.prototype.getCoinsByAddress = function getCoinsByAddress(addresses, opti addresses = utils.uniqs(addresses); - utils.forEach(addresses, function(address, done) { - var iter = self.index.db.iterator({ + utils.forEachSerial(addresses, function(address, done) { + var iter = self.db.db.iterator({ gte: 'u/a/' + address, lte: 'u/a/' + address + '~', keys: true, @@ -527,7 +489,7 @@ BlockDB.prototype.getCoinsByAddress = function getCoinsByAddress(addresses, opti (function next() { iter.next(function(err, key, value) { - var record, parts, hash, index; + var parts, hash, index; if (err) { return iter.end(function() { @@ -546,43 +508,18 @@ BlockDB.prototype.getCoinsByAddress = function getCoinsByAddress(addresses, opti parts = key.split('/'); hash = parts[3]; index = +parts[4]; - record = self.parseOffset(value); - self.data.getAsync(record.size, record.offset, function(err, data) { - var coin; + self.getCoin(hash, index, function(err, coin) { + if (err) + return next(err); - if (err) { - return iter.end(function() { - done(err); - }); - } - - if (!data) + if (!coin) return next(); - try { - data = bcoin.protocol.parser.parseOutput(data); - } catch (e) { - return iter.end(function() { - done(e); - }); - } - - coin = bcoin.coin({ - version: 1, - hash: hash, - index: index, - height: record.height, - script: data.script, - value: data.value, - spent: false - }); - if (self.options.cache) self.cache.unspent.set(id, coin); coins.push(coin); - next(); }); }); @@ -598,43 +535,14 @@ BlockDB.prototype.getCoin = function getCoin(hash, index, callback) { var self = this; var id = 'u/t/' + hash + '/' + index; - this.index.get(id, function(err, record) { + this.db.get(id, function(err, data) { if (err) { if (err.type === 'NotFoundError') return callback(); return callback(err); } - return callback(null, bcoin.coin.fromRaw(record)); - record = self.parseOffset(record); - - self.data.getAsync(record.size, record.offset, function(err, data) { - var coin; - - if (err) - return callback(err); - - if (!data) - return callback(); - - try { - data = bcoin.protocol.parser.parseOutput(data); - } catch (e) { - return callback(e); - } - - coin = bcoin.coin({ - version: 1, - hash: hash, - index: index, - height: record.height, - script: data.script, - value: data.value, - spent: false - }); - - return callback(null, coin); - }); + return callback(null, bcoin.coin.fromRaw(data)); }); }; @@ -653,8 +561,8 @@ BlockDB.prototype.getTXByAddress = function getTXByAddress(addresses, options, c addresses = utils.uniqs(addresses); - utils.forEach(addresses, function(address, done) { - var iter = self.index.db.iterator({ + utils.forEachSerial(addresses, function(address, done) { + var iter = self.db.db.iterator({ gte: 't/a/' + address, lte: 't/a/' + address + '~', keys: true, @@ -666,7 +574,7 @@ BlockDB.prototype.getTXByAddress = function getTXByAddress(addresses, options, c (function next() { iter.next(function(err, key, value) { - var record, hash, index; + var hash; if (err) { return iter.end(function() { @@ -683,7 +591,6 @@ BlockDB.prototype.getTXByAddress = function getTXByAddress(addresses, options, c } hash = key.split('/')[3]; - record = self.parseOffset(value); if (addresses.length > 1) { if (have[hash]) @@ -697,51 +604,13 @@ BlockDB.prototype.getTXByAddress = function getTXByAddress(addresses, options, c return done(); } - self.data.getAsync(record.size, record.offset, function(err, data) { - var coin; - - if (err) { - return iter.end(function() { - done(err); - }); - } - - if (!data) + self.getTX(hash, function(err, tx) { + if (err) + return next(err); + if (!tx) return next(); - - try { - tx = bcoin.protocol.parser.parseTX(data); - tx = new bcoin.tx(tx); - } catch (e) { - return iter.end(function() { - done(e); - }); - } - - return self._getEntry(record.height, function(err, entry) { - if (err) { - return iter.end(function() { - done(err); - }); - } - - tx.height = record.height; - - if (entry) { - tx.ts = entry.ts; - tx.block = entry.hash; - } - - txs.push(tx); - - if (self.options.cache) - self.cache.tx.set(hash, tx); - - if (self.options.paranoid && tx.hash('hex') !== hash) - return next(new Error('BlockDB is corrupt. All is lost.')); - - next(); - }); + txs.push(tx); + next(); }); }); })(); @@ -755,52 +624,21 @@ BlockDB.prototype.getTXByAddress = function getTXByAddress(addresses, options, c BlockDB.prototype.getTX = function getTX(hash, callback) { var self = this; var id = 't/t/' + hash; + var tx; - this.index.get(id, function(err, record) { + this.db.get(id, function(err, data) { if (err) { if (err.type === 'NotFoundError') return callback(); return callback(err); } - return callback(null, bcoin.tx.fromExtended(record)); - record = self.parseOffset(record); + tx = bcoin.tx.fromExtended(data); - self.data.getAsync(record.size, record.offset, function(err, data) { - var tx; + if (self.options.paranoid && tx.hash('hex') !== hash) + return callback(new Error('BlockDB is corrupt. All is lost.')); - if (err) - return callback(err); - - if (data) { - try { - tx = bcoin.protocol.parser.parseTX(data); - tx = new bcoin.tx(tx); - } catch (e) { - return callback(e); - } - return self._getEntry(record.height, function(err, entry) { - if (err) - return callback(err); - - tx.height = record.height; - - if (entry) { - tx.ts = entry.ts; - tx.block = entry.hash; - } - - tx._fileOffset = record.offset; - - if (self.options.paranoid && tx.hash('hex') !== hash) - return callback(new Error('BlockDB is corrupt. All is lost.')); - - return callback(null, tx); - }); - } - - return callback(null, tx); - }); + return callback(null, tx); }); }; @@ -891,42 +729,62 @@ BlockDB.prototype.fillBlock = function fillBlock(block, callback) { }); }; +BlockDB.prototype._getHash = function _getHash(height, callback) { + if (typeof height === 'string') + return callback(null, height); + + this.db.get('b/h/' + height, function(err, hash) { + if (err) + return callback(err); + if (!hash) + return callback(); + return callback(null, utils.toHex(hash)); + }); +}; + BlockDB.prototype.getBlock = function getBlock(hash, callback) { var self = this; - var id = 'b/b/' + hash; + var id, block; - if (typeof hash === 'number') - id = 'b/h/' + hash; - - this.index.get(id, function(err, record) { - if (err) { - if (err.type === 'NotFoundError') - return callback(); + return this._getHash(hash, function(err, hash) { + if (err) return callback(err); - } - var block = bcoin.block.fromSmall(record); - block.txs = []; + if (!hash) + return callback(); - utils.forEach(block.hashes, function(hash, next, i) { - self.getTX(hash, function(err, tx) { - if (err) - return next(err); + id = 'b/b/' + hash; - if (!tx) - return next(new Error('TX not found.')); - - block.txs[i] = tx; - - next(); - }) - }, function(err) { - if (err) + self.db.get(id, function(err, data) { + if (err) { + if (err.type === 'NotFoundError') + return callback(); return callback(err); + } - delete block.hashes; - block = new bcoin.block(block); - return callback(null, block); + block = bcoin.block.fromSmall(data); + block.txs = []; + + utils.forEach(block.hashes, function(hash, next, i) { + self.getTX(hash, function(err, tx) { + if (err) + return next(err); + + if (!tx) + return next(new Error('TX not found.')); + + block.txs[i] = tx; + + next(); + }) + }, function(err) { + if (err) + return callback(err); + + delete block.hashes; + block = new bcoin.block(block); + return callback(null, block); + }); }); }); }; @@ -938,16 +796,11 @@ BlockDB.prototype.hasBlock = function hasBlock(hash, callback) { if (typeof hash === 'number') id = 'b/h/' + hash; - this.index.get(id, function(err, record) { + this.db.get(id, function(err, data) { if (err && err.type !== 'NotFoundError') return callback(err); - if (!record) - return callback(null, false); - - record = self.parseOffset(record); - - if (self.data.size < record.offset + record.size) + if (!data) return callback(null, false); return callback(null, true); @@ -958,16 +811,11 @@ BlockDB.prototype.hasCoin = function hasCoin(hash, index, callback) { var self = this; var id = 'u/t/' + hash + '/' + index; - this.index.get(id, function(err, record) { + this.db.get(id, function(err, data) { if (err && err.type !== 'NotFoundError') return callback(err); - if (!record) - return callback(null, false); - - record = self.parseOffset(record); - - if (self.data.size < record.offset + record.size) + if (!data) return callback(null, false); return callback(null, true); @@ -1012,16 +860,11 @@ BlockDB.prototype.hasTX = function hasTX(hash, callback) { var self = this; var id = 't/t/' + hash; - this.index.get(id, function(err, record) { + this.db.get(id, function(err, data) { if (err && err.type !== 'NotFoundError') return callback(err); - if (!record) - return callback(null, false); - - record = self.parseOffset(record); - - if (self.data.size < record.offset + record.size) + if (!data) return callback(null, false); return callback(null, true); @@ -1042,7 +885,7 @@ BlockDB.prototype.getHeight = function getHeight(callback) { var maxHeight = -1; var iter; - iter = this.index.db.iterator({ + iter = this.db.db.iterator({ gte: 'b/h', lte: 'b/h~', keys: true, @@ -1106,366 +949,6 @@ BlockDB.prototype.reset = function reset(height, callback, emit) { }); }; -BlockDB.prototype._getEntry = function _getEntry(height, callback) { - if (!this.node) - return callback(); - - return this.node.chain.db.get(height, callback); -}; - -/** - * BlockData - */ - -function BlockData(node, blockdb, options) { - if (!(this instanceof BlockData)) - return new BlockData(node, blockdb, options); - - if (!options) - options = {}; - - this.node = node; - this.blockdb = blockdb; - this.options = options; - this.file = options.blockFile; - - bcoin.ensurePrefix(); - - if (!this.file) - this.file = bcoin.prefix + '/block-' + network.type + '.db'; - - this.bufferPool = { used: {} }; - this.size = 0; - this.fd = null; - - this._init(); -} - -BlockData.prototype._init = function _init() { - if (!bcoin.fs) { - utils.debug('`fs` module not available. Falling back to ramdisk.'); - this.ramdisk = new bcoin.ramdisk(40 * 1024 * 1024); - return; - } - - if (+process.env.BCOIN_FRESH === 1) { - try { - fs.unlinkSync(this.file); - } catch (e) { - ; - } - } - - if (!this.exists()) - fs.writeFileSync(this.file, new Buffer([])); - - this.size = this.getFileSize(); - - this.fd = fs.openSync(this.file, 'r+'); -}; - -BlockData.prototype.closeSync = function closeSync() { - if (!bcoin.fs) { - this.ramdisk = null; - return; - } - fs.closeSync(this.fd); - this.fd = null; -}; - -BlockData.prototype.closeAsync = function closeAsync(callback) { - var self = this; - - callback = utils.asyncify(callback); - - if (!bcoin.fs) { - this.ramdisk = null; - return callback(); - } - - fs.close(this.fd, function(err) { - if (err) - return callback(err); - self.fd = null; - return callback(); - }); -}; - -BlockData.prototype._malloc = function _malloc(size) { - if (!this.options.usePool) - return new Buffer(size); - - if (size > 500) - return new Buffer(size); - - if (!this.bufferPool[size]) - this.bufferPool[size] = new Buffer(size); - - if (this.bufferPool.used[size] === this.bufferPool[size]) - return new Buffer(size); - - this.bufferPool.used[size] = this.bufferPool[size]; - - return this.bufferPool[size]; -}; - -BlockData.prototype._free = function _free(buf) { - if (!this.options.usePool) - return; - - if (this.bufferPool.used[buf.length] === buf) { - assert(this.bufferPool[buf.length] === buf); - delete this.bufferPool.used[buf.length]; - } -}; - -BlockData.prototype.exists = function exists() { - if (!bcoin.fs) - return true; - - try { - fs.statSync(this.file); - return true; - } catch (e) { - return false; - } -}; - -BlockData.prototype.getFileSize = function getFileSize() { - if (!bcoin.fs) - return this.ramdisk.size; - - try { - return fs.statSync(this.file).size; - } catch (e) { - return 0; - } -}; - -BlockData.prototype.getSync = function getSync(size, offset) { - return this._readSync(size, offset); -}; - -BlockData.prototype.getAsync = function getAsync(size, offset, callback) { - var self = this; - - callback = utils.asyncify(callback); - - return this._readAsync(size, offset, callback); -}; - -BlockData.prototype.saveSync = function saveSync(data) { - var self = this; - var offset = this.size; - - this._writeSync(data, offset); - - return { size: data.length, offset: offset }; -}; - -BlockData.prototype.saveAsync = function saveAsync(data, callback) { - var self = this; - var offset = this.size; - - callback = utils.asyncify(callback); - - return this._writeAsync(data, offset, function(err, success) { - if (err) - return callback(err); - return callback(null, { size: data.length, offset: offset }); - }); -}; - -BlockData.prototype.truncateSync = function truncateSync(size) { - if (!bcoin.fs) { - this.ramdisk.truncate(size); - this.size = size; - return; - } - - fs.ftruncateSync(this.fd, size); - this.size = size; -}; - -BlockData.prototype.truncateAsync = function truncateAsync(size, callback) { - var self = this; - - callback = utils.asyncify(callback); - - if (!bcoin.fs) { - this.ramdisk.truncate(size); - this.size = size; - return callback(); - } - - fs.ftruncate(this.fd, size, function(err) { - if (err) - return callback(err); - self.size = size; - return callback(); - }); -}; - -BlockData.prototype._ioError = function _ioError(name, size, offset) { - return new Error(name - + '() failed at offset ' - + offset - + ' with ' - + size - + ' bytes left.'); -}; - -BlockData.prototype._readSync = function _readSync(size, offset) { - var index = 0; - var data, bytes; - - if (offset < 0 || offset == null) - return; - - if (!bcoin.fs) - return this.ramdisk.read(size, offset); - - data = this._malloc(size); - - try { - while (bytes = fs.readSync(this.fd, data, index, size, offset)) { - index += bytes; - size -= bytes; - offset += bytes; - if (index === data.length) { - this._free(data); - return data; - } - } - } catch (e) { - this._free(data); - throw e; - } - - this._free(data); - - throw this._ioError('_readSync', size, offset); -}; - -BlockData.prototype._readAsync = function _readAsync(size, offset, callback) { - var self = this; - var index = 0; - var data, bytes; - - callback = utils.asyncify(callback); - - if (offset < 0 || offset == null) - return callback(); - - if (!bcoin.fs) - return callback(null, this.ramdisk.read(size, offset)); - - data = this._malloc(size); - - (function next() { - fs.read(self.fd, data, index, size, offset, function(err, bytes) { - if (err) { - self._free(data); - return callback(err); - } - - if (!bytes) - return callback(self._ioError('_readAsync', size, offset)); - - index += bytes; - size -= bytes; - offset += bytes; - - if (index === data.length) { - self._free(data); - return callback(null, data); - } - - next(); - }); - })(); -}; - -BlockData.prototype._writeSync = function _writeSync(data, offset) { - var size = data.length; - var added = Math.max(0, (offset + data.length) - this.size); - var index = 0; - var bytes; - - if (offset < 0 || offset == null) - return false; - - if (!bcoin.fs) { - this.size += added; - this.ramdisk.write(data, offset); - return; - } - - try { - while (bytes = fs.writeSync(this.fd, data, index, size, offset)) { - index += bytes; - size -= bytes; - offset += bytes; - if (index === data.length) { - this.size += added; - return true; - } - } - } catch (e) { - throw e; - } - - fs.fsyncSync(this.fd); - - throw this._ioError('_writeSync', size, offset); -}; - -BlockData.prototype._writeAsync = function _writeAsync(data, offset, callback) { - var self = this; - var added = Math.max(0, (offset + data.length) - this.size); - var size = data.length; - var index = 0; - - callback = utils.asyncify(callback); - - if (offset < 0 || offset == null) - return callback(null, false); - - if (!bcoin.fs) { - this.size += added; - this.ramdisk.write(data, offset); - return callback(null, true); - } - - this.size += added; - - (function next() { - fs.write(self.fd, data, index, size, offset, function(err, bytes) { - if (err) { - self.size -= (added - index); - return callback(err); - } - - if (!bytes) - return callback(self._ioError('_writeAsync', size, offset)); - - index += bytes; - size -= bytes; - offset += bytes; - - if (index === data.length) { - return fs.fsync(self.fd, function(err) { - if (err) - return callback(err); - return callback(null, true); - }); - } - - next(); - }); - })(); -}; - /** * Expose */ diff --git a/lib/bcoin/pool.js b/lib/bcoin/pool.js index b63a99e2..16e5bcca 100644 --- a/lib/bcoin/pool.js +++ b/lib/bcoin/pool.js @@ -59,7 +59,7 @@ function Pool(node, options) { options.headers = true; } else { if (options.headers == null) - options.headers = false; + options.headers = true; } this.syncing = false; @@ -561,11 +561,7 @@ Pool.prototype._handleHeaders = function _handleHeaders(headers, peer) { if (!header.verify()) break; - self.chain.has(hash, function(err, has) { - assert(!err); - if (!has) - self.getData(peer, self.block.type, hash); - }); + self.getData(peer, self.block.type, hash); last = hash; } @@ -578,7 +574,7 @@ Pool.prototype._handleHeaders = function _handleHeaders(headers, peer) { // simply tries to find the latest block in // the peer's chain. if (last && headers.length === 2000) - self.getHeaders(peer, last, null); + self.getHeaders(peer, last.hash, null); }); // Reset interval to avoid calling getheaders unnecessarily diff --git a/lib/bcoin/protocol/framer.js b/lib/bcoin/protocol/framer.js index 2eddb154..26285168 100644 --- a/lib/bcoin/protocol/framer.js +++ b/lib/bcoin/protocol/framer.js @@ -627,13 +627,22 @@ Framer._block = function _block(block, useWitness) { var i, tx, p; for (i = 0; i < block.txs.length; i++) { - tx = useWitness && bcoin.tx.prototype.hasWitness.call(block.txs[i]) - ? Framer.witnessTX(block.txs[i]) - : Framer.tx(block.txs[i]); + tx = block.txs[i]; + + if (tx.render) { + witnessSize += tx._witnessSize; + tx = useWitness && tx.hasWitness() + ? tx.render() + : tx.renderNormal(); + } else { + tx = useWitness && bcoin.tx.prototype.hasWitness.call(block.txs[i]) + ? Framer.witnessTX(block.txs[i]) + : Framer.tx(block.txs[i]); + witnessSize += tx._witnessSize; + } txs.push(tx); txSize += tx.length; - witnessSize += tx._witnessSize; } p = new Buffer(80 + utils.sizeIntv(block.txs.length) + txSize);