From a7d36269754b45dc24e89cec8c5f66ea5abafc8e Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Thu, 22 Sep 2016 06:11:38 -0700 Subject: [PATCH] db: drop db.fetch. --- lib/chain/chaindb.js | 144 ++++++++++++++++++++---------------- lib/db/lowlevelup.js | 16 ---- lib/mempool/mempool.js | 4 +- lib/wallet/txdb.js | 112 ++++++++++++++-------------- lib/wallet/walletdb.js | 161 +++++++++++++++++++++++------------------ 5 files changed, 230 insertions(+), 207 deletions(-) diff --git a/lib/chain/chaindb.js b/lib/chain/chaindb.js index bd6bccab..bf53ca0f 100644 --- a/lib/chain/chaindb.js +++ b/lib/chain/chaindb.js @@ -406,15 +406,12 @@ ChainDB.prototype.getHeight = co(function* getHeight(hash) { if (entry) return entry.height; - height = yield this.db.fetch(layout.h(hash), function(data) { - assert(data.length === 4, 'Database corruption.'); - return data.readUInt32LE(0, true); - }); + height = yield this.db.get(layout.h(hash)); - if (height == null) + if (!height) 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) { - var entry; + var entry, hash; checkHash(height); @@ -437,10 +434,12 @@ ChainDB.prototype.getHash = co(function* getHash(height) { if (entry) return entry.hash; - return yield this.db.fetch(layout.H(height), function(data) { - assert(data.length === 32, 'Database corruption.'); - return data.toString('hex'); - }); + hash = yield this.db.get(layout.H(height)); + + 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) { - var self = this; var entry; checkHash(hash); @@ -511,9 +509,12 @@ ChainDB.prototype.getEntry = co(function* getEntry(hash) { if (entry) return entry; - return yield this.db.fetch(layout.e(hash), function(data) { - return bcoin.chainentry.fromRaw(self.chain, data); - }); + entry = yield this.db.get(layout.e(hash)); + + 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() { - var state = yield this.db.fetch(layout.R, function(data) { - return ChainState.fromRaw(data); - }); + var data = yield this.db.get(layout.R); + var state; - assert(state); + assert(data); + + state = ChainState.fromRaw(data); this.state = state; @@ -702,12 +704,14 @@ ChainDB.prototype.disconnect = co(function* disconnect(entry) { * @param {Function} callback - Returns [Error, {@link Hash}]. */ -ChainDB.prototype.getNextHash = function getNextHash(hash) { - return this.db.fetch(layout.n(hash), function(data) { - assert(data.length === 32, 'Database corruption.'); - return data.toString('hex'); - }); -}; +ChainDB.prototype.getNextHash = co(function* getNextHash(hash) { + var data = yield this.db.get(layout.n(hash)); + + if (!data) + return; + + return data.toString('hex'); +}); /** * 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) { - var self = this; var coins = this.coinCache.get(hash); if (coins) return bcoin.coins.parseCoin(coins, hash, index); - return yield this.db.fetch(layout.c(hash), function(data) { - self.coinCache.set(hash, data); - return bcoin.coins.parseCoin(data, hash, index); - }); + coins = yield this.db.get(layout.c(hash)); + + 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) { - var self = this; var coins = this.coinCache.get(hash); if (coins) return bcoin.coins.fromRaw(coins, hash); - return yield this.db.fetch(layout.c(hash), function(data) { - self.coinCache.set(hash, data); - return bcoin.coins.fromRaw(data, hash); - }); + coins = yield this.db.get(layout.c(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}]. */ -ChainDB.prototype.getTX = function getTX(hash) { - if (!this.options.indexTX) - return Promise.resolve(null); +ChainDB.prototype.getTX = co(function* getTX(hash) { + var data; - return this.db.fetch(layout.t(hash), function(data) { - return bcoin.tx.fromExtended(data); - }); -}; + if (!this.options.indexTX) + return; + + data = yield this.db.get(layout.t(hash)); + + if (!data) + return; + + return bcoin.tx.fromExtended(data); +}); /** * @param {Hash} hash @@ -1406,17 +1421,21 @@ ChainDB.prototype.getCoinView = co(function* getCoinView(block, callback) { * @param {Function} callback - Returns [Error, {@link Coin}[]]. */ -ChainDB.prototype.getUndoCoins = function getUndoCoins(hash) { - return this.db.fetch(layout.u(hash), function(data) { - var p = new BufferReader(data); - var coins = []; +ChainDB.prototype.getUndoCoins = co(function* getUndoCoins(hash) { + var data = yield this.db.get(layout.u(hash)); + var p, coins; - while (p.left()) - coins.push(bcoin.coin.fromRaw(p)); + if (!data) + 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 @@ -1462,7 +1481,7 @@ ChainDB.prototype.getUndoView = co(function* getUndoView(block) { ChainDB.prototype.getBlock = co(function* getBlock(hash) { var items = yield this.getBoth(hash); - var height; + var height, data, block; if (!items) return; @@ -1470,11 +1489,15 @@ ChainDB.prototype.getBlock = co(function* getBlock(hash) { hash = items[0]; height = items[1]; - return yield this.db.fetch(layout.b(hash), function(data) { - var block = bcoin.block.fromRaw(data); - block.setHeight(height); - return block; - }); + data = yield this.db.get(layout.b(hash)); + + if (!data) + 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) { - var futureHeight, key, hash; + var futureHeight, key, hash, data; if (this.options.spv) return; @@ -1514,10 +1537,7 @@ ChainDB.prototype.pruneBlock = co(function* pruneBlock(block) { key = layout.q(block.height); - hash = yield this.db.fetch(key, function(data) { - assert(data.length === 32, 'Database corruption.'); - return data.toString('hex'); - }); + hash = yield this.db.get(key); if (!hash) return; diff --git a/lib/db/lowlevelup.js b/lib/db/lowlevelup.js index 569a4683..d48fb5ab 100644 --- a/lib/db/lowlevelup.js +++ b/lib/db/lowlevelup.js @@ -296,22 +296,6 @@ LowlevelUp.prototype.has = co(function* has(key) { 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. * @param {Object} options - Iterator options. diff --git a/lib/mempool/mempool.js b/lib/mempool/mempool.js index 47a953be..abf4b62a 100644 --- a/lib/mempool/mempool.js +++ b/lib/mempool/mempool.js @@ -502,8 +502,8 @@ Mempool.prototype.has = function has(hash) { if (this.hasOrphan(hash)) return true; - if (hash === this.currentTX) - return true; + //if (hash === this.currentTX) + //return true; return this.hasTX(hash); }; diff --git a/lib/wallet/txdb.js b/lib/wallet/txdb.js index 639b0b86..6009326d 100644 --- a/lib/wallet/txdb.js +++ b/lib/wallet/txdb.js @@ -317,15 +317,6 @@ TXDB.prototype.drop = function drop() { this.current = null; }; -/** - * Fetch. - * @param {String} key - */ - -TXDB.prototype.fetch = function fetch(key, parse) { - return this.db.fetch(this.prefix(key), parse); -}; - /** * Get. * @param {String} key @@ -416,21 +407,19 @@ TXDB.prototype._addOrphan = co(function* _addOrphan(prevout, spender) { TXDB.prototype._getOrphans = co(function* _getOrphans(hash, index) { var items = []; - var i, orphans, orphan, tx; + var i, data, orphans, orphan, tx, p; - orphans = yield this.fetch(layout.o(hash, index), function(data) { - var p = new BufferReader(data); - var orphans = []; + data = yield this.get(layout.o(hash, index)); - while (p.left()) - orphans.push(bcoin.outpoint.fromRaw(p)); - - return orphans; - }); - - if (!orphans) + if (!data) return; + p = new BufferReader(data); + orphans = []; + + while (p.left()) + orphans.push(bcoin.outpoint.fromRaw(p)); + for (i = 0; i < orphans.length; i++) { orphan = orphans[i]; tx = yield this.getTX(orphan.hash); @@ -839,12 +828,15 @@ TXDB.prototype.isDoubleSpend = co(function* isDoubleSpend(tx) { * @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); - return this.fetch(key, function(data) { - return bcoin.outpoint.fromRaw(data); - }); -}; + var data = yield this.get(key); + + if (!data) + return; + + return bcoin.outpoint.fromRaw(data); +}); /** * Attempt to confirm a transaction. @@ -1692,11 +1684,14 @@ TXDB.prototype.fillCoins = co(function* fillCoins(tx) { * @param {Function} callback - Returns [Error, {@link TX}]. */ -TXDB.prototype.getTX = function getTX(hash) { - return this.fetch(layout.t(hash), function(tx) { - return bcoin.tx.fromExtended(tx); - }); -}; +TXDB.prototype.getTX = co(function* getTX(hash) { + var tx = yield this.get(layout.t(hash)); + + if (!tx) + return; + + return bcoin.tx.fromExtended(tx); +}); /** * Get transaction details. @@ -1766,30 +1761,31 @@ TXDB.prototype.hasTX = function hasTX(hash) { * @param {Function} callback - Returns [Error, {@link Coin}]. */ -TXDB.prototype.getCoin = function getCoin(hash, index) { - var self = this; +TXDB.prototype.getCoin = co(function* getCoin(hash, index) { var key = hash + index; - var coin = this.coinCache.get(key); + var data = this.coinCache.get(key); + var coin; - if (coin) { - try { - coin = bcoin.coin.fromRaw(coin); - } catch (e) { - return Promise.reject(e); - } + if (data) { + coin = bcoin.coin.fromRaw(data); coin.hash = hash; coin.index = index; - return Promise.resolve(coin); + return coin; } - return this.fetch(layout.c(hash, index), function(data) { - var coin = bcoin.coin.fromRaw(data); - coin.hash = hash; - coin.index = index; - self.coinCache.set(key, data); - return coin; - }); -}; + data = yield this.get(layout.c(hash, index)); + + if (!data) + return; + + coin = bcoin.coin.fromRaw(data); + coin.hash = hash; + coin.index = index; + + this.coinCache.set(key, data); + + return coin; +}); /** * Get spender coin. @@ -1798,14 +1794,18 @@ TXDB.prototype.getCoin = function getCoin(hash, index) { * @param {Function} callback - Returns [Error, {@link Coin}]. */ -TXDB.prototype.getSpentCoin = function getSpentCoin(spent, prevout) { - return this.fetch(layout.d(spent.hash, spent.index), function(data) { - var coin = bcoin.coin.fromRaw(data); - coin.hash = prevout.hash; - coin.index = prevout.index; - return coin; - }); -}; +TXDB.prototype.getSpentCoin = co(function* getSpentCoin(spent, prevout) { + var data = yield this.get(layout.d(spent.hash, spent.index)); + var coin; + + if (!data) + return; + + coin = bcoin.coin.fromRaw(data); + coin.hash = prevout.hash; + coin.index = prevout.index; + return coin; +}); /** * Update spent coin height in storage. diff --git a/lib/wallet/walletdb.js b/lib/wallet/walletdb.js index d8e15c04..e4c1f914 100644 --- a/lib/wallet/walletdb.js +++ b/lib/wallet/walletdb.js @@ -381,11 +381,11 @@ WalletDB.prototype.testFilter = function testFilter(hashes) { WalletDB.prototype.dump = co(function* dump() { var records = {}; yield this.db.iterate({ - gte: ' ', - lte: '~', + gte: new Buffer([0x00]), + lte: new Buffer([0xff]), values: true, parse: function(key, value) { - records[key] = value; + records[key.toString('hex')] = value.toString('hex'); } }); return records; @@ -418,27 +418,31 @@ WalletDB.prototype.unregister = function unregister(wallet) { * @param {Function} callback */ -WalletDB.prototype.getWalletID = function getWalletID(id) { - var self = this; - var wid; +WalletDB.prototype.getWalletID = co(function* getWalletID(id) { + var wid, data; if (!id) - return Promise.resolve(null); + return; if (typeof id === 'number') - return Promise.resolve(id); + return id; wid = this.walletCache.get(id); 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; - }); -}; + + 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. @@ -468,16 +472,14 @@ 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; - wallet = yield this.db.fetch(layout.w(wid), function(data) { - return bcoin.wallet.fromRaw(self, data); - }); - - if (!wallet) + if (!data) return; + wallet = bcoin.wallet.fromRaw(this, data); + this.register(wallet); yield wallet.open(); @@ -620,20 +622,25 @@ WalletDB.prototype.getAccount = co(function* getAccount(wid, name) { * @param {Function} callback - Returns [Error, {@link Wallet}]. */ -WalletDB.prototype._getAccount = function getAccount(wid, index) { - var self = this; +WalletDB.prototype._getAccount = co(function* getAccount(wid, index) { var key = wid + '/' + index; var account = this.accountCache.get(key); + var data; if (account) return account; - return this.db.fetch(layout.a(wid, index), function(data) { - account = bcoin.account.fromRaw(self, data); - self.accountCache.set(key, account); - return account; - }); -}; + data = yield this.db.get(layout.a(wid, index)); + + if (!data) + return; + + account = bcoin.account.fromRaw(this, data); + + this.accountCache.set(key, account); + + return account; +}); /** * 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); - if (ring.witness) { - path = path.clone(); - path.hash = ring.getProgramHash('hex'); - yield this.writeAddress(wid, ring.getProgramAddress(), path); - } + if (!ring.witness) + continue; + + 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) { - var paths; + var paths, data; if (!hash) return; @@ -840,13 +849,13 @@ WalletDB.prototype.getAddressPaths = co(function* getAddressPaths(hash) { if (paths) return paths; - paths = yield this.db.fetch(layout.p(hash), function(value) { - return parsePaths(value, hash); - }); + data = yield this.db.get(layout.p(hash)); - if (!paths) + if (!data) return; + paths = parsePaths(data, hash); + this.pathCache.set(hash, paths); return paths; @@ -1001,8 +1010,7 @@ WalletDB.prototype.getPendingKeys = function getPendingKeys() { */ WalletDB.prototype.resend = co(function* resend() { - var self = this; - var i, keys, key, tx; + var i, keys, key, data, tx; keys = yield this.getPendingKeys(); @@ -1011,11 +1019,13 @@ WalletDB.prototype.resend = co(function* resend() { for (i = 0; i < keys.length; i++) { key = keys[i]; - tx = yield self.db.fetch(key, function(data) { - return bcoin.tx.fromExtended(data); - }); - if (!tx) + data = yield this.db.get(key); + + if (!data) continue; + + tx = bcoin.tx.fromExtended(data); + this.emit('send', tx); } }); @@ -1119,11 +1129,14 @@ WalletDB.prototype.writeGenesis = co(function* writeGenesis() { * @param {Function} callback */ -WalletDB.prototype.getTip = function getTip() { - return this.db.fetch(layout.R, function(data) { - return WalletBlock.fromTip(data); - }); -}; +WalletDB.prototype.getTip = co(function* getTip() { + var data = yield this.db.get(layout.R); + + if (!data) + return; + + return WalletBlock.fromTip(data); +}); /** * Write the best block hash. @@ -1153,14 +1166,15 @@ WalletDB.prototype.writeBlock = function writeBlock(block, matches) { batch.put(layout.R, block.toTip()); - if (block.hashes.length > 0) { - batch.put(layout.b(block.hash), block.toRaw()); + if (block.hashes.length === 0) + return batch.write(); - for (i = 0; i < block.hashes.length; i++) { - hash = block.hashes[i]; - wallets = matches[i]; - batch.put(layout.e(hash), serializeWallets(wallets)); - } + batch.put(layout.b(block.hash), block.toRaw()); + + for (i = 0; i < block.hashes.length; i++) { + hash = block.hashes[i]; + wallets = matches[i]; + batch.put(layout.e(hash), serializeWallets(wallets)); } return batch.write(); @@ -1188,11 +1202,14 @@ WalletDB.prototype.unwriteBlock = function unwriteBlock(block) { * @param {Function} callback */ -WalletDB.prototype.getBlock = function getBlock(hash) { - return this.db.fetch(layout.b(hash), function(data) { - return WalletBlock.fromRaw(hash, data); - }); -}; +WalletDB.prototype.getBlock = co(function* getBlock(hash) { + var data = yield this.db.get(layout.b(hash)); + + if (!data) + return; + + return WalletBlock.fromRaw(hash, data); +}); /** * Get a TX->Wallet map. @@ -1200,9 +1217,14 @@ WalletDB.prototype.getBlock = function getBlock(hash) { * @param {Function} callback */ -WalletDB.prototype.getWalletsByTX = function getWalletsByTX(hash) { - return this.db.fetch(layout.e(hash), parseWallets); -}; +WalletDB.prototype.getWalletsByTX = co(function* getWalletsByTX(hash) { + 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. @@ -1237,7 +1259,7 @@ WalletDB.prototype._addBlock = co(function* addBlock(entry, txs) { this.tip = block.hash; 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 // the database back into the correct state. 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) { - 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. // Reorgs cannot be rescanned. The database will be // 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.'); - // Note: // Atomicity doesn't matter here. If we crash, // the automatic rescan will get the database // back in the correct state.