blockdb cleanup.

This commit is contained in:
Christopher Jeffrey 2016-02-15 01:49:06 -08:00
parent 2a20e56f7b
commit 299126225c
3 changed files with 104 additions and 54 deletions

View File

@ -32,15 +32,21 @@ function BlockDB(options) {
options = { file: options }; options = { file: options };
if (!options.file) 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.options = options;
this.parser = new bcoin.protocol.parser(); this.parser = new bcoin.protocol.parser();
this.data = new BlockData(); this.data = new BlockData();
this.index = levelup(options.file, { this.index = levelup(options.file, {
keyEncoding: 'ascii', keyEncoding: 'ascii',
valueEncoding: 'binary', 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(); var batch = this.index.batch();
this.data.saveAsync(block._raw, function(err, data) { this.data.saveAsync(block._raw, function(err, data) {
var batch, blockOffset;
if (err) if (err)
return callback(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/b/' + block.hash('hex'), blockOffset);
batch.put('b/h/' + block.height, blockOffset); batch.put('b/h/' + block.height, blockOffset);
block.txs.forEach(function(tx, i) { block.txs.forEach(function(tx, i) {
var txOffset = self.createOffset(
tx._size, data.offset + tx._offset,
block.height);
var hash = tx.hash('hex'); var hash = tx.hash('hex');
var uniq = {}; var uniq = {};
var txOffset;
txOffset = self.createOffset(
tx._size,
data.offset + tx._offset,
block.height
);
batch.put('t/t/' + hash, txOffset); batch.put('t/t/' + hash, txOffset);
@ -122,8 +134,12 @@ BlockDB.prototype.saveBlock = function saveBlock(block, callback) {
if (uaddr) if (uaddr)
batch.put('t/a/' + uaddr + '/' + hash, txOffset); batch.put('t/a/' + uaddr + '/' + hash, txOffset);
if (address) if (address) {
batch.del('u/a/' + address + '/' + input.prevout.hash + '/' + input.prevout.index); batch.del(
'u/a/' + address
+ '/' + input.prevout.hash
+ '/' + input.prevout.index);
}
batch.del('u/t/' + 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) { tx.outputs.forEach(function(output) {
var type = output.getType(); var type = output.getType();
var address = output.getAddress(); var address = output.getAddress();
var uaddr; var uaddr, coinOffset;
if (type === 'pubkey' || type === 'multisig') if (type === 'pubkey' || type === 'multisig')
address = null; address = null;
@ -145,10 +161,11 @@ BlockDB.prototype.saveBlock = function saveBlock(block, callback) {
uaddr = null; uaddr = null;
} }
var coinOffset = self.createOffset( coinOffset = self.createOffset(
output._size, output._size,
data.offset + tx._offset + output._offset, data.offset + tx._offset + output._offset,
block.height); block.height
);
if (uaddr) if (uaddr)
batch.put('t/a/' + uaddr + '/' + hash, txOffset); batch.put('t/a/' + uaddr + '/' + hash, txOffset);
@ -207,7 +224,7 @@ BlockDB.prototype.removeBlock = function removeBlock(hash, callback) {
tx.inputs.forEach(function(input) { tx.inputs.forEach(function(input) {
var type = input.getType(); var type = input.getType();
var address = input.getAddress(); var address = input.getAddress();
var uaddr; var uaddr, coinOffset;
if (type === 'pubkey' || type === 'multisig') if (type === 'pubkey' || type === 'multisig')
address = null; address = null;
@ -224,15 +241,23 @@ BlockDB.prototype.removeBlock = function removeBlock(hash, callback) {
if (uaddr) if (uaddr)
batch.del('t/a/' + uaddr + '/' + hash); batch.del('t/a/' + uaddr + '/' + hash);
var coinOffset = self.createOffset( coinOffset = self.createOffset(
input.output._size, input.output._size,
block._fileOffset + tx._offset + input.output._offset, block._fileOffset + tx._offset + input.output._offset,
block.height); block.height
);
if (address) if (address) {
batch.put('u/a/' + address + '/' + input.output.hash + '/' + input.output.index, coinOffset); 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) { tx.outputs.forEach(function(output) {
@ -272,6 +297,11 @@ BlockDB.prototype.fillTX = function fillTX(tx, callback) {
var self = this; var self = this;
var pending = tx.inputs.length; var pending = tx.inputs.length;
callback = utils.asyncify(callback);
if (!pending)
return callback();
tx.inputs.forEach(function(input) { tx.inputs.forEach(function(input) {
if (input.output) { if (input.output) {
if (!--pending) if (!--pending)
@ -295,6 +325,11 @@ BlockDB.prototype.fillTX2 = function fillTX2(tx, callback) {
var self = this; var self = this;
var pending = tx.inputs.length; var pending = tx.inputs.length;
callback = utils.asyncify(callback);
if (!pending)
return callback();
tx.inputs.forEach(function(input) { tx.inputs.forEach(function(input) {
if (input.output) { if (input.output) {
if (!--pending) if (!--pending)
@ -324,7 +359,7 @@ BlockDB.prototype.getCoinsByAddress = function getCoinsByAddress(addresses, call
addresses = utils.uniqs(addresses); addresses = utils.uniqs(addresses);
var pending = addresses.length; pending = addresses.length;
addresses.forEach(function(address) { addresses.forEach(function(address) {
self._getCoinsByAddress(address, function(err, coin) { self._getCoinsByAddress(address, function(err, coin) {
@ -345,10 +380,11 @@ BlockDB.prototype._getCoinsByAddress = function _getCoinsByAddress(address, call
var pending = 0; var pending = 0;
var coins = []; var coins = [];
var done = false; var done = false;
var stream;
callback = utils.asyncify(callback); callback = utils.asyncify(callback);
var stream = this.index.createReadStream({ stream = this.index.createReadStream({
start: 'u/a/' + address, start: 'u/a/' + address,
end: 'u/a/' + address + '~' end: 'u/a/' + address + '~'
}); });
@ -366,7 +402,11 @@ BlockDB.prototype._getCoinsByAddress = function _getCoinsByAddress(address, call
return callback(err); return callback(err);
if (data) { if (data) {
data = self.parser.parseTXOut(data); try {
data = self.parser.parseTXOut(data);
} catch (e) {
return callback(e);
}
coin = bcoin.coin({ coin = bcoin.coin({
version: 1, version: 1,
hash: hash, hash: hash,
@ -403,7 +443,7 @@ BlockDB.prototype.getCoin = function getCoin(hash, index, callback) {
var self = this; var self = this;
var id = 'u/t/' + hash + '/' + index; 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) {
if (err.type === 'NotFoundError') if (err.type === 'NotFoundError')
return callback(); return callback();
@ -419,7 +459,11 @@ BlockDB.prototype.getCoin = function getCoin(hash, index, callback) {
return callback(err); return callback(err);
if (data) { if (data) {
data = self.parser.parseTXOut(data); try {
data = self.parser.parseTXOut(data);
} catch (e) {
return callback(e);
}
coin = bcoin.coin({ coin = bcoin.coin({
version: 1, version: 1,
hash: hash, hash: hash,
@ -493,8 +537,13 @@ BlockDB.prototype._getTXByAddress = function _getTXByAddress(address, callback)
return callback(err); return callback(err);
if (data) { if (data) {
tx = bcoin.tx.fromRaw(data); try {
entry = bcoin.chain.global.db.get(record.height); 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.height = record.height;
tx.ts = entry.ts; tx.ts = entry.ts;
tx.block = entry.hash; tx.block = entry.hash;
@ -525,7 +574,7 @@ BlockDB.prototype.getTX = function getTX(hash, callback) {
var self = this; var self = this;
var id = 't/t/' + hash; 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) {
if (err.type === 'NotFoundError') if (err.type === 'NotFoundError')
return callback(); return callback();
@ -541,8 +590,13 @@ BlockDB.prototype.getTX = function getTX(hash, callback) {
return callback(err); return callback(err);
if (data) { if (data) {
tx = bcoin.tx.fromRaw(data); try {
entry = bcoin.chain.global.db.get(record.height); 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.height = record.height;
tx.ts = entry.ts; tx.ts = entry.ts;
tx.block = entry.hash; tx.block = entry.hash;
@ -560,7 +614,7 @@ BlockDB.prototype.getBlock = function getBlock(hash, callback) {
if (typeof hash === 'number') if (typeof hash === 'number')
id = 'b/h/' + value; id = 'b/h/' + value;
this.index.get(id, { valueEncoding: 'binary' }, function(err, record) { this.index.get(id, function(err, record) {
if (err) { if (err) {
if (err.type === 'NotFoundError') if (err.type === 'NotFoundError')
return callback(); return callback();
@ -576,7 +630,11 @@ BlockDB.prototype.getBlock = function getBlock(hash, callback) {
return callback(err); return callback(err);
if (data) { if (data) {
block = bcoin.block.fromRaw(data); try {
block = bcoin.block.fromRaw(data);
} catch (e) {
return callback(e);
}
block._fileOffset = record.offset; block._fileOffset = record.offset;
block.height = record.height; block.height = record.height;
} }
@ -590,19 +648,18 @@ BlockDB.prototype.getBlock = function getBlock(hash, callback) {
* BlockData * BlockData
*/ */
function BlockData(chain, options) { function BlockData(options) {
if (!(this instanceof BlockData)) if (!(this instanceof BlockData))
return new BlockData(chain, options); return new BlockData(options);
if (!options) if (!options)
options = {}; options = {};
this.options = options; this.options = options;
this.chain = chain;
this.file = options.file; this.file = options.file;
if (!this.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._queue = [];
this._cache = {}; this._cache = {};
@ -628,10 +685,8 @@ BlockData.prototype._init = function _init() {
} }
} }
if (!this.exists()) { if (!this.exists())
fs.writeFileSync(this.file, new Buffer(0)); fs.writeFileSync(this.file, new Buffer([]));
fs.truncateSync(this.file, 0);
}
this.size = this.getSize(); this.size = this.getSize();
@ -757,9 +812,8 @@ BlockData.prototype.saveAsync = function saveAsync(data, callback) {
}); });
}; };
BlockData.prototype.truncate = function truncate(height) { BlockData.prototype.truncate = function truncate(size) {
this.size = (height + 1) * BLOCK_SIZE; this.size = size;
this.tip = height;
if (!bcoin.fs) { if (!bcoin.fs) {
this.ramdisk.truncate(this.size); this.ramdisk.truncate(this.size);

View File

@ -33,7 +33,7 @@ function ChainDB(chain, options) {
this.file = options.file; this.file = options.file;
if (!this.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._queue = [];
this._cache = {}; this._cache = {};
@ -70,10 +70,8 @@ ChainDB.prototype._init = function _init() {
} }
} }
if (!this.exists()) { if (!this.exists())
fs.writeFileSync(this.file, new Buffer(0)); fs.writeFileSync(this.file, new Buffer([]));
fs.truncateSync(this.file, 0);
}
this.size = this.getSize(); this.size = this.getSize();

View File

@ -148,7 +148,7 @@ TX.prototype.input = TX.prototype.addInput;
// tx._addInput({ hash: hash, index: index }) // tx._addInput({ hash: hash, index: index })
// tx._addInput({ tx: tx, index: index }) // tx._addInput({ tx: tx, index: index })
TX.prototype._addInput = function _addInput(options, 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) { if (options instanceof TX) {
options = { tx: options, index: index }; options = { tx: options, index: index };
@ -162,7 +162,6 @@ TX.prototype._addInput = function _addInput(options, index) {
if (options.seq != null) if (options.seq != null)
options.sequence = options.seq; options.sequence = options.seq;
var isInput;
if (!options.prevout) { if (!options.prevout) {
if (options instanceof bcoin.coin) { if (options instanceof bcoin.coin) {
options = { options = {
@ -780,8 +779,7 @@ TX.prototype.scriptOutput = function scriptOutput(index, options) {
script = [ script = [
bcoin.script.array(options.locktime), bcoin.script.array(options.locktime),
'checklocktimeverify', 'checklocktimeverify',
'drop', 'drop'
'codeseparator'
].concat(script); ].concat(script);
} }
hash = utils.ripesha(bcoin.script.encode(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 copy = this.clone();
var i, msg, hash; var i, msg, hash;
if (typeof index !== 'number')
index = this.inputs.indexOf(index);
if (!Array.isArray(s)) { if (!Array.isArray(s)) {
type = s; type = s;
s = this.inputs[index].output.script; 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); s = bcoin.script.getRedeem(this.inputs[index].script);
} }
if (typeof index !== 'number')
index = this.inputs.indexOf(index);
if (typeof type === 'string') if (typeof type === 'string')
type = constants.hashType[type]; type = constants.hashType[type];