diff --git a/lib/bcoin/blockdb.js b/lib/bcoin/blockdb.js index 03721d2e..deba0564 100644 --- a/lib/bcoin/blockdb.js +++ b/lib/bcoin/blockdb.js @@ -32,15 +32,21 @@ function BlockDB(options) { options = { file: options }; if (!options.file) - options.file = process.env.HOME + '/bcoin-server-' + network.type + '.ldb'; + options.file = process.env.HOME + '/bcoin-index-' + network.type + '.db'; this.options = options; + this.parser = new bcoin.protocol.parser(); + this.data = new BlockData(); + this.index = levelup(options.file, { keyEncoding: 'ascii', valueEncoding: 'binary', - cacheSize: 16 * 1024 * 1024 + cacheSize: 16 * 1024 * 1024, + db: bcoin.isBrowser + ? require('memdown') + : require('level' + 'down') }); } @@ -83,22 +89,28 @@ BlockDB.prototype.saveBlock = function saveBlock(block, callback) { var batch = this.index.batch(); this.data.saveAsync(block._raw, function(err, data) { + var batch, blockOffset; + if (err) return callback(err); - var blockOffset = self.createOffset(data.size, data.offset, block.height); + batch = self.index.batch(); + + blockOffset = self.createOffset(data.size, data.offset, block.height); - var batch = self.index.batch(); batch.put('b/b/' + block.hash('hex'), blockOffset); batch.put('b/h/' + block.height, blockOffset); block.txs.forEach(function(tx, i) { - var txOffset = self.createOffset( - tx._size, data.offset + tx._offset, - block.height); - var hash = tx.hash('hex'); var uniq = {}; + var txOffset; + + txOffset = self.createOffset( + tx._size, + data.offset + tx._offset, + block.height + ); batch.put('t/t/' + hash, txOffset); @@ -122,8 +134,12 @@ BlockDB.prototype.saveBlock = function saveBlock(block, callback) { if (uaddr) batch.put('t/a/' + uaddr + '/' + hash, txOffset); - if (address) - batch.del('u/a/' + address + '/' + input.prevout.hash + '/' + input.prevout.index); + if (address) { + batch.del( + 'u/a/' + address + + '/' + input.prevout.hash + + '/' + input.prevout.index); + } batch.del('u/t/' + input.prevout.hash + '/' + input.prevout.index); }); @@ -131,7 +147,7 @@ BlockDB.prototype.saveBlock = function saveBlock(block, callback) { tx.outputs.forEach(function(output) { var type = output.getType(); var address = output.getAddress(); - var uaddr; + var uaddr, coinOffset; if (type === 'pubkey' || type === 'multisig') address = null; @@ -145,10 +161,11 @@ BlockDB.prototype.saveBlock = function saveBlock(block, callback) { uaddr = null; } - var coinOffset = self.createOffset( + coinOffset = self.createOffset( output._size, data.offset + tx._offset + output._offset, - block.height); + block.height + ); if (uaddr) batch.put('t/a/' + uaddr + '/' + hash, txOffset); @@ -207,7 +224,7 @@ BlockDB.prototype.removeBlock = function removeBlock(hash, callback) { tx.inputs.forEach(function(input) { var type = input.getType(); var address = input.getAddress(); - var uaddr; + var uaddr, coinOffset; if (type === 'pubkey' || type === 'multisig') address = null; @@ -224,15 +241,23 @@ BlockDB.prototype.removeBlock = function removeBlock(hash, callback) { if (uaddr) batch.del('t/a/' + uaddr + '/' + hash); - var coinOffset = self.createOffset( + coinOffset = self.createOffset( input.output._size, block._fileOffset + tx._offset + input.output._offset, - block.height); + block.height + ); - if (address) - batch.put('u/a/' + address + '/' + input.output.hash + '/' + input.output.index, coinOffset); + if (address) { + batch.put('u/a/' + address + + '/' + input.output.hash + + '/' + input.output.index, + coinOffset); + } - batch.put('u/t/' + input.output.hash + '/' + input.output.index, coinOffset); + batch.put('u/t/' + + input.output.hash + + '/' + input.output.index, + coinOffset); }); tx.outputs.forEach(function(output) { @@ -272,6 +297,11 @@ BlockDB.prototype.fillTX = function fillTX(tx, callback) { var self = this; var pending = tx.inputs.length; + callback = utils.asyncify(callback); + + if (!pending) + return callback(); + tx.inputs.forEach(function(input) { if (input.output) { if (!--pending) @@ -295,6 +325,11 @@ BlockDB.prototype.fillTX2 = function fillTX2(tx, callback) { var self = this; var pending = tx.inputs.length; + callback = utils.asyncify(callback); + + if (!pending) + return callback(); + tx.inputs.forEach(function(input) { if (input.output) { if (!--pending) @@ -324,7 +359,7 @@ BlockDB.prototype.getCoinsByAddress = function getCoinsByAddress(addresses, call addresses = utils.uniqs(addresses); - var pending = addresses.length; + pending = addresses.length; addresses.forEach(function(address) { self._getCoinsByAddress(address, function(err, coin) { @@ -345,10 +380,11 @@ BlockDB.prototype._getCoinsByAddress = function _getCoinsByAddress(address, call var pending = 0; var coins = []; var done = false; + var stream; callback = utils.asyncify(callback); - var stream = this.index.createReadStream({ + stream = this.index.createReadStream({ start: 'u/a/' + address, end: 'u/a/' + address + '~' }); @@ -366,7 +402,11 @@ BlockDB.prototype._getCoinsByAddress = function _getCoinsByAddress(address, call return callback(err); if (data) { - data = self.parser.parseTXOut(data); + try { + data = self.parser.parseTXOut(data); + } catch (e) { + return callback(e); + } coin = bcoin.coin({ version: 1, hash: hash, @@ -403,7 +443,7 @@ BlockDB.prototype.getCoin = function getCoin(hash, index, callback) { var self = this; var id = 'u/t/' + hash + '/' + index; - this.index.get(id, { valueEncoding: 'binary' }, function(err, record) { + this.index.get(id, function(err, record) { if (err) { if (err.type === 'NotFoundError') return callback(); @@ -419,7 +459,11 @@ BlockDB.prototype.getCoin = function getCoin(hash, index, callback) { return callback(err); if (data) { - data = self.parser.parseTXOut(data); + try { + data = self.parser.parseTXOut(data); + } catch (e) { + return callback(e); + } coin = bcoin.coin({ version: 1, hash: hash, @@ -493,8 +537,13 @@ BlockDB.prototype._getTXByAddress = function _getTXByAddress(address, callback) return callback(err); if (data) { - tx = bcoin.tx.fromRaw(data); - entry = bcoin.chain.global.db.get(record.height); + try { + tx = bcoin.tx.fromRaw(data); + entry = bcoin.chain.global.db.get(record.height); + assert(entry); + } catch (e) { + return callback(e); + } tx.height = record.height; tx.ts = entry.ts; tx.block = entry.hash; @@ -525,7 +574,7 @@ BlockDB.prototype.getTX = function getTX(hash, callback) { var self = this; var id = 't/t/' + hash; - this.index.get(id, { valueEncoding: 'binary' }, function(err, record) { + this.index.get(id, function(err, record) { if (err) { if (err.type === 'NotFoundError') return callback(); @@ -541,8 +590,13 @@ BlockDB.prototype.getTX = function getTX(hash, callback) { return callback(err); if (data) { - tx = bcoin.tx.fromRaw(data); - entry = bcoin.chain.global.db.get(record.height); + try { + tx = bcoin.tx.fromRaw(data); + entry = bcoin.chain.global.db.get(record.height); + assert(entry); + } catch (e) { + return callback(e); + } tx.height = record.height; tx.ts = entry.ts; tx.block = entry.hash; @@ -560,7 +614,7 @@ BlockDB.prototype.getBlock = function getBlock(hash, callback) { if (typeof hash === 'number') id = 'b/h/' + value; - this.index.get(id, { valueEncoding: 'binary' }, function(err, record) { + this.index.get(id, function(err, record) { if (err) { if (err.type === 'NotFoundError') return callback(); @@ -576,7 +630,11 @@ BlockDB.prototype.getBlock = function getBlock(hash, callback) { return callback(err); if (data) { - block = bcoin.block.fromRaw(data); + try { + block = bcoin.block.fromRaw(data); + } catch (e) { + return callback(e); + } block._fileOffset = record.offset; block.height = record.height; } @@ -590,19 +648,18 @@ BlockDB.prototype.getBlock = function getBlock(hash, callback) { * BlockData */ -function BlockData(chain, options) { +function BlockData(options) { if (!(this instanceof BlockData)) - return new BlockData(chain, options); + return new BlockData(options); if (!options) options = {}; this.options = options; - this.chain = chain; this.file = options.file; if (!this.file) - this.file = process.env.HOME + '/bcoin-' + network.type + '.data'; + this.file = process.env.HOME + '/bcoin-data-' + network.type + '.db'; this._queue = []; this._cache = {}; @@ -628,10 +685,8 @@ BlockData.prototype._init = function _init() { } } - if (!this.exists()) { - fs.writeFileSync(this.file, new Buffer(0)); - fs.truncateSync(this.file, 0); - } + if (!this.exists()) + fs.writeFileSync(this.file, new Buffer([])); this.size = this.getSize(); @@ -757,9 +812,8 @@ BlockData.prototype.saveAsync = function saveAsync(data, callback) { }); }; -BlockData.prototype.truncate = function truncate(height) { - this.size = (height + 1) * BLOCK_SIZE; - this.tip = height; +BlockData.prototype.truncate = function truncate(size) { + this.size = size; if (!bcoin.fs) { this.ramdisk.truncate(this.size); diff --git a/lib/bcoin/chaindb.js b/lib/bcoin/chaindb.js index 3b048621..f2a468b3 100644 --- a/lib/bcoin/chaindb.js +++ b/lib/bcoin/chaindb.js @@ -33,7 +33,7 @@ function ChainDB(chain, options) { this.file = options.file; if (!this.file) - this.file = process.env.HOME + '/bcoin-' + network.type + '.blockchain'; + this.file = process.env.HOME + '/bcoin-chain-' + network.type + '.db'; this._queue = []; this._cache = {}; @@ -70,10 +70,8 @@ ChainDB.prototype._init = function _init() { } } - if (!this.exists()) { - fs.writeFileSync(this.file, new Buffer(0)); - fs.truncateSync(this.file, 0); - } + if (!this.exists()) + fs.writeFileSync(this.file, new Buffer([])); this.size = this.getSize(); diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index 4c3366a9..378f5a99 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -148,7 +148,7 @@ TX.prototype.input = TX.prototype.addInput; // tx._addInput({ hash: hash, index: index }) // tx._addInput({ tx: tx, index: index }) TX.prototype._addInput = function _addInput(options, index) { - var coin, input, ex, i, prevout; + var coin, input, ex, i, prevout, isInput; if (options instanceof TX) { options = { tx: options, index: index }; @@ -162,7 +162,6 @@ TX.prototype._addInput = function _addInput(options, index) { if (options.seq != null) options.sequence = options.seq; - var isInput; if (!options.prevout) { if (options instanceof bcoin.coin) { options = { @@ -780,8 +779,7 @@ TX.prototype.scriptOutput = function scriptOutput(index, options) { script = [ bcoin.script.array(options.locktime), 'checklocktimeverify', - 'drop', - 'codeseparator' + 'drop' ].concat(script); } hash = utils.ripesha(bcoin.script.encode(script)); @@ -808,6 +806,9 @@ TX.prototype.signatureHash = function signatureHash(index, s, type) { var copy = this.clone(); var i, msg, hash; + if (typeof index !== 'number') + index = this.inputs.indexOf(index); + if (!Array.isArray(s)) { type = s; s = this.inputs[index].output.script; @@ -815,9 +816,6 @@ TX.prototype.signatureHash = function signatureHash(index, s, type) { s = bcoin.script.getRedeem(this.inputs[index].script); } - if (typeof index !== 'number') - index = this.inputs.indexOf(index); - if (typeof type === 'string') type = constants.hashType[type];