diff --git a/lib/wallet/account.js b/lib/wallet/account.js index 9d74ab5b..d6d91790 100644 --- a/lib/wallet/account.js +++ b/lib/wallet/account.js @@ -67,7 +67,7 @@ function Account(db, options) { this.receiveDepth = 0; this.changeDepth = 0; this.nestedDepth = 0; - this.lookahead = 10; + this.lookahead = 20; this.accountKey = null; this.keys = []; @@ -218,7 +218,7 @@ Account.fromOptions = function fromOptions(db, options) { * @const {Number} */ -Account.MAX_LOOKAHEAD = 20; +Account.MAX_LOOKAHEAD = 50; /** * Attempt to intialize the account (generating @@ -719,6 +719,52 @@ Account.prototype.syncDepth = co(function* syncDepth(receive, change, nested) { return result; }); +/** + * Allocate new lookahead addresses. + * @param {Number} lookahead + * @returns {Promise} + */ + +Account.prototype.setLookahead = co(function* setLookahead(lookahead) { + var i, key, depth, target; + + if (lookahead <= this.lookahead) { + this.db.logger.warning( + 'Lookahead is not increasing for: %s/%s.', + this.id, this.name); + return; + } + + depth = this.receiveDepth + this.lookahead + target = this.receiveDepth + lookahead; + + for (i = depth; i < target; i++) { + key = this.deriveReceive(i); + yield this.saveKey(key); + } + + depth = this.changeDepth + this.lookahead + target = this.changeDepth + lookahead; + + for (i = depth; i < target; i++) { + key = this.deriveChange(i); + yield this.saveKey(key); + } + + if (this.witness) { + depth = this.nestedDepth + this.lookahead + target = this.nestedDepth + lookahead; + + for (i = depth; i < target; i++) { + key = this.deriveNested(i); + yield this.saveKey(key); + } + } + + this.lookahead = lookahead; + this.save(); +}); + /** * Convert the account to a more inspection-friendly object. * @returns {Object} diff --git a/lib/wallet/wallet.js b/lib/wallet/wallet.js index b01c3388..6439dddc 100644 --- a/lib/wallet/wallet.js +++ b/lib/wallet/wallet.js @@ -1794,6 +1794,58 @@ Wallet.prototype.getOutputPaths = co(function* getOutputPaths(tx) { return paths; }); +/** + * Increase lookahead for account. + * @param {(Number|String)?} account + * @param {Number} lookahead + * @returns {Promise} + */ + +Wallet.prototype.setLookahead = co(function* setLookahead(acct, lookahead) { + var unlock = yield this.writeLock.lock(); + try { + return this._setLookahead(acct, lookahead); + } finally { + unlock(); + } +}); + +/** + * Increase lookahead for account (without a lock). + * @private + * @param {(Number|String)?} account + * @param {Number} lookahead + * @returns {Promise} + */ + +Wallet.prototype._setLookahead = co(function* setLookahead(acct, lookahead) { + var account; + + if (lookahead == null) { + lookahead = acct; + acct = null; + } + + if (acct == null) + acct = 0; + + account = yield this.getAccount(acct); + + if (!account) + throw new Error('Account not found.'); + + this.start(); + + try { + yield account.setLookahead(lookahead); + } catch (e) { + this.drop(); + throw e; + } + + yield this.commit(); +}); + /** * Sync address depths based on a transaction's outputs. * This is used for deriving new addresses when diff --git a/lib/wallet/walletdb.js b/lib/wallet/walletdb.js index 5bdc35b3..dc90434b 100644 --- a/lib/wallet/walletdb.js +++ b/lib/wallet/walletdb.js @@ -190,6 +190,7 @@ function WalletDB(options) { this.depth = 0; this.wallets = {}; this.keepBlocks = this.network.block.keepBlocks; + this.rescanning = false; // We need one read lock for `get` and `create`. // It will hold locks specific to wallet ids. @@ -387,6 +388,7 @@ WalletDB.prototype._rescan = co(function* rescan(height) { WalletDB.prototype.scan = co(function* scan(height) { var self = this; + var iter = this._addBlock.bind(this); var tip; if (!this.client) @@ -405,9 +407,13 @@ WalletDB.prototype.scan = co(function* scan(height) { tip = yield this.getTip(); - yield this.client.scan(tip.hash, this.filter, function(block, txs) { - return self._addBlock(block, txs); - }); + this.rescanning = true; + + try { + yield this.client.scan(tip.hash, this.filter, iter); + } finally { + this.rescanning = false; + } }); /** diff --git a/migrate/walletdb5to6.js b/migrate/walletdb5to6.js index cb36f202..5737cc05 100644 --- a/migrate/walletdb5to6.js +++ b/migrate/walletdb5to6.js @@ -228,6 +228,42 @@ function r(wid, index, hash) { return key; } +var updateLookahead = co(function* updateLookahead() { + var WalletDB = require('../lib/wallet/walletdb'); + var i, j, db, wallet; + + db = new WalletDB({ + network: process.argv[3], + db: 'leveldb', + location: file, + witness: false, + useCheckpoints: false, + maxFiles: 64, + resolution: false, + verify: false + }); + + yield db.open(); + + for (i = 1; i < db.depth; i++) { + wallet = yield db.get(i); + assert(wallet); + console.log('Updating wallet lookahead: %s', wallet.id); + for (j = 0; j < wallet.accountDepth; j++) + yield wallet.setLookahead(j, 20); + } + + yield db.close(); +}); + +var unstate = co(function* unstate() { + yield db.open(); + batch = db.batch(); + yield wipeTXDB(); + yield batch.write(); + yield db.close(); +}); + co.spawn(function* () { yield db.open(); batch = db.batch(); @@ -239,6 +275,8 @@ co.spawn(function* () { yield patchPathMaps(); yield batch.write(); yield db.close(); + yield updateLookahead(); + yield unstate(); }).then(function() { console.log('Migration complete.'); console.log('Rescan is required...');