diff --git a/lib/bcoin/chain.js b/lib/bcoin/chain.js index 6f27c3f5..c156ad25 100644 --- a/lib/bcoin/chain.js +++ b/lib/bcoin/chain.js @@ -1126,10 +1126,10 @@ Chain.prototype.reset = function reset(height, callback, force) { * @param {Function} callback */ -Chain.prototype.resetTime = function resetTime(ts, callback, force) { +Chain.prototype.resetTime = function resetTime(ts, callback) { var self = this; - callback = this._lock(resetTime, [ts, callback], force); + callback = this._lock(resetTime, [ts, callback]); if (!callback) return; @@ -1172,13 +1172,13 @@ Chain.prototype.isBusy = function isBusy() { * @param {Function} callback - Returns [{@link VerifyError}]. */ -Chain.prototype.add = function add(block, callback, force) { +Chain.prototype.add = function add(block, callback) { var self = this; var ret = {}; assert(this.loaded); - callback = this._lock(add, [block, callback], force); + callback = this._lock(add, [block, callback]); if (!callback) return; @@ -1708,13 +1708,13 @@ Chain.prototype.getProgress = function getProgress() { * @param {Function} callback - Returns [Error, {@link Hash}[]]. */ -Chain.prototype.getLocator = function getLocator(start, callback, force) { +Chain.prototype.getLocator = function getLocator(start, callback) { var self = this; var hashes = []; var step = 1; var height; - callback = this._lock(getLocator, [start, callback], force); + callback = this._lock(getLocator, [start, callback]); if (!callback) return; diff --git a/lib/bcoin/locker.js b/lib/bcoin/locker.js index 3605d18d..bde2eff1 100644 --- a/lib/bcoin/locker.js +++ b/lib/bcoin/locker.js @@ -138,8 +138,10 @@ Locker.prototype.lock = function lock(func, args, force) { */ Locker.prototype.destroy = function destroy() { - this.pending.length = 0; - this.pendingMap = {}; + if (this.add) { + this.pending.length = 0; + this.pendingMap = {}; + } this.jobs.length = 0; }; @@ -149,6 +151,8 @@ Locker.prototype.destroy = function destroy() { */ Locker.prototype.onDrain = function onDrain(callback) { + assert(this.add, 'Cannot wait for drain without add method.'); + if (this.pending.length === 0) return callback(); diff --git a/lib/bcoin/mempool.js b/lib/bcoin/mempool.js index 43dc8ad4..75805fd6 100644 --- a/lib/bcoin/mempool.js +++ b/lib/bcoin/mempool.js @@ -163,6 +163,11 @@ Mempool.prototype.addBlock = function addBlock(block, callback) { var entries = []; var i, entry, tx, hash; + callback = this._lock(addBlock, [block, callback]); + + if (!callback) + return; + for (i = block.txs.length - 1; i >= 0; i--) { tx = block.txs[i]; hash = tx.hash('hex'); @@ -189,7 +194,7 @@ Mempool.prototype.addBlock = function addBlock(block, callback) { if (this.fees) this.fees.processBlock(block.height, entries, this.chain.isFull()); - callback(); + utils.nextTick(callback); }; /** @@ -199,11 +204,11 @@ Mempool.prototype.addBlock = function addBlock(block, callback) { * @param {Function} callback */ -Mempool.prototype.removeBlock = function removeBlock(block, callback, force) { +Mempool.prototype.removeBlock = function removeBlock(block, callback) { var self = this; var entry; - callback = this._lock(removeBlock, [block, callback], force); + callback = this._lock(removeBlock, [block, callback]); if (!callback) return; @@ -512,14 +517,14 @@ Mempool.prototype.has = function has(hash) { * @param {Function} callback - Returns [{@link VerifyError}]. */ -Mempool.prototype.addTX = function addTX(tx, callback, force) { +Mempool.prototype.addTX = function addTX(tx, callback) { var self = this; var lockFlags = constants.flags.STANDARD_LOCKTIME_FLAGS; var hash = tx.hash('hex'); var ret = {}; var entry; - callback = this._lock(addTX, [tx, callback], force); + callback = this._lock(addTX, [tx, callback]); if (!callback) return; diff --git a/lib/bcoin/txdb.js b/lib/bcoin/txdb.js index cadd487b..4397381c 100644 --- a/lib/bcoin/txdb.js +++ b/lib/bcoin/txdb.js @@ -1253,7 +1253,7 @@ TXDB.prototype.unconfirm = function unconfirm(hash, callback, force) { * @param {Function} callback */ -TXDB.prototype._unconfirm = function unconfirm(tx, info, callback, force) { +TXDB.prototype._unconfirm = function unconfirm(tx, info, callback) { var self = this; var hash = tx.hash('hex'); var i, account; @@ -2265,17 +2265,16 @@ TXDB.prototype.getAccountBalance = function getBalance(account, callback) { * @param {Function} callback */ -TXDB.prototype.zap = function zap(account, age, callback, force) { +TXDB.prototype.zap = function zap(account, age, callback) { var self = this; if (typeof age === 'function') { - force = callback; callback = age; age = account; account = null; } - callback = this._lock(zap, [account, age, callback], force); + callback = this._lock(zap, [account, age, callback]); if (!callback) return; @@ -2304,7 +2303,7 @@ TXDB.prototype.zap = function zap(account, age, callback, force) { * @param {Function} callback */ -TXDB.prototype.abandon = function abandon(hash, callback, force) { +TXDB.prototype.abandon = function abandon(hash, callback) { var self = this; this.has(layout.p(hash), function(err, result) { if (err) @@ -2313,7 +2312,7 @@ TXDB.prototype.abandon = function abandon(hash, callback, force) { if (!result) return callback(new Error('TX not eligible.')); - self.remove(hash, callback, force); + self.remove(hash, callback); }); }; diff --git a/lib/bcoin/wallet.js b/lib/bcoin/wallet.js index 28d7c165..d5aded79 100644 --- a/lib/bcoin/wallet.js +++ b/lib/bcoin/wallet.js @@ -75,6 +75,24 @@ function Wallet(db, options) { utils.inherits(Wallet, EventEmitter); +/** + * Invoke write mutex lock. + * @private + */ + +Wallet.prototype._lockWrite = function _lockWrite(func, args, force) { + return this.writeLock.lock(func, args, force); +}; + +/** + * Invoke funding mutex lock. + * @private + */ + +Wallet.prototype._lockFund = function _lockFund(func, args, force) { + return this.fundLock.lock(func, args, force); +}; + /** * Inject properties from options object. * @private @@ -245,7 +263,7 @@ Wallet.prototype.addKey = function addKey(account, key, callback) { account = 0; } - callback = this.writeLock.lock(addKey, [account, key, callback]); + callback = this._lockWrite(addKey, [account, key, callback]); if (!callback) return; @@ -289,7 +307,7 @@ Wallet.prototype.removeKey = function removeKey(account, key, callback) { account = 0; } - callback = this.writeLock.lock(removeKey, [account, key, callback]); + callback = this._lockWrite(removeKey, [account, key, callback]); if (!callback) return; @@ -333,7 +351,7 @@ Wallet.prototype.setPassphrase = function setPassphrase(old, new_, callback) { old = null; } - callback = this.writeLock.lock(setPassphrase, [old, new_, callback]); + callback = this._lockWrite(setPassphrase, [old, new_, callback]); if (!callback) return; @@ -367,7 +385,7 @@ Wallet.prototype.retoken = function retoken(passphrase, callback) { passphrase = null; } - callback = this.writeLock.lock(retoken, [passphrase, callback]); + callback = this._lockWrite(retoken, [passphrase, callback]); if (!callback) return; @@ -468,16 +486,18 @@ Wallet.prototype.getToken = function getToken(master, nonce) { * @param {Function} callback - Returns [Error, {@link Account}]. */ -Wallet.prototype.createAccount = function createAccount(options, callback, force) { +Wallet.prototype.createAccount = function createAccount(options, callback) { var self = this; + var passphrase = options.passphrase; + var timeout = options.timeout; var key; - callback = this.writeLock.lock(createAccount, [options, callback], force); + callback = this._lockWrite(createAccount, [options, callback]); if (!callback) return; - this.unlock(options.passphrase, options.timeout, function(err, master) { + this.unlock(passphrase, timeout, function(err, master) { if (err) return callback(err); @@ -640,7 +660,7 @@ Wallet.prototype.createAddress = function createAddress(account, change, callbac account = 0; } - callback = this.writeLock.lock(createAddress, [account, change, callback]); + callback = this._lockWrite(createAddress, [account, change, callback]); if (!callback) return; @@ -810,7 +830,7 @@ Wallet.prototype.fund = function fund(tx, options, callback, force) { // We use a lock here to ensure we // don't end up double spending coins. - callback = this.fundLock.lock(fund, [tx, options, callback], force); + callback = this._lockFund(fund, [tx, options, callback], force); if (!callback) return; @@ -947,7 +967,7 @@ Wallet.prototype.createTX = function createTX(options, callback, force) { Wallet.prototype.send = function send(options, callback) { var self = this; - callback = this.fundLock.lock(send, [options, callback]); + callback = this._lockFund(send, [options, callback]); if (!callback) return; @@ -1177,7 +1197,7 @@ Wallet.prototype.syncOutputDepth = function syncOutputDepth(info, callback) { var accounts = {}; var i, path; - callback = this.writeLock.lock(syncOutputDepth, [info, callback]); + callback = this._lockWrite(syncOutputDepth, [info, callback]); if (!callback) return; diff --git a/lib/bcoin/walletdb.js b/lib/bcoin/walletdb.js index a5088af5..7d9a9e14 100644 --- a/lib/bcoin/walletdb.js +++ b/lib/bcoin/walletdb.js @@ -216,6 +216,33 @@ WalletDB.prototype._init = function _init() { } }; +/** + * Invoke wallet read mutex lock. + * @private + */ + +WalletDB.prototype._lockRead = function _lockRead(key, func, args, force) { + return this.readLock.lock(key, func, args, force); +}; + +/** + * Invoke wallet write mutex lock. + * @private + */ + +WalletDB.prototype._lockWrite = function _lockWrite(key, func, args, force) { + return this.writeLock.lock(key, func, args, force); +}; + +/** + * Invoke tx handling mutex lock. + * @private + */ + +WalletDB.prototype._lockTX = function _lockTX(func, args, force) { + return this.txLock.lock(func, args, force); +}; + /** * Open the walletdb, wait for the database to load. * @alias WalletDB#open @@ -539,7 +566,7 @@ WalletDB.prototype._get = function get(wid, callback) { var self = this; var wallet; - callback = this.readLock.lock(wid, get, [wid, callback]); + callback = this._lockRead(wid, get, [wid, callback]); if (!callback) return; @@ -613,7 +640,7 @@ WalletDB.prototype.create = function create(options, callback) { options = {}; } - callback = this.writeLock.lock(options.id, create, [options, callback]); + callback = this._lockWrite(options.id, create, [options, callback]); if (!callback) return; @@ -1337,11 +1364,11 @@ WalletDB.prototype.getWalletsByTX = function getWalletsByTX(hash, callback) { * @param {Function} callback */ -WalletDB.prototype.addBlock = function addBlock(entry, txs, callback, force) { +WalletDB.prototype.addBlock = function addBlock(entry, txs, callback) { var self = this; var block, matches, hash; - callback = this.txLock.lock(addBlock, [entry, txs, callback], force); + callback = this._lockTX(addBlock, [entry, txs, callback]); if (!callback) return; @@ -1391,10 +1418,10 @@ WalletDB.prototype.addBlock = function addBlock(entry, txs, callback, force) { * @param {Function} callback */ -WalletDB.prototype.removeBlock = function removeBlock(entry, callback, force) { +WalletDB.prototype.removeBlock = function removeBlock(entry, callback) { var self = this; - callback = this.txLock.lock(removeBlock, [entry, callback], force); + callback = this._lockTX(removeBlock, [entry, callback]); if (!callback) return; @@ -1464,6 +1491,11 @@ WalletDB.prototype.removeBlock = function removeBlock(entry, callback, force) { WalletDB.prototype.addTX = function addTX(tx, callback, force) { var self = this; + callback = this._lockTX(addTX, [tx, callback], force); + + if (!callback) + return; + assert(!tx.mutable, 'Cannot add mutable TX to wallet.'); // Note: