diff --git a/lib/bcoin/keyring.js b/lib/bcoin/keyring.js index f70bd8de..46417964 100644 --- a/lib/bcoin/keyring.js +++ b/lib/bcoin/keyring.js @@ -72,6 +72,9 @@ KeyRing.prototype.addKey = function addKey(key) { if (utils.indexOf(this.keys, key) !== -1) return; + if (this.keys.length === this.n) + throw new Error('Cannot add more keys.'); + utils.binaryInsert(this.keys, key, utils.cmp); }; @@ -81,6 +84,9 @@ KeyRing.prototype.addKey = function addKey(key) { */ KeyRing.prototype.removeKey = function removeKey(key) { + if (this.keys.length === this.n) + throw new Error('Cannot remove key.'); + utils.binaryRemove(this.keys, key, utils.cmp); }; @@ -628,7 +634,7 @@ KeyRing.fromRaw = function fromRaw(data) { }; /** - * Test an object to see if it is an KeyRing. + * Test whether an object is a KeyRing. * @param {Object} obj * @returns {Boolean} */ diff --git a/lib/bcoin/txdb.js b/lib/bcoin/txdb.js index efdbba0f..47390902 100644 --- a/lib/bcoin/txdb.js +++ b/lib/bcoin/txdb.js @@ -560,7 +560,7 @@ TXDB.prototype._add = function add(tx, map, callback, force) { if (err) return callback(err); - self.walletdb.sync(tx, map, function(err) { + self.walletdb.syncOutputs(tx, map, function(err) { if (err) return callback(err); @@ -751,7 +751,7 @@ TXDB.prototype._confirm = function _confirm(tx, map, callback, force) { if (err) return callback(err); - self.walletdb.sync(tx, map, function(err) { + self.walletdb.syncOutputs(tx, map, function(err) { if (err) return callback(err); diff --git a/lib/bcoin/wallet.js b/lib/bcoin/wallet.js index bd6a7f1d..55766a54 100644 --- a/lib/bcoin/wallet.js +++ b/lib/bcoin/wallet.js @@ -918,13 +918,8 @@ Wallet.prototype.scan = function scan(getByAddress, callback) { if (err) return callback(err); - if (result === 0) { - return self.save(function(err) { - if (err) - return callback(err); - return callback(null, total); - }); - } + if (result === 0) + return callback(null, total); total += result; @@ -1568,7 +1563,7 @@ function Account(options) { this.options = options; this.network = bcoin.network.get(options.network); this.db = options.db; - this.lookahead = options.lookahead != null ? options.lookahead : 5; + this.lookahead = Account.LOOKAHEAD; this.id = options.id; this.name = options.name; @@ -1612,6 +1607,13 @@ function Account(options) { utils.inherits(Account, EventEmitter); +/* + * Default address lookahead. + * @const {Number} + */ + +Account.LOOKAHEAD = 5; + /** * Open the account, register with the database. * @param {Function} callback diff --git a/lib/bcoin/walletdb.js b/lib/bcoin/walletdb.js index 65397adf..7e8ba4c4 100644 --- a/lib/bcoin/walletdb.js +++ b/lib/bcoin/walletdb.js @@ -143,36 +143,18 @@ WalletDB.prototype._init = function _init() { }); this.tx.on('updated', function(tx, map) { - var balances = {}; - self.emit('updated', tx, map); map.all.forEach(function(path) { self.fire(path.id, 'updated', tx, path.name); }); - - utils.forEachSerial(map.output, function(path, next) { - if (self.listeners('balance').length === 0 - && !self.hasListener(path.id, 'balance')) { - return next(); - } - - if (balances[path.id] != null) - return next(); - - self.getBalance(path.id, function(err, balance) { - if (err) - return next(err); - - balances[path.id] = balance; - - self.fire(path.id, 'balance', balance); - - next(); - }); - }, function(err) { + self.updateBalances(tx, map, function(err, balances) { if (err) return self.emit('error', err); + Object.keys(balances).forEach(function(id) { + self.fire(id, 'balance', balances[id]); + }); + self.emit('balances', balances, map); }); }); @@ -191,7 +173,36 @@ WalletDB.prototype._init = function _init() { }); }; -WalletDB.prototype.sync = function sync(tx, map, callback) { +WalletDB.prototype.updateBalances = function updateBalances(tx, map, callback) { + var self = this; + var balances = {}; + + utils.forEachSerial(map.output, function(path, next) { + if (self.listeners('balance').length === 0 + && !self.hasListener(path.id, 'balance')) { + return next(); + } + + if (balances[path.id] != null) + return next(); + + self.getBalance(path.id, function(err, balance) { + if (err) + return next(err); + + balances[path.id] = balance; + + next(); + }); + }, function(err) { + if (err) + return callback(err); + + return callback(null, balances); + }); +}; + +WalletDB.prototype.syncOutputs = function syncOutputs(tx, map, callback) { var self = this; utils.forEachSerial(map.output, function(path, next) { self.syncOutputDepth(path.id, tx, next); @@ -832,12 +843,12 @@ WalletDB.prototype.removeBlockSPV = function removeBlockSPV(block, callback) { callback = utils.ensure(callback); - this.tx.getHeightHashes(block.height, function(err, txs) { + this.tx.getHeightHashes(block.height, function(err, hashes) { if (err) return callback(err); - utils.forEachSerial(txs, function(tx, next) { - self.tx.unconfirm(tx, next); + utils.forEachSerial(hashes, function(hash, next) { + self.tx.unconfirm(hash, next); }, callback); }); }; @@ -895,21 +906,9 @@ WalletDB.prototype.syncOutputDepth = function syncOutputDepth(id, tx, callback) }); }; -WalletDB.prototype.createAddress = function createAddress(id, change, callback) { +WalletDB.prototype.createAddress = function createAddress(id, name, change, callback) { this.fetchWallet(id, callback, function(wallet, callback) { - wallet.createAddress(change, callback); - }); -}; - -WalletDB.prototype.getReceiveAddress = function getReceiveAddress(id, callback) { - this.fetchWallet(id, callback, function(wallet, callback) { - callback(null, wallet.receiveAddress); - }); -}; - -WalletDB.prototype.getChangeAddress = function getChangeAddress(id, callback) { - this.fetchWallet(id, callback, function(wallet, callback) { - callback(null, wallet.changeAddress); + wallet.createAddress(name, change, callback); }); }; @@ -947,15 +946,15 @@ WalletDB.prototype.createTX = function createTX(id, options, outputs, callback) }); }; -WalletDB.prototype.addKey = function addKey(id, key, callback) { +WalletDB.prototype.addKey = function addKey(id, name, key, callback) { this.fetchWallet(id, callback, function(wallet, callback) { - wallet.addKey(key, callback); + wallet.addKey(name, key, callback); }); }; -WalletDB.prototype.removeKey = function removeKey(id, key, callback) { +WalletDB.prototype.removeKey = function removeKey(id, name, key, callback) { this.fetchWallet(id, callback, function(wallet, callback) { - wallet.removeKey(key, callback); + wallet.removeKey(name, key, callback); }); }; @@ -1013,7 +1012,8 @@ function serializePaths(out) { } function isAlpha(key) { - return /^[a-zA-Z0-9]+$/.test(key); + // We allow /-~ (exclusive), 0-} (inclusive) + return /^[\u0030-\u007d]+$/.test(key); } /* diff --git a/package.json b/package.json index a4e0e955..60172024 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ }, "homepage": "https://github.com/indutny/bcoin", "engines": { - "node": ">= 0.8.0" + "node": ">= 0.10.0" }, "dependencies": { "bn.js": "4.11.0",