db: drop db.fetch.

This commit is contained in:
Christopher Jeffrey 2016-09-22 06:11:38 -07:00
parent 4e11bbbf9f
commit a7d3626975
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
5 changed files with 230 additions and 207 deletions

View File

@ -406,15 +406,12 @@ ChainDB.prototype.getHeight = co(function* getHeight(hash) {
if (entry) if (entry)
return entry.height; return entry.height;
height = yield this.db.fetch(layout.h(hash), function(data) { height = yield this.db.get(layout.h(hash));
assert(data.length === 4, 'Database corruption.');
return data.readUInt32LE(0, true);
});
if (height == null) if (!height)
return -1; return -1;
return height; return height.readUInt32LE(0, true);
}); });
/** /**
@ -425,7 +422,7 @@ ChainDB.prototype.getHeight = co(function* getHeight(hash) {
*/ */
ChainDB.prototype.getHash = co(function* getHash(height) { ChainDB.prototype.getHash = co(function* getHash(height) {
var entry; var entry, hash;
checkHash(height); checkHash(height);
@ -437,10 +434,12 @@ ChainDB.prototype.getHash = co(function* getHash(height) {
if (entry) if (entry)
return entry.hash; return entry.hash;
return yield this.db.fetch(layout.H(height), function(data) { hash = yield this.db.get(layout.H(height));
assert(data.length === 32, 'Database corruption.');
return data.toString('hex'); if (!hash)
}); return;
return hash.toString('hex');
}); });
/** /**
@ -496,7 +495,6 @@ ChainDB.prototype.getBoth = co(function* getBoth(block) {
*/ */
ChainDB.prototype.getEntry = co(function* getEntry(hash) { ChainDB.prototype.getEntry = co(function* getEntry(hash) {
var self = this;
var entry; var entry;
checkHash(hash); checkHash(hash);
@ -511,9 +509,12 @@ ChainDB.prototype.getEntry = co(function* getEntry(hash) {
if (entry) if (entry)
return entry; return entry;
return yield this.db.fetch(layout.e(hash), function(data) { entry = yield this.db.get(layout.e(hash));
return bcoin.chainentry.fromRaw(self.chain, data);
}); if (!entry)
return;
return bcoin.chainentry.fromRaw(this.chain, entry);
}); });
/** /**
@ -594,11 +595,12 @@ ChainDB.prototype.save = co(function* save(entry, block, view, connect) {
*/ */
ChainDB.prototype.initState = co(function* initState() { ChainDB.prototype.initState = co(function* initState() {
var state = yield this.db.fetch(layout.R, function(data) { var data = yield this.db.get(layout.R);
return ChainState.fromRaw(data); var state;
});
assert(state); assert(data);
state = ChainState.fromRaw(data);
this.state = state; this.state = state;
@ -702,12 +704,14 @@ ChainDB.prototype.disconnect = co(function* disconnect(entry) {
* @param {Function} callback - Returns [Error, {@link Hash}]. * @param {Function} callback - Returns [Error, {@link Hash}].
*/ */
ChainDB.prototype.getNextHash = function getNextHash(hash) { ChainDB.prototype.getNextHash = co(function* getNextHash(hash) {
return this.db.fetch(layout.n(hash), function(data) { var data = yield this.db.get(layout.n(hash));
assert(data.length === 32, 'Database corruption.');
return data.toString('hex'); if (!data)
}); return;
};
return data.toString('hex');
});
/** /**
* Check to see if a block is on the main chain. * Check to see if a block is on the main chain.
@ -1100,16 +1104,19 @@ ChainDB.prototype.fillHistory = co(function* fillHistory(tx) {
*/ */
ChainDB.prototype.getCoin = co(function* getCoin(hash, index) { ChainDB.prototype.getCoin = co(function* getCoin(hash, index) {
var self = this;
var coins = this.coinCache.get(hash); var coins = this.coinCache.get(hash);
if (coins) if (coins)
return bcoin.coins.parseCoin(coins, hash, index); return bcoin.coins.parseCoin(coins, hash, index);
return yield this.db.fetch(layout.c(hash), function(data) { coins = yield this.db.get(layout.c(hash));
self.coinCache.set(hash, data);
return bcoin.coins.parseCoin(data, hash, index); if (!coins)
}); return;
this.coinCache.set(hash, coins);
return bcoin.coins.parseCoin(coins, hash, index);
}); });
/** /**
@ -1119,16 +1126,19 @@ ChainDB.prototype.getCoin = co(function* getCoin(hash, index) {
*/ */
ChainDB.prototype.getCoins = co(function* getCoins(hash) { ChainDB.prototype.getCoins = co(function* getCoins(hash) {
var self = this;
var coins = this.coinCache.get(hash); var coins = this.coinCache.get(hash);
if (coins) if (coins)
return bcoin.coins.fromRaw(coins, hash); return bcoin.coins.fromRaw(coins, hash);
return yield this.db.fetch(layout.c(hash), function(data) { coins = yield this.db.get(layout.c(hash));
self.coinCache.set(hash, data);
return bcoin.coins.fromRaw(data, hash); if (!coins)
}); return;
this.coinCache.set(hash, coins);
return bcoin.coins.fromRaw(coins, hash);
}); });
/** /**
@ -1198,14 +1208,19 @@ ChainDB.prototype.scan = co(function* scan(start, filter, iter) {
* @param {Function} callback - Returns [Error, {@link TX}]. * @param {Function} callback - Returns [Error, {@link TX}].
*/ */
ChainDB.prototype.getTX = function getTX(hash) { ChainDB.prototype.getTX = co(function* getTX(hash) {
if (!this.options.indexTX) var data;
return Promise.resolve(null);
return this.db.fetch(layout.t(hash), function(data) { if (!this.options.indexTX)
return bcoin.tx.fromExtended(data); return;
});
}; data = yield this.db.get(layout.t(hash));
if (!data)
return;
return bcoin.tx.fromExtended(data);
});
/** /**
* @param {Hash} hash * @param {Hash} hash
@ -1406,17 +1421,21 @@ ChainDB.prototype.getCoinView = co(function* getCoinView(block, callback) {
* @param {Function} callback - Returns [Error, {@link Coin}[]]. * @param {Function} callback - Returns [Error, {@link Coin}[]].
*/ */
ChainDB.prototype.getUndoCoins = function getUndoCoins(hash) { ChainDB.prototype.getUndoCoins = co(function* getUndoCoins(hash) {
return this.db.fetch(layout.u(hash), function(data) { var data = yield this.db.get(layout.u(hash));
var p = new BufferReader(data); var p, coins;
var coins = [];
while (p.left()) if (!data)
coins.push(bcoin.coin.fromRaw(p)); return;
return coins; p = new BufferReader(data);
}); coins = [];
};
while (p.left())
coins.push(bcoin.coin.fromRaw(p));
return coins;
});
/** /**
* Get a coin view containing unspent coins as * Get a coin view containing unspent coins as
@ -1462,7 +1481,7 @@ ChainDB.prototype.getUndoView = co(function* getUndoView(block) {
ChainDB.prototype.getBlock = co(function* getBlock(hash) { ChainDB.prototype.getBlock = co(function* getBlock(hash) {
var items = yield this.getBoth(hash); var items = yield this.getBoth(hash);
var height; var height, data, block;
if (!items) if (!items)
return; return;
@ -1470,11 +1489,15 @@ ChainDB.prototype.getBlock = co(function* getBlock(hash) {
hash = items[0]; hash = items[0];
height = items[1]; height = items[1];
return yield this.db.fetch(layout.b(hash), function(data) { data = yield this.db.get(layout.b(hash));
var block = bcoin.block.fromRaw(data);
block.setHeight(height); if (!data)
return block; return;
});
block = bcoin.block.fromRaw(data);
block.setHeight(height);
return block;
}); });
/** /**
@ -1497,7 +1520,7 @@ ChainDB.prototype.hasCoins = function hasCoins(hash) {
*/ */
ChainDB.prototype.pruneBlock = co(function* pruneBlock(block) { ChainDB.prototype.pruneBlock = co(function* pruneBlock(block) {
var futureHeight, key, hash; var futureHeight, key, hash, data;
if (this.options.spv) if (this.options.spv)
return; return;
@ -1514,10 +1537,7 @@ ChainDB.prototype.pruneBlock = co(function* pruneBlock(block) {
key = layout.q(block.height); key = layout.q(block.height);
hash = yield this.db.fetch(key, function(data) { hash = yield this.db.get(key);
assert(data.length === 32, 'Database corruption.');
return data.toString('hex');
});
if (!hash) if (!hash)
return; return;

View File

@ -296,22 +296,6 @@ LowlevelUp.prototype.has = co(function* has(key) {
return value != null; return value != null;
}); });
/**
* Get and deserialize a record with a callback.
* @param {String} key
* @param {Function} parse - Accepts [Buffer(data), String(key)].
* Return value should be the parsed object.
* @param {Function} callback - Returns [Error, Object].
*/
LowlevelUp.prototype.fetch = co(function* fetch(key, parse) {
var value = yield this.get(key);
if (!value)
return;
return parse(value, key);
});
/** /**
* Collect all keys from iterator options. * Collect all keys from iterator options.
* @param {Object} options - Iterator options. * @param {Object} options - Iterator options.

View File

@ -502,8 +502,8 @@ Mempool.prototype.has = function has(hash) {
if (this.hasOrphan(hash)) if (this.hasOrphan(hash))
return true; return true;
if (hash === this.currentTX) //if (hash === this.currentTX)
return true; //return true;
return this.hasTX(hash); return this.hasTX(hash);
}; };

View File

@ -317,15 +317,6 @@ TXDB.prototype.drop = function drop() {
this.current = null; this.current = null;
}; };
/**
* Fetch.
* @param {String} key
*/
TXDB.prototype.fetch = function fetch(key, parse) {
return this.db.fetch(this.prefix(key), parse);
};
/** /**
* Get. * Get.
* @param {String} key * @param {String} key
@ -416,21 +407,19 @@ TXDB.prototype._addOrphan = co(function* _addOrphan(prevout, spender) {
TXDB.prototype._getOrphans = co(function* _getOrphans(hash, index) { TXDB.prototype._getOrphans = co(function* _getOrphans(hash, index) {
var items = []; var items = [];
var i, orphans, orphan, tx; var i, data, orphans, orphan, tx, p;
orphans = yield this.fetch(layout.o(hash, index), function(data) { data = yield this.get(layout.o(hash, index));
var p = new BufferReader(data);
var orphans = [];
while (p.left()) if (!data)
orphans.push(bcoin.outpoint.fromRaw(p));
return orphans;
});
if (!orphans)
return; return;
p = new BufferReader(data);
orphans = [];
while (p.left())
orphans.push(bcoin.outpoint.fromRaw(p));
for (i = 0; i < orphans.length; i++) { for (i = 0; i < orphans.length; i++) {
orphan = orphans[i]; orphan = orphans[i];
tx = yield this.getTX(orphan.hash); tx = yield this.getTX(orphan.hash);
@ -839,12 +828,15 @@ TXDB.prototype.isDoubleSpend = co(function* isDoubleSpend(tx) {
* @param {Function} callback - Returns [Error, Boolean]. * @param {Function} callback - Returns [Error, Boolean].
*/ */
TXDB.prototype.isSpent = function isSpent(hash, index) { TXDB.prototype.isSpent = co(function* isSpent(hash, index) {
var key = layout.s(hash, index); var key = layout.s(hash, index);
return this.fetch(key, function(data) { var data = yield this.get(key);
return bcoin.outpoint.fromRaw(data);
}); if (!data)
}; return;
return bcoin.outpoint.fromRaw(data);
});
/** /**
* Attempt to confirm a transaction. * Attempt to confirm a transaction.
@ -1692,11 +1684,14 @@ TXDB.prototype.fillCoins = co(function* fillCoins(tx) {
* @param {Function} callback - Returns [Error, {@link TX}]. * @param {Function} callback - Returns [Error, {@link TX}].
*/ */
TXDB.prototype.getTX = function getTX(hash) { TXDB.prototype.getTX = co(function* getTX(hash) {
return this.fetch(layout.t(hash), function(tx) { var tx = yield this.get(layout.t(hash));
return bcoin.tx.fromExtended(tx);
}); if (!tx)
}; return;
return bcoin.tx.fromExtended(tx);
});
/** /**
* Get transaction details. * Get transaction details.
@ -1766,30 +1761,31 @@ TXDB.prototype.hasTX = function hasTX(hash) {
* @param {Function} callback - Returns [Error, {@link Coin}]. * @param {Function} callback - Returns [Error, {@link Coin}].
*/ */
TXDB.prototype.getCoin = function getCoin(hash, index) { TXDB.prototype.getCoin = co(function* getCoin(hash, index) {
var self = this;
var key = hash + index; var key = hash + index;
var coin = this.coinCache.get(key); var data = this.coinCache.get(key);
var coin;
if (coin) { if (data) {
try { coin = bcoin.coin.fromRaw(data);
coin = bcoin.coin.fromRaw(coin);
} catch (e) {
return Promise.reject(e);
}
coin.hash = hash; coin.hash = hash;
coin.index = index; coin.index = index;
return Promise.resolve(coin); return coin;
} }
return this.fetch(layout.c(hash, index), function(data) { data = yield this.get(layout.c(hash, index));
var coin = bcoin.coin.fromRaw(data);
coin.hash = hash; if (!data)
coin.index = index; return;
self.coinCache.set(key, data);
return coin; coin = bcoin.coin.fromRaw(data);
}); coin.hash = hash;
}; coin.index = index;
this.coinCache.set(key, data);
return coin;
});
/** /**
* Get spender coin. * Get spender coin.
@ -1798,14 +1794,18 @@ TXDB.prototype.getCoin = function getCoin(hash, index) {
* @param {Function} callback - Returns [Error, {@link Coin}]. * @param {Function} callback - Returns [Error, {@link Coin}].
*/ */
TXDB.prototype.getSpentCoin = function getSpentCoin(spent, prevout) { TXDB.prototype.getSpentCoin = co(function* getSpentCoin(spent, prevout) {
return this.fetch(layout.d(spent.hash, spent.index), function(data) { var data = yield this.get(layout.d(spent.hash, spent.index));
var coin = bcoin.coin.fromRaw(data); var coin;
coin.hash = prevout.hash;
coin.index = prevout.index; if (!data)
return coin; return;
});
}; coin = bcoin.coin.fromRaw(data);
coin.hash = prevout.hash;
coin.index = prevout.index;
return coin;
});
/** /**
* Update spent coin height in storage. * Update spent coin height in storage.

View File

@ -381,11 +381,11 @@ WalletDB.prototype.testFilter = function testFilter(hashes) {
WalletDB.prototype.dump = co(function* dump() { WalletDB.prototype.dump = co(function* dump() {
var records = {}; var records = {};
yield this.db.iterate({ yield this.db.iterate({
gte: ' ', gte: new Buffer([0x00]),
lte: '~', lte: new Buffer([0xff]),
values: true, values: true,
parse: function(key, value) { parse: function(key, value) {
records[key] = value; records[key.toString('hex')] = value.toString('hex');
} }
}); });
return records; return records;
@ -418,27 +418,31 @@ WalletDB.prototype.unregister = function unregister(wallet) {
* @param {Function} callback * @param {Function} callback
*/ */
WalletDB.prototype.getWalletID = function getWalletID(id) { WalletDB.prototype.getWalletID = co(function* getWalletID(id) {
var self = this; var wid, data;
var wid;
if (!id) if (!id)
return Promise.resolve(null); return;
if (typeof id === 'number') if (typeof id === 'number')
return Promise.resolve(id); return id;
wid = this.walletCache.get(id); wid = this.walletCache.get(id);
if (wid) if (wid)
return Promise.resolve(wid);
return this.db.fetch(layout.l(id), function(data) {
wid = data.readUInt32LE(0, true);
self.walletCache.set(id, wid);
return wid; return wid;
});
}; data = yield this.db.get(layout.l(id));
if (!data)
return;
wid = data.readUInt32LE(0, true);
this.walletCache.set(id, wid);
return wid;
});
/** /**
* Get a wallet from the database, setup watcher. * Get a wallet from the database, setup watcher.
@ -468,16 +472,14 @@ WalletDB.prototype.get = co(function* get(wid) {
}); });
WalletDB.prototype._get = co(function* get(wid) { WalletDB.prototype._get = co(function* get(wid) {
var self = this; var data = yield this.db.get(layout.w(wid));
var wallet; var wallet;
wallet = yield this.db.fetch(layout.w(wid), function(data) { if (!data)
return bcoin.wallet.fromRaw(self, data);
});
if (!wallet)
return; return;
wallet = bcoin.wallet.fromRaw(this, data);
this.register(wallet); this.register(wallet);
yield wallet.open(); yield wallet.open();
@ -620,20 +622,25 @@ WalletDB.prototype.getAccount = co(function* getAccount(wid, name) {
* @param {Function} callback - Returns [Error, {@link Wallet}]. * @param {Function} callback - Returns [Error, {@link Wallet}].
*/ */
WalletDB.prototype._getAccount = function getAccount(wid, index) { WalletDB.prototype._getAccount = co(function* getAccount(wid, index) {
var self = this;
var key = wid + '/' + index; var key = wid + '/' + index;
var account = this.accountCache.get(key); var account = this.accountCache.get(key);
var data;
if (account) if (account)
return account; return account;
return this.db.fetch(layout.a(wid, index), function(data) { data = yield this.db.get(layout.a(wid, index));
account = bcoin.account.fromRaw(self, data);
self.accountCache.set(key, account); if (!data)
return account; return;
});
}; account = bcoin.account.fromRaw(this, data);
this.accountCache.set(key, account);
return account;
});
/** /**
* List account names and indexes from the db. * List account names and indexes from the db.
@ -782,11 +789,13 @@ WalletDB.prototype.saveAddress = co(function* saveAddress(wid, rings) {
yield this.writeAddress(wid, ring.getAddress(), path); yield this.writeAddress(wid, ring.getAddress(), path);
if (ring.witness) { if (!ring.witness)
path = path.clone(); continue;
path.hash = ring.getProgramHash('hex');
yield this.writeAddress(wid, ring.getProgramAddress(), path); path = path.clone();
} path.hash = ring.getProgramHash('hex');
yield this.writeAddress(wid, ring.getProgramAddress(), path);
} }
}); });
@ -830,7 +839,7 @@ WalletDB.prototype.writeAddress = co(function* writeAddress(wid, address, path)
*/ */
WalletDB.prototype.getAddressPaths = co(function* getAddressPaths(hash) { WalletDB.prototype.getAddressPaths = co(function* getAddressPaths(hash) {
var paths; var paths, data;
if (!hash) if (!hash)
return; return;
@ -840,13 +849,13 @@ WalletDB.prototype.getAddressPaths = co(function* getAddressPaths(hash) {
if (paths) if (paths)
return paths; return paths;
paths = yield this.db.fetch(layout.p(hash), function(value) { data = yield this.db.get(layout.p(hash));
return parsePaths(value, hash);
});
if (!paths) if (!data)
return; return;
paths = parsePaths(data, hash);
this.pathCache.set(hash, paths); this.pathCache.set(hash, paths);
return paths; return paths;
@ -1001,8 +1010,7 @@ WalletDB.prototype.getPendingKeys = function getPendingKeys() {
*/ */
WalletDB.prototype.resend = co(function* resend() { WalletDB.prototype.resend = co(function* resend() {
var self = this; var i, keys, key, data, tx;
var i, keys, key, tx;
keys = yield this.getPendingKeys(); keys = yield this.getPendingKeys();
@ -1011,11 +1019,13 @@ WalletDB.prototype.resend = co(function* resend() {
for (i = 0; i < keys.length; i++) { for (i = 0; i < keys.length; i++) {
key = keys[i]; key = keys[i];
tx = yield self.db.fetch(key, function(data) { data = yield this.db.get(key);
return bcoin.tx.fromExtended(data);
}); if (!data)
if (!tx)
continue; continue;
tx = bcoin.tx.fromExtended(data);
this.emit('send', tx); this.emit('send', tx);
} }
}); });
@ -1119,11 +1129,14 @@ WalletDB.prototype.writeGenesis = co(function* writeGenesis() {
* @param {Function} callback * @param {Function} callback
*/ */
WalletDB.prototype.getTip = function getTip() { WalletDB.prototype.getTip = co(function* getTip() {
return this.db.fetch(layout.R, function(data) { var data = yield this.db.get(layout.R);
return WalletBlock.fromTip(data);
}); if (!data)
}; return;
return WalletBlock.fromTip(data);
});
/** /**
* Write the best block hash. * Write the best block hash.
@ -1153,14 +1166,15 @@ WalletDB.prototype.writeBlock = function writeBlock(block, matches) {
batch.put(layout.R, block.toTip()); batch.put(layout.R, block.toTip());
if (block.hashes.length > 0) { if (block.hashes.length === 0)
batch.put(layout.b(block.hash), block.toRaw()); return batch.write();
for (i = 0; i < block.hashes.length; i++) { batch.put(layout.b(block.hash), block.toRaw());
hash = block.hashes[i];
wallets = matches[i]; for (i = 0; i < block.hashes.length; i++) {
batch.put(layout.e(hash), serializeWallets(wallets)); hash = block.hashes[i];
} wallets = matches[i];
batch.put(layout.e(hash), serializeWallets(wallets));
} }
return batch.write(); return batch.write();
@ -1188,11 +1202,14 @@ WalletDB.prototype.unwriteBlock = function unwriteBlock(block) {
* @param {Function} callback * @param {Function} callback
*/ */
WalletDB.prototype.getBlock = function getBlock(hash) { WalletDB.prototype.getBlock = co(function* getBlock(hash) {
return this.db.fetch(layout.b(hash), function(data) { var data = yield this.db.get(layout.b(hash));
return WalletBlock.fromRaw(hash, data);
}); if (!data)
}; return;
return WalletBlock.fromRaw(hash, data);
});
/** /**
* Get a TX->Wallet map. * Get a TX->Wallet map.
@ -1200,9 +1217,14 @@ WalletDB.prototype.getBlock = function getBlock(hash) {
* @param {Function} callback * @param {Function} callback
*/ */
WalletDB.prototype.getWalletsByTX = function getWalletsByTX(hash) { WalletDB.prototype.getWalletsByTX = co(function* getWalletsByTX(hash) {
return this.db.fetch(layout.e(hash), parseWallets); var data = yield this.db.get(layout.e(hash));
};
if (!data)
return;
return parseWallets(data);
});
/** /**
* Add a block's transactions and write the new best hash. * Add a block's transactions and write the new best hash.
@ -1237,7 +1259,7 @@ WalletDB.prototype._addBlock = co(function* addBlock(entry, txs) {
this.tip = block.hash; this.tip = block.hash;
this.height = block.height; this.height = block.height;
// NOTE: Atomicity doesn't matter here. If we crash // Atomicity doesn't matter here. If we crash
// during this loop, the automatic rescan will get // during this loop, the automatic rescan will get
// the database back into the correct state. // the database back into the correct state.
for (i = 0; i < txs.length; i++) { for (i = 0; i < txs.length; i++) {
@ -1278,11 +1300,9 @@ WalletDB.prototype.removeBlock = co(function* removeBlock(entry) {
}); });
WalletDB.prototype._removeBlock = co(function* removeBlock(entry) { WalletDB.prototype._removeBlock = co(function* removeBlock(entry) {
var i, j, block, data, hash, wallets, wid, wallet; var block = WalletBlock.fromEntry(entry);
var i, j, data, hash, wallets, wid, wallet;
block = WalletBlock.fromEntry(entry);
// Note:
// If we crash during a reorg, there's not much to do. // If we crash during a reorg, there's not much to do.
// Reorgs cannot be rescanned. The database will be // Reorgs cannot be rescanned. The database will be
// in an odd state, with some txs being confirmed // in an odd state, with some txs being confirmed
@ -1346,7 +1366,6 @@ WalletDB.prototype._addTX = co(function* addTX(tx, force) {
assert(!tx.mutable, 'Cannot add mutable TX to wallet.'); assert(!tx.mutable, 'Cannot add mutable TX to wallet.');
// Note:
// Atomicity doesn't matter here. If we crash, // Atomicity doesn't matter here. If we crash,
// the automatic rescan will get the database // the automatic rescan will get the database
// back in the correct state. // back in the correct state.