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)
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;

View File

@ -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.

View File

@ -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);
};

View File

@ -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.

View File

@ -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.