diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 1fc48aadd..5f3d84ebe 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -484,12 +484,15 @@ module.exports = class TransactionController extends EventEmitter { // if confirmed sets the tx status as 'confirmed' async _checkPendingTxs () { const signedTxList = this.getFilteredTxList({status: 'submitted'}) + // in order to keep the nonceTracker accurate we block it while updating pending transactions + const nonceGlobalLock = await this.nonceTracker.getGlobalLock() try { await Promise.all(signedTxList.map((txMeta) => this._checkPendingTx(txMeta))) } catch (err) { console.error('TransactionController - Error updating pending transactions') console.error(err) } + nonceGlobalLock.releaseLock() } async _checkPendingTx (txMeta) { diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index 7a450cb78..b76dac4e8 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -11,9 +11,18 @@ class NonceTracker { this.lockMap = {} } + async getGlobalLock () { + const globalMutex = this._lookupMutex('global') + // await global mutex free + const releaseLock = await globalMutex.acquire() + return { releaseLock } + } + // releaseLock must be called // releaseLock must be called after adding signed tx to pending transactions (or discarding) async getNonceLock (address) { + // await global mutex free + await this._globalMutexFree() // await lock free, then take lock const releaseLock = await this._takeMutex(address) // calculate next nonce @@ -40,21 +49,6 @@ class NonceTracker { }) } - _lookupMutex (lockId) { - let mutex = this.lockMap[lockId] - if (!mutex) { - mutex = new Mutex() - this.lockMap[lockId] = mutex - } - return mutex - } - - async _takeMutex (lockId) { - const mutex = this._lookupMutex(lockId) - const releaseLock = await mutex.acquire() - return releaseLock - } - async _getTxCount (address, currentBlock) { const blockNumber = currentBlock.number return new Promise((resolve, reject) => { @@ -64,6 +58,27 @@ class NonceTracker { }) } + async _globalMutexFree () { + const globalMutex = this._lookupMutex('global') + const release = await globalMutex.acquire() + release() + } + + async _takeMutex (lockId) { + const mutex = this._lookupMutex(lockId) + const releaseLock = await mutex.acquire() + return releaseLock + } + + _lookupMutex (lockId) { + let mutex = this.lockMap[lockId] + if (!mutex) { + mutex = new Mutex() + this.lockMap[lockId] = mutex + } + return mutex + } + } module.exports = NonceTracker