aboutsummaryrefslogtreecommitdiffstats
path: root/app/scripts
diff options
context:
space:
mode:
authorDan <danjm.com@gmail.com>2018-03-09 13:37:27 +0800
committerDan <danjm.com@gmail.com>2018-03-09 13:37:27 +0800
commit81e72147ef829acbbed85bced7f0eb4533f2fb17 (patch)
tree0e13f8ea4e6fb80fe57e437a466e3f7ae04c6c22 /app/scripts
parent2d6b378bf8f8f0b23ef54b48118b61fb6c7deee1 (diff)
parentf28bbe5b0392a9ae45f7f17fbc979ef796b27d16 (diff)
downloadtangerine-wallet-browser-81e72147ef829acbbed85bced7f0eb4533f2fb17.tar
tangerine-wallet-browser-81e72147ef829acbbed85bced7f0eb4533f2fb17.tar.gz
tangerine-wallet-browser-81e72147ef829acbbed85bced7f0eb4533f2fb17.tar.bz2
tangerine-wallet-browser-81e72147ef829acbbed85bced7f0eb4533f2fb17.tar.lz
tangerine-wallet-browser-81e72147ef829acbbed85bced7f0eb4533f2fb17.tar.xz
tangerine-wallet-browser-81e72147ef829acbbed85bced7f0eb4533f2fb17.tar.zst
tangerine-wallet-browser-81e72147ef829acbbed85bced7f0eb4533f2fb17.zip
Merge branch 'master' into retry-tx-refractor
Diffstat (limited to 'app/scripts')
-rw-r--r--app/scripts/controllers/transactions.js4
-rw-r--r--app/scripts/lib/seed-phrase-verifier.js48
-rw-r--r--app/scripts/lib/tx-state-manager.js2
-rw-r--r--app/scripts/metamask-controller.js53
4 files changed, 95 insertions, 12 deletions
diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js
index 3dbd424ca..a3f731b6e 100644
--- a/app/scripts/controllers/transactions.js
+++ b/app/scripts/controllers/transactions.js
@@ -3,7 +3,7 @@ const ObservableStore = require('obs-store')
const ethUtil = require('ethereumjs-util')
const Transaction = require('ethereumjs-tx')
const EthQuery = require('ethjs-query')
-const TransactionStateManger = require('../lib/tx-state-manager')
+const TransactionStateManager = require('../lib/tx-state-manager')
const TxGasUtil = require('../lib/tx-gas-utils')
const PendingTransactionTracker = require('../lib/pending-tx-tracker')
const NonceTracker = require('../lib/nonce-tracker')
@@ -37,7 +37,7 @@ module.exports = class TransactionController extends EventEmitter {
this.query = new EthQuery(this.provider)
this.txGasUtil = new TxGasUtil(this.provider)
- this.txStateManager = new TransactionStateManger({
+ this.txStateManager = new TransactionStateManager({
initState: opts.initState,
txHistoryLimit: opts.txHistoryLimit,
getNetwork: this.getNetwork.bind(this),
diff --git a/app/scripts/lib/seed-phrase-verifier.js b/app/scripts/lib/seed-phrase-verifier.js
new file mode 100644
index 000000000..9cea22029
--- /dev/null
+++ b/app/scripts/lib/seed-phrase-verifier.js
@@ -0,0 +1,48 @@
+const KeyringController = require('eth-keyring-controller')
+
+const seedPhraseVerifier = {
+
+ // Verifies if the seed words can restore the accounts.
+ //
+ // The seed words can recreate the primary keyring and the accounts belonging to it.
+ // The created accounts in the primary keyring are always the same.
+ // The keyring always creates the accounts in the same sequence.
+ verifyAccounts (createdAccounts, seedWords) {
+
+ return new Promise((resolve, reject) => {
+
+ if (!createdAccounts || createdAccounts.length < 1) {
+ return reject(new Error('No created accounts defined.'))
+ }
+
+ const keyringController = new KeyringController({})
+ const Keyring = keyringController.getKeyringClassForType('HD Key Tree')
+ const opts = {
+ mnemonic: seedWords,
+ numberOfAccounts: createdAccounts.length,
+ }
+
+ const keyring = new Keyring(opts)
+ keyring.getAccounts()
+ .then((restoredAccounts) => {
+
+ log.debug('Created accounts: ' + JSON.stringify(createdAccounts))
+ log.debug('Restored accounts: ' + JSON.stringify(restoredAccounts))
+
+ if (restoredAccounts.length !== createdAccounts.length) {
+ // this should not happen...
+ return reject(new Error('Wrong number of accounts'))
+ }
+
+ for (let i = 0; i < restoredAccounts.length; i++) {
+ if (restoredAccounts[i].toLowerCase() !== createdAccounts[i].toLowerCase()) {
+ return reject(new Error('Not identical accounts! Original: ' + createdAccounts[i] + ', Restored: ' + restoredAccounts[i]))
+ }
+ }
+ return resolve()
+ })
+ })
+ },
+}
+
+module.exports = seedPhraseVerifier
diff --git a/app/scripts/lib/tx-state-manager.js b/app/scripts/lib/tx-state-manager.js
index 25442ce47..e75f733aa 100644
--- a/app/scripts/lib/tx-state-manager.js
+++ b/app/scripts/lib/tx-state-manager.js
@@ -16,7 +16,7 @@ const txStateHistoryHelper = require('./tx-state-history-helper')
// - `'failed'` the tx failed for some reason, included on tx data.
// - `'dropped'` the tx nonce was already used
-module.exports = class TransactionStateManger extends EventEmitter {
+module.exports = class TransactionStateManager extends EventEmitter {
constructor ({ initState, txHistoryLimit, getNetwork }) {
super()
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index ad4e71792..0a5c1d36f 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -37,6 +37,7 @@ const version = require('../manifest.json').version
const BN = require('ethereumjs-util').BN
const GWEI_BN = new BN('1000000000')
const percentile = require('percentile')
+const seedPhraseVerifier = require('./lib/seed-phrase-verifier')
module.exports = class MetamaskController extends EventEmitter {
@@ -344,6 +345,7 @@ module.exports = class MetamaskController extends EventEmitter {
// primary HD keyring management
addNewAccount: nodeify(this.addNewAccount, this),
placeSeedWords: this.placeSeedWords.bind(this),
+ verifySeedPhrase: nodeify(this.verifySeedPhrase, this),
clearSeedWordCache: this.clearSeedWordCache.bind(this),
resetAccount: this.resetAccount.bind(this),
importAccountWithStrategy: this.importAccountWithStrategy.bind(this),
@@ -565,14 +567,18 @@ module.exports = class MetamaskController extends EventEmitter {
// Opinionated Keyring Management
//
- async addNewAccount (cb) {
+ async addNewAccount () {
const primaryKeyring = this.keyringController.getKeyringsByType('HD Key Tree')[0]
- if (!primaryKeyring) return cb(new Error('MetamaskController - No HD Key Tree found'))
+ if (!primaryKeyring) {
+ throw new Error('MetamaskController - No HD Key Tree found')
+ }
const keyringController = this.keyringController
const oldAccounts = await keyringController.getAccounts()
const keyState = await keyringController.addNewAccount(primaryKeyring)
const newAccounts = await keyringController.getAccounts()
+ await this.verifySeedPhrase()
+
newAccounts.forEach((address) => {
if (!oldAccounts.includes(address)) {
this.preferencesController.setSelectedAddress(address)
@@ -587,14 +593,43 @@ module.exports = class MetamaskController extends EventEmitter {
// Used when creating a first vault, to allow confirmation.
// Also used when revealing the seed words in the confirmation view.
placeSeedWords (cb) {
+
+ this.verifySeedPhrase()
+ .then((seedWords) => {
+ this.configManager.setSeedWords(seedWords)
+ return cb(null, seedWords)
+ })
+ .catch((err) => {
+ return cb(err)
+ })
+ }
+
+ // Verifies the current vault's seed words if they can restore the
+ // accounts belonging to the current vault.
+ //
+ // Called when the first account is created and on unlocking the vault.
+ async verifySeedPhrase () {
+
const primaryKeyring = this.keyringController.getKeyringsByType('HD Key Tree')[0]
- if (!primaryKeyring) return cb(new Error('MetamaskController - No HD Key Tree found'))
- primaryKeyring.serialize()
- .then((serialized) => {
- const seedWords = serialized.mnemonic
- this.configManager.setSeedWords(seedWords)
- cb(null, seedWords)
- })
+ if (!primaryKeyring) {
+ throw new Error('MetamaskController - No HD Key Tree found')
+ }
+
+ const serialized = await primaryKeyring.serialize()
+ const seedWords = serialized.mnemonic
+
+ const accounts = await primaryKeyring.getAccounts()
+ if (accounts.length < 1) {
+ throw new Error('MetamaskController - No accounts found')
+ }
+
+ try {
+ await seedPhraseVerifier.verifyAccounts(accounts, seedWords)
+ return seedWords
+ } catch (err) {
+ log.error(err.message)
+ throw err
+ }
}
// ClearSeedWordCache