From a5a32f3d5742972586893741847ea4516afa19ac Mon Sep 17 00:00:00 2001 From: frankiebee Date: Fri, 18 Aug 2017 13:54:16 -0700 Subject: [PATCH] use "localNonce" when the network returns a nonce that is lower then a known confirmed tx --- app/scripts/controllers/transactions.js | 7 +++++++ app/scripts/lib/nonce-tracker.js | 23 ++++++++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 58c468e22..f21cb6e00 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -33,6 +33,13 @@ module.exports = class TransactionController extends EventEmitter { err: undefined, }) }, + getConfirmedTransactions: (address) => { + return this.getFilteredTxList({ + from: address, + status: 'confirmed', + err: undefined, + }) + }, }) this.query = new EthQuery(this.provider) this.txProviderUtil = new TxProviderUtil(this.provider) diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index 8328e81ec..3a26c374c 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -4,10 +4,11 @@ const Mutex = require('await-semaphore').Mutex class NonceTracker { - constructor ({ provider, getPendingTransactions }) { + constructor ({ provider, getPendingTransactions, getConfirmedTransactions }) { this.provider = provider this.ethQuery = new EthQuery(provider) this.getPendingTransactions = getPendingTransactions + this.getConfirmedTransactions = getConfirmedTransactions this.lockMap = {} } @@ -28,6 +29,14 @@ class NonceTracker { // calculate next nonce // we need to make sure our base count // and pending count are from the same block + const localNonceHex = this._getLocalNonce(address) + let localNonce = parseInt(localNonceHex, 16) + try { + assert(Number.isInteger(localNonce), `nonce-tracker - localNonce is not an integer - got: (${typeof localNonce}) "${localNonce}"`) + } catch (e) { + // throw out localNonce if not a number + localNonce = 0 + } const currentBlock = await this._getCurrentBlock() const pendingTransactions = this.getPendingTransactions(address) const pendingCount = pendingTransactions.length @@ -35,11 +44,11 @@ class NonceTracker { const baseCountHex = await this._getTxCount(address, currentBlock) const baseCount = parseInt(baseCountHex, 16) assert(Number.isInteger(baseCount), `nonce-tracker - baseCount is not an integer - got: (${typeof baseCount}) "${baseCount}"`) - const nextNonce = baseCount + pendingCount + const nextNonce = Math.max(baseCount, localNonce + 1) + pendingCount assert(Number.isInteger(nextNonce), `nonce-tracker - nextNonce is not an integer - got: (${typeof nextNonce}) "${nextNonce}"`) // collect the numbers used to calculate the nonce for debugging const blockNumber = currentBlock.number - const nonceDetails = { blockNumber, baseCount, baseCountHex, pendingCount } + const nonceDetails = { blockNumber, baseCount, baseCountHex, pendingCount, localNonceHex, localNonce } // return nonce and release cb return { nextNonce, nonceDetails, releaseLock } } @@ -83,6 +92,14 @@ class NonceTracker { return mutex } + _getLocalNonce (address) { + const confirmedTransactions = this.getConfirmedTransactions(address) + const localNonces = confirmedTransactions.map((txMeta) => txMeta.txParams.nonce) + return localNonces.reduce((nonce, highestNonce) => { + return parseInt(nonce, 16) > parseInt(highestNonce, 16) ? nonce : highestNonce + }, '0x0') + } + // this is a hotfix for the fact that the blockTracker will // change when the network changes _getBlockTracker () {