aboutsummaryrefslogtreecommitdiffstats
path: root/app/scripts/lib/nonce-tracker.js
diff options
context:
space:
mode:
Diffstat (limited to 'app/scripts/lib/nonce-tracker.js')
-rw-r--r--app/scripts/lib/nonce-tracker.js59
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