aboutsummaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
authorDan Finlay <flyswatter@users.noreply.github.com>2016-12-23 06:43:43 +0800
committerGitHub <noreply@github.com>2016-12-23 06:43:43 +0800
commit898e96fd6ae905932a60d60c42e2c3bddab65556 (patch)
tree23fba23503db1da05c1b397487aa71e3d9cb7d58 /app
parent98527c1c254fe2d438191c73053dcf3223062ef3 (diff)
parentd3b2698f341e1d0dda86612cdf331e51067719c5 (diff)
downloadtangerine-wallet-browser-898e96fd6ae905932a60d60c42e2c3bddab65556.tar
tangerine-wallet-browser-898e96fd6ae905932a60d60c42e2c3bddab65556.tar.gz
tangerine-wallet-browser-898e96fd6ae905932a60d60c42e2c3bddab65556.tar.bz2
tangerine-wallet-browser-898e96fd6ae905932a60d60c42e2c3bddab65556.tar.lz
tangerine-wallet-browser-898e96fd6ae905932a60d60c42e2c3bddab65556.tar.xz
tangerine-wallet-browser-898e96fd6ae905932a60d60c42e2c3bddab65556.tar.zst
tangerine-wallet-browser-898e96fd6ae905932a60d60c42e2c3bddab65556.zip
Merge pull request #948 from MetaMask/RecoverLostAccounts
Auto-Recover accounts lost to BIP44 derivation fix
Diffstat (limited to 'app')
-rw-r--r--app/scripts/keyring-controller.js51
-rw-r--r--app/scripts/lib/config-manager.js2
-rw-r--r--app/scripts/lib/idStore-migrator.js7
-rw-r--r--app/scripts/lib/idStore.js3
-rw-r--r--app/scripts/metamask-controller.js80
5 files changed, 92 insertions, 51 deletions
diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js
index 2888e58a9..4e9193ab2 100644
--- a/app/scripts/keyring-controller.js
+++ b/app/scripts/keyring-controller.js
@@ -9,7 +9,6 @@ const encryptor = require('browser-passworder')
const normalize = require('./lib/sig-util').normalize
const messageManager = require('./lib/message-manager')
-const IdStoreMigrator = require('./lib/idStore-migrator')
const BN = ethUtil.BN
// Keyrings:
@@ -45,11 +44,6 @@ module.exports = class KeyringController extends EventEmitter {
this._unconfMsgCbs = {}
this.getNetwork = opts.getNetwork
-
- // TEMPORARY UNTIL FULL DEPRECATION:
- this.idStoreMigrator = new IdStoreMigrator({
- configManager: this.configManager,
- })
}
// Set Store
@@ -114,7 +108,6 @@ module.exports = class KeyringController extends EventEmitter {
conversionDate: this.configManager.getConversionDate(),
keyringTypes: this.keyringTypes.map(krt => krt.type),
identities: this.identities,
- lostAccounts: this.configManager.getLostAccounts(),
}
}
@@ -222,10 +215,7 @@ module.exports = class KeyringController extends EventEmitter {
// Temporarily also migrates any old-style vaults first, as well.
// (Pre MetaMask 3.0.0)
submitPassword (password) {
- return this.migrateOldVaultIfAny(password)
- .then(() => {
- return this.unlockKeyrings(password)
- })
+ return this.unlockKeyrings(password)
.then((keyrings) => {
this.keyrings = keyrings
return this.fullUpdate()
@@ -611,41 +601,6 @@ module.exports = class KeyringController extends EventEmitter {
// THESE METHODS ARE ONLY USED INTERNALLY TO THE KEYRING-CONTROLLER
// AND SO MAY BE CHANGED MORE LIBERALLY THAN THE ABOVE METHODS.
- // Migrate Old Vault If Any
- // @string password
- //
- // returns Promise()
- //
- // Temporary step used when logging in.
- // Checks if old style (pre-3.0.0) Metamask Vault exists.
- // If so, persists that vault in the new vault format
- // with the provided password, so the other unlock steps
- // may be completed without interruption.
- migrateOldVaultIfAny (password) {
- const shouldMigrate = !!this.configManager.getWallet() && !this.configManager.getVault()
- if (!shouldMigrate) {
- return Promise.resolve()
- }
-
- return this.idStoreMigrator.migratedVaultForPassword(password)
- .then((result) => {
- this.password = password
-
- if (result && shouldMigrate) {
- const { serialized, lostAccounts } = result
- this.configManager.setLostAccounts(lostAccounts)
- return this.restoreKeyring(serialized)
- .then(keyring => keyring.getAccounts())
- .then((accounts) => {
- this.configManager.setSelectedAccount(accounts[0])
- return this.persistAllKeyrings()
- })
- } else {
- return Promise.resolve()
- }
- })
- }
-
// Create First Key Tree
// returns @Promise
//
@@ -766,6 +721,10 @@ module.exports = class KeyringController extends EventEmitter {
// initializing the persisted keyrings to RAM.
unlockKeyrings (password) {
const encryptedVault = this.configManager.getVault()
+ if (!encryptedVault) {
+ throw new Error('Cannot unlock without a previous vault.')
+ }
+
return this.encryptor.decrypt(password, encryptedVault)
.then((vault) => {
this.password = password
diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js
index d36ccf0db..ede877b76 100644
--- a/app/scripts/lib/config-manager.js
+++ b/app/scripts/lib/config-manager.js
@@ -121,7 +121,7 @@ ConfigManager.prototype.setVault = function (encryptedString) {
ConfigManager.prototype.getVault = function () {
var data = this.getData()
- return ('vault' in data) && data.vault
+ return data.vault
}
ConfigManager.prototype.getKeychains = function () {
diff --git a/app/scripts/lib/idStore-migrator.js b/app/scripts/lib/idStore-migrator.js
index 2e9418376..655aed0af 100644
--- a/app/scripts/lib/idStore-migrator.js
+++ b/app/scripts/lib/idStore-migrator.js
@@ -63,7 +63,12 @@ module.exports = class IdentityStoreMigrator {
return {
serialized,
- lostAccounts,
+ lostAccounts: lostAccounts.map((address) => {
+ return {
+ address,
+ privateKey: this.idStore.exportAccount(address),
+ }
+ }),
}
})
}
diff --git a/app/scripts/lib/idStore.js b/app/scripts/lib/idStore.js
index cf4353e48..66e5d966c 100644
--- a/app/scripts/lib/idStore.js
+++ b/app/scripts/lib/idStore.js
@@ -202,7 +202,8 @@ IdentityStore.prototype.submitPassword = function (password, cb) {
IdentityStore.prototype.exportAccount = function (address, cb) {
var privateKey = this._idmgmt.exportPrivateKey(address)
- cb(null, privateKey)
+ if (cb) cb(null, privateKey)
+ return privateKey
}
//
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index 4b8fa4323..983a590d7 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -10,6 +10,7 @@ const ConfigManager = require('./lib/config-manager')
const extension = require('./lib/extension')
const autoFaucet = require('./lib/auto-faucet')
const nodeify = require('./lib/nodeify')
+const IdStoreMigrator = require('./lib/idStore-migrator')
module.exports = class MetamaskController {
@@ -44,6 +45,11 @@ module.exports = class MetamaskController {
this.checkTOSChange()
this.scheduleConversionInterval()
+
+ // TEMPORARY UNTIL FULL DEPRECATION:
+ this.idStoreMigrator = new IdStoreMigrator({
+ configManager: this.configManager,
+ })
}
getState () {
@@ -52,7 +58,9 @@ module.exports = class MetamaskController {
this.ethStore.getState(),
this.configManager.getConfig(),
this.keyringController.getState(),
- this.noticeController.getState()
+ this.noticeController.getState(), {
+ lostAccounts: this.configManager.getLostAccounts(),
+ }
)
}
@@ -71,6 +79,7 @@ module.exports = class MetamaskController {
setTOSHash: this.setTOSHash.bind(this),
checkTOSChange: this.checkTOSChange.bind(this),
setGasMultiplier: this.setGasMultiplier.bind(this),
+ markAccountsFound: this.markAccountsFound.bind(this),
// forward directly to keyringController
createNewVaultAndKeychain: nodeify(keyringController.createNewVaultAndKeychain).bind(keyringController),
@@ -78,7 +87,12 @@ module.exports = class MetamaskController {
placeSeedWords: nodeify(keyringController.placeSeedWords).bind(keyringController),
clearSeedWordCache: nodeify(keyringController.clearSeedWordCache).bind(keyringController),
setLocked: nodeify(keyringController.setLocked).bind(keyringController),
- submitPassword: nodeify(keyringController.submitPassword).bind(keyringController),
+ submitPassword: (password, cb) => {
+ this.migrateOldVaultIfAny(password)
+ .then(keyringController.submitPassword.bind(keyringController))
+ .then((newState) => { cb(null, newState) })
+ .catch((reason) => { cb(reason) })
+ },
addNewKeyring: nodeify(keyringController.addNewKeyring).bind(keyringController),
addNewAccount: nodeify(keyringController.addNewAccount).bind(keyringController),
setSelectedAccount: nodeify(keyringController.setSelectedAccount).bind(keyringController),
@@ -410,4 +424,66 @@ module.exports = class MetamaskController {
getStateNetwork () {
return this.state.network
}
+
+ markAccountsFound(cb) {
+ this.configManager.setLostAccounts([])
+ this.sendUpdate()
+ cb(null, this.getState())
+ }
+
+ // Migrate Old Vault If Any
+ // @string password
+ //
+ // returns Promise()
+ //
+ // Temporary step used when logging in.
+ // Checks if old style (pre-3.0.0) Metamask Vault exists.
+ // If so, persists that vault in the new vault format
+ // with the provided password, so the other unlock steps
+ // may be completed without interruption.
+ migrateOldVaultIfAny (password) {
+
+ if (!this.checkIfShouldMigrate()) {
+ return Promise.resolve(password)
+ }
+
+ const keyringController = this.keyringController
+
+ return this.idStoreMigrator.migratedVaultForPassword(password)
+ .then(this.restoreOldVaultAccounts.bind(this))
+ .then(this.restoreOldLostAccounts.bind(this))
+ .then(keyringController.persistAllKeyrings.bind(keyringController))
+ .then(() => password)
+ }
+
+ checkIfShouldMigrate() {
+ return !!this.configManager.getWallet() && !this.configManager.getVault()
+ }
+
+ restoreOldVaultAccounts(migratorOutput) {
+ const { serialized } = migratorOutput
+ return this.keyringController.restoreKeyring(serialized)
+ .then(() => migratorOutput)
+ }
+
+ restoreOldLostAccounts(migratorOutput) {
+ const { lostAccounts } = migratorOutput
+ if (lostAccounts) {
+ this.configManager.setLostAccounts(lostAccounts.map(acct => acct.address))
+ return this.importLostAccounts(migratorOutput)
+ }
+ return Promise.resolve(migratorOutput)
+ }
+
+ // IMPORT LOST ACCOUNTS
+ // @Object with key lostAccounts: @Array accounts <{ address, privateKey }>
+ // Uses the array's private keys to create a new Simple Key Pair keychain
+ // and add it to the keyring controller.
+ importLostAccounts ({ lostAccounts }) {
+ const privKeys = lostAccounts.map(acct => acct.privateKey)
+ return this.keyringController.restoreKeyring({
+ type: 'Simple Key Pair',
+ data: privKeys,
+ })
+ }
}