refactor txdb and chaindb db usage.
This commit is contained in:
parent
5a2834dcec
commit
f4be7651cd
@ -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);
|
||||
});
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user