From fdffb6fedc6a29a2f952f7db669bdc2907afb854 Mon Sep 17 00:00:00 2001 From: kumavis Date: Mon, 14 Aug 2017 18:46:04 -0700 Subject: introduce tx-state-history-helper and diff-based history --- app/scripts/controllers/transactions.js | 34 +++++++++++++++------------ app/scripts/lib/tx-state-history-helper.js | 37 ++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 15 deletions(-) create mode 100644 app/scripts/lib/tx-state-history-helper.js (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 58c468e22..872d11b50 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -8,6 +8,7 @@ const TxProviderUtil = require('../lib/tx-utils') const PendingTransactionTracker = require('../lib/pending-tx-tracker') const createId = require('../lib/random-id') const NonceTracker = require('../lib/nonce-tracker') +const txStateHistoryHelper = require('../lib/tx-state-history-helper') module.exports = class TransactionController extends EventEmitter { constructor (opts) { @@ -128,19 +129,17 @@ module.exports = class TransactionController extends EventEmitter { updateTx (txMeta) { // create txMeta snapshot for history - const txMetaForHistory = clone(txMeta) - // dont include previous history in this snapshot - delete txMetaForHistory.history - // add snapshot to tx history - if (!txMeta.history) txMeta.history = [] - txMeta.history.push(txMetaForHistory) - + const currentState = txStateHistoryHelper.snapshotFromTxMeta(txMeta) + // recover previous tx state obj + const previousState = txStateHistoryHelper.replayHistory(txMeta.history) + // generate history entry and add to history + const entry = txStateHistoryHelper.generateHistoryEntry(previousState, currentState) + txMeta.history.push(entry) + + // commit txMeta to state const txId = txMeta.id const txList = this.getFullTxList() const index = txList.findIndex(txData => txData.id === txId) - if (!txMeta.history) txMeta.history = [] - txMeta.history.push(txMetaForHistory) - txList[index] = txMeta this._saveTxList(txList) this.emit('update') @@ -148,16 +147,22 @@ module.exports = class TransactionController extends EventEmitter { // Adds a tx to the txlist addTx (txMeta) { - const txCount = this.getTxCount() - const network = this.getNetwork() - const fullTxList = this.getFullTxList() - const txHistoryLimit = this.txHistoryLimit + // initialize history + txMeta.history = [] + // capture initial snapshot of txMeta for history + const snapshot = txStateHistoryHelper.snapshotFromTxMeta(txMeta) + txMeta.history.push(snapshot) // checks if the length of the tx history is // longer then desired persistence limit // and then if it is removes only confirmed // or rejected tx's. // not tx's that are pending or unapproved + const txCount = this.getTxCount() + const network = this.getNetwork() + const fullTxList = this.getFullTxList() + const txHistoryLimit = this.txHistoryLimit + if (txCount > txHistoryLimit - 1) { const index = fullTxList.findIndex((metaTx) => ((metaTx.status === 'confirmed' || metaTx.status === 'rejected') && network === txMeta.metamaskNetworkId)) fullTxList.splice(index, 1) @@ -206,7 +211,6 @@ module.exports = class TransactionController extends EventEmitter { status: 'unapproved', metamaskNetworkId: this.getNetwork(), txParams: txParams, - history: [], } // add default tx params await this.addTxDefaults(txMeta) diff --git a/app/scripts/lib/tx-state-history-helper.js b/app/scripts/lib/tx-state-history-helper.js new file mode 100644 index 000000000..87b9a1d63 --- /dev/null +++ b/app/scripts/lib/tx-state-history-helper.js @@ -0,0 +1,37 @@ +const jsonDiffer = require('fast-json-patch') +const clone = require('clone') + +module.exports = { + generateHistoryEntry, + replayHistory, + snapshotFromTxMeta, + migrateFromSnapshotsToDiffs, +} + + +function migrateFromSnapshotsToDiffs(longHistory) { + return ( + longHistory + // convert non-initial history entries into diffs + .map((entry, index) => { + if (index === 0) return entry + return generateHistoryEntry(longHistory[index-1], entry) + }) + ) +} + +function generateHistoryEntry(previousState, newState) { + return jsonDiffer.compare(previousState, newState) +} + +function replayHistory(shortHistory) { + return shortHistory.reduce((val, entry) => jsonDiffer.applyPatch(val, entry).newDocument) +} + +function snapshotFromTxMeta(txMeta) { + // create txMeta snapshot for history + const snapshot = clone(txMeta) + // dont include previous history in this snapshot + delete snapshot.history + return snapshot +} \ No newline at end of file -- cgit From accd057b1abf519551dab253845085c40eb1415c Mon Sep 17 00:00:00 2001 From: kumavis Date: Mon, 14 Aug 2017 18:46:18 -0700 Subject: migration 18 - move to diff-based history --- app/scripts/migrations/018.js | 52 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 app/scripts/migrations/018.js (limited to 'app') diff --git a/app/scripts/migrations/018.js b/app/scripts/migrations/018.js new file mode 100644 index 000000000..c8d2332ab --- /dev/null +++ b/app/scripts/migrations/018.js @@ -0,0 +1,52 @@ +const version = 18 + +/* + +This migration updates "transaction state history" to diffs style + +*/ + +const clone = require('clone') +const txStateHistoryHelper = require('../tx-state-history-helper') + + +module.exports = { + version, + + migrate: function (originalVersionedData) { + const versionedData = clone(originalVersionedData) + versionedData.meta.version = version + try { + const state = versionedData.data + const newState = transformState(state) + versionedData.data = newState + } catch (err) { + console.warn(`MetaMask Migration #${version}` + err.stack) + } + return Promise.resolve(versionedData) + }, +} + +function transformState (state) { + const newState = state + const transactions = newState.TransactionController.transactions + newState.TransactionController.transactions = transactions.map((txMeta) => { + // no history: initialize + if (!txMeta.history || tx.history.length === 0) { + const snapshot = txStateHistoryHelper.snapshotFromTxMeta(txMeta) + txMeta.history = [snapshot] + return txMeta + } + // has history: migrate + const newHistory = ( + txStateHistoryHelper.migrateFromSnapshotsToDiffs(txMeta.history) + // remove empty diffs + .filter((entry) => { + return !Array.isArray(entry) || entry.length > 0 + }) + ) + txMeta.history = newHistory + return txMeta + }) + return newState +} -- cgit From 1af797b1b3a37d8fe00afbd0d84cb3349b8fd471 Mon Sep 17 00:00:00 2001 From: kumavis Date: Mon, 14 Aug 2017 19:15:36 -0700 Subject: tx controller - tx state history various small fixes --- app/scripts/controllers/transactions.js | 1 - app/scripts/lib/tx-state-history-helper.js | 2 +- app/scripts/migrations/018.js | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 872d11b50..1bcee60ab 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -1,6 +1,5 @@ const EventEmitter = require('events') const extend = require('xtend') -const clone = require('clone') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') const EthQuery = require('ethjs-query') diff --git a/app/scripts/lib/tx-state-history-helper.js b/app/scripts/lib/tx-state-history-helper.js index 87b9a1d63..304069d57 100644 --- a/app/scripts/lib/tx-state-history-helper.js +++ b/app/scripts/lib/tx-state-history-helper.js @@ -15,7 +15,7 @@ function migrateFromSnapshotsToDiffs(longHistory) { // convert non-initial history entries into diffs .map((entry, index) => { if (index === 0) return entry - return generateHistoryEntry(longHistory[index-1], entry) + return generateHistoryEntry(longHistory[index - 1], entry) }) ) } diff --git a/app/scripts/migrations/018.js b/app/scripts/migrations/018.js index c8d2332ab..41e7de391 100644 --- a/app/scripts/migrations/018.js +++ b/app/scripts/migrations/018.js @@ -32,7 +32,7 @@ function transformState (state) { const transactions = newState.TransactionController.transactions newState.TransactionController.transactions = transactions.map((txMeta) => { // no history: initialize - if (!txMeta.history || tx.history.length === 0) { + if (!txMeta.history || txMeta.history.length === 0) { const snapshot = txStateHistoryHelper.snapshotFromTxMeta(txMeta) txMeta.history = [snapshot] return txMeta -- cgit From ac2b572c3442a42286f3d10be454e3b21d06dde8 Mon Sep 17 00:00:00 2001 From: kumavis Date: Mon, 14 Aug 2017 20:05:57 -0700 Subject: migration 18 - fix an oops --- app/scripts/migrations/018.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/migrations/018.js b/app/scripts/migrations/018.js index 41e7de391..d27fe3f46 100644 --- a/app/scripts/migrations/018.js +++ b/app/scripts/migrations/018.js @@ -7,7 +7,7 @@ This migration updates "transaction state history" to diffs style */ const clone = require('clone') -const txStateHistoryHelper = require('../tx-state-history-helper') +const txStateHistoryHelper = require('../lib/tx-state-history-helper') module.exports = { -- cgit From 588b8f0d3963a88be68782e93cebbafd9934756d Mon Sep 17 00:00:00 2001 From: kumavis Date: Mon, 14 Aug 2017 20:06:15 -0700 Subject: migration 18 - activate --- app/scripts/migrations/index.js | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index f4c87499f..6bfc622f7 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -28,4 +28,5 @@ module.exports = [ require('./015'), require('./016'), require('./017'), + require('./018'), ] -- cgit From 474b037de66d047faf11fe94342e6bfc1dd2b6fc Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 15 Aug 2017 12:47:35 -0700 Subject: v3.9.7 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index f34bdcec3..025fe31bb 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.9.6", + "version": "3.9.7", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 27d030b1a13d3b23ee0e948661867e1754e5796d Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 16 Aug 2017 15:43:34 -0700 Subject: Version 3.9.8 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 025fe31bb..4af7923c2 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.9.7", + "version": "3.9.8", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From a5a32f3d5742972586893741847ea4516afa19ac Mon Sep 17 00:00:00 2001 From: frankiebee Date: Fri, 18 Aug 2017 13:54:16 -0700 Subject: 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(-) (limited to 'app') 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 () { -- cgit From f8eca95ca513c6d8af8e599ce143ae0e78b77e26 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Fri, 18 Aug 2017 15:01:05 -0700 Subject: include pendingTxs in localNonce --- app/scripts/lib/nonce-tracker.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index 3a26c374c..a4ee5c38f 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -29,14 +29,10 @@ 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) + const localNonceHex = this._getHighestLocalNonce(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 - } + // throw out localNonce if not a number + if (!Number.isInteger(localNonce)) localNonce = 0 const currentBlock = await this._getCurrentBlock() const pendingTransactions = this.getPendingTransactions(address) const pendingCount = pendingTransactions.length @@ -44,7 +40,8 @@ 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 = Math.max(baseCount, localNonce + 1) + pendingCount + if (localNonce) ++localNonce + const nextNonce = Math.max(baseCount + pendingCount, localNonce) 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 @@ -92,9 +89,11 @@ class NonceTracker { return mutex } - _getLocalNonce (address) { + _getHighestLocalNonce (address) { const confirmedTransactions = this.getConfirmedTransactions(address) - const localNonces = confirmedTransactions.map((txMeta) => txMeta.txParams.nonce) + const pendingTransactions = this.getPendingTransactions(address) + const transactions = confirmedTransactions.concat(pendingTransactions) + const localNonces = transactions.map((txMeta) => txMeta.txParams.nonce) return localNonces.reduce((nonce, highestNonce) => { return parseInt(nonce, 16) > parseInt(highestNonce, 16) ? nonce : highestNonce }, '0x0') -- cgit From 37f86e874f8c3c3d5f6d78cd8abeb0c835f20ae2 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Fri, 18 Aug 2017 15:44:32 -0700 Subject: fix 0x0 nonce calc. --- app/scripts/lib/nonce-tracker.js | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index a4ee5c38f..3063209ee 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -29,10 +29,8 @@ class NonceTracker { // calculate next nonce // we need to make sure our base count // and pending count are from the same block - const localNonceHex = this._getHighestLocalNonce(address) - let localNonce = parseInt(localNonceHex, 16) + const localNextNonce = this._getLocalNextNonce(address) // throw out localNonce if not a number - if (!Number.isInteger(localNonce)) localNonce = 0 const currentBlock = await this._getCurrentBlock() const pendingTransactions = this.getPendingTransactions(address) const pendingCount = pendingTransactions.length @@ -40,12 +38,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}"`) - if (localNonce) ++localNonce - const nextNonce = Math.max(baseCount + pendingCount, localNonce) + const nextNonce = Math.max(baseCount + pendingCount, localNextNonce) 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, localNonceHex, localNonce } + const nonceDetails = { blockNumber, baseCount, baseCountHex, pendingCount, localNextNonce } // return nonce and release cb return { nextNonce, nonceDetails, releaseLock } } @@ -89,14 +86,27 @@ class NonceTracker { return mutex } - _getHighestLocalNonce (address) { + // _getNetworkNonce (address) { + + // } + + _getLocalNextNonce (address) { const confirmedTransactions = this.getConfirmedTransactions(address) const pendingTransactions = this.getPendingTransactions(address) const transactions = confirmedTransactions.concat(pendingTransactions) const localNonces = transactions.map((txMeta) => txMeta.txParams.nonce) - return localNonces.reduce((nonce, highestNonce) => { + const localNonceHex = localNonces.reduce((nonce, highestNonce) => { return parseInt(nonce, 16) > parseInt(highestNonce, 16) ? nonce : highestNonce }, '0x0') + let localNonce = parseInt(localNonceHex, 16) + if ( + // the local nonce is not 0 + localNonce || + // or their are pending or confirmed transactions + pendingTransactions.length || + confirmedTransactions.length + ) ++localNonce + return localNonce } // this is a hotfix for the fact that the blockTracker will -- cgit From 1ffb40648066189cd9e3abffc94299bbeecb6334 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Fri, 18 Aug 2017 16:05:21 -0700 Subject: break out network nonce calc. --- app/scripts/lib/nonce-tracker.js | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index 3063209ee..01d8e5f19 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -26,23 +26,13 @@ class NonceTracker { 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 localNextNonce = this._getLocalNextNonce(address) - // throw out localNonce if not a number - const currentBlock = await this._getCurrentBlock() - const pendingTransactions = this.getPendingTransactions(address) - const pendingCount = pendingTransactions.length - assert(Number.isInteger(pendingCount), `nonce-tracker - pendingCount is not an integer - got: (${typeof pendingCount}) "${pendingCount}"`) - 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 = Math.max(baseCount + pendingCount, localNextNonce) + const nonceDetails = await this._getNetworkNonceAndDetails(address) + const networkNonce = nonceDetails.networkNonce + const nextNonce = Math.max(networkNonce, localNextNonce) 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, localNextNonce } + nonceDetails.localNextNonce = localNextNonce // return nonce and release cb return { nextNonce, nonceDetails, releaseLock } } @@ -86,9 +76,21 @@ class NonceTracker { return mutex } - // _getNetworkNonce (address) { - - // } + async _getNetworkNonceAndDetails (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 blockNumber = currentBlock.blockNumber + const pendingTransactions = this.getPendingTransactions(address) + const pendingCount = pendingTransactions.length + assert(Number.isInteger(pendingCount), `nonce-tracker - pendingCount is not an integer - got: (${typeof pendingCount}) "${pendingCount}"`) + 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 networkNonce = baseCount + pendingCount + return {networkNonce, blockNumber, baseCountHex, baseCount, pendingCount} + } _getLocalNextNonce (address) { const confirmedTransactions = this.getConfirmedTransactions(address) @@ -99,6 +101,8 @@ class NonceTracker { return parseInt(nonce, 16) > parseInt(highestNonce, 16) ? nonce : highestNonce }, '0x0') let localNonce = parseInt(localNonceHex, 16) + // throw out localNonce if not a number + if (!Number.isInteger(localNonce)) localNonce = 0 if ( // the local nonce is not 0 localNonce || -- cgit From f24cfea35e2443d961a3302bb522ad84aeeef9f9 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 18 Aug 2017 16:12:36 -0700 Subject: Version 3.9.9 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 4af7923c2..293981d70 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.9.8", + "version": "3.9.9", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 5c74f316a8adbcbcca642f9ba0734bd1fc181bc1 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Mon, 21 Aug 2017 16:45:10 -0700 Subject: nonce-tracker - pass tests --- app/scripts/lib/nonce-tracker.js | 49 +++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 11 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index 01d8e5f19..92a9cf4f1 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -37,6 +37,25 @@ class NonceTracker { return { nextNonce, nonceDetails, releaseLock } } + getPendingTransactionCount (address) { + const pendingTransactions = this.getPendingTransactions(address) + return this.reduceTxListToUniqueNonces(pendingTransactions).length + } + + + reduceTxListToUniqueNonces (txList) { + const reducedTxList = txList.reduce((reducedList, txMeta, index) => { + if (!index) return [txMeta] + const nonceMatches = txList.filter((txData) => { + return txMeta.txParams.nonce === txData.txParams.nonce + }) + if (nonceMatches.length > 1) return reducedList + reducedList.push(txMeta) + return reducedList + }, []) + return reducedTxList + } + async _getCurrentBlock () { const blockTracker = this._getBlockTracker() const currentBlock = blockTracker.getCurrentBlock() @@ -82,22 +101,31 @@ class NonceTracker { // and pending count are from the same block const currentBlock = await this._getCurrentBlock() const blockNumber = currentBlock.blockNumber - const pendingTransactions = this.getPendingTransactions(address) - const pendingCount = pendingTransactions.length + const pendingNonce = this._getLocalPendingNonce(address) + const pendingCount = this.getPendingTransactionCount(address) assert(Number.isInteger(pendingCount), `nonce-tracker - pendingCount is not an integer - got: (${typeof pendingCount}) "${pendingCount}"`) 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 networkNonce = baseCount + pendingCount - return {networkNonce, blockNumber, baseCountHex, baseCount, pendingCount} + let networkNonce = pendingNonce > baseCount ? baseCount + pendingCount : baseCount + return {networkNonce, blockNumber, baseCountHex, baseCount, pendingCount, pendingNonce} + } + + _getLocalPendingNonce (address) { + const pendingTransactions = this.reduceTxListToUniqueNonces(this.getPendingTransactions(address)) + const localNonces = pendingTransactions.map((txMeta) => txMeta.txParams.nonce) + const localNonceHex = localNonces.reduce((highestNonce, nonce) => { + return parseInt(nonce, 16) > parseInt(highestNonce, 16) ? nonce : highestNonce + }, '0x0') + return parseInt(localNonceHex, 16) } _getLocalNextNonce (address) { - const confirmedTransactions = this.getConfirmedTransactions(address) - const pendingTransactions = this.getPendingTransactions(address) - const transactions = confirmedTransactions.concat(pendingTransactions) + const confirmedTransactions = this.reduceTxListToUniqueNonces(this.getConfirmedTransactions(address)) + const pendingTransactions = this.reduceTxListToUniqueNonces(this.getPendingTransactions(address)) + const transactions = this.reduceTxListToUniqueNonces(confirmedTransactions.concat(pendingTransactions)) const localNonces = transactions.map((txMeta) => txMeta.txParams.nonce) - const localNonceHex = localNonces.reduce((nonce, highestNonce) => { + const localNonceHex = localNonces.reduce((highestNonce, nonce) => { return parseInt(nonce, 16) > parseInt(highestNonce, 16) ? nonce : highestNonce }, '0x0') let localNonce = parseInt(localNonceHex, 16) @@ -107,9 +135,9 @@ class NonceTracker { // the local nonce is not 0 localNonce || // or their are pending or confirmed transactions - pendingTransactions.length || + this.getPendingTransactionCount(address) || confirmedTransactions.length - ) ++localNonce + ) ++localNonce return localNonce } @@ -118,7 +146,6 @@ class NonceTracker { _getBlockTracker () { return this.provider._blockTracker } - } module.exports = NonceTracker -- cgit From 7d34b22d78713aa1a12dbdab0559ccaf4c1be93c Mon Sep 17 00:00:00 2001 From: frankiebee Date: Mon, 21 Aug 2017 17:04:47 -0700 Subject: clean up code --- app/scripts/lib/nonce-tracker.js | 82 +++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 39 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index 92a9cf4f1..c20459650 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -37,25 +37,6 @@ class NonceTracker { return { nextNonce, nonceDetails, releaseLock } } - getPendingTransactionCount (address) { - const pendingTransactions = this.getPendingTransactions(address) - return this.reduceTxListToUniqueNonces(pendingTransactions).length - } - - - reduceTxListToUniqueNonces (txList) { - const reducedTxList = txList.reduce((reducedList, txMeta, index) => { - if (!index) return [txMeta] - const nonceMatches = txList.filter((txData) => { - return txMeta.txParams.nonce === txData.txParams.nonce - }) - if (nonceMatches.length > 1) return reducedList - reducedList.push(txMeta) - return reducedList - }, []) - return reducedTxList - } - async _getCurrentBlock () { const blockTracker = this._getBlockTracker() const currentBlock = blockTracker.getCurrentBlock() @@ -102,45 +83,68 @@ class NonceTracker { const currentBlock = await this._getCurrentBlock() const blockNumber = currentBlock.blockNumber const pendingNonce = this._getLocalPendingNonce(address) - const pendingCount = this.getPendingTransactionCount(address) + const pendingCount = this._getPendingTransactionCount(address) assert(Number.isInteger(pendingCount), `nonce-tracker - pendingCount is not an integer - got: (${typeof pendingCount}) "${pendingCount}"`) 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}"`) - let networkNonce = pendingNonce > baseCount ? baseCount + pendingCount : baseCount - return {networkNonce, blockNumber, baseCountHex, baseCount, pendingCount, pendingNonce} - } + // if the nonce provided by the network is higher then a pending tx + // toss out the pending txCount + const networkNonce = pendingNonce > baseCount ? baseCount + pendingCount : baseCount - _getLocalPendingNonce (address) { - const pendingTransactions = this.reduceTxListToUniqueNonces(this.getPendingTransactions(address)) - const localNonces = pendingTransactions.map((txMeta) => txMeta.txParams.nonce) - const localNonceHex = localNonces.reduce((highestNonce, nonce) => { - return parseInt(nonce, 16) > parseInt(highestNonce, 16) ? nonce : highestNonce - }, '0x0') - return parseInt(localNonceHex, 16) + return {networkNonce, blockNumber, baseCountHex, baseCount, pendingCount, pendingNonce} } _getLocalNextNonce (address) { - const confirmedTransactions = this.reduceTxListToUniqueNonces(this.getConfirmedTransactions(address)) - const pendingTransactions = this.reduceTxListToUniqueNonces(this.getPendingTransactions(address)) - const transactions = this.reduceTxListToUniqueNonces(confirmedTransactions.concat(pendingTransactions)) - const localNonces = transactions.map((txMeta) => txMeta.txParams.nonce) - const localNonceHex = localNonces.reduce((highestNonce, nonce) => { - return parseInt(nonce, 16) > parseInt(highestNonce, 16) ? nonce : highestNonce - }, '0x0') - let localNonce = parseInt(localNonceHex, 16) + const confirmedTransactions = this._reduceTxListToUniqueNonces(this.getConfirmedTransactions(address)) + const pendingTransactions = this._reduceTxListToUniqueNonces(this.getPendingTransactions(address)) + const transactions = this._reduceTxListToUniqueNonces(confirmedTransactions.concat(pendingTransactions)) + let localNonce = this._getHighestNonce(transactions) // throw out localNonce if not a number if (!Number.isInteger(localNonce)) localNonce = 0 if ( // the local nonce is not 0 localNonce || // or their are pending or confirmed transactions - this.getPendingTransactionCount(address) || + this._getPendingTransactionCount(address) || confirmedTransactions.length ) ++localNonce return localNonce } + _getLocalPendingNonce (address) { + const pendingTransactions = this._reduceTxListToUniqueNonces(this.getPendingTransactions(address)) + const localNonce = this._getHighestNonce(pendingTransactions) + return localNonce + } + + _getPendingTransactionCount (address) { + const pendingTransactions = this.getPendingTransactions(address) + return this._reduceTxListToUniqueNonces(pendingTransactions).length + } + + + _reduceTxListToUniqueNonces (txList) { + const reducedTxList = txList.reduce((reducedList, txMeta, index) => { + if (!index) return [txMeta] + const nonceMatches = txList.filter((txData) => { + return txMeta.txParams.nonce === txData.txParams.nonce + }) + if (nonceMatches.length > 1) return reducedList + reducedList.push(txMeta) + return reducedList + }, []) + return reducedTxList + } + + _getHighestNonce (txList) { + const nonces = txList.map((txMeta) => txMeta.txParams.nonce) + const nonceHex = nonces.reduce((highestNonce, nonce) => { + return parseInt(nonce, 16) > parseInt(highestNonce, 16) ? nonce : highestNonce + }, '0x0') + return parseInt(nonceHex, 16) + } + // this is a hotfix for the fact that the blockTracker will // change when the network changes _getBlockTracker () { -- cgit From 604c91f7b2158b09acfcf0e56ea77d0fad0d9dec Mon Sep 17 00:00:00 2001 From: frankiebee Date: Mon, 21 Aug 2017 18:04:05 -0700 Subject: nonce-tracker - pass tests --- app/scripts/lib/nonce-tracker.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index c20459650..ee36e3d5d 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -30,9 +30,11 @@ class NonceTracker { const nonceDetails = await this._getNetworkNonceAndDetails(address) const networkNonce = nonceDetails.networkNonce const nextNonce = Math.max(networkNonce, localNextNonce) + const currentPendingNonce = this._getLocalPendingNonce(address) 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 nonceDetails.localNextNonce = localNextNonce + nonceDetails.currentPendingNonce = currentPendingNonce // return nonce and release cb return { nextNonce, nonceDetails, releaseLock } } @@ -82,17 +84,14 @@ class NonceTracker { // and pending count are from the same block const currentBlock = await this._getCurrentBlock() const blockNumber = currentBlock.blockNumber - const pendingNonce = this._getLocalPendingNonce(address) - const pendingCount = this._getPendingTransactionCount(address) - assert(Number.isInteger(pendingCount), `nonce-tracker - pendingCount is not an integer - got: (${typeof pendingCount}) "${pendingCount}"`) 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}"`) // if the nonce provided by the network is higher then a pending tx // toss out the pending txCount - const networkNonce = pendingNonce > baseCount ? baseCount + pendingCount : baseCount + const networkNonce = baseCount - return {networkNonce, blockNumber, baseCountHex, baseCount, pendingCount, pendingNonce} + return {networkNonce, blockNumber, baseCountHex, baseCount} } _getLocalNextNonce (address) { -- cgit From 98bc9b6656a7fd712085df76252030ddadc653dd Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 22 Aug 2017 13:52:15 -0700 Subject: nonce-tracker - make nonce strategy api and naming more symmetical --- app/scripts/lib/nonce-tracker.js | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index ee36e3d5d..0a87f040d 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -26,14 +26,16 @@ class NonceTracker { await this._globalMutexFree() // await lock free, then take lock const releaseLock = await this._takeMutex(address) - const localNextNonce = this._getLocalNextNonce(address) - const nonceDetails = await this._getNetworkNonceAndDetails(address) - const networkNonce = nonceDetails.networkNonce - const nextNonce = Math.max(networkNonce, localNextNonce) - const currentPendingNonce = this._getLocalPendingNonce(address) + // evaluate multiple nextNonce strategies + const nonceDetails = {} + const localNonceResult = await this._getlocalNextNonce(address) + nonceDetails.local = localNonceResult.details + const networkNonceResult = await this._getNetworkNextNonce(address) + nonceDetails.network = networkNonceResult.details + const nextNonce = Math.max(networkNonceResult.nonce, localNonceResult.nonce) 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 - nonceDetails.localNextNonce = localNextNonce + const currentPendingNonce = this._getLocalPendingNonce(address) nonceDetails.currentPendingNonce = currentPendingNonce // return nonce and release cb return { nextNonce, nonceDetails, releaseLock } @@ -78,7 +80,7 @@ class NonceTracker { return mutex } - async _getNetworkNonceAndDetails (address) { + async _getNetworkNextNonce (address) { // calculate next nonce // we need to make sure our base count // and pending count are from the same block @@ -87,28 +89,29 @@ 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}"`) - // if the nonce provided by the network is higher then a pending tx - // toss out the pending txCount - const networkNonce = baseCount - - return {networkNonce, blockNumber, baseCountHex, baseCount} + const nonceDetails = { blockNumber, baseCountHex, baseCount } + return { name: 'network', nonce: baseCount, details: nonceDetails } } - _getLocalNextNonce (address) { + async _getlocalNextNonce (address) { const confirmedTransactions = this._reduceTxListToUniqueNonces(this.getConfirmedTransactions(address)) const pendingTransactions = this._reduceTxListToUniqueNonces(this.getPendingTransactions(address)) const transactions = this._reduceTxListToUniqueNonces(confirmedTransactions.concat(pendingTransactions)) - let localNonce = this._getHighestNonce(transactions) + const highestNonce = this._getHighestNonce(transactions) + let localNonce = highestNonce // throw out localNonce if not a number - if (!Number.isInteger(localNonce)) localNonce = 0 + if (!Number.isInteger(highestNonce)) localNonce = 0 + const pendingCount = this._getPendingTransactionCount(address) + const confirmedCount = confirmedTransactions.length if ( // the local nonce is not 0 localNonce || // or their are pending or confirmed transactions - this._getPendingTransactionCount(address) || - confirmedTransactions.length + pendingCount || + confirmedCount ) ++localNonce - return localNonce + const nonceDetails = { highestNonce, localNonce, pendingCount, confirmedCount } + return { name: 'local', nonce: localNonce, details: nonceDetails } } _getLocalPendingNonce (address) { @@ -122,7 +125,6 @@ class NonceTracker { return this._reduceTxListToUniqueNonces(pendingTransactions).length } - _reduceTxListToUniqueNonces (txList) { const reducedTxList = txList.reduce((reducedList, txMeta, index) => { if (!index) return [txMeta] -- cgit From b191649ef5ee952c636b224658181fdf2fd73b97 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 22 Aug 2017 13:58:26 -0700 Subject: nonce-tracker - getHighestNonce doesnt need uniqued input --- app/scripts/lib/nonce-tracker.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index 0a87f040d..d44f9c858 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -94,9 +94,9 @@ class NonceTracker { } async _getlocalNextNonce (address) { - const confirmedTransactions = this._reduceTxListToUniqueNonces(this.getConfirmedTransactions(address)) - const pendingTransactions = this._reduceTxListToUniqueNonces(this.getPendingTransactions(address)) - const transactions = this._reduceTxListToUniqueNonces(confirmedTransactions.concat(pendingTransactions)) + const confirmedTransactions = this.getConfirmedTransactions(address) + const pendingTransactions = this.getPendingTransactions(address) + const transactions = confirmedTransactions.concat(pendingTransactions) const highestNonce = this._getHighestNonce(transactions) let localNonce = highestNonce // throw out localNonce if not a number @@ -115,7 +115,7 @@ class NonceTracker { } _getLocalPendingNonce (address) { - const pendingTransactions = this._reduceTxListToUniqueNonces(this.getPendingTransactions(address)) + const pendingTransactions = this.getPendingTransactions(address) const localNonce = this._getHighestNonce(pendingTransactions) return localNonce } -- cgit From e43da3e4aa703cf49543df7726b8cbeea987943d Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 22 Aug 2017 14:04:31 -0700 Subject: nonce-tracker - simplify getHighestNonce --- app/scripts/lib/nonce-tracker.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index d44f9c858..dab6ace1f 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -139,11 +139,9 @@ class NonceTracker { } _getHighestNonce (txList) { - const nonces = txList.map((txMeta) => txMeta.txParams.nonce) - const nonceHex = nonces.reduce((highestNonce, nonce) => { - return parseInt(nonce, 16) > parseInt(highestNonce, 16) ? nonce : highestNonce - }, '0x0') - return parseInt(nonceHex, 16) + const nonces = txList.map((txMeta) => parseInt(txMeta.txParams.nonce, 16)) + const highestNonce = Math.max.apply(null, nonces) + return highestNonce } // this is a hotfix for the fact that the blockTracker will -- cgit From a7e3dc83272d795a48ee7e10c2588a18affbe72e Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 22 Aug 2017 14:15:56 -0700 Subject: nonce-tracker - simplify _getlocalNextNonce --- app/scripts/lib/nonce-tracker.js | 49 ++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 20 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index dab6ace1f..0fb245f7b 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -94,30 +94,39 @@ class NonceTracker { } async _getlocalNextNonce (address) { - const confirmedTransactions = this.getConfirmedTransactions(address) - const pendingTransactions = this.getPendingTransactions(address) - const transactions = confirmedTransactions.concat(pendingTransactions) - const highestNonce = this._getHighestNonce(transactions) - let localNonce = highestNonce - // throw out localNonce if not a number - if (!Number.isInteger(highestNonce)) localNonce = 0 - const pendingCount = this._getPendingTransactionCount(address) - const confirmedCount = confirmedTransactions.length - if ( - // the local nonce is not 0 - localNonce || - // or their are pending or confirmed transactions - pendingCount || - confirmedCount - ) ++localNonce - const nonceDetails = { highestNonce, localNonce, pendingCount, confirmedCount } - return { name: 'local', nonce: localNonce, details: nonceDetails } + let nextNonce + // check our local tx history for the highest nonce (if any) + const highestNonce = this._getLocalHighestNonce(address) + const haveHighestNonce = Number.isInteger(highestNonce) + if (haveHighestNonce) { + // next nonce is the nonce after our last + nextNonce = highestNonce + 1 + } else { + // no local tx history so next must be first (zero) + nextNonce = 0 + } + const nonceDetails = { highestNonce } + return { name: 'local', nonce: nextNonce, details: nonceDetails } } _getLocalPendingNonce (address) { const pendingTransactions = this.getPendingTransactions(address) - const localNonce = this._getHighestNonce(pendingTransactions) - return localNonce + const highestNonce = this._getHighestNonce(pendingTransactions) + return highestNonce + } + + _getLocalConfirmedNonce (address) { + const pendingTransactions = this.getConfirmedTransactions(address) + const highestNonce = this._getHighestNonce(pendingTransactions) + return highestNonce + } + + _getLocalHighestNonce (address) { + const confirmedTransactions = this.getConfirmedTransactions(address) + const pendingTransactions = this.getPendingTransactions(address) + const transactions = confirmedTransactions.concat(pendingTransactions) + const highestNonce = this._getHighestNonce(transactions) + return highestNonce } _getPendingTransactionCount (address) { -- cgit From 6d596bd9e6921b92de62befadebe32b270f2b784 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 22 Aug 2017 14:17:00 -0700 Subject: nonce-tracker - getlocalNextNonce - add entry to nonceDetails --- app/scripts/lib/nonce-tracker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index 0fb245f7b..1c51ef647 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -105,7 +105,7 @@ class NonceTracker { // no local tx history so next must be first (zero) nextNonce = 0 } - const nonceDetails = { highestNonce } + const nonceDetails = { highestNonce, haveHighestNonce } return { name: 'local', nonce: nextNonce, details: nonceDetails } } -- cgit From dc3e8d60ef22b268b4146e28e9dcb262aaa63304 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 22 Aug 2017 14:24:09 -0700 Subject: nonce-tracker - fix var name --- app/scripts/lib/nonce-tracker.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index 1c51ef647..13fdf27eb 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -110,14 +110,14 @@ class NonceTracker { } _getLocalPendingNonce (address) { - const pendingTransactions = this.getPendingTransactions(address) - const highestNonce = this._getHighestNonce(pendingTransactions) + const transactions = this.getPendingTransactions(address) + const highestNonce = this._getHighestNonce(transactions) return highestNonce } _getLocalConfirmedNonce (address) { - const pendingTransactions = this.getConfirmedTransactions(address) - const highestNonce = this._getHighestNonce(pendingTransactions) + const transactions = this.getConfirmedTransactions(address) + const highestNonce = this._getHighestNonce(transactions) return highestNonce } -- cgit From fb2c6cc8acacfbdf134877beb68090a6fc127b94 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 22 Aug 2017 14:33:54 -0700 Subject: nonce-tracker - use ethjs-query --- app/scripts/lib/nonce-tracker.js | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index 13fdf27eb..427c09508 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -1,4 +1,4 @@ -const EthQuery = require('eth-query') +const EthQuery = require('ethjs-query') const assert = require('assert') const Mutex = require('await-semaphore').Mutex @@ -50,15 +50,6 @@ class NonceTracker { }) } - async _getTxCount (address, currentBlock) { - const blockNumber = currentBlock.number - return new Promise((resolve, reject) => { - this.ethQuery.getTransactionCount(address, blockNumber, (err, result) => { - err ? reject(err) : resolve(result) - }) - }) - } - async _globalMutexFree () { const globalMutex = this._lookupMutex('global') const release = await globalMutex.acquire() @@ -86,7 +77,7 @@ class NonceTracker { // and pending count are from the same block const currentBlock = await this._getCurrentBlock() const blockNumber = currentBlock.blockNumber - const baseCountHex = await this._getTxCount(address, currentBlock) + const baseCountHex = await this.ethQuery.getTransactionCount(address, blockNumber) const baseCount = parseInt(baseCountHex, 16) assert(Number.isInteger(baseCount), `nonce-tracker - baseCount is not an integer - got: (${typeof baseCount}) "${baseCount}"`) const nonceDetails = { blockNumber, baseCountHex, baseCount } -- cgit From 0a93b65a3dea32a85a73674fb40ee40257ed18d7 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 22 Aug 2017 15:06:54 -0700 Subject: remove unused code --- app/scripts/lib/nonce-tracker.js | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index 427c09508..03bc3c278 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -34,9 +34,6 @@ class NonceTracker { nonceDetails.network = networkNonceResult.details const nextNonce = Math.max(networkNonceResult.nonce, localNonceResult.nonce) 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 currentPendingNonce = this._getLocalPendingNonce(address) - nonceDetails.currentPendingNonce = currentPendingNonce // return nonce and release cb return { nextNonce, nonceDetails, releaseLock } } @@ -100,18 +97,6 @@ class NonceTracker { return { name: 'local', nonce: nextNonce, details: nonceDetails } } - _getLocalPendingNonce (address) { - const transactions = this.getPendingTransactions(address) - const highestNonce = this._getHighestNonce(transactions) - return highestNonce - } - - _getLocalConfirmedNonce (address) { - const transactions = this.getConfirmedTransactions(address) - const highestNonce = this._getHighestNonce(transactions) - return highestNonce - } - _getLocalHighestNonce (address) { const confirmedTransactions = this.getConfirmedTransactions(address) const pendingTransactions = this.getPendingTransactions(address) -- cgit From 247965ebbe99bd611aaa6b7a5c6e86f33dcdea1d Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 22 Aug 2017 15:34:30 -0700 Subject: nonce-tracker - more debugging numbers for nonceDetails --- app/scripts/lib/nonce-tracker.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index 03bc3c278..30c59fa46 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -84,7 +84,13 @@ class NonceTracker { async _getlocalNextNonce (address) { let nextNonce // check our local tx history for the highest nonce (if any) - const highestNonce = this._getLocalHighestNonce(address) + const confirmedTransactions = this.getConfirmedTransactions(address) + const pendingTransactions = this.getPendingTransactions(address) + const transactions = confirmedTransactions.concat(pendingTransactions) + const highestConfirmedNonce = this._getHighestNonce(confirmedTransactions) + const highestPendingNonce = this._getHighestNonce(pendingTransactions) + const highestNonce = this._getHighestNonce(transactions) + const haveHighestNonce = Number.isInteger(highestNonce) if (haveHighestNonce) { // next nonce is the nonce after our last @@ -93,18 +99,10 @@ class NonceTracker { // no local tx history so next must be first (zero) nextNonce = 0 } - const nonceDetails = { highestNonce, haveHighestNonce } + const nonceDetails = { highestNonce, haveHighestNonce, highestConfirmedNonce, highestPendingNonce } return { name: 'local', nonce: nextNonce, details: nonceDetails } } - _getLocalHighestNonce (address) { - const confirmedTransactions = this.getConfirmedTransactions(address) - const pendingTransactions = this.getPendingTransactions(address) - const transactions = confirmedTransactions.concat(pendingTransactions) - const highestNonce = this._getHighestNonce(transactions) - return highestNonce - } - _getPendingTransactionCount (address) { const pendingTransactions = this.getPendingTransactions(address) return this._reduceTxListToUniqueNonces(pendingTransactions).length -- cgit From df78020c18b725b24e9467a12ee0ff7ac08a7636 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 23 Aug 2017 11:51:10 -0700 Subject: Version 3.9.10 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 293981d70..60eeb2a35 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.9.9", + "version": "3.9.10", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 53e410167b25b8914fa927efc822515d6b22e0ee Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 23 Aug 2017 16:13:33 -0700 Subject: inpage provider - sync rpc - default to null values --- app/scripts/lib/inpage-provider.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index fd032a673..8b36b4433 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -27,7 +27,7 @@ function MetamaskInpageProvider (connectionStream) { ) // ignore phishing warning message (handled elsewhere) - multiStream.ignoreStream('phishing') + multiStream.ignoreStream('phishing') // connect to async provider const asyncProvider = self.asyncProvider = new StreamProvider() @@ -80,7 +80,7 @@ MetamaskInpageProvider.prototype.send = function (payload) { case 'eth_coinbase': // read from localStorage selectedAddress = self.publicConfigStore.getState().selectedAddress - result = selectedAddress + result = selectedAddress || null break case 'eth_uninstallFilter': @@ -90,7 +90,7 @@ MetamaskInpageProvider.prototype.send = function (payload) { case 'net_version': const networkVersion = self.publicConfigStore.getState().networkVersion - result = networkVersion + result = networkVersion || null break // throw not-supported Error -- cgit From 44dc2ba7128704f26bf2a530aa24c2a62b862b75 Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 23 Aug 2017 16:26:55 -0700 Subject: inpage provider - only warn web3 usage once per session --- app/scripts/lib/auto-reload.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/auto-reload.js b/app/scripts/lib/auto-reload.js index 6abce73ea..f3566cff5 100644 --- a/app/scripts/lib/auto-reload.js +++ b/app/scripts/lib/auto-reload.js @@ -2,17 +2,22 @@ module.exports = setupDappAutoReload function setupDappAutoReload (web3, observable) { // export web3 as a global, checking for usage + let hasBeenWarned = false global.web3 = new Proxy(web3, { - get: (_web3, name) => { - // get the time of use - if (name !== '_used') { + get: (_web3, key) => { + // show warning once on web3 access + if (!hasBeenWarned && key !== 'currentProvider') { console.warn('MetaMask: web3 will be deprecated in the near future in favor of the ethereumProvider \nhttps://github.com/ethereum/mist/releases/tag/v0.9.0') + hasBeenWarned = true + } + // get the time of use + if (key !== '_used') { _web3._used = Date.now() } - return _web3[name] + return _web3[key] }, - set: (_web3, name, value) => { - _web3[name] = value + set: (_web3, key, value) => { + _web3[key] = value }, }) var networkVersion -- cgit From 4019f318fe48e85ac7325ac1cb942c230644547c Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 23 Aug 2017 16:44:57 -0700 Subject: inpage provider - autoreload - improve readability --- app/scripts/lib/auto-reload.js | 47 ++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 15 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/auto-reload.js b/app/scripts/lib/auto-reload.js index f3566cff5..62aaf405c 100644 --- a/app/scripts/lib/auto-reload.js +++ b/app/scripts/lib/auto-reload.js @@ -3,6 +3,10 @@ module.exports = setupDappAutoReload function setupDappAutoReload (web3, observable) { // export web3 as a global, checking for usage let hasBeenWarned = false + let reloadInProgress = false + let lastTimeUsed + let lastSeenNetwork + global.web3 = new Proxy(web3, { get: (_web3, key) => { // show warning once on web3 access @@ -11,29 +15,42 @@ function setupDappAutoReload (web3, observable) { hasBeenWarned = true } // get the time of use - if (key !== '_used') { - _web3._used = Date.now() - } + lastTimeUsed = Date.now() + // return value normally return _web3[key] }, set: (_web3, key, value) => { + // set value normally _web3[key] = value }, }) - var networkVersion observable.subscribe(function (state) { - // get the initial network - const curentNetVersion = state.networkVersion - if (!networkVersion) networkVersion = curentNetVersion - - if (curentNetVersion !== networkVersion && web3._used) { - const timeSinceUse = Date.now() - web3._used - // if web3 was recently used then delay the reloading of the page - timeSinceUse > 500 ? triggerReset() : setTimeout(triggerReset, 500) - // prevent reentry into if statement if state updates again before - // reload - networkVersion = curentNetVersion + // if reload in progress, no need to check reload logic + if (reloadInProgress) return + + const currentNetwork = state.networkVersion + + // set the initial network + if (!lastSeenNetwork) { + lastSeenNetwork = currentNetwork + return + } + + // skip reload logic if web3 not used + if (!lastTimeUsed) return + + // if network did not change, exit + if (currentNetwork === lastSeenNetwork) return + + // initiate page reload + reloadInProgress = true + const timeSinceUse = Date.now() - lastTimeUsed + // if web3 was recently used then delay the reloading of the page + if (timeSinceUse > 500) { + triggerReset() + } else { + setTimeout(triggerReset, 500) } }) } -- cgit From 1f0223d0a0b617ffaf1704210b7ed328d12c48d1 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 23 Aug 2017 19:34:20 -0700 Subject: Simplify nonce calculation --- app/scripts/lib/nonce-tracker.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index 30c59fa46..db5a5327f 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -28,9 +28,9 @@ class NonceTracker { const releaseLock = await this._takeMutex(address) // evaluate multiple nextNonce strategies const nonceDetails = {} - const localNonceResult = await this._getlocalNextNonce(address) - nonceDetails.local = localNonceResult.details const networkNonceResult = await this._getNetworkNextNonce(address) + const localNonceResult = await this._getLocalNextNonce(address, networkNonceResult) + nonceDetails.local = localNonceResult.details nonceDetails.network = networkNonceResult.details const nextNonce = Math.max(networkNonceResult.nonce, localNonceResult.nonce) assert(Number.isInteger(nextNonce), `nonce-tracker - nextNonce is not an integer - got: (${typeof nextNonce}) "${nextNonce}"`) @@ -81,15 +81,16 @@ class NonceTracker { return { name: 'network', nonce: baseCount, details: nonceDetails } } - async _getlocalNextNonce (address) { + async _getLocalNextNonce (address, networkNonce) { let nextNonce // check our local tx history for the highest nonce (if any) const confirmedTransactions = this.getConfirmedTransactions(address) const pendingTransactions = this.getPendingTransactions(address) const transactions = confirmedTransactions.concat(pendingTransactions) + const highestConfirmedNonce = this._getHighestNonce(confirmedTransactions) const highestPendingNonce = this._getHighestNonce(pendingTransactions) - const highestNonce = this._getHighestNonce(transactions) + const highestNonce = Math.max(highestConfirmedNonce, highestPendingNonce) const haveHighestNonce = Number.isInteger(highestNonce) if (haveHighestNonce) { -- cgit From c4ab7a57799167904b863b9cb9423885a9c1cc66 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 23 Aug 2017 19:35:49 -0700 Subject: Linted --- app/scripts/lib/nonce-tracker.js | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index db5a5327f..d3c76c230 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -86,7 +86,6 @@ class NonceTracker { // check our local tx history for the highest nonce (if any) const confirmedTransactions = this.getConfirmedTransactions(address) const pendingTransactions = this.getPendingTransactions(address) - const transactions = confirmedTransactions.concat(pendingTransactions) const highestConfirmedNonce = this._getHighestNonce(confirmedTransactions) const highestPendingNonce = this._getHighestNonce(pendingTransactions) -- cgit From 221575a191a0a8b8c4c17465a0530561e1905297 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 23 Aug 2017 20:04:03 -0700 Subject: Fix new test, break an older maybe wrong one --- app/scripts/lib/nonce-tracker.js | 50 +++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 26 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index d3c76c230..4f2473cf5 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -29,11 +29,16 @@ class NonceTracker { // evaluate multiple nextNonce strategies const nonceDetails = {} const networkNonceResult = await this._getNetworkNextNonce(address) - const localNonceResult = await this._getLocalNextNonce(address, networkNonceResult) + const highestLocallyConfirmed = this._getHighestLocallyConfirmed(address) + const highestConfirmed = Math.max(networkNonceResult.nonce, highestLocallyConfirmed) + const pendingTxs = this.getPendingTransactions(address) + const localNonceResult = this._getHighestContinuousFrom(pendingTxs, highestConfirmed) || 0 + nonceDetails.local = localNonceResult.details nonceDetails.network = networkNonceResult.details 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 } } @@ -77,35 +82,14 @@ class NonceTracker { const baseCountHex = await this.ethQuery.getTransactionCount(address, blockNumber) const baseCount = parseInt(baseCountHex, 16) assert(Number.isInteger(baseCount), `nonce-tracker - baseCount is not an integer - got: (${typeof baseCount}) "${baseCount}"`) - const nonceDetails = { blockNumber, baseCountHex, baseCount } + const nonceDetails = { blockNumber, baseCount } return { name: 'network', nonce: baseCount, details: nonceDetails } } - async _getLocalNextNonce (address, networkNonce) { - let nextNonce - // check our local tx history for the highest nonce (if any) + _getHighestLocallyConfirmed (address) { const confirmedTransactions = this.getConfirmedTransactions(address) - const pendingTransactions = this.getPendingTransactions(address) - - const highestConfirmedNonce = this._getHighestNonce(confirmedTransactions) - const highestPendingNonce = this._getHighestNonce(pendingTransactions) - const highestNonce = Math.max(highestConfirmedNonce, highestPendingNonce) - - const haveHighestNonce = Number.isInteger(highestNonce) - if (haveHighestNonce) { - // next nonce is the nonce after our last - nextNonce = highestNonce + 1 - } else { - // no local tx history so next must be first (zero) - nextNonce = 0 - } - const nonceDetails = { highestNonce, haveHighestNonce, highestConfirmedNonce, highestPendingNonce } - return { name: 'local', nonce: nextNonce, details: nonceDetails } - } - - _getPendingTransactionCount (address) { - const pendingTransactions = this.getPendingTransactions(address) - return this._reduceTxListToUniqueNonces(pendingTransactions).length + const highest = this._getHighestNonce(confirmedTransactions) + return highest } _reduceTxListToUniqueNonces (txList) { @@ -127,6 +111,20 @@ class NonceTracker { return highestNonce } + _getHighestContinuousFrom (txList, startPoint) { + const nonces = txList.map((txMeta) => parseInt(txMeta.txParams.nonce, 16)) + + let highest = startPoint + while (nonces.includes(highest + 1)) { + highest++ + } + + const haveHighestNonce = Number.isInteger(highest) && highest > 0 + const nonce = haveHighestNonce ? highest + 1 : 0 + + return { name: 'local', nonce } + } + // this is a hotfix for the fact that the blockTracker will // change when the network changes _getBlockTracker () { -- cgit From 04d40b114dd12237710f605fe2f0a5f2c337d2cb Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 23 Aug 2017 20:11:37 -0700 Subject: Got all tests but one passing --- app/scripts/lib/nonce-tracker.js | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index 4f2473cf5..6fcd716f2 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -30,6 +30,7 @@ class NonceTracker { const nonceDetails = {} const networkNonceResult = await this._getNetworkNextNonce(address) const highestLocallyConfirmed = this._getHighestLocallyConfirmed(address) + const highestConfirmed = Math.max(networkNonceResult.nonce, highestLocallyConfirmed) const pendingTxs = this.getPendingTransactions(address) const localNonceResult = this._getHighestContinuousFrom(pendingTxs, highestConfirmed) || 0 -- cgit From 855f4eeacbcf7b3e056cf7956edea2c84fa256d5 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 23 Aug 2017 20:31:03 -0700 Subject: Pass nonce tests --- app/scripts/lib/nonce-tracker.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index 6fcd716f2..8c2568c3f 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -30,10 +30,12 @@ class NonceTracker { const nonceDetails = {} const networkNonceResult = await this._getNetworkNextNonce(address) const highestLocallyConfirmed = this._getHighestLocallyConfirmed(address) + const nextNetworkNonce = networkNonceResult.nonce + const highestLocalNonce = highestLocallyConfirmed + const highestSuggested = Math.max(nextNetworkNonce, highestLocalNonce) - const highestConfirmed = Math.max(networkNonceResult.nonce, highestLocallyConfirmed) const pendingTxs = this.getPendingTransactions(address) - const localNonceResult = this._getHighestContinuousFrom(pendingTxs, highestConfirmed) || 0 + const localNonceResult = this._getHighestContinuousFrom(pendingTxs, highestSuggested) || 0 nonceDetails.local = localNonceResult.details nonceDetails.network = networkNonceResult.details @@ -90,7 +92,7 @@ class NonceTracker { _getHighestLocallyConfirmed (address) { const confirmedTransactions = this.getConfirmedTransactions(address) const highest = this._getHighestNonce(confirmedTransactions) - return highest + return Number.isInteger(highest) ? highest + 1 : 0 } _reduceTxListToUniqueNonces (txList) { @@ -116,14 +118,11 @@ class NonceTracker { const nonces = txList.map((txMeta) => parseInt(txMeta.txParams.nonce, 16)) let highest = startPoint - while (nonces.includes(highest + 1)) { + while (nonces.includes(highest)) { highest++ } - const haveHighestNonce = Number.isInteger(highest) && highest > 0 - const nonce = haveHighestNonce ? highest + 1 : 0 - - return { name: 'local', nonce } + return { name: 'local', nonce: highest, details: { startPoint, highest } } } // this is a hotfix for the fact that the blockTracker will -- cgit From 55c1a259b1ac01e8a8f6b241bac7a3b1cd16f3ec Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 23 Aug 2017 21:14:46 -0700 Subject: Fix network nonce parsing --- app/scripts/lib/nonce-tracker.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index 8c2568c3f..d49c7f205 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -37,8 +37,14 @@ class NonceTracker { const pendingTxs = this.getPendingTransactions(address) const localNonceResult = this._getHighestContinuousFrom(pendingTxs, highestSuggested) || 0 - nonceDetails.local = localNonceResult.details - nonceDetails.network = networkNonceResult.details + nonceDetails.params = { + highestLocalNonce, + 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}"`) @@ -82,8 +88,9 @@ class NonceTracker { // and pending count are from the same block const currentBlock = await this._getCurrentBlock() const blockNumber = currentBlock.blockNumber - const baseCountHex = await this.ethQuery.getTransactionCount(address, blockNumber) - const baseCount = parseInt(baseCountHex, 16) + const baseCountBN = await this.ethQuery.getTransactionCount(address, blockNumber) + const baseString = baseCountBN.toString() + const baseCount = parseInt(baseString) assert(Number.isInteger(baseCount), `nonce-tracker - baseCount is not an integer - got: (${typeof baseCount}) "${baseCount}"`) const nonceDetails = { blockNumber, baseCount } return { name: 'network', nonce: baseCount, details: nonceDetails } -- cgit From a122ec1f8ba0935d26a45ce0b26be991d222aaad Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 23 Aug 2017 21:37:07 -0700 Subject: Use toNumber method --- app/scripts/lib/nonce-tracker.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index d49c7f205..e0e065d82 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -89,8 +89,7 @@ class NonceTracker { const currentBlock = await this._getCurrentBlock() const blockNumber = currentBlock.blockNumber const baseCountBN = await this.ethQuery.getTransactionCount(address, blockNumber) - const baseString = baseCountBN.toString() - const baseCount = parseInt(baseString) + const baseCount = baseCountBN.toNumber() assert(Number.isInteger(baseCount), `nonce-tracker - baseCount is not an integer - got: (${typeof baseCount}) "${baseCount}"`) const nonceDetails = { blockNumber, baseCount } return { name: 'network', nonce: baseCount, details: nonceDetails } -- cgit From c620123fab9e1eac8d3038204c9cfb04ca85afb1 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 23 Aug 2017 21:50:28 -0700 Subject: Enforce nonces as type string --- app/scripts/lib/nonce-tracker.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index e0e065d82..08f1e1e86 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -115,13 +115,21 @@ class NonceTracker { } _getHighestNonce (txList) { - const nonces = txList.map((txMeta) => parseInt(txMeta.txParams.nonce, 16)) + const nonces = txList.map((txMeta) => { + const nonce = txMeta.txParams.nonce + assert(typeof nonce, 'string', 'nonces should be hex strings') + return parseInt(nonce, 16) + }) const highestNonce = Math.max.apply(null, nonces) return highestNonce } _getHighestContinuousFrom (txList, startPoint) { - const nonces = txList.map((txMeta) => parseInt(txMeta.txParams.nonce, 16)) + const nonces = txList.map((txMeta) => { + const nonce = txMeta.txParams.nonce + assert(typeof nonce, 'string', 'nonces should be hex strings') + return parseInt(nonce, 16) + }) let highest = startPoint while (nonces.includes(highest)) { -- cgit From 0ad310e096fe8c13553dc40f65363d296a7e84ce Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 23 Aug 2017 22:29:08 -0700 Subject: Fail transactions after a day of retries --- app/scripts/controllers/transactions.js | 6 +++++- app/scripts/lib/pending-tx-tracker.js | 8 +++++++- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 6f49c9633..fb3be6073 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -40,6 +40,10 @@ module.exports = class TransactionController extends EventEmitter { err: undefined, }) }, + giveUpOnTransaction: (txId) => { + const msg = `Gave up submitting after 3500 blocks un-mined.` + this.setTxStatusFailed(txId, msg) + }, }) this.query = new EthQuery(this.provider) this.txProviderUtil = new TxProviderUtil(this.provider) @@ -451,4 +455,4 @@ module.exports = class TransactionController extends EventEmitter { }) this.memStore.updateState({ unapprovedTxs, selectedAddressTxList }) } -} \ No newline at end of file +} diff --git a/app/scripts/lib/pending-tx-tracker.js b/app/scripts/lib/pending-tx-tracker.js index 19720db3f..b90851b58 100644 --- a/app/scripts/lib/pending-tx-tracker.js +++ b/app/scripts/lib/pending-tx-tracker.js @@ -1,6 +1,7 @@ const EventEmitter = require('events') const EthQuery = require('ethjs-query') const sufficientBalance = require('./util').sufficientBalance +const RETRY_LIMIT = 3500 // Retry 3500 blocks, or about 1 day. /* Utility class for tracking the transactions as they @@ -28,6 +29,7 @@ module.exports = class PendingTransactionTracker extends EventEmitter { this.getBalance = config.getBalance this.getPendingTransactions = config.getPendingTransactions this.publishTransaction = config.publishTransaction + this.giveUpOnTransaction = config.giveUpOnTransaction } // checks if a signed tx is in a block and @@ -100,6 +102,10 @@ module.exports = class PendingTransactionTracker extends EventEmitter { if (balance === undefined) return if (!('retryCount' in txMeta)) txMeta.retryCount = 0 + if (txMeta.retryCount > RETRY_LIMIT) { + return this.giveUpOnTransaction(txMeta.id) + } + // if the value of the transaction is greater then the balance, fail. if (!sufficientBalance(txMeta.txParams, balance)) { const insufficientFundsError = new Error('Insufficient balance during rebroadcast.') @@ -160,4 +166,4 @@ module.exports = class PendingTransactionTracker extends EventEmitter { } nonceGlobalLock.releaseLock() } -} \ No newline at end of file +} -- cgit From dadee1ed79715c7dcdfe1d208e2bd554a1d4da8b Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 23 Aug 2017 22:48:19 -0700 Subject: hotfix - fail submitted txs whos nonce is out of bound --- app/scripts/migrations/019.js | 60 +++++++++++++++++++++++++++++++++++++++++ app/scripts/migrations/index.js | 1 + 2 files changed, 61 insertions(+) create mode 100644 app/scripts/migrations/019.js (limited to 'app') diff --git a/app/scripts/migrations/019.js b/app/scripts/migrations/019.js new file mode 100644 index 000000000..e6e8f1f01 --- /dev/null +++ b/app/scripts/migrations/019.js @@ -0,0 +1,60 @@ + +const version = 19 + +/* + +This migration sets transactions with the 'Gave up submitting tx.' err message +to a 'failed' stated + +*/ + +const clone = require('clone') + +module.exports = { + version, + + migrate: function (originalVersionedData) { + const versionedData = clone(originalVersionedData) + versionedData.meta.version = version + try { + const state = versionedData.data + const newState = transformState(state) + versionedData.data = newState + } catch (err) { + console.warn(`MetaMask Migration #${version}` + err.stack) + } + return Promise.resolve(versionedData) + }, +} + +function transformState (state) { + const newState = state + const transactions = newState.TransactionController.transactions + newState.TransactionController.transactions = transactions.map((txMeta, _, txList) => { + if (txMeta.status !== 'submitted') return txMeta + + const confirmedTxs = txList.filter((tx) => tx.status === 'confirmed') + .filter((tx) => tx.txParams.from === txMeta.txParams.from) + .filter((tx) => tx.metamaskNetworkId.from === txMeta.metamaskNetworkId.from) + const highestConfirmedNonce = getHighestNonce(confirmedTxs) + + if (parseInt(txMeta.txParams.nonce, 16) > highestConfirmedNonce + 1) { + txMeta.status = 'failed' + txMeta.err = { + message: 'nonce too high', + note: 'migration 019 custom error', + } + } + return txMeta + }) + return newState +} + +function getHighestNonce (txList) { + const nonces = txList.map((txMeta) => { + const nonce = txMeta.txParams.nonce + return parseInt(nonce || '0x0', 16) + }) + const highestNonce = Math.max.apply(null, nonces) + return highestNonce +} diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index 6bfc622f7..e9cbd7b98 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -29,4 +29,5 @@ module.exports = [ require('./016'), require('./017'), require('./018'), + require('./019'), ] -- cgit From f42687d25f844efd3be915e077cddcb4ccd458cf Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 23 Aug 2017 22:53:29 -0700 Subject: fix description --- app/scripts/migrations/019.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/migrations/019.js b/app/scripts/migrations/019.js index e6e8f1f01..9dfe96050 100644 --- a/app/scripts/migrations/019.js +++ b/app/scripts/migrations/019.js @@ -3,8 +3,8 @@ const version = 19 /* -This migration sets transactions with the 'Gave up submitting tx.' err message -to a 'failed' stated +This migration sets transactions as failed +whos nonce is too high */ -- cgit From 17a71a9b4cb5cc23cbedfc52ba35c562dffdc02e Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 23 Aug 2017 23:09:57 -0700 Subject: Only cancel pending txs with non continuously high nonces --- app/scripts/migrations/019.js | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/migrations/019.js b/app/scripts/migrations/019.js index 9dfe96050..d41b39d1c 100644 --- a/app/scripts/migrations/019.js +++ b/app/scripts/migrations/019.js @@ -30,6 +30,7 @@ module.exports = { function transformState (state) { const newState = state const transactions = newState.TransactionController.transactions + newState.TransactionController.transactions = transactions.map((txMeta, _, txList) => { if (txMeta.status !== 'submitted') return txMeta @@ -38,7 +39,14 @@ function transformState (state) { .filter((tx) => tx.metamaskNetworkId.from === txMeta.metamaskNetworkId.from) const highestConfirmedNonce = getHighestNonce(confirmedTxs) - if (parseInt(txMeta.txParams.nonce, 16) > highestConfirmedNonce + 1) { + const pendingTxs = txList.filter((tx) => tx.status === 'submitted') + .filter((tx) => tx.txParams.from === txMeta.txParams.from) + .filter((tx) => tx.metamaskNetworkId.from === txMeta.metamaskNetworkId.from) + const highestContinuousNonce = getHighestContinuousFrom(pendingTxs, highestConfirmedNonce) + + const maxNonce = Math.max(highestContinuousNonce, highestConfirmedNonce) + + if (parseInt(txMeta.txParams.nonce, 16) > maxNonce + 1) { txMeta.status = 'failed' txMeta.err = { message: 'nonce too high', @@ -50,6 +58,20 @@ function transformState (state) { return newState } +function getHighestContinuousFrom (txList, startPoint) { + const nonces = txList.map((txMeta) => { + const nonce = txMeta.txParams.nonce + return parseInt(nonce, 16) + }) + + let highest = startPoint + while (nonces.includes(highest)) { + highest++ + } + + return { name: 'local', nonce: highest, details: { startPoint, highest } } +} + function getHighestNonce (txList) { const nonces = txList.map((txMeta) => { const nonce = txMeta.txParams.nonce @@ -58,3 +80,4 @@ function getHighestNonce (txList) { const highestNonce = Math.max.apply(null, nonces) return highestNonce } + -- cgit From 803e696cdc2a2f60d6097f1ff1efa8202d8e4320 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 23 Aug 2017 23:24:01 -0700 Subject: Make method return a number --- app/scripts/migrations/019.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/migrations/019.js b/app/scripts/migrations/019.js index d41b39d1c..072c96370 100644 --- a/app/scripts/migrations/019.js +++ b/app/scripts/migrations/019.js @@ -69,7 +69,7 @@ function getHighestContinuousFrom (txList, startPoint) { highest++ } - return { name: 'local', nonce: highest, details: { startPoint, highest } } + return highest } function getHighestNonce (txList) { -- cgit From c2624dd1a071ea4388df23400f4319e863d061c6 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Thu, 24 Aug 2017 00:02:06 -0700 Subject: fall back to `latest` if blockNumber is null --- app/scripts/lib/nonce-tracker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index 08f1e1e86..0029ac953 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -88,7 +88,7 @@ class NonceTracker { // and pending count are from the same block const currentBlock = await this._getCurrentBlock() const blockNumber = currentBlock.blockNumber - const baseCountBN = await this.ethQuery.getTransactionCount(address, blockNumber) + const baseCountBN = await this.ethQuery.getTransactionCount(address, blockNumber || 'latest') const baseCount = baseCountBN.toNumber() assert(Number.isInteger(baseCount), `nonce-tracker - baseCount is not an integer - got: (${typeof baseCount}) "${baseCount}"`) const nonceDetails = { blockNumber, baseCount } -- cgit From 72bccec440179d8126391d9e249e9f3acbbb5a88 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 24 Aug 2017 00:16:19 -0700 Subject: Version 3.9.11 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 60eeb2a35..7ec32ea78 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.9.10", + "version": "3.9.11", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From cc56d0d2f61da576acc72b1e7f63df4015469267 Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 24 Aug 2017 15:44:40 -0700 Subject: inpage - use json-rpc-engine for inpage-provider --- app/scripts/lib/inpage-provider.js | 46 +++++++++----------------------------- app/scripts/metamask-controller.js | 42 +++++++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 46 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index fd032a673..de6e8b811 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -1,8 +1,8 @@ const pipe = require('pump') -const StreamProvider = require('web3-stream-provider') +const RpcEngine = require('json-rpc-engine') +const createStreamMiddleware = require('json-rpc-middleware-stream') const LocalStorageStore = require('obs-store') const ObjectMultiplex = require('./obj-multiplex') -const createRandomId = require('./random-id') module.exports = MetamaskInpageProvider @@ -30,38 +30,20 @@ function MetamaskInpageProvider (connectionStream) { multiStream.ignoreStream('phishing') // connect to async provider - const asyncProvider = self.asyncProvider = new StreamProvider() + const streamMiddleware = createStreamMiddleware() pipe( - asyncProvider, + streamMiddleware.stream, multiStream.createStream('provider'), - asyncProvider, + streamMiddleware.stream, (err) => logStreamDisconnectWarning('MetaMask RpcProvider', err) ) // start and stop polling to unblock first block lock - self.idMap = {} - // handle sendAsync requests via asyncProvider - self.sendAsync = function (payload, cb) { - // rewrite request ids - var request = eachJsonMessage(payload, (message) => { - var newId = createRandomId() - self.idMap[newId] = message.id - message.id = newId - return message - }) - // forward to asyncProvider - asyncProvider.sendAsync(request, function (err, res) { - if (err) return cb(err) - // transform messages to original ids - eachJsonMessage(res, (message) => { - var oldId = self.idMap[message.id] - delete self.idMap[message.id] - message.id = oldId - return message - }) - cb(null, res) - }) - } + // handle sendAsync requests via dapp-side rpc engine + const engine = new RpcEngine() + engine.push(streamMiddleware) + + self.sendAsync = engine.handle.bind(engine) } MetamaskInpageProvider.prototype.send = function (payload) { @@ -121,14 +103,6 @@ MetamaskInpageProvider.prototype.isMetaMask = true // util -function eachJsonMessage (payload, transformFn) { - if (Array.isArray(payload)) { - return payload.map(transformFn) - } else { - return transformFn(payload) - } -} - function logStreamDisconnectWarning (remoteLabel, err) { let warningMsg = `MetamaskInpageProvider - lost connection to ${remoteLabel}` if (err) warningMsg += '\n' + err.stack diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index a007d6fc5..e4b1b5975 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -6,7 +6,8 @@ const Dnode = require('dnode') const ObservableStore = require('obs-store') const EthStore = require('./lib/eth-store') const EthQuery = require('eth-query') -const streamIntoProvider = require('web3-stream-provider/handler') +const RpcEngine = require('json-rpc-engine') +const createEngineStream = require('json-rpc-middleware-stream/engineStream') const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex const KeyringController = require('./keyring-controller') const NetworkController = require('./controllers/network') @@ -375,19 +376,40 @@ module.exports = class MetamaskController extends EventEmitter { } setupProviderConnection (outStream, originDomain) { - streamIntoProvider(outStream, this.provider, onRequest, onResponse) + const engine = new RpcEngine() + engine.push(originMiddleware) + engine.push(loggerMiddleware) + engine.push(createProviderMiddleware({ provider: this.provider })) + + // setup connection + const providerStream = createEngineStream({ engine }) + outStream.pipe(providerStream).pipe(outStream) + // append dapp origin domain to request - function onRequest (request) { - request.origin = originDomain + function originMiddleware (req, res, next, end) { + req.origin = originDomain + next() } // log rpc activity - function onResponse (err, request, response) { - if (err) return console.error(err) - if (response.error) { - console.error('Error in RPC response:\n', response) + function loggerMiddleware (req, res, next, end) { + next((cb) => { + if (res.error) { + console.error('Error in RPC response:\n', res) + } + if (req.isMetamaskInternal) return + log.info(`RPC (${originDomain}):`, req, '->', res) + cb() + }) + } + // forward requests to provider + function createProviderMiddleware({ provider }) { + return (req, res, next, end) => { + provider.sendAsync(req, (err, _res) => { + if (err) return end(err) + res.result = _res.result + end() + }) } - if (request.isMetamaskInternal) return - log.info(`RPC (${originDomain}):`, request, '->', response) } } -- cgit From e294aa7e0dd4c773c7724f0fb152cfafece431fe Mon Sep 17 00:00:00 2001 From: kumavis Date: Mon, 28 Aug 2017 10:41:01 -0700 Subject: inpage - lint fix --- app/scripts/lib/inpage-provider.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index 8b36b4433..7c74a62d3 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -90,7 +90,7 @@ MetamaskInpageProvider.prototype.send = function (payload) { case 'net_version': const networkVersion = self.publicConfigStore.getState().networkVersion - result = networkVersion || null + result = networkVersion || null break // throw not-supported Error -- cgit From 70a61f8712db89687db5df99275a71e018d1e430 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 5 Sep 2017 11:35:33 -0700 Subject: Make web3 deprecation notice more useful Linking to a descriptive & precriptive article on a path forward. --- app/scripts/lib/auto-reload.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/auto-reload.js b/app/scripts/lib/auto-reload.js index 62aaf405c..cce31c3d2 100644 --- a/app/scripts/lib/auto-reload.js +++ b/app/scripts/lib/auto-reload.js @@ -11,7 +11,7 @@ function setupDappAutoReload (web3, observable) { get: (_web3, key) => { // show warning once on web3 access if (!hasBeenWarned && key !== 'currentProvider') { - console.warn('MetaMask: web3 will be deprecated in the near future in favor of the ethereumProvider \nhttps://github.com/ethereum/mist/releases/tag/v0.9.0') + console.warn('MetaMask: web3 will be deprecated in the near future in favor of the ethereumProvider \nhttps://github.com/MetaMask/faq/blob/master/detecting_metamask.md#web3-deprecation') hasBeenWarned = true } // get the time of use -- cgit From ea7e46ed3843b2d38fe04efa232dc8f5cddb6186 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 5 Sep 2017 16:46:21 -0700 Subject: inpage - bug fix prevents mutation of original message object which causes problems with web3 1.0 --- app/scripts/lib/inpage-provider.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index 7c74a62d3..c63af06dc 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -43,8 +43,9 @@ function MetamaskInpageProvider (connectionStream) { // handle sendAsync requests via asyncProvider self.sendAsync = function (payload, cb) { // rewrite request ids - var request = eachJsonMessage(payload, (message) => { - var newId = createRandomId() + var request = eachJsonMessage(payload, (_message) => { + const message = Object.assign({}, _message) + const newId = createRandomId() self.idMap[newId] = message.id message.id = newId return message -- cgit From 5e934994d1f1fdfd97da9ef1cbbce52e3583cc33 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 6 Sep 2017 13:33:30 -0700 Subject: Version 3.9.12 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 7ec32ea78..256737c89 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.9.11", + "version": "3.9.12", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From b5f48730cd2c024997d30fa272ab08ba7f686893 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 6 Sep 2017 13:59:41 -0700 Subject: Properly update keyring state on new account addition. --- app/scripts/keyring-controller.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 2edc8060e..fd57fac70 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -171,9 +171,9 @@ class KeyringController extends EventEmitter { return this.setupAccounts(checkedAccounts) }) .then(() => this.persistAllKeyrings()) + .then(() => this._updateMemStoreKeyrings()) .then(() => this.fullUpdate()) .then(() => { - this._updateMemStoreKeyrings() return keyring }) } @@ -208,6 +208,7 @@ class KeyringController extends EventEmitter { return selectedKeyring.addAccounts(1) .then(this.setupAccounts.bind(this)) .then(this.persistAllKeyrings.bind(this)) + .then(this._updateMemStoreKeyrings.bind(this)) .then(this.fullUpdate.bind(this)) } -- cgit From 440a42bbc38ed53b64dc017fd56bd3281355df33 Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 7 Sep 2017 10:08:07 -0700 Subject: inpage - add idRemapMiddleware --- app/scripts/lib/inpage-provider.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index de6e8b811..c095846e1 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -1,5 +1,6 @@ const pipe = require('pump') const RpcEngine = require('json-rpc-engine') +const createIdRemapMiddleware = require('json-rpc-engine/src/idRemapMiddleware') const createStreamMiddleware = require('json-rpc-middleware-stream') const LocalStorageStore = require('obs-store') const ObjectMultiplex = require('./obj-multiplex') @@ -27,7 +28,7 @@ function MetamaskInpageProvider (connectionStream) { ) // ignore phishing warning message (handled elsewhere) - multiStream.ignoreStream('phishing') + multiStream.ignoreStream('phishing') // connect to async provider const streamMiddleware = createStreamMiddleware() @@ -41,6 +42,7 @@ function MetamaskInpageProvider (connectionStream) { // handle sendAsync requests via dapp-side rpc engine const engine = new RpcEngine() + engine.push(createIdRemapMiddleware()) engine.push(streamMiddleware) self.sendAsync = engine.handle.bind(engine) -- cgit From b7e24dcda7d67d0504ceb463ab1c1c1d77450bca Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Thu, 7 Sep 2017 18:17:43 -0700 Subject: Remove cryptonator from chrome permissions. --- app/manifest.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 256737c89..96d495178 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -57,9 +57,8 @@ "permissions": [ "storage", "clipboardWrite", - "http://localhost:8545/", - "https://api.cryptonator.com/" - ], + "http://localhost:8545/" + ], "web_accessible_resources": [ "scripts/inpage.js" ], -- cgit From 57e4805c621155cd86169064f4aaba34b73644c6 Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 7 Sep 2017 21:17:49 -0700 Subject: streams - use pump and published obj-multiplex --- app/scripts/lib/obj-multiplex.js | 48 -------------------------------------- app/scripts/lib/port-stream.js | 16 ++----------- app/scripts/lib/stream-utils.js | 23 +++++++++--------- app/scripts/metamask-controller.js | 34 +++++++++++++++++++++------ 4 files changed, 41 insertions(+), 80 deletions(-) delete mode 100644 app/scripts/lib/obj-multiplex.js (limited to 'app') diff --git a/app/scripts/lib/obj-multiplex.js b/app/scripts/lib/obj-multiplex.js deleted file mode 100644 index 0034febe0..000000000 --- a/app/scripts/lib/obj-multiplex.js +++ /dev/null @@ -1,48 +0,0 @@ -const through = require('through2') - -module.exports = ObjectMultiplex - -function ObjectMultiplex (opts) { - opts = opts || {} - // create multiplexer - const mx = through.obj(function (chunk, enc, cb) { - const name = chunk.name - const data = chunk.data - if (!name) { - console.warn(`ObjectMultiplex - Malformed chunk without name "${chunk}"`) - return cb() - } - const substream = mx.streams[name] - if (!substream) { - console.warn(`ObjectMultiplex - orphaned data for stream "${name}"`) - } else { - if (substream.push) substream.push(data) - } - return cb() - }) - mx.streams = {} - // create substreams - mx.createStream = function (name) { - const substream = mx.streams[name] = through.obj(function (chunk, enc, cb) { - mx.push({ - name: name, - data: chunk, - }) - return cb() - }) - mx.on('end', function () { - return substream.emit('end') - }) - if (opts.error) { - mx.on('error', function () { - return substream.emit('error') - }) - } - return substream - } - // ignore streams (dont display orphaned data warning) - mx.ignoreStream = function (name) { - mx.streams[name] = true - } - return mx -} diff --git a/app/scripts/lib/port-stream.js b/app/scripts/lib/port-stream.js index 607a9c9ed..648d88087 100644 --- a/app/scripts/lib/port-stream.js +++ b/app/scripts/lib/port-stream.js @@ -1,5 +1,6 @@ const Duplex = require('readable-stream').Duplex const inherits = require('util').inherits +const noop = function(){} module.exports = PortDuplexStream @@ -20,20 +21,14 @@ PortDuplexStream.prototype._onMessage = function (msg) { if (Buffer.isBuffer(msg)) { delete msg._isBuffer var data = new Buffer(msg) - // console.log('PortDuplexStream - saw message as buffer', data) this.push(data) } else { - // console.log('PortDuplexStream - saw message', msg) this.push(msg) } } PortDuplexStream.prototype._onDisconnect = function () { - try { - this.push(null) - } catch (err) { - this.emit('error', err) - } + this.destroy() } // stream plumbing @@ -45,19 +40,12 @@ PortDuplexStream.prototype._write = function (msg, encoding, cb) { if (Buffer.isBuffer(msg)) { var data = msg.toJSON() data._isBuffer = true - // console.log('PortDuplexStream - sent message as buffer', data) this._port.postMessage(data) } else { - // console.log('PortDuplexStream - sent message', msg) this._port.postMessage(msg) } } catch (err) { - // console.error(err) return cb(new Error('PortDuplexStream - disconnected')) } cb() } - -// util - -function noop () {} diff --git a/app/scripts/lib/stream-utils.js b/app/scripts/lib/stream-utils.js index ba79990cc..89e2a359e 100644 --- a/app/scripts/lib/stream-utils.js +++ b/app/scripts/lib/stream-utils.js @@ -1,6 +1,7 @@ const Through = require('through2') const endOfStream = require('end-of-stream') -const ObjectMultiplex = require('./obj-multiplex') +const ObjectMultiplex = require('obj-multiplex') +const pump = require('pump') module.exports = { jsonParseStream: jsonParseStream, @@ -23,14 +24,14 @@ function jsonStringifyStream () { } function setupMultiplex (connectionStream) { - var mx = ObjectMultiplex() - connectionStream.pipe(mx).pipe(connectionStream) - endOfStream(mx, function (err) { - if (err) console.error(err) - }) - endOfStream(connectionStream, function (err) { - if (err) console.error(err) - mx.destroy() - }) - return mx + const mux = new ObjectMultiplex() + pump( + connectionStream, + mux, + connectionStream, + (err) => { + if (err) console.error(err) + } + ) + return mux } diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index e4b1b5975..1a6732338 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -1,7 +1,7 @@ const EventEmitter = require('events') const extend = require('xtend') const promiseToCallback = require('promise-to-callback') -const pipe = require('pump') +const pump = require('pump') const Dnode = require('dnode') const ObservableStore = require('obs-store') const EthStore = require('./lib/eth-store') @@ -367,7 +367,14 @@ module.exports = class MetamaskController extends EventEmitter { setupControllerConnection (outStream) { const api = this.getApi() const dnode = Dnode(api) - outStream.pipe(dnode).pipe(outStream) + pump( + outStream, + dnode, + outStream, + (err) => { + if (err) console.error(err) + } + ) dnode.on('remote', (remote) => { // push updates to popup const sendUpdate = remote.sendUpdate.bind(remote) @@ -376,20 +383,29 @@ module.exports = class MetamaskController extends EventEmitter { } setupProviderConnection (outStream, originDomain) { + // setup json rpc engine stack const engine = new RpcEngine() engine.push(originMiddleware) engine.push(loggerMiddleware) engine.push(createProviderMiddleware({ provider: this.provider })) - + // setup connection const providerStream = createEngineStream({ engine }) - outStream.pipe(providerStream).pipe(outStream) - + pump( + outStream, + providerStream, + outStream, + (err) => { + if (err) console.error(err) + } + ) + // append dapp origin domain to request function originMiddleware (req, res, next, end) { req.origin = originDomain next() } + // log rpc activity function loggerMiddleware (req, res, next, end) { next((cb) => { @@ -401,6 +417,7 @@ module.exports = class MetamaskController extends EventEmitter { cb() }) } + // forward requests to provider function createProviderMiddleware({ provider }) { return (req, res, next, end) => { @@ -414,9 +431,12 @@ module.exports = class MetamaskController extends EventEmitter { } setupPublicConfig (outStream) { - pipe( + pump( this.publicConfigStore, - outStream + outStream, + (err) => { + if (err) console.error(err) + } ) } -- cgit From 0e8e655fdb9b65df151f23ede74807025226ab66 Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 7 Sep 2017 21:19:24 -0700 Subject: inpage - distinguish pump vs pipe --- app/scripts/lib/inpage-provider.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index c095846e1..eb24dfcab 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -1,4 +1,4 @@ -const pipe = require('pump') +const pump = require('pump') const RpcEngine = require('json-rpc-engine') const createIdRemapMiddleware = require('json-rpc-engine/src/idRemapMiddleware') const createStreamMiddleware = require('json-rpc-middleware-stream') @@ -12,7 +12,7 @@ function MetamaskInpageProvider (connectionStream) { // setup connectionStream multiplexing var multiStream = self.multiStream = ObjectMultiplex() - pipe( + pump( connectionStream, multiStream, connectionStream, @@ -21,7 +21,7 @@ function MetamaskInpageProvider (connectionStream) { // subscribe to metamask public config (one-way) self.publicConfigStore = new LocalStorageStore({ storageKey: 'MetaMask-Config' }) - pipe( + pump( multiStream.createStream('publicConfig'), self.publicConfigStore, (err) => logStreamDisconnectWarning('MetaMask PublicConfigStore', err) @@ -32,7 +32,7 @@ function MetamaskInpageProvider (connectionStream) { // connect to async provider const streamMiddleware = createStreamMiddleware() - pipe( + pump( streamMiddleware.stream, multiStream.createStream('provider'), streamMiddleware.stream, -- cgit From 9d4c02e57f2b147759d979d8a6c051aa008cdff0 Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 7 Sep 2017 21:26:25 -0700 Subject: metamask - add jsonrpc filter middleware on per-connection engine --- app/scripts/metamask-controller.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 1a6732338..735fc4af0 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -8,6 +8,7 @@ const EthStore = require('./lib/eth-store') const EthQuery = require('eth-query') const RpcEngine = require('json-rpc-engine') const createEngineStream = require('json-rpc-middleware-stream/engineStream') +const createFilterMiddleware = require('eth-json-rpc-filters') const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex const KeyringController = require('./keyring-controller') const NetworkController = require('./controllers/network') @@ -78,12 +79,13 @@ module.exports = class MetamaskController extends EventEmitter { // rpc provider this.provider = this.initializeProvider() + this.blockTracker = this.provider // eth data query tools this.ethQuery = new EthQuery(this.provider) this.ethStore = new EthStore({ provider: this.provider, - blockTracker: this.provider, + blockTracker: this.blockTracker, }) // key mgmt @@ -110,7 +112,7 @@ module.exports = class MetamaskController extends EventEmitter { getNetwork: this.networkController.getNetworkState.bind(this), signTransaction: this.keyringController.signTransaction.bind(this.keyringController), provider: this.provider, - blockTracker: this.provider, + blockTracker: this.blockTracker, ethQuery: this.ethQuery, ethStore: this.ethStore, }) @@ -387,6 +389,10 @@ module.exports = class MetamaskController extends EventEmitter { const engine = new RpcEngine() engine.push(originMiddleware) engine.push(loggerMiddleware) + engine.push(createFilterMiddleware({ + provider: this.provider, + blockTracker: this.blockTracker, + })) engine.push(createProviderMiddleware({ provider: this.provider })) // setup connection -- cgit From 70401626e2544f254ddb06a21b5d3de7fdd7fb82 Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 7 Sep 2017 22:35:38 -0700 Subject: lint - remove dead code --- app/scripts/lib/stream-utils.js | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/stream-utils.js b/app/scripts/lib/stream-utils.js index 89e2a359e..8bb0b4f3c 100644 --- a/app/scripts/lib/stream-utils.js +++ b/app/scripts/lib/stream-utils.js @@ -1,5 +1,4 @@ const Through = require('through2') -const endOfStream = require('end-of-stream') const ObjectMultiplex = require('obj-multiplex') const pump = require('pump') -- cgit From ef3bf810bf14da6651ef849e481eb0253be3c8d1 Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 7 Sep 2017 22:47:08 -0700 Subject: inpage - use obj-multiplex module --- app/scripts/lib/inpage-provider.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index db46e4f17..b2515bfb8 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -3,7 +3,7 @@ const RpcEngine = require('json-rpc-engine') const createIdRemapMiddleware = require('json-rpc-engine/src/idRemapMiddleware') const createStreamMiddleware = require('json-rpc-middleware-stream') const LocalStorageStore = require('obs-store') -const ObjectMultiplex = require('./obj-multiplex') +const ObjectMultiplex = require('obj-multiplex') module.exports = MetamaskInpageProvider @@ -11,10 +11,10 @@ function MetamaskInpageProvider (connectionStream) { const self = this // setup connectionStream multiplexing - var multiStream = self.multiStream = ObjectMultiplex() + const mux = self.mux = new ObjectMultiplex() pump( connectionStream, - multiStream, + mux, connectionStream, (err) => logStreamDisconnectWarning('MetaMask', err) ) @@ -22,19 +22,19 @@ function MetamaskInpageProvider (connectionStream) { // subscribe to metamask public config (one-way) self.publicConfigStore = new LocalStorageStore({ storageKey: 'MetaMask-Config' }) pump( - multiStream.createStream('publicConfig'), + mux.createStream('publicConfig'), self.publicConfigStore, (err) => logStreamDisconnectWarning('MetaMask PublicConfigStore', err) ) // ignore phishing warning message (handled elsewhere) - multiStream.ignoreStream('phishing') + mux.ignoreStream('phishing') // connect to async provider const streamMiddleware = createStreamMiddleware() pump( streamMiddleware.stream, - multiStream.createStream('provider'), + mux.createStream('provider'), streamMiddleware.stream, (err) => logStreamDisconnectWarning('MetaMask RpcProvider', err) ) -- cgit From d03b0547bb63c4d60fef9ba0d8ebbc88e3aa7b1e Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 8 Sep 2017 11:52:00 -0700 Subject: inpage provider - define sendAsync on the prototype --- app/scripts/lib/inpage-provider.js | 52 ++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 25 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index c63af06dc..13888dc67 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -40,31 +40,37 @@ function MetamaskInpageProvider (connectionStream) { // start and stop polling to unblock first block lock self.idMap = {} - // handle sendAsync requests via asyncProvider - self.sendAsync = function (payload, cb) { - // rewrite request ids - var request = eachJsonMessage(payload, (_message) => { - const message = Object.assign({}, _message) - const newId = createRandomId() - self.idMap[newId] = message.id - message.id = newId +} + +// handle sendAsync requests via asyncProvider +// also remap ids inbound and outbound +MetamaskInpageProvider.prototype.sendAsync = function (payload, cb) { + const self = this + + // rewrite request ids + const request = eachJsonMessage(payload, (_message) => { + const message = Object.assign({}, _message) + const newId = createRandomId() + self.idMap[newId] = message.id + message.id = newId + return message + }) + + // forward to asyncProvider + self.asyncProvider.sendAsync(request, (err, _res) => { + if (err) return cb(err) + // transform messages to original ids + const res = eachJsonMessage(_res, (message) => { + const oldId = self.idMap[message.id] + delete self.idMap[message.id] + message.id = oldId return message }) - // forward to asyncProvider - asyncProvider.sendAsync(request, function (err, res) { - if (err) return cb(err) - // transform messages to original ids - eachJsonMessage(res, (message) => { - var oldId = self.idMap[message.id] - delete self.idMap[message.id] - message.id = oldId - return message - }) - cb(null, res) - }) - } + cb(null, res) + }) } + MetamaskInpageProvider.prototype.send = function (payload) { const self = this @@ -110,10 +116,6 @@ MetamaskInpageProvider.prototype.send = function (payload) { } } -MetamaskInpageProvider.prototype.sendAsync = function () { - throw new Error('MetamaskInpageProvider - sendAsync not overwritten') -} - MetamaskInpageProvider.prototype.isConnected = function () { return true } -- cgit From 585a32534d9415eec9f91b19732e121a4a4c3a79 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 8 Sep 2017 12:17:58 -0700 Subject: Version 3.9.13 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 256737c89..51e82d6e3 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.9.12", + "version": "3.9.13", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 8545453a9d58d7a54c10beef52e38107ed937117 Mon Sep 17 00:00:00 2001 From: kumavis Date: Mon, 11 Sep 2017 14:30:30 -0700 Subject: contentscript - fix obj-multiplex instantiation and use pump for streams --- app/scripts/contentscript.js | 45 ++++++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 12 deletions(-) (limited to 'app') diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index acacf5d4c..90a0f1f22 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -1,11 +1,12 @@ +const fs = require('fs') +const path = require('path') +const pump = require('pump') const LocalMessageDuplexStream = require('post-message-stream') const PongStream = require('ping-pong-stream/pong') -const PortStream = require('./lib/port-stream.js') -const ObjectMultiplex = require('./lib/obj-multiplex') +const ObjectMultiplex = require('obj-multiplex') const extension = require('extensionizer') +const PortStream = require('./lib/port-stream.js') -const fs = require('fs') -const path = require('path') const inpageText = fs.readFileSync(path.join(__dirname, 'inpage.js')).toString() // Eventually this streaming injection could be replaced with: @@ -50,22 +51,42 @@ function setupStreams () { pageStream.pipe(pluginStream).pipe(pageStream) // setup local multistream channels - const mx = ObjectMultiplex() - mx.on('error', console.error) - mx.pipe(pageStream).pipe(mx) - mx.pipe(pluginStream).pipe(mx) + const mux = new ObjectMultiplex() + pump( + mux, + pageStream, + mux, + (err) => logStreamDisconnectWarning('MetaMask Inpage', err) + ) + pump( + mux, + pluginStream, + mux, + (err) => logStreamDisconnectWarning('MetaMask Background', err) + ) // connect ping stream const pongStream = new PongStream({ objectMode: true }) - pongStream.pipe(mx.createStream('pingpong')).pipe(pongStream) + pump( + mux, + pongStream, + mux, + (err) => logStreamDisconnectWarning('MetaMask PingPongStream', err) + ) // connect phishing warning stream - const phishingStream = mx.createStream('phishing') + const phishingStream = mux.createStream('phishing') phishingStream.once('data', redirectToPhishingWarning) // ignore unused channels (handled by background, inpage) - mx.ignoreStream('provider') - mx.ignoreStream('publicConfig') + mux.ignoreStream('provider') + mux.ignoreStream('publicConfig') +} + +function logStreamDisconnectWarning (remoteLabel, err) { + let warningMsg = `MetamaskContentscript - lost connection to ${remoteLabel}` + if (err) warningMsg += '\n' + err.stack + console.warn(warningMsg) } function shouldInjectWeb3 () { -- cgit From 6c318f238d6b6739c302c90ec86ed604a85a8f37 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 11 Sep 2017 14:37:53 -0700 Subject: Version 3.10.0 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index f597bec7f..bd25c1f6f 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.9.13", + "version": "3.10.0", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From a265144176658220c5d8279ecb18c3ac0810e2c2 Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 13 Sep 2017 10:21:00 -0700 Subject: metamask cont - standardize multiplex stream naming --- app/scripts/metamask-controller.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 735fc4af0..b28f5042a 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -346,23 +346,23 @@ module.exports = class MetamaskController extends EventEmitter { } // setup multiplexing - const mx = setupMultiplex(connectionStream) + const mux = setupMultiplex(connectionStream) // connect features - this.setupProviderConnection(mx.createStream('provider'), originDomain) - this.setupPublicConfig(mx.createStream('publicConfig')) + this.setupProviderConnection(mux.createStream('provider'), originDomain) + this.setupPublicConfig(mux.createStream('publicConfig')) } setupTrustedCommunication (connectionStream, originDomain) { // setup multiplexing - const mx = setupMultiplex(connectionStream) + const mux = setupMultiplex(connectionStream) // connect features - this.setupControllerConnection(mx.createStream('controller')) - this.setupProviderConnection(mx.createStream('provider'), originDomain) + this.setupControllerConnection(mux.createStream('controller')) + this.setupProviderConnection(mux.createStream('provider'), originDomain) } sendPhishingWarning (connectionStream, hostname) { - const mx = setupMultiplex(connectionStream) - const phishingStream = mx.createStream('phishing') + const mux = setupMultiplex(connectionStream) + const phishingStream = mux.createStream('phishing') phishingStream.write({ hostname }) } -- cgit From 96d1175834bb5d400f6a70d228cebbd23bded4db Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 13 Sep 2017 10:28:29 -0700 Subject: debug - prefer logger over console --- app/scripts/background.js | 8 ++++---- app/scripts/metamask-controller.js | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index f077ca7a8..1b96d68b5 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -1,6 +1,8 @@ const urlUtil = require('url') const endOfStream = require('end-of-stream') const pipe = require('pump') +const log = require('loglevel') +const extension = require('extensionizer') const LocalStorageStore = require('obs-store/lib/localStorage') const storeTransform = require('obs-store/lib/transform') const ExtensionPlatform = require('./platforms/extension') @@ -9,13 +11,11 @@ const migrations = require('./migrations/') const PortStream = require('./lib/port-stream.js') const NotificationManager = require('./lib/notification-manager.js') const MetamaskController = require('./metamask-controller') -const extension = require('extensionizer') const firstTimeState = require('./first-time-state') const STORAGE_KEY = 'metamask-config' const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' -const log = require('loglevel') window.log = log log.setDefaultLevel(METAMASK_DEBUG ? 'debug' : 'warn') @@ -29,12 +29,12 @@ let popupIsOpen = false const diskStore = new LocalStorageStore({ storageKey: STORAGE_KEY }) // initialization flow -initialize().catch(console.error) +initialize().catch(log.error) async function initialize () { const initState = await loadStateFromPersistence() await setupController(initState) - console.log('MetaMask initialization complete.') + log.debug('MetaMask initialization complete.') } // diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index b28f5042a..0c9602568 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -340,7 +340,7 @@ module.exports = class MetamaskController extends EventEmitter { setupUntrustedCommunication (connectionStream, originDomain) { // Check if new connection is blacklisted if (this.blacklistController.checkForPhishing(originDomain)) { - console.log('MetaMask - sending phishing warning for', originDomain) + log.debug('MetaMask - sending phishing warning for', originDomain) this.sendPhishingWarning(connectionStream, originDomain) return } @@ -374,7 +374,7 @@ module.exports = class MetamaskController extends EventEmitter { dnode, outStream, (err) => { - if (err) console.error(err) + if (err) log.error(err) } ) dnode.on('remote', (remote) => { @@ -402,7 +402,7 @@ module.exports = class MetamaskController extends EventEmitter { providerStream, outStream, (err) => { - if (err) console.error(err) + if (err) log.error(err) } ) @@ -416,7 +416,7 @@ module.exports = class MetamaskController extends EventEmitter { function loggerMiddleware (req, res, next, end) { next((cb) => { if (res.error) { - console.error('Error in RPC response:\n', res) + log.error('Error in RPC response:\n', res) } if (req.isMetamaskInternal) return log.info(`RPC (${originDomain}):`, req, '->', res) @@ -441,7 +441,7 @@ module.exports = class MetamaskController extends EventEmitter { this.publicConfigStore, outStream, (err) => { - if (err) console.error(err) + if (err) log.error(err) } ) } -- cgit From 245c0f0c2741d1dcb706faa93ff681333a40b9c8 Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 13 Sep 2017 15:17:26 -0700 Subject: metamask controller - move middleware into seperate files --- app/scripts/lib/createLoggerMiddleware.js | 15 +++++++++++ app/scripts/lib/createOriginMiddleware.js | 9 +++++++ app/scripts/lib/createProviderMiddleware.js | 13 +++++++++ app/scripts/metamask-controller.js | 41 +++++------------------------ 4 files changed, 44 insertions(+), 34 deletions(-) create mode 100644 app/scripts/lib/createLoggerMiddleware.js create mode 100644 app/scripts/lib/createOriginMiddleware.js create mode 100644 app/scripts/lib/createProviderMiddleware.js (limited to 'app') diff --git a/app/scripts/lib/createLoggerMiddleware.js b/app/scripts/lib/createLoggerMiddleware.js new file mode 100644 index 000000000..b92a965de --- /dev/null +++ b/app/scripts/lib/createLoggerMiddleware.js @@ -0,0 +1,15 @@ +// log rpc activity +module.exports = createLoggerMiddleware + +function createLoggerMiddleware({ origin }) { + return function loggerMiddleware (req, res, next, end) { + next((cb) => { + if (res.error) { + log.error('Error in RPC response:\n', res) + } + if (req.isMetamaskInternal) return + log.info(`RPC (${origin}):`, req, '->', res) + cb() + }) + } +} \ No newline at end of file diff --git a/app/scripts/lib/createOriginMiddleware.js b/app/scripts/lib/createOriginMiddleware.js new file mode 100644 index 000000000..f21d79512 --- /dev/null +++ b/app/scripts/lib/createOriginMiddleware.js @@ -0,0 +1,9 @@ +// append dapp origin domain to request +module.exports = createOriginMiddleware + +function createOriginMiddleware({ origin }) { + return function originMiddleware (req, res, next, end) { + req.origin = originDomain + next() + } +} \ No newline at end of file diff --git a/app/scripts/lib/createProviderMiddleware.js b/app/scripts/lib/createProviderMiddleware.js new file mode 100644 index 000000000..6dd192411 --- /dev/null +++ b/app/scripts/lib/createProviderMiddleware.js @@ -0,0 +1,13 @@ + +module.exports = createProviderMiddleware + +// forward requests to provider +function createProviderMiddleware({ provider }) { + return (req, res, next, end) => { + provider.sendAsync(req, (err, _res) => { + if (err) return end(err) + res.result = _res.result + end() + }) + } +} \ No newline at end of file diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 0c9602568..f114d22f3 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -7,8 +7,12 @@ const ObservableStore = require('obs-store') const EthStore = require('./lib/eth-store') const EthQuery = require('eth-query') const RpcEngine = require('json-rpc-engine') +const debounce = require('debounce') const createEngineStream = require('json-rpc-middleware-stream/engineStream') const createFilterMiddleware = require('eth-json-rpc-filters') +const createOriginMiddleware = require('./lib/createOriginMiddleware') +const createLoggerMiddleware = require('./lib/createLoggerMiddleware') +const createProviderMiddleware = require('./lib/createProviderMiddleware') const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex const KeyringController = require('./keyring-controller') const NetworkController = require('./controllers/network') @@ -26,8 +30,6 @@ const ConfigManager = require('./lib/config-manager') const nodeify = require('./lib/nodeify') const accountImporter = require('./account-import-strategies') const getBuyEthUrl = require('./lib/buy-eth-url') -const debounce = require('debounce') - const version = require('../manifest.json').version module.exports = class MetamaskController extends EventEmitter { @@ -384,11 +386,11 @@ module.exports = class MetamaskController extends EventEmitter { }) } - setupProviderConnection (outStream, originDomain) { + setupProviderConnection (outStream, origin) { // setup json rpc engine stack const engine = new RpcEngine() - engine.push(originMiddleware) - engine.push(loggerMiddleware) + engine.push(createOriginMiddleware({ origin })) + engine.push(createLoggerMiddleware({ origin })) engine.push(createFilterMiddleware({ provider: this.provider, blockTracker: this.blockTracker, @@ -405,35 +407,6 @@ module.exports = class MetamaskController extends EventEmitter { if (err) log.error(err) } ) - - // append dapp origin domain to request - function originMiddleware (req, res, next, end) { - req.origin = originDomain - next() - } - - // log rpc activity - function loggerMiddleware (req, res, next, end) { - next((cb) => { - if (res.error) { - log.error('Error in RPC response:\n', res) - } - if (req.isMetamaskInternal) return - log.info(`RPC (${originDomain}):`, req, '->', res) - cb() - }) - } - - // forward requests to provider - function createProviderMiddleware({ provider }) { - return (req, res, next, end) => { - provider.sendAsync(req, (err, _res) => { - if (err) return end(err) - res.result = _res.result - end() - }) - } - } } setupPublicConfig (outStream) { -- cgit From 765ef640610584a3fdd7fa0ef716f6c7a553407c Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 13 Sep 2017 15:19:44 -0700 Subject: metamask controller - destroy filter polyfill on disconnect --- app/scripts/metamask-controller.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index f114d22f3..fef16c3a9 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -389,12 +389,16 @@ module.exports = class MetamaskController extends EventEmitter { setupProviderConnection (outStream, origin) { // setup json rpc engine stack const engine = new RpcEngine() - engine.push(createOriginMiddleware({ origin })) - engine.push(createLoggerMiddleware({ origin })) - engine.push(createFilterMiddleware({ + + // create filter polyfill middleware + const filterMiddleware = createFilterMiddleware({ provider: this.provider, blockTracker: this.blockTracker, - })) + }) + + engine.push(createOriginMiddleware({ origin })) + engine.push(createLoggerMiddleware({ origin })) + engine.push(filterMiddleware) engine.push(createProviderMiddleware({ provider: this.provider })) // setup connection @@ -404,6 +408,8 @@ module.exports = class MetamaskController extends EventEmitter { providerStream, outStream, (err) => { + // cleanup filter polyfill middleware + filterMiddleware.destroy() if (err) log.error(err) } ) -- cgit From d7097db0221cf6b6958ceb65e9ce4c893a8dfb61 Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 13 Sep 2017 15:29:44 -0700 Subject: createOriginMiddleware - fix var name --- app/scripts/lib/createOriginMiddleware.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/createOriginMiddleware.js b/app/scripts/lib/createOriginMiddleware.js index f21d79512..e1e097cc4 100644 --- a/app/scripts/lib/createOriginMiddleware.js +++ b/app/scripts/lib/createOriginMiddleware.js @@ -3,7 +3,7 @@ module.exports = createOriginMiddleware function createOriginMiddleware({ origin }) { return function originMiddleware (req, res, next, end) { - req.origin = originDomain + req.origin = origin next() } } \ No newline at end of file -- cgit