mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Restructured migration
Migrator now returns a lostAccount array that includes objects these objects include keys of address and privateKey, this allows the MetamaskController to restore the lost accounts even without customizing the idStore or the KeyringController. Also includes a patch that allows idStore to synchronously export private keys.
This commit is contained in:
parent
a3a64afdd5
commit
ebeaf3b3d6
@ -63,7 +63,12 @@ module.exports = class IdentityStoreMigrator {
|
||||
|
||||
return {
|
||||
serialized,
|
||||
lostAccounts,
|
||||
lostAccounts: lostAccounts.map((address) => {
|
||||
return {
|
||||
address,
|
||||
privateKey: this.idStore.exportAccount(address),
|
||||
}
|
||||
}),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -67,7 +67,6 @@ module.exports = class MetamaskController {
|
||||
getApi () {
|
||||
const keyringController = this.keyringController
|
||||
const noticeController = this.noticeController
|
||||
const submitPassword = keyringController.submitPassword.bind(keyringController)
|
||||
|
||||
return {
|
||||
getState: (cb) => { cb(null, this.getState()) },
|
||||
@ -89,10 +88,10 @@ module.exports = class MetamaskController {
|
||||
clearSeedWordCache: nodeify(keyringController.clearSeedWordCache).bind(keyringController),
|
||||
setLocked: nodeify(keyringController.setLocked).bind(keyringController),
|
||||
submitPassword: (password, cb) => {
|
||||
this.migrateOldVaultIfAny()
|
||||
.then(submitPassword)
|
||||
.then((newState) => { cb(null, newState) })
|
||||
.catch((reason) => { cb(reason) })
|
||||
this.migrateOldVaultIfAny(password)
|
||||
.then(keyringController.submitPassword.bind(keyringController))
|
||||
.then((newState) => { console.log('succeeded submitting!'); cb(null, newState) })
|
||||
.catch((reason) => { console.error(reason); cb(reason) })
|
||||
},
|
||||
addNewKeyring: nodeify(keyringController.addNewKeyring).bind(keyringController),
|
||||
addNewAccount: nodeify(keyringController.addNewAccount).bind(keyringController),
|
||||
@ -456,21 +455,46 @@ module.exports = class MetamaskController {
|
||||
|
||||
return this.idStoreMigrator.migratedVaultForPassword(password)
|
||||
.then((result) => {
|
||||
if (result && shouldMigrate) {
|
||||
const { serialized, lostAccounts } = result
|
||||
this.configManager.setLostAccounts(lostAccounts)
|
||||
return this.keyringController.restoreKeyring(serialized)
|
||||
.then(keyring => keyring.getAccounts())
|
||||
.then((accounts) => {
|
||||
this.configManager.setSelectedAccount(accounts[0])
|
||||
return this.keyringController.persistAllKeyrings()
|
||||
.then(() => password)
|
||||
})
|
||||
} else {
|
||||
return Promise.resolve(password)
|
||||
|
||||
this.keyringController.password = password
|
||||
const { serialized, lostAccounts } = result
|
||||
|
||||
// Restore the correct accounts first:
|
||||
return this.keyringController.restoreKeyring(serialized)
|
||||
.then(keyring => keyring.getAccounts())
|
||||
.then((accounts) => {
|
||||
this.configManager.setSelectedAccount(accounts[0])
|
||||
return result
|
||||
})
|
||||
|
||||
}).then((result) => {
|
||||
|
||||
// Now we restore any lost accounts:
|
||||
const { serialized, lostAccounts } = result
|
||||
if (result && lostAccounts) {
|
||||
this.configManager.setLostAccounts(lostAccounts.map((acct) => acct.address))
|
||||
return this.importLostAccounts(result)
|
||||
}
|
||||
})
|
||||
return Promise.resolve(result)
|
||||
}).then(() => {
|
||||
|
||||
// Persist all these newly restored items to disk:
|
||||
return this.keyringController.persistAllKeyrings()
|
||||
|
||||
// Ultimately pass the password back for normal unlocking:
|
||||
}).then((result) => password)
|
||||
}
|
||||
|
||||
|
||||
// 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 (result) {
|
||||
const { serialized, lostAccounts } = result
|
||||
const privKeys = lostAccounts.map(acct => acct.privateKey)
|
||||
return this.keyringController.restoreKeyring({
|
||||
type: 'Simple Key Pair',
|
||||
data: privKeys,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ QUnit.test('agree to terms', function (assert) {
|
||||
var createButton = app.find('button.primary')[0]
|
||||
createButton.click()
|
||||
|
||||
return wait(1500)
|
||||
return wait(1000)
|
||||
}).then(function() {
|
||||
|
||||
var detail = app.find('.account-detail-section')[0]
|
||||
|
74
test/integration/lib/idStore-migrator-test.js
Normal file
74
test/integration/lib/idStore-migrator-test.js
Normal file
@ -0,0 +1,74 @@
|
||||
var KeyringController = require('../../../app/scripts/keyring-controller')
|
||||
var ConfigManager = require('../../../app/scripts/lib/config-manager')
|
||||
var IdStoreMigrator = require('../../../app/scripts/lib/idStore-migrator')
|
||||
|
||||
var oldStyleVault = require('../mocks/oldVault.json')
|
||||
var badStyleVault = require('../mocks/badVault.json')
|
||||
|
||||
var STORAGE_KEY = 'metamask-config'
|
||||
var PASSWORD = '12345678'
|
||||
var FIRST_ADDRESS = '0x4dd5d356c5A016A220bCD69e82e5AF680a430d00'.toLowerCase()
|
||||
var SEED = 'fringe damage bounce extend tunnel afraid alert sound all soldier all dinner'
|
||||
|
||||
var BAD_STYLE_FIRST_ADDRESS = '0xac39b311dceb2a4b2f5d8461c1cdaf756f4f7ae9'
|
||||
|
||||
QUnit.module('Old Style Vaults', {
|
||||
beforeEach: function () {
|
||||
window.localStorage[STORAGE_KEY] = JSON.stringify(oldStyleVault)
|
||||
|
||||
this.configManager = new ConfigManager({
|
||||
loadData: () => { return JSON.parse(window.localStorage[STORAGE_KEY]) },
|
||||
setData: (data) => { window.localStorage[STORAGE_KEY] = JSON.stringify(data) },
|
||||
})
|
||||
|
||||
this.migrator = new IdStoreMigrator({
|
||||
configManager: this.configManager,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
QUnit.test('migrator:isInitialized', function (assert) {
|
||||
assert.ok(this.migrator)
|
||||
})
|
||||
|
||||
QUnit.test('migrator:migratedVaultForPassword', function (assert) {
|
||||
var done = assert.async()
|
||||
|
||||
this.migrator.migratedVaultForPassword(PASSWORD)
|
||||
.then((result) => {
|
||||
const { serialized, lostAccounts } = result
|
||||
assert.equal(serialized.data.mnemonic, SEED, 'seed phrase recovered')
|
||||
assert.equal(lostAccounts.length, 0, 'no lost accounts')
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
QUnit.module('Old Style Vaults with bad HD seed', {
|
||||
beforeEach: function () {
|
||||
window.localStorage[STORAGE_KEY] = JSON.stringify(badStyleVault)
|
||||
|
||||
this.configManager = new ConfigManager({
|
||||
loadData: () => { return JSON.parse(window.localStorage[STORAGE_KEY]) },
|
||||
setData: (data) => { window.localStorage[STORAGE_KEY] = JSON.stringify(data) },
|
||||
})
|
||||
|
||||
this.migrator = new IdStoreMigrator({
|
||||
configManager: this.configManager,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
QUnit.test('migrator:migratedVaultForPassword', function (assert) {
|
||||
var done = assert.async()
|
||||
|
||||
this.migrator.migratedVaultForPassword(PASSWORD)
|
||||
.then((result) => {
|
||||
const { serialized, lostAccounts } = result
|
||||
|
||||
assert.equal(lostAccounts.length, 1, 'one lost account')
|
||||
assert.equal(lostAccounts[0].address, '0xe15D894BeCB0354c501AE69429B05143679F39e0'.toLowerCase())
|
||||
assert.ok(lostAccounts[0].privateKey, 'private key exported')
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
@ -1,122 +0,0 @@
|
||||
var KeyringController = require('../../../app/scripts/keyring-controller')
|
||||
var ConfigManager = require('../../../app/scripts/lib/config-manager')
|
||||
|
||||
var oldStyleVault = require('../mocks/oldVault.json')
|
||||
var badStyleVault = require('../mocks/badVault.json')
|
||||
|
||||
var STORAGE_KEY = 'metamask-config'
|
||||
var PASSWORD = '12345678'
|
||||
var FIRST_ADDRESS = '0x4dd5d356c5A016A220bCD69e82e5AF680a430d00'.toLowerCase()
|
||||
|
||||
var BAD_STYLE_FIRST_ADDRESS = '0xac39b311dceb2a4b2f5d8461c1cdaf756f4f7ae9'
|
||||
|
||||
|
||||
QUnit.module('Old Style Vaults', {
|
||||
beforeEach: function () {
|
||||
window.localStorage[STORAGE_KEY] = JSON.stringify(oldStyleVault)
|
||||
|
||||
this.configManager = new ConfigManager({
|
||||
loadData: () => { return JSON.parse(window.localStorage[STORAGE_KEY]) },
|
||||
setData: (data) => { window.localStorage[STORAGE_KEY] = JSON.stringify(data) },
|
||||
})
|
||||
|
||||
this.keyringController = new KeyringController({
|
||||
configManager: this.configManager,
|
||||
getNetwork: () => { return '2' },
|
||||
})
|
||||
|
||||
this.ethStore = {
|
||||
addAccount: () => {},
|
||||
removeAccount: () => {},
|
||||
}
|
||||
|
||||
this.keyringController.setStore(this.ethStore)
|
||||
}
|
||||
})
|
||||
|
||||
QUnit.test('keyringController:isInitialized', function (assert) {
|
||||
assert.ok(this.keyringController.getState().isInitialized)
|
||||
})
|
||||
|
||||
QUnit.test('keyringController:submitPassword', function (assert) {
|
||||
var done = assert.async()
|
||||
|
||||
this.keyringController.submitPassword(PASSWORD)
|
||||
.then((state) => {
|
||||
assert.ok(state.identities[FIRST_ADDRESS])
|
||||
assert.ok(state.lostAccounts, 'no lost accounts')
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
QUnit.test('keyringController:setLocked', function (assert) {
|
||||
var done = assert.async()
|
||||
var self = this
|
||||
|
||||
this.keyringController.setLocked()
|
||||
.then(function() {
|
||||
assert.notOk(self.keyringController.password, 'password should be deallocated')
|
||||
assert.deepEqual(self.keyringController.keyrings, [], 'keyrings should be deallocated')
|
||||
done()
|
||||
})
|
||||
.catch((reason) => {
|
||||
assert.ifError(reason)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
QUnit.module('Old Style Vaults with bad HD seed', {
|
||||
beforeEach: function () {
|
||||
window.localStorage[STORAGE_KEY] = JSON.stringify(badStyleVault)
|
||||
|
||||
this.configManager = new ConfigManager({
|
||||
loadData: () => { return JSON.parse(window.localStorage[STORAGE_KEY]) },
|
||||
setData: (data) => { window.localStorage[STORAGE_KEY] = JSON.stringify(data) },
|
||||
})
|
||||
|
||||
this.keyringController = new KeyringController({
|
||||
configManager: this.configManager,
|
||||
getNetwork: () => { return '2' },
|
||||
})
|
||||
|
||||
this.ethStore = {
|
||||
addAccount: () => {},
|
||||
removeAccount: () => {},
|
||||
}
|
||||
|
||||
this.keyringController.setStore(this.ethStore)
|
||||
}
|
||||
})
|
||||
|
||||
QUnit.test('keyringController:isInitialized', function (assert) {
|
||||
assert.ok(this.keyringController.getState().isInitialized, 'vault is initialized')
|
||||
})
|
||||
|
||||
QUnit.test('keyringController:submitPassword', function (assert) {
|
||||
var done = assert.async()
|
||||
|
||||
this.keyringController.submitPassword(PASSWORD)
|
||||
.then((state) => {
|
||||
assert.ok(state.identities[BAD_STYLE_FIRST_ADDRESS])
|
||||
assert.equal(state.lostAccounts.length, 1, 'one lost account')
|
||||
assert.equal(state.lostAccounts[0], '0xe15D894BeCB0354c501AE69429B05143679F39e0'.toLowerCase())
|
||||
assert.deepEqual(this.configManager.getLostAccounts(), state.lostAccounts, 'persisted')
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
QUnit.test('keyringController:setLocked', function (assert) {
|
||||
var done = assert.async()
|
||||
var self = this
|
||||
|
||||
this.keyringController.setLocked()
|
||||
.then(function() {
|
||||
assert.notOk(self.keyringController.password, 'password should be deallocated')
|
||||
assert.deepEqual(self.keyringController.keyrings, [], 'keyrings should be deallocated')
|
||||
done()
|
||||
})
|
||||
.catch((reason) => {
|
||||
assert.ifError(reason)
|
||||
done()
|
||||
})
|
||||
})
|
Loading…
Reference in New Issue
Block a user