diff options
Diffstat (limited to 'app/scripts/lib/nonce-tracker.js')
-rw-r--r-- | app/scripts/lib/nonce-tracker.js | 59 |
1 files changed, 42 insertions, 17 deletions
diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index ab2893b10..b76dac4e8 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -1,4 +1,6 @@ const EthQuery = require('eth-query') +const assert = require('assert') +const Mutex = require('await-semaphore').Mutex class NonceTracker { @@ -9,22 +11,34 @@ 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 lock free - await this.lockMap[address] - // take lock - const releaseLock = this._takeLock(address) + // await global mutex free + await this._globalMutexFree() + // await lock free, then take lock + const releaseLock = await this._takeMutex(address) // calculate next nonce // we need to make sure our base count // and pending count are from the same block const currentBlock = await this._getCurrentBlock() const pendingTransactions = this.getPendingTransactions(address) - const baseCount = await this._getTxCount(address, currentBlock) - const nextNonce = parseInt(baseCount) + pendingTransactions.length + const pendingCount = pendingTransactions.length + assert(Number.isInteger(pendingCount), 'nonce-tracker - pendingCount is an integer') + const baseCountHex = await this._getTxCount(address, currentBlock) + const baseCount = parseInt(baseCountHex, 16) + assert(Number.isInteger(baseCount), 'nonce-tracker - baseCount is an integer') + const nextNonce = baseCount + pendingCount + assert(Number.isInteger(nextNonce), 'nonce-tracker - nextNonce is an integer') // return next nonce and release cb - return { nextNonce: nextNonce.toString(16), releaseLock } + return { nextNonce, releaseLock } } async _getCurrentBlock () { @@ -35,16 +49,6 @@ class NonceTracker { }) } - _takeLock (lockId) { - let releaseLock = null - // create and store lock - const lock = new Promise((resolve, reject) => { releaseLock = resolve }) - this.lockMap[lockId] = lock - // setup lock teardown - lock.then(() => delete this.lockMap[lockId]) - return releaseLock - } - async _getTxCount (address, currentBlock) { const blockNumber = currentBlock.number return new Promise((resolve, reject) => { @@ -54,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 |