From bad028ab671bb63c835cc57a43dc6be19f61f7a5 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Wed, 6 Dec 2017 10:25:23 -0800 Subject: [PATCH] chaindb: refactor. --- lib/blockchain/chain.js | 27 +++---------- lib/blockchain/chaindb.js | 82 +++++++++++++++++++-------------------- lib/wallet/txdb.js | 7 ---- lib/wallet/walletdb.js | 14 ++----- migrate/chaindb3to4.js | 3 +- migrate/walletdb5to6.js | 2 + 6 files changed, 53 insertions(+), 82 deletions(-) diff --git a/lib/blockchain/chain.js b/lib/blockchain/chain.js index d302c72d..8e41f03c 100644 --- a/lib/blockchain/chain.js +++ b/lib/blockchain/chain.js @@ -31,19 +31,6 @@ const thresholdStates = common.thresholdStates; * @property {ChainEntry?} tip * @property {Number} height * @property {DeploymentState} state - * @emits Chain#open - * @emits Chain#error - * @emits Chain#block - * @emits Chain#competitor - * @emits Chain#resolved - * @emits Chain#checkpoint - * @emits Chain#fork - * @emits Chain#reorganize - * @emits Chain#invalid - * @emits Chain#exists - * @emits Chain#connect - * @emits Chain#reconnect - * @emits Chain#disconnect */ class Chain extends AsyncEmitter { @@ -945,7 +932,7 @@ class Chain extends AsyncEmitter { 'Chain replay from height %d necessary.', fork.height); - await this.emitAsync('reorganize', tip, competitor); + return this.emitAsync('reorganize', tip, competitor); } /** @@ -973,7 +960,7 @@ class Chain extends AsyncEmitter { this.emit('tip', prev); - await this.emitAsync('disconnect', entry, block, view); + return this.emitAsync('disconnect', entry, block, view); } /** @@ -1023,7 +1010,7 @@ class Chain extends AsyncEmitter { this.emit('tip', entry); this.emit('reconnect', entry, block); - await this.emitAsync('connect', entry, block, view); + return this.emitAsync('connect', entry, block, view); } /** @@ -1047,10 +1034,8 @@ class Chain extends AsyncEmitter { // In spv-mode, we reset the // chain and redownload the blocks. - if (this.options.spv) { - await this.reorganizeSPV(entry); - return; - } + if (this.options.spv) + return this.reorganizeSPV(entry); await this.reorganize(entry); } @@ -1091,7 +1076,7 @@ class Chain extends AsyncEmitter { this.emit('tip', entry); this.emit('block', block, entry); - await this.emitAsync('connect', entry, block, view); + return this.emitAsync('connect', entry, block, view); } /** diff --git a/lib/blockchain/chaindb.js b/lib/blockchain/chaindb.js index 9dd92294..973bc5b6 100644 --- a/lib/blockchain/chaindb.js +++ b/lib/blockchain/chaindb.js @@ -514,7 +514,7 @@ class ChainDB { this.logger.info('Writing genesis block to ChainDB.'); - await this.save(entry, block, new CoinView()); + return this.save(entry, block, new CoinView()); } /** @@ -635,9 +635,9 @@ class ChainDB { */ saveDeployments() { - const batch = this.db.batch(); - this.writeDeployments(batch); - return batch.write(); + const b = this.db.batch(); + this.writeDeployments(b); + return b.write(); } /** @@ -645,7 +645,7 @@ class ChainDB { * @returns {Promise} */ - writeDeployments(batch) { + writeDeployments(b) { const bw = bio.write(1 + 17 * this.network.deploys.length); bw.writeU8(this.network.deploys.length); @@ -658,7 +658,7 @@ class ChainDB { bw.writeI32(deployment.window); } - batch.put(layout.D.build(), bw.render()); + b.put(layout.D.build(), bw.render()); } /** @@ -719,17 +719,17 @@ class ChainDB { if (invalid.length === 0) return true; - const batch = this.db.batch(); + const b = this.db.batch(); for (const bit of invalid) { this.logger.warning('Versionbit deployment params modified.'); this.logger.warning('Invalidating cache for bit %d.', bit); - await this.invalidateCache(bit, batch); + await this.invalidateCache(bit, b); } - this.writeDeployments(batch); + this.writeDeployments(b); - await batch.write(); + await b.write(); return false; } @@ -740,14 +740,14 @@ class ChainDB { * @returns {Promise} */ - async invalidateCache(bit, batch) { + async invalidateCache(bit, b) { const keys = await this.db.keys({ gte: layout.v.min(bit), lte: layout.v.max(bit) }); for (const key of keys) - batch.del(key); + b.del(key); } /** @@ -772,7 +772,7 @@ class ChainDB { const start = pruneAfter + 1; const end = height - keepBlocks; - const batch = this.db.batch(); + const b = this.db.batch(); for (let i = start; i <= end; i++) { const hash = await this.getHash(i); @@ -780,8 +780,8 @@ class ChainDB { if (!hash) throw new Error(`Cannot find hash for ${i}.`); - batch.del(layout.b.build(hash)); - batch.del(layout.u.build(hash)); + b.del(layout.b.build(hash)); + b.del(layout.u.build(hash)); } try { @@ -790,9 +790,9 @@ class ChainDB { const flags = ChainFlags.fromOptions(options); assert(flags.prune); - batch.put(layout.O.build(), flags.toRaw()); + b.put(layout.O.build(), flags.toRaw()); - await batch.write(); + await b.write(); } catch (e) { options.prune = false; throw e; @@ -1309,6 +1309,7 @@ class ChainDB { for (let i = 0; i < block.txs.length; i++) { const tx = block.txs[i]; + let found = false; for (let j = 0; j < tx.outputs.length; j++) { @@ -1372,7 +1373,7 @@ class ChainDB { } /** - * Save an entry without a batch. + * Save an entry. * @private * @param {ChainEntry} entry * @param {Block} block @@ -1438,7 +1439,7 @@ class ChainDB { } /** - * Reconnect block without a batch. + * Reconnect block. * @private * @param {ChainEntry} entry * @param {Block} block @@ -1495,7 +1496,7 @@ class ChainDB { } /** - * Disconnect block without a batch. + * Disconnect block. * @private * @param {ChainEntry} entry * @param {Block} block @@ -1756,7 +1757,7 @@ class ChainDB { async connectBlock(entry, block, view) { if (this.options.spv) - return; + return undefined; const hash = block.hash(); @@ -1764,7 +1765,7 @@ class ChainDB { // Genesis block's coinbase is unspendable. if (entry.isGenesis()) - return; + return undefined; // Update chain state value. for (let i = 0; i < block.txs.length; i++) { @@ -1794,7 +1795,7 @@ class ChainDB { this.put(layout.u.build(hash), view.undo.commit()); // Prune height-288 if pruning is enabled. - await this.pruneBlock(entry); + return this.pruneBlock(entry); } /** @@ -1891,9 +1892,9 @@ class ChainDB { saveFlags() { const flags = ChainFlags.fromOptions(this.options); - const batch = this.db.batch(); - batch.put(layout.O.build(), flags.toRaw()); - return batch.write(); + const b = this.db.batch(); + b.put(layout.O.build(), flags.toRaw()); + return b.write(); } /** @@ -1914,8 +1915,7 @@ class ChainDB { this.put(layout.t.build(hash), meta.toRaw()); if (this.options.indexAddress) { - const hashes = tx.getHashes(view); - for (const addr of hashes) + for (const addr of tx.getHashes(view)) this.put(layout.T.build(addr, hash), null); } } @@ -1925,12 +1925,16 @@ class ChainDB { if (!tx.isCoinbase()) { for (const {prevout} of tx.inputs) { - const addr = view.getOutput(prevout).getHash(); + const {hash, index} = prevout; + const coin = view.getOutput(prevout); + assert(coin); + + const addr = coin.getHash(); if (!addr) continue; - this.del(layout.C.build(addr, prevout.hash, prevout.index)); + this.del(layout.C.build(addr, hash, index)); } } @@ -1958,8 +1962,7 @@ class ChainDB { if (this.options.indexTX) { this.del(layout.t.build(hash)); if (this.options.indexAddress) { - const hashes = tx.getHashes(view); - for (const addr of hashes) + for (const addr of tx.getHashes(view)) this.del(layout.T.build(addr, hash)); } } @@ -1969,12 +1972,16 @@ class ChainDB { if (!tx.isCoinbase()) { for (const {prevout} of tx.inputs) { - const addr = view.getOutput(prevout).getHash(); + const {hash, index} = prevout; + const coin = view.getOutput(prevout); + assert(coin); + + const addr = coin.getHash(); if (!addr) continue; - this.put(layout.C.build(addr, prevout.hash, prevout.index), null); + this.put(layout.C.build(addr, hash, index), null); } } @@ -1990,13 +1997,6 @@ class ChainDB { } } -/** - * Database layout. - * @type {Object} - */ - -ChainDB.layout = layout; - /** * ChainFlags */ diff --git a/lib/wallet/txdb.js b/lib/wallet/txdb.js index 50932de8..b809bf73 100644 --- a/lib/wallet/txdb.js +++ b/lib/wallet/txdb.js @@ -2048,13 +2048,6 @@ class TXDB { } } -/** - * Database layout. - * @type {Object} - */ - -TXDB.layout = layout; - /** * Balance * @alias module:wallet.Balance diff --git a/lib/wallet/walletdb.js b/lib/wallet/walletdb.js index afd36073..32f30995 100644 --- a/lib/wallet/walletdb.js +++ b/lib/wallet/walletdb.js @@ -219,9 +219,8 @@ class WalletDB extends EventEmitter { } const magic = raw.readUInt32LE(0, true); - const network = Network.fromMagic(magic); - if (network !== this.network) + if (magic !== this.network.magic) throw new Error('Network mismatch for WalletDB.'); return undefined; @@ -585,7 +584,7 @@ class WalletDB extends EventEmitter { this.logger.warning('Wiped %d txdb records.', total); - await b.write(); + return b.write(); } /** @@ -2113,17 +2112,10 @@ class WalletDB extends EventEmitter { if (entry.height > this.state.height) throw new Error('WDB: Bad reset height.'); - await this.rollback(entry.height); + return this.rollback(entry.height); } } -/** - * Database layout. - * @type {Object} - */ - -WalletDB.layout = layout; - /** * Wallet Options * @alias module:wallet.WalletOptions diff --git a/migrate/chaindb3to4.js b/migrate/chaindb3to4.js index 5f2487a5..5abcf609 100644 --- a/migrate/chaindb3to4.js +++ b/migrate/chaindb3to4.js @@ -3,7 +3,6 @@ const assert = require('assert'); const bdb = require('bdb'); const layout = require('../lib/blockchain/layout'); -const DUMMY = Buffer.alloc(1, 0x00); // changes: // db version record @@ -59,7 +58,7 @@ async function migrateKeys(id, from, to) { let items = 0; await iter.each(async (key) => { - batch.put(to.build(...from(key)), DUMMY); + batch.put(to.build(...from(key)), null); batch.del(key); total += (key.length + 80) * 2; diff --git a/migrate/walletdb5to6.js b/migrate/walletdb5to6.js index eec19c3c..fec21ea6 100644 --- a/migrate/walletdb5to6.js +++ b/migrate/walletdb5to6.js @@ -235,6 +235,8 @@ async function updateLookahead() { await db.close(); } +updateLookahead; + async function unstate() { await db.open(); batch = db.batch();