refactor txdb and chaindb db usage.

This commit is contained in:
Christopher Jeffrey 2016-05-13 04:49:21 -07:00
parent 5a2834dcec
commit f4be7651cd
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
5 changed files with 187 additions and 540 deletions

View File

@ -106,7 +106,7 @@ Chain.prototype._init = function _init() {
if (self.height < network.block.slowHeight)
return;
bcoin.debug('Block %s (%d) added to chain',
bcoin.debug('Block %s (%d) added to chain.',
utils.revHex(entry.hash), entry.height);
});

View File

@ -24,6 +24,7 @@ module.exports = function(bcoin) {
var EventEmitter = require('events').EventEmitter;
var network = bcoin.protocol.network;
var constants = bcoin.protocol.constants;
var utils = require('./utils');
var assert = utils.assert;
var pad32 = utils.pad32;
@ -125,8 +126,8 @@ ChainDB.prototype._init = function _init() {
self.emit('open');
}
self.db.get('h/' + network.genesis.hash, function(err, exists) {
if (err && err.type !== 'NotFoundError')
self.db.has('h/' + network.genesis.hash, function(err, exists) {
if (err)
return self.emit('error', err);
if (exists)
@ -233,21 +234,23 @@ ChainDB.prototype.getHeight = function getHeight(hash, callback) {
if (typeof hash === 'number')
return callback(null, hash);
// When prevBlock=zero-hash
if (+hash === 0)
if (hash === constants.NULL_HASH)
return callback(null, -1);
if (this.cacheHash.has(hash))
return callback(null, this.cacheHash.get(hash).height);
this.db.get('h/' + hash, function(err, height) {
if (err && err.type !== 'NotFoundError')
this.db.fetch('h/' + hash, function(data) {
assert(data.length === 4, 'Database corruption.');
return utils.readU32(data, 0);
}, function(err, height) {
if (err)
return callback(err);
if (height == null)
return callback(null, -1);
return callback(null, utils.readU32(height, 0));
return callback(null, height);
});
};
@ -270,15 +273,10 @@ ChainDB.prototype.getHash = function getHash(height, callback) {
if (this.cacheHeight.has(height))
return callback(null, this.cacheHeight.get(height).hash);
this.db.get('H/' + pad32(height), function(err, hash) {
if (err && err.type !== 'NotFoundError')
return callback(err);
if (hash == null)
return callback(null, null);
return callback(null, hash.toString('hex'));
});
this.db.fetch('H/' + pad32(height), function(data) {
assert(data.length === 32, 'Database corruption.');
return data.toString('hex');
}, callback);
};
/**
@ -387,14 +385,13 @@ ChainDB.prototype.getBoth = function getBoth(block, callback) {
* @param {Function} callback - Returns [Error, {@link ChainBlock}].
*/
ChainDB.prototype._getEntry = function _getEntry(hash, callback) {
ChainDB.prototype.getEntry = function getEntry(hash, callback) {
var self = this;
var entry;
if (hash == null || hash < 0)
return utils.nextTick(callback);
return this.getBoth(hash, function(err, hash, height) {
return this.getHash(hash, function(err, hash) {
if (err && err.type !== 'NotFoundError')
return callback(err);
@ -404,21 +401,9 @@ ChainDB.prototype._getEntry = function _getEntry(hash, callback) {
if (self.cacheHash.has(hash))
return callback(null, self.cacheHash.get(hash));
return self.db.get('e/' + hash, function(err, data) {
if (err && err.type !== 'NotFoundError')
return callback(err);
if (!data)
return callback();
try {
entry = bcoin.chainblock.fromRaw(self.chain, data);
} catch (e) {
return callback(e);
}
return callback(null, entry);
});
return self.db.fetch('e/' + hash, function(data) {
return bcoin.chainblock.fromRaw(self.chain, data);
}, callback);
});
};
@ -428,10 +413,10 @@ ChainDB.prototype._getEntry = function _getEntry(hash, callback) {
* @param {Function} callback - Returns [Error, {@link ChainBlock}].
*/
ChainDB.prototype.get = function get(height, callback) {
ChainDB.prototype.get = function get(hash, callback) {
var self = this;
return this._getEntry(height, function(err, entry) {
return this.getEntry(hash, function(err, entry) {
if (err)
return callback(err);
@ -509,14 +494,17 @@ ChainDB.prototype.save = function save(entry, block, connect, callback) {
ChainDB.prototype.getTip = function getTip(callback) {
var self = this;
return this.db.get('R', function(err, hash) {
if (err && err.type !== 'NotFoundError')
return this.db.fetch('R', function(data) {
assert(data.length === 32, 'Database corruption.');
return data.toString('hex');
}, function(err, hash) {
if (err)
return callback(err);
if (!hash)
return callback();
return self.get(hash.toString('hex'), callback);
return self.get(hash, callback);
});
};
@ -605,15 +593,10 @@ ChainDB.prototype._ensureEntry = function _ensureEntry(block, callback) {
*/
ChainDB.prototype.getNextHash = function getNextHash(hash, callback) {
return this.db.get('n/' + hash, function(err, nextHash) {
if (err && err.type !== 'NotFoundError')
return callback(err);
if (!nextHash)
return callback();
return callback(null, nextHash.toString('hex'));
});
return this.db.fetch('n/' + hash, function(data) {
assert(data.length === 32, 'Database corruption.');
return data.toString('hex');
}, callback);
};
/**
@ -1057,68 +1040,33 @@ ChainDB.prototype.fillHistory = function fillHistory(tx, callback) {
ChainDB.prototype.getCoinsByAddress = function getCoinsByAddress(addresses, callback) {
var self = this;
var ids = [];
var coins = [];
if (typeof addresses === 'string')
if (!Array.isArray(addresses))
addresses = [addresses];
addresses = utils.uniq(addresses);
utils.forEachSerial(addresses, function(address, done) {
var iter = self.db.iterator({
gte: 'C/' + address + '/',
lte: 'C/' + address + '/~',
keys: true,
values: true,
fillCache: true,
keyAsBuffer: false,
valueAsBuffer: true
});
(function next() {
iter.next(function(err, key, value) {
var parts, hash, index;
if (err) {
return iter.end(function() {
done(err);
});
}
if (key === undefined)
return iter.end(done);
parts = key.split('/');
hash = parts[2];
index = +parts[3];
ids.push([hash, index]);
next();
});
})();
}, function(err) {
if (err)
return callback(err);
utils.forEachSerial(ids, function(item, next) {
var hash = item[0];
var index = item[1];
self.getCoin(hash, index, function(err, coin) {
if (err)
return next(err);
if (!coin)
return next();
coins.push(coin);
next();
});
}, function(err) {
utils.forEachSerial(addresses, function(address, next) {
self.db.lookup({
gte: 'C/' + address,
lte: 'C/' + address + '~',
transform: function(key) {
key = key.split('/');
return 'c/' + key[2] + '/' + key[3];
},
parse: function(data, key) {
var coin = bcoin.coin.fromRaw(data);
var hash = key.split('/');
coin.hash = hash[1];
coin.index = +hash[2];
return coin;
}
}, function(err, coin) {
if (err)
return callback(err);
return callback(null, coins);
return next(err);
coins = coins.concat(coin);
next();
});
});
};
@ -1139,25 +1087,13 @@ ChainDB.prototype.getCoin = function getCoin(hash, index, callback) {
if (coin)
return utils.asyncify(callback)(null, coin);
this.db.get('c/' + key, function(err, data) {
if (err && err.type !== 'NotFoundError')
return callback(err);
if (!data)
return callback();
try {
coin = bcoin.coin.fromRaw(data);
coin.hash = hash;
coin.index = index;
} catch (e) {
return callback(e);
}
this.db.fetch('c/' + key, function(data) {
var coin = bcoin.coin.fromRaw(data);
coin.hash = hash;
coin.index = index;
self.coinCache.set(key, coin);
return callback(null, coin);
});
return coin;
}, callback);
};
/**
@ -1168,73 +1104,40 @@ ChainDB.prototype.getCoin = function getCoin(hash, index, callback) {
ChainDB.prototype.getTXByAddress = function getTXByAddress(addresses, callback) {
var self = this;
var hashes = [];
var txs = [];
var have = {};
if (typeof addresses === 'string')
if (!Array.isArray(addresses))
addresses = [addresses];
addresses = utils.uniq(addresses);
utils.forEachSerial(addresses, function(address, done) {
var iter = self.db.iterator({
gte: 'T/' + address + '/',
lte: 'T/' + address + '/~',
keys: true,
values: true,
fillCache: true,
keyAsBuffer: false,
valueAsBuffer: true
});
(function next() {
iter.next(function(err, key, value) {
var hash;
if (err) {
return iter.end(function() {
done(err);
});
}
if (key === undefined)
return iter.end(done);
hash = key.split('/')[2];
self.db.lookup({
gte: 'T/' + address,
lte: 'T/' + address + '~',
transform: function(key) {
var hash = key.split('/')[2];
if (addresses.length > 1) {
if (have[hash])
return next();
return false;
have[hash] = true;
}
hashes.push(hash);
next();
});
})();
return 't/' + hash;
},
parse: function(data, key) {
return bcoin.tx.fromRaw(data);
}
}, function(err, tx) {
if (err)
return next(err);
txs = txs.concat(tx);
next();
});
}, function(err) {
if (err)
return callback(err);
utils.forEachSerial(hashes, function(hash, next) {
self.getTX(hash, function(err, tx) {
if (err)
return next(err);
if (!tx)
return next();
txs.push(tx);
next();
});
}, function(err) {
if (err)
return callback(err);
return callback(null, txs);
});
return callback(null, txs);
});
};
@ -1246,25 +1149,16 @@ ChainDB.prototype.getTXByAddress = function getTXByAddress(addresses, callback)
ChainDB.prototype.getTX = function getTX(hash, callback) {
var self = this;
var key = 't/' + hash;
var tx;
if (!this.options.indexTX)
return utils.nextTick(callback);
this.db.get(key, function(err, data) {
if (err && err.type !== 'NotFoundError')
this.db.fetch('t/' + hash, function(data) {
return bcoin.tx.fromExtended(data);
}, function(err, tx) {
if (err)
return callback(err);
if (!data)
return callback();
try {
tx = bcoin.tx.fromExtended(data);
} catch (e) {
return callback(e);
}
if (self.options.paranoid)
assert(tx.hash('hex') === hash, 'Database is corrupt.');
@ -1281,12 +1175,7 @@ ChainDB.prototype.hasTX = function hasTX(hash, callback) {
if (!this.options.indexTX)
return utils.asyncify(callback)(null, false);
return this.getTX(hash, function(err, tx) {
if (err)
return callback(err);
return callback(null, tx != null);
});
return this.db.has('t/' + hash, callback);
};
/**
@ -1406,29 +1295,18 @@ ChainDB.prototype.fillBlock = function fillBlock(block, callback) {
*/
ChainDB.prototype.getUndoCoins = function getUndoCoins(hash, callback) {
var coins, p, coin, i, tx;
return this.db.fetch('u/' + hash, function(data) {
var p = new BufferReader(data);
var coins = [];
var coin;
return this.db.get('u/' + hash, function(err, data) {
if (err && err.type !== 'NotFoundError')
return callback(err);
if (!data)
return callback();
coins = [];
p = new BufferReader(data);
try {
while (p.left()) {
coin = Parser.parseCoin(p, false);
coins.push(new bcoin.coin(coin));
}
} catch (e) {
return callback(e);
while (p.left()) {
coin = Parser.parseCoin(p, false);
coins.push(new bcoin.coin(coin));
}
return callback(null, coins);
});
return coins;
}, callback);
};
/**
@ -1473,8 +1351,6 @@ ChainDB.prototype.fillHistoryBlock = function fillHistoryBlock(block, callback)
ChainDB.prototype.getBlock = function getBlock(hash, callback) {
var self = this;
var key, block;
return this.getBoth(hash, function(err, hash, height) {
if (err)
return callback(err);
@ -1482,24 +1358,11 @@ ChainDB.prototype.getBlock = function getBlock(hash, callback) {
if (!hash)
return callback();
key = 'b/' + hash;
self.db.get(key, function(err, data) {
if (err && err.type !== 'NotFoundError')
return callback(err);
if (!data)
return callback();
try {
block = bcoin.block.fromRaw(data);
block.setHeight(height);
} catch (e) {
return callback(e);
}
return callback(null, block);
});
self.db.fetch('b/' + hash, function(data) {
var block = bcoin.block.fromRaw(data);
block.setHeight(height);
return block;
}, callback);
});
};
@ -1577,15 +1440,16 @@ ChainDB.prototype._pruneBlock = function _pruneBlock(block, batch, callback) {
key = 'b/q/' + pad32(block.height);
this.db.get(key, function(err, hash) {
if (err && err.type !== 'NotFoundError')
this.db.fetch(key, function(data) {
assert(data.length === 32, 'Database corruption.');
return data.toString('hex');
}, function(err, hash) {
if (err)
return callback(err);
if (!hash)
return callback();
hash = hash.toString('hex');
batch.del(key);
batch.del('b/' + hash);
batch.del('u/' + hash);

View File

@ -86,6 +86,7 @@ try {
* @property {Function} chaindb - {@link ChainDB} constructor.
* @property {Function} chain - {@link Chain} constructor.
* @property {Function} mempool - {@link Mempool} constructor.
* @property {Function} mempoolentry - {@link MempoolEntry} constructor.
* @property {Function} keypair - {@link KeyPair} constructor.
* @property {Function} hd - {@link HD} constructor.
* @property {Function} address - {@link Address} constructor.
@ -207,6 +208,7 @@ function Environment(options) {
this.chaindb = require('./chaindb')(this);
this.chain = require('./chain')(this);
this.mempool = require('./mempool')(this);
this.mempoolentry = this.mempool.mempoolentry;
this.keypair = require('./keypair')(this);
this.hd = require('./hd')(this);
this.address = require('./address')(this);

View File

@ -694,7 +694,7 @@ Parser.parseBlockHeaders = function parseBlockHeaders(p) {
/**
* Parse a transaction in "extended" serialization format.
* @param {Buffer} p
* @param {Buffer|BufferReader} p
* @param {Boolean?} saveCoins - If true, the function will
* attempt to parse the coins.
* @param {String?} enc - One of `"hex"` or `null`.
@ -702,7 +702,7 @@ Parser.parseBlockHeaders = function parseBlockHeaders(p) {
*/
Parser.parseExtendedTX = function parseExtendedTX(p, saveCoins) {
var tx, coinCount, coin, i, tmp;
var i, tx, coinCount, coin;
p = new BufferReader(p);

View File

@ -134,7 +134,6 @@ TXDB.prototype.getMap = function getMap(tx, callback) {
TXDB.prototype.mapAddresses = function mapAddresses(address, callback) {
var self = this;
var table = {};
var iter;
if (Array.isArray(address)) {
return utils.forEachSerial(address, function(address, next) {
@ -155,41 +154,20 @@ TXDB.prototype.mapAddresses = function mapAddresses(address, callback) {
});
}
iter = this.db.iterator({
this.db.iterate({
gte: 'W/' + address,
lte: 'W/' + address + '~',
keys: true,
values: false,
fillCache: false,
keyAsBuffer: false
transform: function(key) {
return key.split('/')[2];
}
}, function(err, keys) {
if (err)
return callback(err);
table[address] = keys;
return callback(null, table);
});
callback = utils.ensure(callback);
table[address] = [];
(function next() {
iter.next(function(err, key, value) {
if (err) {
return iter.end(function() {
callback(err);
});
}
if (key === undefined) {
return iter.end(function(err) {
if (err)
return callback(err);
return callback(null, table);
});
}
key = key.split('/')[2];
table[address].push(key);
next();
});
})();
};
/**
@ -230,29 +208,26 @@ TXDB.prototype._addOrphan = function _addOrphan(key, hash, index, callback) {
TXDB.prototype._getOrphans = function _getOrphans(key, callback) {
var self = this;
var p, orphans;
this.db.get('o/' + key, function(err, buf) {
if (err && err.type !== 'NotFoundError')
this.db.fetch('o/' + key, function(buf) {
var p = new BufferReader(buf);
var orphans = [];
while (p.left()) {
orphans.push({
hash: p.readHash('hex'),
index: p.readU32()
});
}
return orphans;
}, function(err, orphans) {
if (err)
return callback(err);
if (!buf)
if (!orphans)
return callback();
p = new BufferReader(buf);
orphans = [];
try {
while (p.left()) {
orphans.push({
hash: p.readHash('hex'),
index: p.readU32()
});
}
} catch (e) {
return callback(e);
}
utils.forEach(orphans, function(orphan, next) {
self.getTX(orphan.hash, function(err, tx) {
if (err)
@ -627,14 +602,11 @@ TXDB.prototype.isDoubleSpend = function isDoubleSpend(tx, callback) {
self.isSpent(input.prevout.hash, input.prevout.index, function(err, spent) {
if (err)
return next(err);
if (spent)
return next(null, false);
return next(null, true);
return next(null, !spent);
});
}, function(err, result) {
if (err)
return callback(err);
return callback(null, !result);
});
};
@ -647,18 +619,10 @@ TXDB.prototype.isDoubleSpend = function isDoubleSpend(tx, callback) {
*/
TXDB.prototype.isSpent = function isSpent(hash, index, callback) {
var self = this;
var key = 's/' + hash + '/' + index;
return this.db.get(key, function(err, hash) {
if (err && err.type !== 'NotFoundError')
return callback(err);
if (!hash)
return callback(null, null);
return callback(null, hash.toString('hex'));
});
return this.db.fetch(key, function(hash) {
return hash.toString('hex');
}, callback);
};
/**
@ -1070,8 +1034,6 @@ TXDB.prototype._unconfirm = function unconfirm(tx, map, callback, force) {
TXDB.prototype.getHistoryHashes = function getHistoryHashes(address, callback) {
var self = this;
var txs = [];
var iter;
if (typeof address === 'function') {
callback = address;
@ -1100,39 +1062,16 @@ TXDB.prototype.getHistoryHashes = function getHistoryHashes(address, callback) {
});
}
iter = this.db.iterator({
this.db.iterate({
gte: address ? 'T/' + address : 't',
lte: address ? 'T/' + address + '~' : 't~',
keys: true,
values: false,
fillCache: false,
keyAsBuffer: false
});
(function next() {
iter.next(function(err, key, value) {
if (err) {
return iter.end(function() {
callback(err);
});
}
if (key === undefined) {
return iter.end(function(err) {
if (err)
return callback(err);
return callback(null, txs);
});
}
transform: function(key) {
key = key.split('/');
if (address)
txs.push(key.split('/')[2]);
else
txs.push(key.split('/')[1]);
next();
});
})();
return key[2];
return key[1];
}
}, callback);
};
/**
@ -1143,8 +1082,6 @@ TXDB.prototype.getHistoryHashes = function getHistoryHashes(address, callback) {
TXDB.prototype.getUnconfirmedHashes = function getUnconfirmedHashes(address, callback) {
var self = this;
var txs = [];
var iter;
if (typeof address === 'function') {
callback = address;
@ -1174,39 +1111,16 @@ TXDB.prototype.getUnconfirmedHashes = function getUnconfirmedHashes(address, cal
});
}
iter = this.db.iterator({
this.db.iterate({
gte: address ? 'P/' + address : 'p',
lte: address ? 'P/' + address + '~' : 'p~',
keys: true,
values: false,
fillCache: false,
keyAsBuffer: false
});
(function next() {
iter.next(function(err, key, value) {
if (err) {
return iter.end(function() {
callback(err);
});
}
if (key === undefined) {
return iter.end(function(err) {
if (err)
return callback(err);
return callback(null, txs);
});
}
transform: function(key) {
key = key.split('/');
if (address)
txs.push(key.split('/')[2]);
else
txs.push(key.split('/')[1]);
next();
});
})();
return key[2];
return key[1];
}
}, callback);
};
/**
@ -1217,8 +1131,6 @@ TXDB.prototype.getUnconfirmedHashes = function getUnconfirmedHashes(address, cal
TXDB.prototype.getCoinHashes = function getCoinHashes(address, callback) {
var self = this;
var coins = [];
var iter;
if (typeof address === 'function') {
callback = address;
@ -1245,45 +1157,16 @@ TXDB.prototype.getCoinHashes = function getCoinHashes(address, callback) {
});
}
iter = this.db.iterator({
gte: address
? 'C/' + address
: 'c',
lte: address
? 'C/' + address + '~'
: 'c~',
keys: true,
values: false,
fillCache: false,
keyAsBuffer: false
});
(function next() {
iter.next(function(err, key, value) {
if (err) {
return iter.end(function() {
callback(err);
});
}
if (key === undefined) {
return iter.end(function(err) {
if (err)
return callback(err);
return callback(null, coins);
});
}
this.db.iterate({
gte: address ? 'C/' + address : 'c',
lte: address ? 'C/' + address + '~' : 'c~',
transform: function(key) {
key = key.split('/');
if (address)
coins.push([key[2], +key[3]]);
else
coins.push([key[1], +key[2]]);
next();
});
})();
return [key[2], +key[3]];
return [key[1], +key[2]];
}
}, callback);
};
/**
@ -1298,13 +1181,7 @@ TXDB.prototype.getCoinHashes = function getCoinHashes(address, callback) {
*/
TXDB.prototype.getHeightRangeHashes = function getHeightRangeHashes(address, options, callback) {
var txs = [];
var iter;
if (typeof address === 'function') {
callback = address;
address = null;
} else if (address && typeof address === 'object') {
if (typeof address !== 'string') {
callback = options;
options = address;
address = null;
@ -1312,45 +1189,22 @@ TXDB.prototype.getHeightRangeHashes = function getHeightRangeHashes(address, opt
callback = utils.ensure(callback);
iter = this.db.iterator({
this.db.iterate({
gte: address
? 'H/' + address + '/' + pad32(options.start) + '/'
: 'h/' + pad32(options.start) + '/',
lte: address
? 'H/' + address + '/' + pad32(options.end) + '/~'
: 'h/' + pad32(options.end) + '/~',
keys: true,
values: false,
fillCache: false,
keyAsBuffer: false,
limit: options.limit,
reverse: options.reverse
});
(function next() {
iter.next(function(err, key, value) {
if (err) {
return iter.end(function() {
callback(err);
});
}
if (key === undefined) {
return iter.end(function(err) {
if (err)
return callback(err);
return callback(null, txs);
});
}
reverse: options.reverse,
transform: function(key) {
key = key.split('/');
if (address)
txs.push(key.split('/')[3]);
else
txs.push(key.split('/')[2]);
next();
});
})();
return key[3];
return key[2];
}
}, callback);
};
/**
@ -1375,9 +1229,6 @@ TXDB.prototype.getHeightHashes = function getHeightHashes(height, callback) {
*/
TXDB.prototype.getRangeHashes = function getRangeHashes(address, options, callback) {
var txs = [];
var iter;
if (typeof address === 'function') {
callback = address;
address = null;
@ -1385,45 +1236,22 @@ TXDB.prototype.getRangeHashes = function getRangeHashes(address, options, callba
callback = utils.ensure(callback);
iter = this.db.iterator({
this.db.iterate({
gte: address
? 'M/' + address + '/' + pad32(options.start) + '/'
: 'm/' + pad32(options.start) + '/',
lte: address
? 'M/' + address + '/' + pad32(options.end) + '/~'
: 'm/' + pad32(options.end) + '/~',
keys: true,
values: false,
fillCache: false,
keyAsBuffer: false,
limit: options.limit,
reverse: options.reverse
});
(function next() {
iter.next(function(err, key, value) {
if (err) {
return iter.end(function() {
callback(err);
});
}
if (key === undefined) {
return iter.end(function(err) {
if (err)
return callback(err);
return callback(null, txs);
});
}
reverse: options.reverse,
transform: function(key) {
key = key.split('/');
if (address)
txs.push(key.split('/')[3]);
else
txs.push(key.split('/')[2]);
next();
});
})();
return key[3];
return key[2];
}
}, callback);
};
/**
@ -1657,12 +1485,7 @@ TXDB.prototype.fillHistory = function fillHistory(tx, callback) {
if (Array.isArray(tx)) {
return utils.forEachSerial(tx, function(tx, next) {
self.fillHistory(tx, function(err) {
if (err)
return next(err);
next();
});
self.fillHistory(tx, next);
}, callback);
}
@ -1702,12 +1525,7 @@ TXDB.prototype.fillCoins = function fillCoins(tx, callback) {
if (Array.isArray(tx)) {
return utils.forEachSerial(tx, function(tx, next) {
self.fillCoins(tx, function(err) {
if (err)
return next(err);
next();
});
self.fillCoins(tx, next);
}, callback);
}
@ -1743,23 +1561,9 @@ TXDB.prototype.fillCoins = function fillCoins(tx, callback) {
*/
TXDB.prototype.getTX = function getTX(hash, callback) {
var key = 't/' + hash;
this.db.get(key, function(err, tx) {
if (err && err.type !== 'NotFoundError')
return callback(err);
if (!tx)
return callback();
try {
tx = bcoin.tx.fromExtended(tx);
} catch (e) {
return callback(e);
}
return callback(null, tx);
});
this.db.fetch('t/' + hash, function(tx) {
return bcoin.tx.fromExtended(tx);
}, callback);
};
/**
@ -1769,12 +1573,7 @@ TXDB.prototype.getTX = function getTX(hash, callback) {
*/
TXDB.prototype.hasTX = function hasTX(hash, callback) {
return this.getTX(hash, function(err, tx) {
if (err)
return callback(err);
return callback(null, tx != null);
});
return this.db.has('t/' + hash, callback);
};
/**
@ -1785,25 +1584,12 @@ TXDB.prototype.hasTX = function hasTX(hash, callback) {
*/
TXDB.prototype.getCoin = function getCoin(hash, index, callback) {
var key = 'c/' + hash + '/' + index;
this.db.get(key, function(err, coin) {
if (err && err.type !== 'NotFoundError')
return callback(err);
if (!coin)
return callback();
try {
coin = bcoin.coin.fromRaw(coin);
coin.hash = hash;
coin.index = index;
} catch (e) {
return callback(e);
}
return callback(null, coin);
});
this.db.fetch('c/' + hash + '/' + index, function(coin) {
coin = bcoin.coin.fromRaw(coin);
coin.hash = hash;
coin.index = index;
return coin;
}, callback);
};
/**
@ -1813,12 +1599,7 @@ TXDB.prototype.getCoin = function getCoin(hash, index, callback) {
*/
TXDB.prototype.hasCoin = function hasCoin(hash, index, callback) {
return this.getCoin(hash, index, function(err, coin) {
if (err)
return callback(err);
return callback(null, coin != null);
});
return this.db.has('c/' + hash + '/' + index, callback);
};
/**