mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Merge pull request #4557 from MetaMask/nonce-tracker-mutex-fix
Bug: Mutex locks not released on error
This commit is contained in:
commit
0740dd6a5b
@ -165,7 +165,7 @@ class TransactionController extends EventEmitter {
|
||||
// add default tx params
|
||||
txMeta = await this.addTxGasDefaults(txMeta)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
log.warn(error)
|
||||
this.txStateManager.setTxStatusFailed(txMeta.id, error)
|
||||
throw error
|
||||
}
|
||||
@ -264,7 +264,12 @@ class TransactionController extends EventEmitter {
|
||||
// must set transaction to submitted/failed before releasing lock
|
||||
nonceLock.releaseLock()
|
||||
} catch (err) {
|
||||
this.txStateManager.setTxStatusFailed(txId, err)
|
||||
// this is try-catch wrapped so that we can guarantee that the nonceLock is released
|
||||
try {
|
||||
this.txStateManager.setTxStatusFailed(txId, err)
|
||||
} catch (err) {
|
||||
log.error(err)
|
||||
}
|
||||
// must set transaction to submitted/failed before releasing lock
|
||||
if (nonceLock) nonceLock.releaseLock()
|
||||
// continue with error chain
|
||||
|
@ -49,29 +49,35 @@ class NonceTracker {
|
||||
await this._globalMutexFree()
|
||||
// await lock free, then take lock
|
||||
const releaseLock = await this._takeMutex(address)
|
||||
// evaluate multiple nextNonce strategies
|
||||
const nonceDetails = {}
|
||||
const networkNonceResult = await this._getNetworkNextNonce(address)
|
||||
const highestLocallyConfirmed = this._getHighestLocallyConfirmed(address)
|
||||
const nextNetworkNonce = networkNonceResult.nonce
|
||||
const highestSuggested = Math.max(nextNetworkNonce, highestLocallyConfirmed)
|
||||
try {
|
||||
// evaluate multiple nextNonce strategies
|
||||
const nonceDetails = {}
|
||||
const networkNonceResult = await this._getNetworkNextNonce(address)
|
||||
const highestLocallyConfirmed = this._getHighestLocallyConfirmed(address)
|
||||
const nextNetworkNonce = networkNonceResult.nonce
|
||||
const highestSuggested = Math.max(nextNetworkNonce, highestLocallyConfirmed)
|
||||
|
||||
const pendingTxs = this.getPendingTransactions(address)
|
||||
const localNonceResult = this._getHighestContinuousFrom(pendingTxs, highestSuggested) || 0
|
||||
const pendingTxs = this.getPendingTransactions(address)
|
||||
const localNonceResult = this._getHighestContinuousFrom(pendingTxs, highestSuggested) || 0
|
||||
|
||||
nonceDetails.params = {
|
||||
highestLocallyConfirmed,
|
||||
highestSuggested,
|
||||
nextNetworkNonce,
|
||||
nonceDetails.params = {
|
||||
highestLocallyConfirmed,
|
||||
highestSuggested,
|
||||
nextNetworkNonce,
|
||||
}
|
||||
nonceDetails.local = localNonceResult
|
||||
nonceDetails.network = networkNonceResult
|
||||
|
||||
const nextNonce = Math.max(networkNonceResult.nonce, localNonceResult.nonce)
|
||||
assert(Number.isInteger(nextNonce), `nonce-tracker - nextNonce is not an integer - got: (${typeof nextNonce}) "${nextNonce}"`)
|
||||
|
||||
// return nonce and release cb
|
||||
return { nextNonce, nonceDetails, releaseLock }
|
||||
} catch (err) {
|
||||
// release lock if we encounter an error
|
||||
releaseLock()
|
||||
throw err
|
||||
}
|
||||
nonceDetails.local = localNonceResult
|
||||
nonceDetails.network = networkNonceResult
|
||||
|
||||
const nextNonce = Math.max(networkNonceResult.nonce, localNonceResult.nonce)
|
||||
assert(Number.isInteger(nextNonce), `nonce-tracker - nextNonce is not an integer - got: (${typeof nextNonce}) "${nextNonce}"`)
|
||||
|
||||
// return nonce and release cb
|
||||
return { nextNonce, nonceDetails, releaseLock }
|
||||
}
|
||||
|
||||
async _getCurrentBlock () {
|
||||
@ -85,8 +91,8 @@ class NonceTracker {
|
||||
|
||||
async _globalMutexFree () {
|
||||
const globalMutex = this._lookupMutex('global')
|
||||
const release = await globalMutex.acquire()
|
||||
release()
|
||||
const releaseLock = await globalMutex.acquire()
|
||||
releaseLock()
|
||||
}
|
||||
|
||||
async _takeMutex (lockId) {
|
||||
|
@ -196,14 +196,14 @@ class PendingTransactionTracker extends EventEmitter {
|
||||
async _checkPendingTxs () {
|
||||
const signedTxList = this.getPendingTransactions()
|
||||
// in order to keep the nonceTracker accurate we block it while updating pending transactions
|
||||
const nonceGlobalLock = await this.nonceTracker.getGlobalLock()
|
||||
const { releaseLock } = await this.nonceTracker.getGlobalLock()
|
||||
try {
|
||||
await Promise.all(signedTxList.map((txMeta) => this._checkPendingTx(txMeta)))
|
||||
} catch (err) {
|
||||
log.error('PendingTransactionWatcher - Error updating pending transactions')
|
||||
log.error(err)
|
||||
}
|
||||
nonceGlobalLock.releaseLock()
|
||||
releaseLock()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -436,28 +436,24 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
* @returns {Object} vault
|
||||
*/
|
||||
async createNewVaultAndKeychain (password) {
|
||||
const release = await this.createVaultMutex.acquire()
|
||||
let vault
|
||||
|
||||
const releaseLock = await this.createVaultMutex.acquire()
|
||||
try {
|
||||
let vault
|
||||
const accounts = await this.keyringController.getAccounts()
|
||||
|
||||
if (accounts.length > 0) {
|
||||
vault = await this.keyringController.fullUpdate()
|
||||
|
||||
} else {
|
||||
vault = await this.keyringController.createNewVaultAndKeychain(password)
|
||||
const accounts = await this.keyringController.getAccounts()
|
||||
this.preferencesController.setAddresses(accounts)
|
||||
this.selectFirstIdentity()
|
||||
}
|
||||
release()
|
||||
releaseLock()
|
||||
return vault
|
||||
} catch (err) {
|
||||
release()
|
||||
releaseLock()
|
||||
throw err
|
||||
}
|
||||
|
||||
return vault
|
||||
}
|
||||
|
||||
/**
|
||||
@ -466,7 +462,7 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
* @param {} seed
|
||||
*/
|
||||
async createNewVaultAndRestore (password, seed) {
|
||||
const release = await this.createVaultMutex.acquire()
|
||||
const releaseLock = await this.createVaultMutex.acquire()
|
||||
try {
|
||||
// clear known identities
|
||||
this.preferencesController.setAddresses([])
|
||||
@ -476,10 +472,10 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
const accounts = await this.keyringController.getAccounts()
|
||||
this.preferencesController.setAddresses(accounts)
|
||||
this.selectFirstIdentity()
|
||||
release()
|
||||
releaseLock()
|
||||
return vault
|
||||
} catch (err) {
|
||||
release()
|
||||
releaseLock()
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user