From ea1a934c7defe7e1b077b675ae9125118f1f3d87 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 11 Oct 2016 15:09:22 -0700 Subject: Add initial KeyringController files --- app/scripts/keyring-controller.js | 42 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 app/scripts/keyring-controller.js (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js new file mode 100644 index 000000000..b61242973 --- /dev/null +++ b/app/scripts/keyring-controller.js @@ -0,0 +1,42 @@ +const scrypt = require('scrypt-async') +const bitcore = require('bitcore-lib') +const configManager = require('./lib/config-manager') + +module.exports = class KeyringController { + + constructor (opts) { + this.configManager = opts.configManager + this.keyChains = [] + } + + getKeyForPassword(password, callback) { + let salt = this.configManager.getSalt() + + if (!salt) { + salt = generateSalt(32) + configManager.setSalt(salt) + } + + var logN = 14 + var r = 8 + var dkLen = 32 + var interruptStep = 200 + + var cb = function(derKey) { + try { + var ui8arr = (new Uint8Array(derKey)) + this.pwDerivedKey = ui8arr + callback(null, ui8arr) + } catch (err) { + callback(err) + } + } + + scrypt(password, salt, logN, r, dkLen, interruptStep, cb, null) + } + +} + +function generateSalt (byteCount) { + return bitcore.crypto.Random.getRandomBuffer(byteCount || 32).toString('base64') +} -- cgit v1.2.3 From cd2c00a31873490c9129023abb35dd7983604b60 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 12 Oct 2016 16:43:48 -0700 Subject: Add minimal method signatures to new keyring controller --- app/scripts/keyring-controller.js | 62 +++++++++++++++++++++++++++++++++++++- app/scripts/metamask-controller.js | 44 +++++++++++++++++++-------- 2 files changed, 92 insertions(+), 14 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index b61242973..d96b9c101 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -1,11 +1,14 @@ const scrypt = require('scrypt-async') const bitcore = require('bitcore-lib') const configManager = require('./lib/config-manager') +const EventEmitter = require('events').EventEmitter -module.exports = class KeyringController { +module.exports = class KeyringController extends EventEmitter { constructor (opts) { + super() this.configManager = opts.configManager + this.ethStore = opts.ethStore this.keyChains = [] } @@ -35,6 +38,63 @@ module.exports = class KeyringController { scrypt(password, salt, logN, r, dkLen, interruptStep, cb, null) } + getState() { + return {} + } + + setStore(ethStore) { + this.ethStore = ethStore + } + + createNewVault(password, entropy, cb) { + cb() + } + + submitPassword(password, cb) { + cb() + } + + setSelectedAddress(address, cb) { + this.selectedAddress = address + cb(null, address) + } + + approveTransaction(txId, cb) { + cb() + } + + cancelTransaction(txId, cb) { + if (cb && typeof cb === 'function') { + cb() + } + } + + signMessage(msgParams, cb) { + cb() + } + + cancelMessage(msgId, cb) { + if (cb && typeof cb === 'function') { + cb() + } + } + + setLocked(cb) { + cb() + } + + exportAccount(address, cb) { + cb(null, '0xPrivateKey') + } + + saveAccountLabel(account, label, cb) { + cb(/* null, label */) + } + + tryPassword(password, cb) { + cb() + } + } function generateSalt (byteCount) { diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 550531d6e..462c132e6 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -1,7 +1,7 @@ const extend = require('xtend') const EthStore = require('eth-store') const MetaMaskProvider = require('web3-provider-engine/zero.js') -const IdentityStore = require('./lib/idStore') +const IdentityStore = require('./keyring-controller') const messageManager = require('./lib/message-manager') const HostStore = require('./lib/remote-store.js').HostStore const Web3 = require('web3') @@ -11,6 +11,7 @@ const extension = require('./lib/extension') module.exports = class MetamaskController { constructor (opts) { + this.state = { network: 'loading' } this.opts = opts this.listeners = [] this.configManager = new ConfigManager(opts) @@ -20,6 +21,7 @@ module.exports = class MetamaskController { this.provider = this.initializeProvider(opts) this.ethStore = new EthStore(this.provider) this.idStore.setStore(this.ethStore) + this.getNetwork() this.messageManager = messageManager this.publicConfigStore = this.initPublicConfigStore() @@ -30,11 +32,11 @@ module.exports = class MetamaskController { this.checkTOSChange() this.scheduleConversionInterval() - } getState () { return extend( + this.state, this.ethStore.getState(), this.idStore.getState(), this.configManager.getConfig() @@ -58,7 +60,6 @@ module.exports = class MetamaskController { // forward directly to idStore createNewVault: idStore.createNewVault.bind(idStore), - recoverFromSeed: idStore.recoverFromSeed.bind(idStore), submitPassword: idStore.submitPassword.bind(idStore), setSelectedAddress: idStore.setSelectedAddress.bind(idStore), approveTransaction: idStore.approveTransaction.bind(idStore), @@ -66,12 +67,9 @@ module.exports = class MetamaskController { signMessage: idStore.signMessage.bind(idStore), cancelMessage: idStore.cancelMessage.bind(idStore), setLocked: idStore.setLocked.bind(idStore), - clearSeedWordCache: idStore.clearSeedWordCache.bind(idStore), exportAccount: idStore.exportAccount.bind(idStore), - revealAccount: idStore.revealAccount.bind(idStore), saveAccountLabel: idStore.saveAccountLabel.bind(idStore), tryPassword: idStore.tryPassword.bind(idStore), - recoverSeed: idStore.recoverSeed.bind(idStore), // coinbase buyEth: this.buyEth.bind(this), // shapeshift @@ -160,11 +158,11 @@ module.exports = class MetamaskController { var provider = MetaMaskProvider(providerOpts) var web3 = new Web3(provider) + this.web3 = web3 idStore.web3 = web3 - idStore.getNetwork() provider.on('block', this.processBlock.bind(this)) - provider.on('error', idStore.getNetwork.bind(idStore)) + provider.on('error', this.getNetwork.bind(this)) return provider } @@ -261,8 +259,8 @@ module.exports = class MetamaskController { verifyNetwork () { // Check network when restoring connectivity: - if (this.idStore._currentState.network === 'loading') { - this.idStore.getNetwork() + if (this.state.network === 'loading') { + this.getNetwork() } } @@ -345,13 +343,13 @@ module.exports = class MetamaskController { setRpcTarget (rpcTarget) { this.configManager.setRpcTarget(rpcTarget) extension.runtime.reload() - this.idStore.getNetwork() + this.getNetwork() } setProviderType (type) { this.configManager.setProviderType(type) extension.runtime.reload() - this.idStore.getNetwork() + this.getNetwork() } useEtherscanProvider () { @@ -362,7 +360,7 @@ module.exports = class MetamaskController { buyEth (address, amount) { if (!amount) amount = '5' - var network = this.idStore._currentState.network + var network = this.state.network var url = `https://buy.coinbase.com/?code=9ec56d01-7e81-5017-930c-513daa27bb6a&amount=${amount}&address=${address}&crypto_currency=ETH` if (network === '2') { @@ -377,4 +375,24 @@ module.exports = class MetamaskController { createShapeShiftTx (depositAddress, depositType) { this.configManager.createShapeShiftTx(depositAddress, depositType) } + + getNetwork(err) { + if (err) { + this.state.network = 'loading' + this.sendUpdate() + } + + this.web3.version.getNetwork((err, network) => { + if (err) { + this.state.network = 'loading' + return this.sendUpdate() + } + if (global.METAMASK_DEBUG) { + console.log('web3.getNetwork returned ' + network) + } + this.state.network = network + this.sendUpdate() + }) + } + } -- cgit v1.2.3 From 1481a3ef8e3352eb74fa11c4f578d15d84c76de7 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Sat, 15 Oct 2016 10:48:12 -0700 Subject: Initial work on UI side --- app/scripts/keyring-controller.js | 5 +++++ app/scripts/lib/config-manager.js | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index d96b9c101..5b527b0d9 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -12,6 +12,11 @@ module.exports = class KeyringController extends EventEmitter { this.keyChains = [] } + keyFromPassword(password, callback) { + deriveKeyFromPassword(password, callback); + } + + // Takes a pw and callback, returns a password-dervied key getKeyForPassword(password, callback) { let salt = this.configManager.getSalt() diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index ecc9bc5f7..d775e73fd 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -110,6 +110,16 @@ ConfigManager.prototype.setWallet = function (wallet) { this.setData(data) } +ConfigManager.prototype.getKeychains = function () { + return this.migrator.getData().keychains || [] +} + +ConfigManager.prototype.setKeychains = function (keychains) { + var data = this.migrator.getData() + data.keychains = keychains + this.setData(data) +} + ConfigManager.prototype.getSelectedAccount = function () { var config = this.getConfig() return config.selectedAccount @@ -249,6 +259,17 @@ ConfigManager.prototype.setNicknameForWallet = function (account, nickname) { // observable +ConfigManager.prototype.getSalt = function () { + var data = this.getData() + return ('salt' in data) && data.salt +} + +ConfigManager.prototype.setSalt = function(salt) { + var data = this.getData() + data.salt = salt + this.setData(data) +} + ConfigManager.prototype.subscribe = function (fn) { this._subs.push(fn) var unsubscribe = this.unsubscribe.bind(this, fn) -- cgit v1.2.3 From 17506fe14f84680bc6b5421eff4c797154a513bd Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 19 Oct 2016 11:17:29 -0700 Subject: Merge in crypto. --- app/scripts/lib/encryptor.js | 119 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 app/scripts/lib/encryptor.js (limited to 'app/scripts') diff --git a/app/scripts/lib/encryptor.js b/app/scripts/lib/encryptor.js new file mode 100644 index 000000000..91d6ed5ce --- /dev/null +++ b/app/scripts/lib/encryptor.js @@ -0,0 +1,119 @@ +var ethUtil = require('ethereumjs-util') + +module.exports = { + + // Simple encryption methods: + encrypt, + decrypt, + + // More advanced encryption methods: + keyFromPassword, + encryptWithKey, + decryptWithKey, + + // Buffer <-> String methods + convertArrayBufferViewtoString, + convertStringToArrayBufferView, + + // Buffer <-> Hex string methods + serializeBufferForStorage, + serializeBufferFromStorage, +} + +// Takes a Pojo, returns encrypted text. +function encrypt (password, dataObj) { + return keyFromPassword(password) + .then(function (passwordDerivedKey) { + return encryptWithKey(passwordDerivedKey, dataObj) + }) +} + +function encryptWithKey (key, dataObj) { + var data = JSON.stringify(dataObj) + var dataBuffer = convertStringToArrayBufferView(data) + var vector = global.crypto.getRandomValues(new Uint8Array(16)) + + return global.crypto.subtle.encrypt({ + name: 'AES-GCM', + iv: vector, + }, key, dataBuffer).then(function(buf){ + var buffer = new Uint8Array(buf) + var vectorStr = serializeBufferForStorage(vector) + return serializeBufferForStorage(buffer) + vectorStr + }) +} + +// Takes encrypted text, returns the restored Pojo. +function decrypt (password, text) { + return keyFromPassword(password) + .then(function (key) { + return decryptWithKey(key, text) + }) +} + +function decryptWithKey (key, text) { + const parts = text.split('0x') + const encryptedData = serializeBufferFromStorage(parts[1]) + const vector = serializeBufferFromStorage(parts[2]) + return crypto.subtle.decrypt({name: 'AES-GCM', iv: vector}, key, encryptedData) + .then(function(result){ + const decryptedData = new Uint8Array(result) + const decryptedStr = convertArrayBufferViewtoString(decryptedData) + const decryptedObj = JSON.parse(decryptedStr) + return decryptedObj + }) +} + +function convertStringToArrayBufferView (str) { + var bytes = new Uint8Array(str.length) + for (var i = 0; i < str.length; i++) { + bytes[i] = str.charCodeAt(i) + } + + return bytes +} + +function convertArrayBufferViewtoString (buffer) { + var str = '' + for (var i = 0; i < buffer.byteLength; i++) { + str += String.fromCharCode(buffer[i]) + } + + return str +} + +function keyFromPassword (password) { + var passBuffer = convertStringToArrayBufferView(password) + return global.crypto.subtle.digest('SHA-256', passBuffer) + .then(function (passHash){ + return global.crypto.subtle.importKey('raw', passHash, {name: 'AES-GCM'}, false, ['encrypt', 'decrypt']) + }) +} + +function serializeBufferFromStorage (str) { + str = ethUtil.stripHexPrefix(str) + var buf = new Uint8Array(str.length / 2) + for (var i = 0; i < str.length; i += 2) { + var seg = str.substr(i, 2) + buf[i / 2] = parseInt(seg, 16) + } + return buf +} + +// Should return a string, ready for storage, in hex format. +function serializeBufferForStorage (buffer) { + var result = '0x' + var len = buffer.length || buffer.byteLength + for (var i = 0; i < len; i++) { + result += unprefixedHex(buffer[i]) + } + return result +} + +function unprefixedHex (num) { + var hex = num.toString(16) + while (hex.length < 2) { + hex = '0' + hex + } + return hex +} -- cgit v1.2.3 From 725d503f68f533e0d1dfc402c4316dcf677c0d89 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 19 Oct 2016 14:06:48 -0700 Subject: Remove unused crypto dependencies. --- app/scripts/keyring-controller.js | 2 -- 1 file changed, 2 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 5b527b0d9..246a45484 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -1,5 +1,3 @@ -const scrypt = require('scrypt-async') -const bitcore = require('bitcore-lib') const configManager = require('./lib/config-manager') const EventEmitter = require('events').EventEmitter -- cgit v1.2.3 From ad3fa24a28c0ec45dca43a257005626a4027487a Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 19 Oct 2016 14:55:08 -0700 Subject: Intermediary commit. --- app/scripts/keyring-controller.js | 37 +++++++++++++++++++++++++++++++++---- app/scripts/lib/config-manager.js | 11 +++++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 246a45484..db7e5e61e 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -1,5 +1,7 @@ -const configManager = require('./lib/config-manager') const EventEmitter = require('events').EventEmitter +const encryptor = require('./lib/encryptor') +const messageManager = require('./lib/message-manager') + module.exports = class KeyringController extends EventEmitter { @@ -20,7 +22,7 @@ module.exports = class KeyringController extends EventEmitter { if (!salt) { salt = generateSalt(32) - configManager.setSalt(salt) + this.configManager.setSalt(salt) } var logN = 14 @@ -42,7 +44,21 @@ module.exports = class KeyringController extends EventEmitter { } getState() { - return {} + return { + isInitialized: !!this.key, + isUnlocked: !!this.key, + isConfirmed: true, // this.configManager.getConfirmed(), + isEthConfirmed: this.configManager.getShouldntShowWarning(), + unconfTxs: this.configManager.unconfirmedTxs(), + transactions: this.configManager.getTxList(), + unconfMsgs: messageManager.unconfirmedMsgs(), + messages: messageManager.getMsgList(), + selectedAddress: this.configManager.getSelectedAccount(), + shapeShiftTxList: this.configManager.getShapeShiftTxList(), + currentFiat: this.configManager.getCurrentFiat(), + conversionRate: this.configManager.getConversionRate(), + conversionDate: this.configManager.getConversionDate(), + } } setStore(ethStore) { @@ -50,9 +66,22 @@ module.exports = class KeyringController extends EventEmitter { } createNewVault(password, entropy, cb) { - cb() + encryptor.keyFromPassword(password) + .then((key) => { + this.key = key + return encryptor.encryptWithKey(key, {}) + }) + .then((encryptedString) => { + this.configManager.setVault(encryptedString) + cb(null, []) + }) + .catch((err) => { + cb(err) + }) } + + submitPassword(password, cb) { cb() } diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index d775e73fd..1c0e3b696 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -110,6 +110,17 @@ ConfigManager.prototype.setWallet = function (wallet) { this.setData(data) } +ConfigManager.prototype.setVault = function (encryptedString) { + var data = this.getData() + data.vault = encryptedString + this.setData(data) +} + +ConfigManager.prototype.getVault = function () { + var data = this.getData() + return ('vault' in data) && data.vault +} + ConfigManager.prototype.getKeychains = function () { return this.migrator.getData().keychains || [] } -- cgit v1.2.3 From 2132477797660a87fec20dbc0a3f839895b23309 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 20 Oct 2016 10:28:45 -0700 Subject: Fix unlock logic --- app/scripts/keyring-controller.js | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index db7e5e61e..416d6093c 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -45,7 +45,7 @@ module.exports = class KeyringController extends EventEmitter { getState() { return { - isInitialized: !!this.key, + isInitialized: !!this.configManager.getVault(), isUnlocked: !!this.key, isConfirmed: true, // this.configManager.getConfirmed(), isEthConfirmed: this.configManager.getShouldntShowWarning(), @@ -66,9 +66,8 @@ module.exports = class KeyringController extends EventEmitter { } createNewVault(password, entropy, cb) { - encryptor.keyFromPassword(password) + this.loadKey(password) .then((key) => { - this.key = key return encryptor.encryptWithKey(key, {}) }) .then((encryptedString) => { @@ -80,10 +79,22 @@ module.exports = class KeyringController extends EventEmitter { }) } - - submitPassword(password, cb) { - cb() + this.loadKey(password) + .then((key) => { + cb(null, []) + }) + .catch((err) => { + cb(err) + }) + } + + loadKey(password) { + return encryptor.keyFromPassword(password) + .then((key) => { + this.key = key + return key + }) } setSelectedAddress(address, cb) { -- cgit v1.2.3 From e5c95d68f80eba3e3d4645f7ac1f6606d0dddd52 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 20 Oct 2016 11:00:38 -0700 Subject: Fix state updating after vault creation and unlocking --- app/scripts/keyring-controller.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 416d6093c..84601916f 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -72,7 +72,7 @@ module.exports = class KeyringController extends EventEmitter { }) .then((encryptedString) => { this.configManager.setVault(encryptedString) - cb(null, []) + cb(null, this.getState()) }) .catch((err) => { cb(err) @@ -82,7 +82,7 @@ module.exports = class KeyringController extends EventEmitter { submitPassword(password, cb) { this.loadKey(password) .then((key) => { - cb(null, []) + cb(null, this.getState()) }) .catch((err) => { cb(err) -- cgit v1.2.3 From 383f8ea7dc4a264613cfe92b257878eb78438ce7 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 20 Oct 2016 11:33:18 -0700 Subject: Linted & added salting to vault --- app/scripts/keyring-controller.js | 43 ++++++++------------------------------- app/scripts/lib/config-manager.js | 2 +- app/scripts/lib/encryptor.js | 16 +++++++++++++++ 3 files changed, 26 insertions(+), 35 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 84601916f..f6b1e9358 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -12,37 +12,6 @@ module.exports = class KeyringController extends EventEmitter { this.keyChains = [] } - keyFromPassword(password, callback) { - deriveKeyFromPassword(password, callback); - } - - // Takes a pw and callback, returns a password-dervied key - getKeyForPassword(password, callback) { - let salt = this.configManager.getSalt() - - if (!salt) { - salt = generateSalt(32) - this.configManager.setSalt(salt) - } - - var logN = 14 - var r = 8 - var dkLen = 32 - var interruptStep = 200 - - var cb = function(derKey) { - try { - var ui8arr = (new Uint8Array(derKey)) - this.pwDerivedKey = ui8arr - callback(null, ui8arr) - } catch (err) { - callback(err) - } - } - - scrypt(password, salt, logN, r, dkLen, interruptStep, cb, null) - } - getState() { return { isInitialized: !!this.configManager.getVault(), @@ -66,11 +35,13 @@ module.exports = class KeyringController extends EventEmitter { } createNewVault(password, entropy, cb) { + const salt = generateNewSalt() + this.configManager.setSalt(salt) this.loadKey(password) .then((key) => { return encryptor.encryptWithKey(key, {}) }) - .then((encryptedString) => { + .then((encryptedString) => { this.configManager.setVault(encryptedString) cb(null, this.getState()) }) @@ -90,7 +61,8 @@ module.exports = class KeyringController extends EventEmitter { } loadKey(password) { - return encryptor.keyFromPassword(password) + const salt = this.configManager.getSalt() + return encryptor.keyFromPassword(password + salt) .then((key) => { this.key = key return key @@ -141,5 +113,8 @@ module.exports = class KeyringController extends EventEmitter { } function generateSalt (byteCount) { - return bitcore.crypto.Random.getRandomBuffer(byteCount || 32).toString('base64') + var view = new Uint8Array(32) + global.crypto.getRandomValues(view) + var b64encoded = btoa(String.fromCharCode.apply(null, view)) + return b64encoded } diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index d12304c46..ae4a84082 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -118,7 +118,7 @@ ConfigManager.prototype.setVault = function (encryptedString) { ConfigManager.prototype.getVault = function () { var data = this.getData() - return ('vault' in data) && data.vault + return ('vault' in data) && data.vault } ConfigManager.prototype.getKeychains = function () { diff --git a/app/scripts/lib/encryptor.js b/app/scripts/lib/encryptor.js index 91d6ed5ce..8a3b0b023 100644 --- a/app/scripts/lib/encryptor.js +++ b/app/scripts/lib/encryptor.js @@ -18,6 +18,10 @@ module.exports = { // Buffer <-> Hex string methods serializeBufferForStorage, serializeBufferFromStorage, + + // Buffer <-> base64 string methods + encodeBufferToBase64, + decodeBase64ToBuffer, } // Takes a Pojo, returns encrypted text. @@ -117,3 +121,15 @@ function unprefixedHex (num) { } return hex } + +function encodeBufferToBase64 (buf) { + var b64encoded = btoa(String.fromCharCode.apply(null, buf)) + return b64encoded +} + +function decodeBase64ToBuffer (base64) { + var u8_2 = new Uint8Array(atob(b64encoded).split("") + .map(function(c) { + return c.charCodeAt(0) + })) +} -- cgit v1.2.3 From 0deed1775237bc8d48eb41e83b5a661b55e4b6be Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 20 Oct 2016 12:07:53 -0700 Subject: Fix tests --- app/scripts/keyring-controller.js | 2 +- app/scripts/lib/encryptor.js | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index f6b1e9358..d25dddba1 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -35,7 +35,7 @@ module.exports = class KeyringController extends EventEmitter { } createNewVault(password, entropy, cb) { - const salt = generateNewSalt() + const salt = generateSalt() this.configManager.setSalt(salt) this.loadKey(password) .then((key) => { diff --git a/app/scripts/lib/encryptor.js b/app/scripts/lib/encryptor.js index 8a3b0b023..3d069ab33 100644 --- a/app/scripts/lib/encryptor.js +++ b/app/scripts/lib/encryptor.js @@ -42,8 +42,9 @@ function encryptWithKey (key, dataObj) { iv: vector, }, key, dataBuffer).then(function(buf){ var buffer = new Uint8Array(buf) - var vectorStr = serializeBufferForStorage(vector) - return serializeBufferForStorage(buffer) + vectorStr + var vectorStr = encodeBufferToBase64(vector) + var vaultStr = encodeBufferToBase64(buffer) + return `${vaultStr}\\${vectorStr}` }) } @@ -56,9 +57,9 @@ function decrypt (password, text) { } function decryptWithKey (key, text) { - const parts = text.split('0x') - const encryptedData = serializeBufferFromStorage(parts[1]) - const vector = serializeBufferFromStorage(parts[2]) + const parts = text.split('\\') + const encryptedData = decodeBase64ToBuffer(parts[0]) + const vector = decodeBase64ToBuffer(parts[1]) return crypto.subtle.decrypt({name: 'AES-GCM', iv: vector}, key, encryptedData) .then(function(result){ const decryptedData = new Uint8Array(result) @@ -128,8 +129,9 @@ function encodeBufferToBase64 (buf) { } function decodeBase64ToBuffer (base64) { - var u8_2 = new Uint8Array(atob(b64encoded).split("") + var buf = new Uint8Array(atob(base64).split('') .map(function(c) { return c.charCodeAt(0) })) + return buf } -- cgit v1.2.3 From 55d56f77cf42a9c4e80768fd7e4a9bb6f0485606 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 20 Oct 2016 16:44:31 -0700 Subject: Began adding first basic keyring --- app/scripts/keyring-controller.js | 111 ++++++++++++++++++++++++++++++++++--- app/scripts/keyrings/simple.js | 41 ++++++++++++++ app/scripts/lib/idStore.js | 1 - app/scripts/metamask-controller.js | 2 + 4 files changed, 146 insertions(+), 9 deletions(-) create mode 100644 app/scripts/keyrings/simple.js (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index d25dddba1..86d61b22b 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -1,7 +1,13 @@ const EventEmitter = require('events').EventEmitter const encryptor = require('./lib/encryptor') const messageManager = require('./lib/message-manager') +const ethUtil = require('ethereumjs-util') +// Keyrings: +const SimpleKeyring = require('./keyrings/simple') +const keyringTypes = [ + SimpleKeyring, +] module.exports = class KeyringController extends EventEmitter { @@ -9,14 +15,15 @@ module.exports = class KeyringController extends EventEmitter { super() this.configManager = opts.configManager this.ethStore = opts.ethStore - this.keyChains = [] + this.keyrings = [] + this.identities = {} // Essentially a nickname hash } getState() { return { isInitialized: !!this.configManager.getVault(), isUnlocked: !!this.key, - isConfirmed: true, // this.configManager.getConfirmed(), + isConfirmed: true, // AUDIT this.configManager.getConfirmed(), isEthConfirmed: this.configManager.getShouldntShowWarning(), unconfTxs: this.configManager.unconfirmedTxs(), transactions: this.configManager.getTxList(), @@ -27,6 +34,8 @@ module.exports = class KeyringController extends EventEmitter { currentFiat: this.configManager.getCurrentFiat(), conversionRate: this.configManager.getConversionRate(), conversionDate: this.configManager.getConversionDate(), + keyringTypes: keyringTypes.map((krt) => krt.type()), + identities: this.identities, } } @@ -39,7 +48,7 @@ module.exports = class KeyringController extends EventEmitter { this.configManager.setSalt(salt) this.loadKey(password) .then((key) => { - return encryptor.encryptWithKey(key, {}) + return encryptor.encryptWithKey(key, []) }) .then((encryptedString) => { this.configManager.setVault(encryptedString) @@ -53,6 +62,10 @@ module.exports = class KeyringController extends EventEmitter { submitPassword(password, cb) { this.loadKey(password) .then((key) => { + return this.unlockKeyrings(key) + }) + .then((keyrings) => { + this.keyrings = keyrings cb(null, this.getState()) }) .catch((err) => { @@ -69,8 +82,94 @@ module.exports = class KeyringController extends EventEmitter { }) } + addNewKeyring(type, opts, cb) { + const i = this.getAccounts().length + const Keyring = this.getKeyringClassForType(type) + const keyring = new Keyring(opts) + const accounts = keyring.addAccounts(1) + + accounts.forEach((account) => { + this.createBalanceAndNickname(account, i) + }) + + this.persistAllKeyrings() + .then(() => { + cb(this.getState()) + }) + .catch((reason) => { + cb(reason) + }) + } + + // Takes an account address and an iterator representing + // the current number of nicknamed accounts. + createBalanceAndNickname(account, i) { + this.ethStore.addAccount(ethUtil.addHexPrefix(account)) + const oldNickname = this.configManager.nicknameForWallet(account) + const nickname = oldNickname || `Account ${++i}` + this.identities[account] = { + address: account, + nickname, + } + this.saveAccountLabel(account, nickname) + } + + saveAccountLabel (account, label, cb) { + const configManager = this.configManager + configManager.setNicknameForWallet(account, label) + if (cb) { + cb(null, label) + } + } + + persistAllKeyrings() { + const serialized = this.keyrings.map(k => k.serialize()) + return encryptor.encryptWithKey(this.key, serialized) + .then((encryptedString) => { + this.configManager.setVault(encryptedString) + return true + }) + .catch((reason) => { + console.error('Failed to persist keyrings.', reason) + }) + } + + unlockKeyrings(key) { + const encryptedVault = this.configManager.getVault() + return encryptor.decryptWithKey(key, encryptedVault) + .then((vault) => { + this.keyrings = vault.map(this.restoreKeyring) + return this.keyrings + }) + } + + restoreKeyring(serialized) { + const { type } = serialized + const Keyring = this.getKeyringClassForType(type) + const keyring = new Keyring(serialized) + return keyring + } + + getKeyringClassForType(type) { + const Keyring = keyringTypes.reduce((res, kr) => { + if (kr.type() === type) { + return kr + } else { + return res + } + }) + return Keyring + } + + getAccounts() { + return this.keyrings.map(kr => kr.getAccounts()) + .reduce((res, arr) => { + return res.concat(arr) + }, []) + } + setSelectedAddress(address, cb) { - this.selectedAddress = address + this.configManager.setSelectedAccount(address) cb(null, address) } @@ -102,10 +201,6 @@ module.exports = class KeyringController extends EventEmitter { cb(null, '0xPrivateKey') } - saveAccountLabel(account, label, cb) { - cb(/* null, label */) - } - tryPassword(password, cb) { cb() } diff --git a/app/scripts/keyrings/simple.js b/app/scripts/keyrings/simple.js new file mode 100644 index 000000000..3eda9b8f9 --- /dev/null +++ b/app/scripts/keyrings/simple.js @@ -0,0 +1,41 @@ +const EventEmitter = require('events').EventEmitter +const Wallet = require('ethereumjs-wallet') +const type = 'Simple Key Pair' + +module.exports = class SimpleKeyring extends EventEmitter { + + static type() { + return type + } + + constructor(opts) { + super() + this.type = type + this.opts = opts || {} + const walletData = this.opts.wallets || [] + this.wallets = walletData.map((w) => { + return Wallet.fromPrivateKey(w) + }) + } + + serialize() { + return { + type, + wallets: this.wallets.map(w => w.getPrivateKey()), + } + } + + addAccounts(n = 1) { + var newWallets = [] + for (var i = 0; i < n; i++) { + newWallets.push(Wallet.generate()) + } + this.wallets.concat(newWallets) + return newWallets.map(w => w.getAddress()) + } + + getAccounts() { + return this.wallets.map(w => w.getAddress()) + } + +} diff --git a/app/scripts/lib/idStore.js b/app/scripts/lib/idStore.js index 9d0ca7f19..416b65b85 100644 --- a/app/scripts/lib/idStore.js +++ b/app/scripts/lib/idStore.js @@ -114,7 +114,6 @@ IdentityStore.prototype.getState = function () { conversionRate: configManager.getConversionRate(), conversionDate: configManager.getConversionDate(), gasMultiplier: configManager.getGasMultiplier(), - })) } diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 92551d633..0d12931f6 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -61,6 +61,7 @@ module.exports = class MetamaskController { // forward directly to idStore createNewVault: idStore.createNewVault.bind(idStore), + addNewKeyring: idStore.addNewKeyring.bind(idStore), submitPassword: idStore.submitPassword.bind(idStore), setSelectedAddress: idStore.setSelectedAddress.bind(idStore), approveTransaction: idStore.approveTransaction.bind(idStore), @@ -183,6 +184,7 @@ module.exports = class MetamaskController { }) this.idStore.on('update', function (state) { storeSetFromObj(publicConfigStore, idStoreToPublic(state)) + this.sendUpdate() }) // idStore substate -- cgit v1.2.3 From 957b7a72b55be864320a346108673d02448caefd Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 20 Oct 2016 17:24:03 -0700 Subject: Improved simple account generation --- app/scripts/keyring-controller.js | 61 ++++++++++++++++++++++++--------------- app/scripts/keyrings/simple.js | 24 ++++++++------- 2 files changed, 51 insertions(+), 34 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 86d61b22b..7179f756a 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -16,7 +16,7 @@ module.exports = class KeyringController extends EventEmitter { this.configManager = opts.configManager this.ethStore = opts.ethStore this.keyrings = [] - this.identities = {} // Essentially a nickname hash + this.identities = {} // Essentially a name hash } getState() { @@ -64,8 +64,7 @@ module.exports = class KeyringController extends EventEmitter { .then((key) => { return this.unlockKeyrings(key) }) - .then((keyrings) => { - this.keyrings = keyrings + .then(() => { cb(null, this.getState()) }) .catch((err) => { @@ -74,7 +73,7 @@ module.exports = class KeyringController extends EventEmitter { } loadKey(password) { - const salt = this.configManager.getSalt() + const salt = this.configManager.getSalt() || generateSalt() return encryptor.keyFromPassword(password + salt) .then((key) => { this.key = key @@ -89,9 +88,10 @@ module.exports = class KeyringController extends EventEmitter { const accounts = keyring.addAccounts(1) accounts.forEach((account) => { - this.createBalanceAndNickname(account, i) + this.loadBalanceAndNickname(account, i) }) + this.keyrings.push(keyring) this.persistAllKeyrings() .then(() => { cb(this.getState()) @@ -102,28 +102,36 @@ module.exports = class KeyringController extends EventEmitter { } // Takes an account address and an iterator representing - // the current number of nicknamed accounts. - createBalanceAndNickname(account, i) { - this.ethStore.addAccount(ethUtil.addHexPrefix(account)) - const oldNickname = this.configManager.nicknameForWallet(account) - const nickname = oldNickname || `Account ${++i}` - this.identities[account] = { - address: account, - nickname, + // the current number of named accounts. + loadBalanceAndNickname(account, i) { + const address = ethUtil.addHexPrefix(account) + this.ethStore.addAccount(address) + const oldNickname = this.configManager.nicknameForWallet(address) + const name = oldNickname || `Account ${++i}` + this.identities[address] = { + address, + name, } - this.saveAccountLabel(account, nickname) + this.saveAccountLabel(address, name) } saveAccountLabel (account, label, cb) { + const address = ethUtil.addHexPrefix(account) const configManager = this.configManager - configManager.setNicknameForWallet(account, label) + configManager.setNicknameForWallet(address, label) if (cb) { cb(null, label) } } persistAllKeyrings() { - const serialized = this.keyrings.map(k => k.serialize()) + const serialized = this.keyrings.map((k) => { + return { + type: k.type, + // keyring.serialize() must return a JSON-encodable object. + data: k.serialize(), + } + }) return encryptor.encryptWithKey(this.key, serialized) .then((encryptedString) => { this.configManager.setVault(encryptedString) @@ -138,15 +146,21 @@ module.exports = class KeyringController extends EventEmitter { const encryptedVault = this.configManager.getVault() return encryptor.decryptWithKey(key, encryptedVault) .then((vault) => { - this.keyrings = vault.map(this.restoreKeyring) + this.keyrings = vault.map(this.restoreKeyring.bind(this, 0)) return this.keyrings }) } - restoreKeyring(serialized) { - const { type } = serialized + restoreKeyring(serialized, i) { + const { type, data } = serialized const Keyring = this.getKeyringClassForType(type) - const keyring = new Keyring(serialized) + const keyring = new Keyring() + keyring.deserialize(data) + + keyring.getAccounts().forEach((account) => { + this.loadBalanceAndNickname(account, i) + }) + return keyring } @@ -162,7 +176,8 @@ module.exports = class KeyringController extends EventEmitter { } getAccounts() { - return this.keyrings.map(kr => kr.getAccounts()) + const keyrings = this.keyrings || [] + return keyrings.map(kr => kr.getAccounts()) .reduce((res, arr) => { return res.concat(arr) }, []) @@ -207,8 +222,8 @@ module.exports = class KeyringController extends EventEmitter { } -function generateSalt (byteCount) { - var view = new Uint8Array(32) +function generateSalt (byteCount = 32) { + var view = new Uint8Array(byteCount) global.crypto.getRandomValues(view) var b64encoded = btoa(String.fromCharCode.apply(null, view)) return b64encoded diff --git a/app/scripts/keyrings/simple.js b/app/scripts/keyrings/simple.js index 3eda9b8f9..59d4691c6 100644 --- a/app/scripts/keyrings/simple.js +++ b/app/scripts/keyrings/simple.js @@ -12,17 +12,19 @@ module.exports = class SimpleKeyring extends EventEmitter { super() this.type = type this.opts = opts || {} - const walletData = this.opts.wallets || [] - this.wallets = walletData.map((w) => { - return Wallet.fromPrivateKey(w) - }) + this.wallets = [] } serialize() { - return { - type, - wallets: this.wallets.map(w => w.getPrivateKey()), - } + return this.wallets.map(w => w.getPrivateKey().toString('hex')) + } + + deserialize(wallets = []) { + this.wallets = wallets.map((w) => { + var b = new Buffer(w, 'hex') + const wallet = Wallet.fromPrivateKey(b) + return wallet + }) } addAccounts(n = 1) { @@ -30,12 +32,12 @@ module.exports = class SimpleKeyring extends EventEmitter { for (var i = 0; i < n; i++) { newWallets.push(Wallet.generate()) } - this.wallets.concat(newWallets) - return newWallets.map(w => w.getAddress()) + this.wallets = this.wallets.concat(newWallets) + return newWallets.map(w => w.getAddress().toString('hex')) } getAccounts() { - return this.wallets.map(w => w.getAddress()) + return this.wallets.map(w => w.getAddress().toString('hex')) } } -- cgit v1.2.3 From 9560ae93ee66cd9466c95c98b6853c2062f21235 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 20 Oct 2016 19:01:04 -0700 Subject: Added tx and msg signing to keychain & controller --- app/scripts/background.js | 8 ++--- app/scripts/keyring-controller.js | 56 ++++++++++++++++++++++++++++++- app/scripts/keyrings/simple.js | 41 +++++++++++++++++++++++ app/scripts/metamask-controller.js | 68 +++++++++++++++++++------------------- 4 files changed, 134 insertions(+), 39 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/background.js b/app/scripts/background.js index 652acc113..f05760ac3 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -21,7 +21,7 @@ const controller = new MetamaskController({ setData, loadData, }) -const idStore = controller.idStore +const keyringController = controller.keyringController function triggerUi () { if (!popupIsOpen) notification.show() @@ -82,7 +82,7 @@ function setupControllerConnection (stream) { // push updates to popup controller.ethStore.on('update', controller.sendUpdate.bind(controller)) controller.listeners.push(remote) - idStore.on('update', controller.sendUpdate.bind(controller)) + keyringController.on('update', controller.sendUpdate.bind(controller)) // teardown on disconnect eos(stream, () => { @@ -96,9 +96,9 @@ function setupControllerConnection (stream) { // plugin badge text // -idStore.on('update', updateBadge) +keyringController.on('update', updateBadge) -function updateBadge (state) { +function updateBadge () { var label = '' var unconfTxs = controller.configManager.unconfirmedTxs() var unconfTxLen = Object.keys(unconfTxs).length diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 7179f756a..7ebcc6b2c 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -2,6 +2,8 @@ const EventEmitter = require('events').EventEmitter const encryptor = require('./lib/encryptor') const messageManager = require('./lib/message-manager') const ethUtil = require('ethereumjs-util') +const BN = ethUtil.BN +const Transaction = require('ethereumjs-tx') // Keyrings: const SimpleKeyring = require('./keyrings/simple') @@ -198,8 +200,60 @@ module.exports = class KeyringController extends EventEmitter { } } + signTransaction(txParams, cb) { + try { + const address = ethUtil.addHexPrefix(txParams.from.toLowercase()) + const keyring = this.getKeyringForAccount(address) + + // Handle gas pricing + var gasMultiplier = this.configManager.getGasMultiplier() || 1 + var gasPrice = new BN(ethUtil.stripHexPrefix(txParams.gasPrice), 16) + gasPrice = gasPrice.mul(new BN(gasMultiplier * 100, 10)).div(new BN(100, 10)) + txParams.gasPrice = ethUtil.intToHex(gasPrice.toNumber()) + + // normalize values + txParams.to = ethUtil.addHexPrefix(txParams.to.toLowerCase()) + txParams.from = ethUtil.addHexPrefix(txParams.from.toLowerCase()) + txParams.value = ethUtil.addHexPrefix(txParams.value) + txParams.data = ethUtil.addHexPrefix(txParams.data) + txParams.gasLimit = ethUtil.addHexPrefix(txParams.gasLimit || txParams.gas) + txParams.nonce = ethUtil.addHexPrefix(txParams.nonce) + + let tx = new Transaction(txParams) + tx = keyring.signTransaction(address, tx) + + // Add the tx hash to the persisted meta-tx object + var txHash = ethUtil.bufferToHex(tx.hash()) + var metaTx = this.configManager.getTx(txParams.metamaskId) + metaTx.hash = txHash + this.configManager.updateTx(metaTx) + + // return raw serialized tx + var rawTx = ethUtil.bufferToHex(tx.serialize()) + cb(null, rawTx) + } catch (e) { + cb(e) + } + } + signMessage(msgParams, cb) { - cb() + try { + const keyring = this.getKeyringForAccount(msgParams.from) + const address = ethUtil.addHexPrefix(msgParams.from.toLowercase()) + const rawSig = keyring.signMessage(address, msgParams.data) + cb(null, rawSig) + } catch (e) { + cb(e) + } + } + + getKeyringForAccount(address) { + const hexed = ethUtil.addHexPrefix(address.toLowerCase()) + return this.keyrings.find((ring) => { + return ring.getAccounts() + .map(acct => ethUtil.addHexPrefix(acct.toLowerCase())) + .includes(hexed) + }) } cancelMessage(msgId, cb) { diff --git a/app/scripts/keyrings/simple.js b/app/scripts/keyrings/simple.js index 59d4691c6..6c5af1884 100644 --- a/app/scripts/keyrings/simple.js +++ b/app/scripts/keyrings/simple.js @@ -1,5 +1,6 @@ const EventEmitter = require('events').EventEmitter const Wallet = require('ethereumjs-wallet') +const ethUtil = require('ethereumjs-util') const type = 'Simple Key Pair' module.exports = class SimpleKeyring extends EventEmitter { @@ -40,4 +41,44 @@ module.exports = class SimpleKeyring extends EventEmitter { return this.wallets.map(w => w.getAddress().toString('hex')) } + // tx is an instance of the ethereumjs-transaction class. + signTransaction(address, tx) { + const wallet = this.getWalletForAccount(address) + var privKey = wallet.getPrivateKey() + tx.sign(privKey) + return tx + } + + // For eth_sign, we need to sign transactions: + signMessage(withAccount, data) { + const wallet = this.getWalletForAccount(withAccount) + const message = ethUtil.removeHexPrefix(data) + var privKey = wallet.getPrivateKey() + var msgSig = ethUtil.ecsign(new Buffer(message, 'hex'), privKey) + var rawMsgSig = ethUtil.bufferToHex(concatSig(msgSig.v, msgSig.r, msgSig.s)) + return rawMsgSig + } + + getWalletForAccount(account) { + return this.wallets.find(w => w.getAddress().toString('hex') === account) + } + +} + +function concatSig (v, r, s) { + const rSig = ethUtil.fromSigned(r) + const sSig = ethUtil.fromSigned(s) + const vSig = ethUtil.bufferToInt(v) + const rStr = padWithZeroes(ethUtil.toUnsigned(rSig).toString('hex'), 64) + const sStr = padWithZeroes(ethUtil.toUnsigned(sSig).toString('hex'), 64) + const vStr = ethUtil.stripHexPrefix(ethUtil.intToHex(vSig)) + return ethUtil.addHexPrefix(rStr.concat(sStr, vStr)).toString('hex') +} + +function padWithZeroes (number, length) { + var myString = '' + number + while (myString.length < length) { + myString = '0' + myString + } + return myString } diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 0d12931f6..96bd42513 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -1,7 +1,7 @@ const extend = require('xtend') const EthStore = require('eth-store') const MetaMaskProvider = require('web3-provider-engine/zero.js') -const IdentityStore = require('./keyring-controller') +const KeyringController = require('./keyring-controller') const messageManager = require('./lib/message-manager') const HostStore = require('./lib/remote-store.js').HostStore const Web3 = require('web3') @@ -15,12 +15,12 @@ module.exports = class MetamaskController { this.opts = opts this.listeners = [] this.configManager = new ConfigManager(opts) - this.idStore = new IdentityStore({ + this.keyringController = new KeyringController({ configManager: this.configManager, }) this.provider = this.initializeProvider(opts) this.ethStore = new EthStore(this.provider) - this.idStore.setStore(this.ethStore) + this.keyringController.setStore(this.ethStore) this.getNetwork() this.messageManager = messageManager this.publicConfigStore = this.initPublicConfigStore() @@ -38,13 +38,13 @@ module.exports = class MetamaskController { return extend( this.state, this.ethStore.getState(), - this.idStore.getState(), + this.keyringController.getState(), this.configManager.getConfig() ) } getApi () { - const idStore = this.idStore + const keyringController = this.keyringController return { getState: (cb) => { cb(null, this.getState()) }, @@ -59,19 +59,19 @@ module.exports = class MetamaskController { checkTOSChange: this.checkTOSChange.bind(this), setGasMultiplier: this.setGasMultiplier.bind(this), - // forward directly to idStore - createNewVault: idStore.createNewVault.bind(idStore), - addNewKeyring: idStore.addNewKeyring.bind(idStore), - submitPassword: idStore.submitPassword.bind(idStore), - setSelectedAddress: idStore.setSelectedAddress.bind(idStore), - approveTransaction: idStore.approveTransaction.bind(idStore), - cancelTransaction: idStore.cancelTransaction.bind(idStore), - signMessage: idStore.signMessage.bind(idStore), - cancelMessage: idStore.cancelMessage.bind(idStore), - setLocked: idStore.setLocked.bind(idStore), - exportAccount: idStore.exportAccount.bind(idStore), - saveAccountLabel: idStore.saveAccountLabel.bind(idStore), - tryPassword: idStore.tryPassword.bind(idStore), + // forward directly to keyringController + createNewVault: keyringController.createNewVault.bind(keyringController), + addNewKeyring: keyringController.addNewKeyring.bind(keyringController), + submitPassword: keyringController.submitPassword.bind(keyringController), + setSelectedAddress: keyringController.setSelectedAddress.bind(keyringController), + approveTransaction: keyringController.approveTransaction.bind(keyringController), + cancelTransaction: keyringController.cancelTransaction.bind(keyringController), + signMessage: keyringController.signMessage.bind(keyringController), + cancelMessage: keyringController.cancelMessage.bind(keyringController), + setLocked: keyringController.setLocked.bind(keyringController), + exportAccount: keyringController.exportAccount.bind(keyringController), + saveAccountLabel: keyringController.saveAccountLabel.bind(keyringController), + tryPassword: keyringController.tryPassword.bind(keyringController), // coinbase buyEth: this.buyEth.bind(this), // shapeshift @@ -133,27 +133,27 @@ module.exports = class MetamaskController { } initializeProvider (opts) { - const idStore = this.idStore + const keyringController = this.keyringController var providerOpts = { rpcUrl: this.configManager.getCurrentRpcAddress(), // account mgmt getAccounts: (cb) => { - var selectedAddress = idStore.getSelectedAddress() + var selectedAddress = this.configManager.getSelectedAccount() var result = selectedAddress ? [selectedAddress] : [] cb(null, result) }, // tx signing approveTransaction: this.newUnsignedTransaction.bind(this), signTransaction: (...args) => { - idStore.signTransaction(...args) + keyringController.signTransaction(...args) this.sendUpdate() }, // msg signing approveMessage: this.newUnsignedMessage.bind(this), signMessage: (...args) => { - idStore.signMessage(...args) + keyringController.signMessage(...args) this.sendUpdate() }, } @@ -161,7 +161,7 @@ module.exports = class MetamaskController { var provider = MetaMaskProvider(providerOpts) var web3 = new Web3(provider) this.web3 = web3 - idStore.web3 = web3 + keyringController.web3 = web3 provider.on('block', this.processBlock.bind(this)) provider.on('error', this.getNetwork.bind(this)) @@ -172,7 +172,7 @@ module.exports = class MetamaskController { initPublicConfigStore () { // get init state var initPublicState = extend( - idStoreToPublic(this.idStore.getState()), + keyringControllerToPublic(this.keyringController.getState()), configToPublic(this.configManager.getConfig()) ) @@ -182,13 +182,13 @@ module.exports = class MetamaskController { this.configManager.subscribe(function (state) { storeSetFromObj(publicConfigStore, configToPublic(state)) }) - this.idStore.on('update', function (state) { - storeSetFromObj(publicConfigStore, idStoreToPublic(state)) + this.keyringController.on('update', function (state) { + storeSetFromObj(publicConfigStore, keyringControllerToPublic(state)) this.sendUpdate() }) - // idStore substate - function idStoreToPublic (state) { + // keyringController substate + function keyringControllerToPublic (state) { return { selectedAddress: state.selectedAddress, } @@ -211,12 +211,12 @@ module.exports = class MetamaskController { } newUnsignedTransaction (txParams, onTxDoneCb) { - const idStore = this.idStore + const keyringController = this.keyringController let err = this.enforceTxValidations(txParams) if (err) return onTxDoneCb(err) - idStore.addUnconfirmedTransaction(txParams, onTxDoneCb, (err, txData) => { + keyringController.addUnconfirmedTransaction(txParams, onTxDoneCb, (err, txData) => { if (err) return onTxDoneCb(err) this.sendUpdate() this.opts.showUnconfirmedTx(txParams, txData, onTxDoneCb) @@ -231,9 +231,9 @@ module.exports = class MetamaskController { } newUnsignedMessage (msgParams, cb) { - var state = this.idStore.getState() + var state = this.keyringController.getState() if (!state.isUnlocked) { - this.idStore.addUnconfirmedMessage(msgParams, cb) + this.keyringController.addUnconfirmedMessage(msgParams, cb) this.opts.unlockAccountMessage() } else { this.addUnconfirmedMessage(msgParams, cb) @@ -242,8 +242,8 @@ module.exports = class MetamaskController { } addUnconfirmedMessage (msgParams, cb) { - const idStore = this.idStore - const msgId = idStore.addUnconfirmedMessage(msgParams, cb) + const keyringController = this.keyringController + const msgId = keyringController.addUnconfirmedMessage(msgParams, cb) this.opts.showUnconfirmedMessage(msgParams, msgId) } -- cgit v1.2.3 From c3e1c5c57f2062155626647e239c2a760f3e4b8a Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 21 Oct 2016 11:10:36 -0700 Subject: Added SimpleKeyring tests --- app/scripts/keyring-controller.js | 2 ++ app/scripts/keyrings/simple.js | 20 ++------------------ app/scripts/lib/sig-util.js | 23 +++++++++++++++++++++++ 3 files changed, 27 insertions(+), 18 deletions(-) create mode 100644 app/scripts/lib/sig-util.js (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 7ebcc6b2c..8192ed790 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -263,6 +263,8 @@ module.exports = class KeyringController extends EventEmitter { } setLocked(cb) { + this.key = null + this.keyrings = [] cb() } diff --git a/app/scripts/keyrings/simple.js b/app/scripts/keyrings/simple.js index 6c5af1884..9e832f274 100644 --- a/app/scripts/keyrings/simple.js +++ b/app/scripts/keyrings/simple.js @@ -2,6 +2,7 @@ const EventEmitter = require('events').EventEmitter const Wallet = require('ethereumjs-wallet') const ethUtil = require('ethereumjs-util') const type = 'Simple Key Pair' +const sigUtil = require('../lib/sig-util') module.exports = class SimpleKeyring extends EventEmitter { @@ -55,7 +56,7 @@ module.exports = class SimpleKeyring extends EventEmitter { const message = ethUtil.removeHexPrefix(data) var privKey = wallet.getPrivateKey() var msgSig = ethUtil.ecsign(new Buffer(message, 'hex'), privKey) - var rawMsgSig = ethUtil.bufferToHex(concatSig(msgSig.v, msgSig.r, msgSig.s)) + var rawMsgSig = ethUtil.bufferToHex(sigUtil.concatSig(msgSig.v, msgSig.r, msgSig.s)) return rawMsgSig } @@ -65,20 +66,3 @@ module.exports = class SimpleKeyring extends EventEmitter { } -function concatSig (v, r, s) { - const rSig = ethUtil.fromSigned(r) - const sSig = ethUtil.fromSigned(s) - const vSig = ethUtil.bufferToInt(v) - const rStr = padWithZeroes(ethUtil.toUnsigned(rSig).toString('hex'), 64) - const sStr = padWithZeroes(ethUtil.toUnsigned(sSig).toString('hex'), 64) - const vStr = ethUtil.stripHexPrefix(ethUtil.intToHex(vSig)) - return ethUtil.addHexPrefix(rStr.concat(sStr, vStr)).toString('hex') -} - -function padWithZeroes (number, length) { - var myString = '' + number - while (myString.length < length) { - myString = '0' + myString - } - return myString -} diff --git a/app/scripts/lib/sig-util.js b/app/scripts/lib/sig-util.js new file mode 100644 index 000000000..f8748f535 --- /dev/null +++ b/app/scripts/lib/sig-util.js @@ -0,0 +1,23 @@ +const ethUtil = require('ethereumjs-util') + +module.exports = { + + concatSig: function (v, r, s) { + const rSig = ethUtil.fromSigned(r) + const sSig = ethUtil.fromSigned(s) + const vSig = ethUtil.bufferToInt(v) + const rStr = padWithZeroes(ethUtil.toUnsigned(rSig).toString('hex'), 64) + const sStr = padWithZeroes(ethUtil.toUnsigned(sSig).toString('hex'), 64) + const vStr = ethUtil.stripHexPrefix(ethUtil.intToHex(vSig)) + return ethUtil.addHexPrefix(rStr.concat(sStr, vStr)).toString('hex') + }, + +} + +function padWithZeroes (number, length) { + var myString = '' + number + while (myString.length < length) { + myString = '0' + myString + } + return myString +} -- cgit v1.2.3 From 44aa1be2778a1647c9a607fd02c61bf93704d92d Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 21 Oct 2016 12:11:54 -0700 Subject: Create basic keyring-controller unit test file --- app/scripts/keyring-controller.js | 19 +++++++------------ app/scripts/lib/encryptor.js | 9 +++++++++ 2 files changed, 16 insertions(+), 12 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 8192ed790..5cf2542cc 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -17,6 +17,7 @@ module.exports = class KeyringController extends EventEmitter { super() this.configManager = opts.configManager this.ethStore = opts.ethStore + this.encryptor = encryptor this.keyrings = [] this.identities = {} // Essentially a name hash } @@ -46,11 +47,11 @@ module.exports = class KeyringController extends EventEmitter { } createNewVault(password, entropy, cb) { - const salt = generateSalt() + const salt = this.encryptor.generateSalt() this.configManager.setSalt(salt) this.loadKey(password) .then((key) => { - return encryptor.encryptWithKey(key, []) + return this.encryptor.encryptWithKey(key, []) }) .then((encryptedString) => { this.configManager.setVault(encryptedString) @@ -75,8 +76,8 @@ module.exports = class KeyringController extends EventEmitter { } loadKey(password) { - const salt = this.configManager.getSalt() || generateSalt() - return encryptor.keyFromPassword(password + salt) + const salt = this.configManager.getSalt() || this.encryptor.generateSalt() + return this.encryptor.keyFromPassword(password + salt) .then((key) => { this.key = key return key @@ -134,7 +135,7 @@ module.exports = class KeyringController extends EventEmitter { data: k.serialize(), } }) - return encryptor.encryptWithKey(this.key, serialized) + return this.encryptor.encryptWithKey(this.key, serialized) .then((encryptedString) => { this.configManager.setVault(encryptedString) return true @@ -146,7 +147,7 @@ module.exports = class KeyringController extends EventEmitter { unlockKeyrings(key) { const encryptedVault = this.configManager.getVault() - return encryptor.decryptWithKey(key, encryptedVault) + return this.encryptor.decryptWithKey(key, encryptedVault) .then((vault) => { this.keyrings = vault.map(this.restoreKeyring.bind(this, 0)) return this.keyrings @@ -278,9 +279,3 @@ module.exports = class KeyringController extends EventEmitter { } -function generateSalt (byteCount = 32) { - var view = new Uint8Array(byteCount) - global.crypto.getRandomValues(view) - var b64encoded = btoa(String.fromCharCode.apply(null, view)) - return b64encoded -} diff --git a/app/scripts/lib/encryptor.js b/app/scripts/lib/encryptor.js index 3d069ab33..832e6d528 100644 --- a/app/scripts/lib/encryptor.js +++ b/app/scripts/lib/encryptor.js @@ -22,6 +22,8 @@ module.exports = { // Buffer <-> base64 string methods encodeBufferToBase64, decodeBase64ToBuffer, + + generateSalt, } // Takes a Pojo, returns encrypted text. @@ -135,3 +137,10 @@ function decodeBase64ToBuffer (base64) { })) return buf } + +function generateSalt (byteCount = 32) { + var view = new Uint8Array(byteCount) + global.crypto.getRandomValues(view) + var b64encoded = btoa(String.fromCharCode.apply(null, view)) + return b64encoded +} -- cgit v1.2.3 From 626b52d24a3db05bf4f4e05df53f886615cc9538 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 21 Oct 2016 13:11:30 -0700 Subject: Fix bug in new KeyringController vault restoring logic. --- app/scripts/keyring-controller.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 5cf2542cc..807752a94 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -18,6 +18,8 @@ module.exports = class KeyringController extends EventEmitter { this.configManager = opts.configManager this.ethStore = opts.ethStore this.encryptor = encryptor + this.keyringTypes = keyringTypes + this.keyrings = [] this.identities = {} // Essentially a name hash } @@ -37,7 +39,7 @@ module.exports = class KeyringController extends EventEmitter { currentFiat: this.configManager.getCurrentFiat(), conversionRate: this.configManager.getConversionRate(), conversionDate: this.configManager.getConversionDate(), - keyringTypes: keyringTypes.map((krt) => krt.type()), + keyringTypes: this.keyringTypes.map((krt) => krt.type()), identities: this.identities, } } @@ -154,7 +156,7 @@ module.exports = class KeyringController extends EventEmitter { }) } - restoreKeyring(serialized, i) { + restoreKeyring(i, serialized) { const { type, data } = serialized const Keyring = this.getKeyringClassForType(type) const keyring = new Keyring() @@ -168,7 +170,7 @@ module.exports = class KeyringController extends EventEmitter { } getKeyringClassForType(type) { - const Keyring = keyringTypes.reduce((res, kr) => { + const Keyring = this.keyringTypes.reduce((res, kr) => { if (kr.type() === type) { return kr } else { -- cgit v1.2.3 From 1ddb8b9aec02e5e38a6eed8eeea1733ee3cd99c0 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 21 Oct 2016 13:41:33 -0700 Subject: Added tx & msg managing functionality to new KeyringController --- app/scripts/keyring-controller.js | 148 +++++++++++++++++++++++++++++++++++++ app/scripts/metamask-controller.js | 3 +- 2 files changed, 150 insertions(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 807752a94..45deb40c8 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -1,9 +1,13 @@ +const async = require('async') const EventEmitter = require('events').EventEmitter const encryptor = require('./lib/encryptor') const messageManager = require('./lib/message-manager') const ethUtil = require('ethereumjs-util') +const ethBinToOps = require('eth-bin-to-ops') +const EthQuery = require('eth-query') const BN = ethUtil.BN const Transaction = require('ethereumjs-tx') +const createId = require('web3-provider-engine/util/random-id') // Keyrings: const SimpleKeyring = require('./keyrings/simple') @@ -15,6 +19,7 @@ module.exports = class KeyringController extends EventEmitter { constructor (opts) { super() + this.web3 = opts.web3 this.configManager = opts.configManager this.ethStore = opts.ethStore this.encryptor = encryptor @@ -22,6 +27,11 @@ module.exports = class KeyringController extends EventEmitter { this.keyrings = [] this.identities = {} // Essentially a name hash + + this._unconfTxCbs = {} + this._unconfMsgCbs = {} + + this.network = 'loading' } getState() { @@ -41,6 +51,7 @@ module.exports = class KeyringController extends EventEmitter { conversionDate: this.configManager.getConversionDate(), keyringTypes: this.keyringTypes.map((krt) => krt.type()), identities: this.identities, + network: this.network, } } @@ -193,11 +204,121 @@ module.exports = class KeyringController extends EventEmitter { cb(null, address) } + addUnconfirmedTransaction(txParams, onTxDoneCb, cb) { + var self = this + const configManager = this.configManager + + // create txData obj with parameters and meta data + var time = (new Date()).getTime() + var txId = createId() + txParams.metamaskId = txId + txParams.metamaskNetworkId = this.network + var txData = { + id: txId, + txParams: txParams, + time: time, + status: 'unconfirmed', + gasMultiplier: configManager.getGasMultiplier() || 1, + } + + console.log('addUnconfirmedTransaction:', txData) + + // keep the onTxDoneCb around for after approval/denial (requires user interaction) + // This onTxDoneCb fires completion to the Dapp's write operation. + this._unconfTxCbs[txId] = onTxDoneCb + + var provider = this.ethStore._query.currentProvider + var query = new EthQuery(provider) + + // calculate metadata for tx + async.parallel([ + analyzeForDelegateCall, + estimateGas, + ], didComplete) + + // perform static analyis on the target contract code + function analyzeForDelegateCall(cb){ + if (txParams.to) { + query.getCode(txParams.to, function (err, result) { + if (err) return cb(err) + var code = ethUtil.toBuffer(result) + if (code !== '0x') { + var ops = ethBinToOps(code) + var containsDelegateCall = ops.some((op) => op.name === 'DELEGATECALL') + txData.containsDelegateCall = containsDelegateCall + cb() + } else { + cb() + } + }) + } else { + cb() + } + } + + function estimateGas(cb){ + query.estimateGas(txParams, function(err, result){ + if (err) return cb(err) + txData.estimatedGas = self.addGasBuffer(result) + cb() + }) + } + + function didComplete (err) { + if (err) return cb(err) + configManager.addTx(txData) + // signal update + self.emit('update') + // signal completion of add tx + cb(null, txData) + } + } + + addUnconfirmedMessage(msgParams, cb) { + // create txData obj with parameters and meta data + var time = (new Date()).getTime() + var msgId = createId() + var msgData = { + id: msgId, + msgParams: msgParams, + time: time, + status: 'unconfirmed', + } + messageManager.addMsg(msgData) + console.log('addUnconfirmedMessage:', msgData) + + // keep the cb around for after approval (requires user interaction) + // This cb fires completion to the Dapp's write operation. + this._unconfMsgCbs[msgId] = cb + + // signal update + this.emit('update') + return msgId + } + approveTransaction(txId, cb) { + const configManager = this.configManager + var approvalCb = this._unconfTxCbs[txId] || noop + + // accept tx cb() + approvalCb(null, true) + // clean up + configManager.confirmTx(txId) + delete this._unconfTxCbs[txId] + this.emit('update') } cancelTransaction(txId, cb) { + const configManager = this.configManager + var approvalCb = this._unconfTxCbs[txId] || noop + + // reject tx + approvalCb(null, false) + // clean up + configManager.rejectTx(txId) + delete this._unconfTxCbs[txId] + if (cb && typeof cb === 'function') { cb() } @@ -279,5 +400,32 @@ module.exports = class KeyringController extends EventEmitter { cb() } + getNetwork(err) { + if (err) { + this.network = 'loading' + this.emit('update') + } + + this.web3.version.getNetwork((err, network) => { + if (err) { + this.network = 'loading' + return this.emit('update') + } + if (global.METAMASK_DEBUG) { + console.log('web3.getNetwork returned ' + network) + } + this.network = network + this.emit('update') + }) + } + + addGasBuffer(gasHex) { + var gas = new BN(gasHex, 16) + var buffer = new BN('100000', 10) + var result = gas.add(buffer) + return ethUtil.addHexPrefix(result.toString(16)) + } + } +function noop () {} diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 96bd42513..c0da7cdaa 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -182,7 +182,8 @@ module.exports = class MetamaskController { this.configManager.subscribe(function (state) { storeSetFromObj(publicConfigStore, configToPublic(state)) }) - this.keyringController.on('update', function (state) { + this.keyringController.on('update', () => { + const state = this.keyringController.getState() storeSetFromObj(publicConfigStore, keyringControllerToPublic(state)) this.sendUpdate() }) -- cgit v1.2.3 From 518ff399fbf17bc747d956bbb64ca76f6bbd4057 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 21 Oct 2016 14:11:04 -0700 Subject: Fix loading indication --- app/scripts/keyring-controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 45deb40c8..28c920d22 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -31,7 +31,7 @@ module.exports = class KeyringController extends EventEmitter { this._unconfTxCbs = {} this._unconfMsgCbs = {} - this.network = 'loading' + this.network = null } getState() { -- cgit v1.2.3 From 678301a20e6112d79a052c13f921bb75c451c613 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 25 Oct 2016 13:24:03 -0700 Subject: Phase out extra warning screen. --- app/scripts/keyring-controller.js | 1 - app/scripts/lib/config-manager.js | 15 --------------- app/scripts/lib/idStore.js | 1 - app/scripts/metamask-controller.js | 10 ---------- 4 files changed, 27 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 28c920d22..5e7900b10 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -39,7 +39,6 @@ module.exports = class KeyringController extends EventEmitter { isInitialized: !!this.configManager.getVault(), isUnlocked: !!this.key, isConfirmed: true, // AUDIT this.configManager.getConfirmed(), - isEthConfirmed: this.configManager.getShouldntShowWarning(), unconfTxs: this.configManager.unconfirmedTxs(), transactions: this.configManager.getTxList(), unconfMsgs: messageManager.unconfirmedMsgs(), diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index ae4a84082..abe5dfc87 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -368,21 +368,6 @@ ConfigManager.prototype.getConversionDate = function () { return (('conversionDate' in data) && data.conversionDate) || 'N/A' } -ConfigManager.prototype.setShouldntShowWarning = function () { - var data = this.getData() - if (data.isEthConfirmed) { - data.isEthConfirmed = !data.isEthConfirmed - } else { - data.isEthConfirmed = true - } - this.setData(data) -} - -ConfigManager.prototype.getShouldntShowWarning = function () { - var data = this.getData() - return ('isEthConfirmed' in data) && data.isEthConfirmed -} - ConfigManager.prototype.getShapeShiftTxList = function () { var data = this.getData() var shapeShiftTxList = data.shapeShiftTxList ? data.shapeShiftTxList : [] diff --git a/app/scripts/lib/idStore.js b/app/scripts/lib/idStore.js index 416b65b85..5943826a3 100644 --- a/app/scripts/lib/idStore.js +++ b/app/scripts/lib/idStore.js @@ -103,7 +103,6 @@ IdentityStore.prototype.getState = function () { isUnlocked: this._isUnlocked(), seedWords: seedWords, isConfirmed: configManager.getConfirmed(), - isEthConfirmed: configManager.getShouldntShowWarning(), unconfTxs: configManager.unconfirmedTxs(), transactions: configManager.getTxList(), unconfMsgs: messageManager.unconfirmedMsgs(), diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index c0da7cdaa..9c89d752b 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -54,7 +54,6 @@ module.exports = class MetamaskController { agreeToDisclaimer: this.agreeToDisclaimer.bind(this), resetDisclaimer: this.resetDisclaimer.bind(this), setCurrentFiat: this.setCurrentFiat.bind(this), - agreeToEthWarning: this.agreeToEthWarning.bind(this), setTOSHash: this.setTOSHash.bind(this), checkTOSChange: this.checkTOSChange.bind(this), setGasMultiplier: this.setGasMultiplier.bind(this), @@ -334,15 +333,6 @@ module.exports = class MetamaskController { }, 300000) } - agreeToEthWarning (cb) { - try { - this.configManager.setShouldntShowWarning() - cb() - } catch (e) { - cb(e) - } - } - // called from popup setRpcTarget (rpcTarget) { this.configManager.setRpcTarget(rpcTarget) -- cgit v1.2.3 From f02e02bef845fb4b55dfa315c29da1e0afe9e68c Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 27 Oct 2016 16:50:01 -0700 Subject: Add hd wallet keyring --- app/scripts/keyrings/hd.js | 78 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 app/scripts/keyrings/hd.js (limited to 'app/scripts') diff --git a/app/scripts/keyrings/hd.js b/app/scripts/keyrings/hd.js new file mode 100644 index 000000000..a852c9d29 --- /dev/null +++ b/app/scripts/keyrings/hd.js @@ -0,0 +1,78 @@ +const EventEmitter = require('events').EventEmitter +const hdkey = require('ethereumjs-wallet/hdkey') +const bip39 = require('bip39') +const ethUtil = require('ethereumjs-util') +const type = 'HD Key Tree' +const sigUtil = require('../lib/sig-util') + +module.exports = class SimpleKeyring extends EventEmitter { + + static type() { + return type + } + + constructor(opts) { + super() + this.type = type + this.opts = opts || {} + this.wallets = [] + this.mnemonic = null + } + + deserialize({ mnemonic, n }) { + this.initFromMnemonic(mnemonic || bip39.generateMnemonic()) + this.addAccounts(n) + } + + initFromMnemonic(mnemonic) { + const seed = bip39.mnemonicToSeed(mnemonic) + this.mnemonic = mnemonic + this.hdWallet = hdkey.fromMasterSeed(seed) + this.seed = bip39.mnemonicToSeedHex(seed) + } + + serialize() { + return { + mnemonic: this.mnemonic, + n: this.wallets.length, + } + } + + addAccounts(n = 1) { + const newWallets = [] + for (let i = 0; i < n; i++) { + const wallet = this.hdWallet.getWallet() + newWallets.push(wallet) + this.wallets.push(wallet) + } + return newWallets.map(w => w.getAddress().toString('hex')) + } + + getAccounts() { + return this.wallets.map(w => w.getAddress().toString('hex')) + } + + // tx is an instance of the ethereumjs-transaction class. + signTransaction(address, tx) { + const wallet = this.getWalletForAccount(address) + var privKey = wallet.getPrivateKey() + tx.sign(privKey) + return tx + } + + // For eth_sign, we need to sign transactions: + signMessage(withAccount, data) { + const wallet = this.getWalletForAccount(withAccount) + const message = ethUtil.removeHexPrefix(data) + var privKey = wallet.getPrivateKey() + var msgSig = ethUtil.ecsign(new Buffer(message, 'hex'), privKey) + var rawMsgSig = ethUtil.bufferToHex(sigUtil.concatSig(msgSig.v, msgSig.r, msgSig.s)) + return rawMsgSig + } + + getWalletForAccount(account) { + return this.wallets.find(w => w.getAddress().toString('hex') === account) + } + +} + -- cgit v1.2.3 From 2690d1acfd3042f468cb2cd7ccc2dccd63c20cc9 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 27 Oct 2016 17:23:26 -0700 Subject: Added hd wallet tests --- app/scripts/keyrings/hd.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyrings/hd.js b/app/scripts/keyrings/hd.js index a852c9d29..61df8f28e 100644 --- a/app/scripts/keyrings/hd.js +++ b/app/scripts/keyrings/hd.js @@ -5,7 +5,9 @@ const ethUtil = require('ethereumjs-util') const type = 'HD Key Tree' const sigUtil = require('../lib/sig-util') -module.exports = class SimpleKeyring extends EventEmitter { +const hdPathString = `m/44'/60'/0'/0` + +module.exports = class HdKeyring extends EventEmitter { static type() { return type @@ -28,7 +30,7 @@ module.exports = class SimpleKeyring extends EventEmitter { const seed = bip39.mnemonicToSeed(mnemonic) this.mnemonic = mnemonic this.hdWallet = hdkey.fromMasterSeed(seed) - this.seed = bip39.mnemonicToSeedHex(seed) + this.root = this.hdWallet.derivePath(hdPathString) } serialize() { @@ -39,9 +41,15 @@ module.exports = class SimpleKeyring extends EventEmitter { } addAccounts(n = 1) { + if (!this.root) { + this.initFromMnemonic(bip39.generateMnemonic()) + } + + const oldLen = this.wallets.length const newWallets = [] - for (let i = 0; i < n; i++) { - const wallet = this.hdWallet.getWallet() + for (let i = oldLen; i < n + oldLen; i++) { + const child = this.root.deriveChild(i) + const wallet = child.getWallet() newWallets.push(wallet) this.wallets.push(wallet) } -- cgit v1.2.3 From 6ec471c6dcc52a9d2b599b849fa5017f3056fd43 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 28 Oct 2016 12:10:35 -0700 Subject: Configure BIP44 Keychain as default one --- app/scripts/keyring-controller.js | 31 ++++++++++++++++++++++++------- app/scripts/metamask-controller.js | 1 + 2 files changed, 25 insertions(+), 7 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 5e7900b10..3ac101ad8 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -11,8 +11,10 @@ const createId = require('web3-provider-engine/util/random-id') // Keyrings: const SimpleKeyring = require('./keyrings/simple') +const HdKeyring = require('./keyrings/hd') const keyringTypes = [ SimpleKeyring, + HdKeyring, ] module.exports = class KeyringController extends EventEmitter { @@ -67,7 +69,12 @@ module.exports = class KeyringController extends EventEmitter { }) .then((encryptedString) => { this.configManager.setVault(encryptedString) - cb(null, this.getState()) + + // TEMPORARY SINGLE-KEYRING CONFIG: + this.addNewKeyring('HD Key Tree', null, cb) + + // NORMAL BEHAVIOR: + // cb(null, this.getState()) }) .catch((err) => { cb(err) @@ -97,25 +104,35 @@ module.exports = class KeyringController extends EventEmitter { } addNewKeyring(type, opts, cb) { - const i = this.getAccounts().length const Keyring = this.getKeyringClassForType(type) const keyring = new Keyring(opts) const accounts = keyring.addAccounts(1) - accounts.forEach((account) => { - this.loadBalanceAndNickname(account, i) - }) - + this.setupAccounts(accounts) this.keyrings.push(keyring) this.persistAllKeyrings() .then(() => { - cb(this.getState()) + cb(null, this.getState()) }) .catch((reason) => { cb(reason) }) } + addNewAccount(keyRingNum = 0, cb) { + const ring = this.keyrings[keyRingNum] + const accounts = ring.addAccounts(1) + this.setupAccounts(accounts) + cb(null, this.getState()) + } + + setupAccounts(accounts) { + const i = this.getAccounts().length + accounts.forEach((account) => { + this.loadBalanceAndNickname(account, i) + }) + } + // Takes an account address and an iterator representing // the current number of named accounts. loadBalanceAndNickname(account, i) { diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 9c89d752b..a7d9a8ec2 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -61,6 +61,7 @@ module.exports = class MetamaskController { // forward directly to keyringController createNewVault: keyringController.createNewVault.bind(keyringController), addNewKeyring: keyringController.addNewKeyring.bind(keyringController), + addNewAccount: keyringController.addNewAccount.bind(keyringController), submitPassword: keyringController.submitPassword.bind(keyringController), setSelectedAddress: keyringController.setSelectedAddress.bind(keyringController), approveTransaction: keyringController.approveTransaction.bind(keyringController), -- cgit v1.2.3 From 18e5173f061c2e21b5acb3e1b329343b5cffc558 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Sat, 29 Oct 2016 02:29:25 -0700 Subject: Now migrating old vaults to new DEN format --- app/scripts/keyring-controller.js | 33 +++++++++++++++++++++---- app/scripts/lib/idStore-migrator.js | 48 +++++++++++++++++++++++++++++++++++++ app/scripts/lib/idStore.js | 4 +++- 3 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 app/scripts/lib/idStore-migrator.js (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 3ac101ad8..b8066e303 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -9,6 +9,9 @@ const BN = ethUtil.BN const Transaction = require('ethereumjs-tx') const createId = require('web3-provider-engine/util/random-id') +// TEMPORARY UNTIL FULL DEPRECATION: +const IdStoreMigrator = require('./lib/idStore-migrator') + // Keyrings: const SimpleKeyring = require('./keyrings/simple') const HdKeyring = require('./keyrings/hd') @@ -34,6 +37,11 @@ module.exports = class KeyringController extends EventEmitter { this._unconfMsgCbs = {} this.network = null + + // TEMPORARY UNTIL FULL DEPRECATION: + this.idStoreMigrator = new IdStoreMigrator({ + configManager: this.configManager, + }) } getState() { @@ -63,18 +71,32 @@ module.exports = class KeyringController extends EventEmitter { createNewVault(password, entropy, cb) { const salt = this.encryptor.generateSalt() this.configManager.setSalt(salt) - this.loadKey(password) + + let serialized + + this.idStoreMigrator.oldSeedForPassword(password) + .then((oldSerialized) => { + if (oldSerialized) { + serialized = oldSerialized + } + return this.loadKey(password) + }) .then((key) => { - return this.encryptor.encryptWithKey(key, []) + const first = serialized ? [serialized] : [] + return this.encryptor.encryptWithKey(key, first) }) .then((encryptedString) => { this.configManager.setVault(encryptedString) - // TEMPORARY SINGLE-KEYRING CONFIG: - this.addNewKeyring('HD Key Tree', null, cb) + if (!serialized) { + // TEMPORARY SINGLE-KEYRING CONFIG: + return this.addNewKeyring('HD Key Tree', null, cb) + } else { + return this.submitPassword(password, cb) + } // NORMAL BEHAVIOR: - // cb(null, this.getState()) + // return cb(null, this.getState()) }) .catch((err) => { cb(err) @@ -99,6 +121,7 @@ module.exports = class KeyringController extends EventEmitter { return this.encryptor.keyFromPassword(password + salt) .then((key) => { this.key = key + this.configManager.setSalt(salt) return key }) } diff --git a/app/scripts/lib/idStore-migrator.js b/app/scripts/lib/idStore-migrator.js new file mode 100644 index 000000000..f8f7cb51a --- /dev/null +++ b/app/scripts/lib/idStore-migrator.js @@ -0,0 +1,48 @@ +const IdentityStore = require('./idStore') + + +module.exports = class IdentityStoreMigrator { + + constructor ({ configManager }) { + this.configManager = configManager + this.idStore = new IdentityStore({ configManager }) + } + + oldSeedForPassword( password ) { + const isOldVault = this.hasOldVault() + if (!isOldVault) { + console.log('does not seem to have old vault') + console.log('THE DATA:') + console.log(this.configManager.getData()) + return Promise.resolve(null) + } + + return new Promise((resolve, reject) => { + this.idStore.submitPassword(password, (err) => { + if (err) return reject(err) + try { + resolve(this.serializeVault()) + } catch (e) { + reject(e) + } + }) + }) + } + + serializeVault() { + const mnemonic = this.idStore._idmgmt.getSeed() + console.dir(this.idStore._idmgmt) + const n = this.idStore._getAddresses().length + + return { + type: 'HD Key Tree', + data: { mnemonic, n }, + } + } + + hasOldVault() { + const wallet = this.configManager.getWallet() + console.log('found old wallet: ' + wallet) + return wallet + } +} diff --git a/app/scripts/lib/idStore.js b/app/scripts/lib/idStore.js index 14f25dd1d..8ee2b62dd 100644 --- a/app/scripts/lib/idStore.js +++ b/app/scripts/lib/idStore.js @@ -422,7 +422,9 @@ IdentityStore.prototype._loadIdentities = function () { var addresses = this._getAddresses() addresses.forEach((address, i) => { // // add to ethStore - this._ethStore.addAccount(ethUtil.addHexPrefix(address)) + if (this._ethStore) { + this._ethStore.addAccount(ethUtil.addHexPrefix(address)) + } // add to identities const defaultLabel = 'Wallet ' + (i + 1) const nickname = configManager.nicknameForWallet(address) -- cgit v1.2.3 From 6fc498f8a030ea00bcef9b8b3400fc527fc4aeed Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Mon, 31 Oct 2016 09:47:20 -0700 Subject: Implement auto-fauceting --- app/scripts/keyring-controller.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index b8066e303..e7b9612bf 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -8,6 +8,7 @@ const EthQuery = require('eth-query') const BN = ethUtil.BN const Transaction = require('ethereumjs-tx') const createId = require('web3-provider-engine/util/random-id') +const autoFaucet = require('./lib/auto-faucet') // TEMPORARY UNTIL FULL DEPRECATION: const IdStoreMigrator = require('./lib/idStore-migrator') @@ -90,7 +91,11 @@ module.exports = class KeyringController extends EventEmitter { if (!serialized) { // TEMPORARY SINGLE-KEYRING CONFIG: - return this.addNewKeyring('HD Key Tree', null, cb) + return this.addNewKeyring('HD Key Tree', null, (err, newState) => { + const firstAccount = this.keyrings[0].getAccounts()[0] + autoFaucet(ethUtil.addHexPrefix(firstAccount)) + cb(err, newState) + }) } else { return this.submitPassword(password, cb) } -- cgit v1.2.3 From 96643c222a74552d98218fe1f9fc81e493a1960f Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Mon, 31 Oct 2016 11:35:09 -0700 Subject: Implement seed word confirmation page. Remove logs. Move HD render files to ui/app. --- app/scripts/keyring-controller.js | 18 ++++++++++++++---- app/scripts/lib/config-manager.js | 15 ++++++++++++++- app/scripts/lib/idStore-migrator.js | 5 ----- app/scripts/metamask-controller.js | 1 + 4 files changed, 29 insertions(+), 10 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index e7b9612bf..ee6445121 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -47,6 +47,7 @@ module.exports = class KeyringController extends EventEmitter { getState() { return { + seedWords: this.configManager.getSeedWords(), isInitialized: !!this.configManager.getVault(), isUnlocked: !!this.key, isConfirmed: true, // AUDIT this.configManager.getConfirmed(), @@ -90,10 +91,14 @@ module.exports = class KeyringController extends EventEmitter { this.configManager.setVault(encryptedString) if (!serialized) { - // TEMPORARY SINGLE-KEYRING CONFIG: - return this.addNewKeyring('HD Key Tree', null, (err, newState) => { - const firstAccount = this.keyrings[0].getAccounts()[0] - autoFaucet(ethUtil.addHexPrefix(firstAccount)) + this.addNewKeyring('HD Key Tree', null, (err, newState) => { + const firstKeyring = this.keyrings[0] + const firstAccount = firstKeyring.getAccounts()[0] + const hexAccount = ethUtil.addHexPrefix(firstAccount) + const seedWords = firstKeyring.serialize().mnemonic + this.configManager.setSelectedAccount(hexAccount) + this.configManager.setSeedWords(seedWords) + autoFaucet(hexAccount) cb(err, newState) }) } else { @@ -470,6 +475,11 @@ module.exports = class KeyringController extends EventEmitter { return ethUtil.addHexPrefix(result.toString(16)) } + clearSeedWordCache(cb) { + this.configManager.setSeedWords(null) + cb(null, this.configManager.getSelectedAccount()) + } + } function noop () {} diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index abe5dfc87..8f5590738 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -2,6 +2,7 @@ const Migrator = require('pojo-migrator') const MetamaskConfig = require('../config.js') const migrations = require('./migrations') const rp = require('request-promise') +const ethUtil = require('ethereumjs-util') const TESTNET_RPC = MetamaskConfig.network.testnet const MAINNET_RPC = MetamaskConfig.network.mainnet @@ -138,7 +139,7 @@ ConfigManager.prototype.getSelectedAccount = function () { ConfigManager.prototype.setSelectedAccount = function (address) { var config = this.getConfig() - config.selectedAccount = address + config.selectedAccount = ethUtil.addHexPrefix(address) this.setConfig(config) } @@ -153,11 +154,23 @@ ConfigManager.prototype.setShowSeedWords = function (should) { this.setData(data) } + ConfigManager.prototype.getShouldShowSeedWords = function () { var data = this.migrator.getData() return data.showSeedWords } +ConfigManager.prototype.setSeedWords = function (words) { + var data = this.getData() + data.seedWords = words + this.setData(data) +} + +ConfigManager.prototype.getSeedWords = function () { + var data = this.getData() + return ('seedWords' in data) && data.seedWords +} + ConfigManager.prototype.getCurrentRpcAddress = function () { var provider = this.getProvider() if (!provider) return null diff --git a/app/scripts/lib/idStore-migrator.js b/app/scripts/lib/idStore-migrator.js index f8f7cb51a..c81e7ddfe 100644 --- a/app/scripts/lib/idStore-migrator.js +++ b/app/scripts/lib/idStore-migrator.js @@ -11,9 +11,6 @@ module.exports = class IdentityStoreMigrator { oldSeedForPassword( password ) { const isOldVault = this.hasOldVault() if (!isOldVault) { - console.log('does not seem to have old vault') - console.log('THE DATA:') - console.log(this.configManager.getData()) return Promise.resolve(null) } @@ -31,7 +28,6 @@ module.exports = class IdentityStoreMigrator { serializeVault() { const mnemonic = this.idStore._idmgmt.getSeed() - console.dir(this.idStore._idmgmt) const n = this.idStore._getAddresses().length return { @@ -42,7 +38,6 @@ module.exports = class IdentityStoreMigrator { hasOldVault() { const wallet = this.configManager.getWallet() - console.log('found old wallet: ' + wallet) return wallet } } diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index a7d9a8ec2..48c56d915 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -60,6 +60,7 @@ module.exports = class MetamaskController { // forward directly to keyringController createNewVault: keyringController.createNewVault.bind(keyringController), + clearSeedWordCache: keyringController.clearSeedWordCache.bind(keyringController), addNewKeyring: keyringController.addNewKeyring.bind(keyringController), addNewAccount: keyringController.addNewAccount.bind(keyringController), submitPassword: keyringController.submitPassword.bind(keyringController), -- cgit v1.2.3 From e2f67a2cb85552bd8fcf2f7929c14a9d028adccb Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 1 Nov 2016 11:21:46 -0700 Subject: Do not open MM page in dev mode. --- app/scripts/background.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/background.js b/app/scripts/background.js index f05760ac3..27c9179a7 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -10,6 +10,7 @@ const MetamaskController = require('./metamask-controller') const extension = require('./lib/extension') const STORAGE_KEY = 'metamask-config' +const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' var popupIsOpen = false const controller = new MetamaskController({ @@ -29,7 +30,7 @@ function triggerUi () { // On first install, open a window to MetaMask website to how-it-works. extension.runtime.onInstalled.addListener(function (details) { - if (details.reason === 'install') { + if ((details.reason === 'install') && (!METAMASK_DEBUG)) { extension.tabs.create({url: 'https://metamask.io/#how-it-works'}) } }) -- cgit v1.2.3 From db356a181a3fde4ad528c699f6da517053171866 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 1 Nov 2016 11:25:38 -0700 Subject: Made progress on parity for MultiVault - Deleted some unused items - Renamed files and paths to match with new locations. - Modified keyring controller logic to separate concerns. - Fix account naming issues. - Enable creation of new vault with default HD keyring. - Formatting issues. --- app/scripts/background.js | 2 +- app/scripts/keyring-controller.js | 65 ++++++++++++++++++++++++++------------ app/scripts/keyrings/hd.js | 18 ++++++++--- app/scripts/metamask-controller.js | 3 +- 4 files changed, 60 insertions(+), 28 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/background.js b/app/scripts/background.js index 27c9179a7..7cb25d8bf 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -30,7 +30,7 @@ function triggerUi () { // On first install, open a window to MetaMask website to how-it-works. extension.runtime.onInstalled.addListener(function (details) { - if ((details.reason === 'install') && (!METAMASK_DEBUG)) { + if ((details.reason === 'install') && (!METAMASK_DEBUG)) { extension.tabs.create({url: 'https://metamask.io/#how-it-works'}) } }) diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index ee6445121..f6e71b005 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -70,6 +70,23 @@ module.exports = class KeyringController extends EventEmitter { this.ethStore = ethStore } + createNewVaultAndKeychain(password, entropy, cb) { + this.createNewVault(password, entropy, (err, serialized) => { + if (err) return cb(err) + this.createFirstKeyTree(serialized, password, cb) + }) + } + + createNewVaultAndRestore(password, seed, cb) { + this.createNewVault(password, '', (err) => { + if (err) return cb(err) + this.addNewKeyring('HD Key Tree', { + mnemonic: seed, + n: 0, + }, cb) + }) + } + createNewVault(password, entropy, cb) { const salt = this.encryptor.generateSalt() this.configManager.setSalt(salt) @@ -89,22 +106,7 @@ module.exports = class KeyringController extends EventEmitter { }) .then((encryptedString) => { this.configManager.setVault(encryptedString) - - if (!serialized) { - this.addNewKeyring('HD Key Tree', null, (err, newState) => { - const firstKeyring = this.keyrings[0] - const firstAccount = firstKeyring.getAccounts()[0] - const hexAccount = ethUtil.addHexPrefix(firstAccount) - const seedWords = firstKeyring.serialize().mnemonic - this.configManager.setSelectedAccount(hexAccount) - this.configManager.setSeedWords(seedWords) - autoFaucet(hexAccount) - cb(err, newState) - }) - } else { - return this.submitPassword(password, cb) - } - + cb(null, serialized) // NORMAL BEHAVIOR: // return cb(null, this.getState()) }) @@ -113,6 +115,23 @@ module.exports = class KeyringController extends EventEmitter { }) } + createFirstKeyTree(serialized, password, cb) { + if (!serialized) { + this.addNewKeyring('HD Key Tree', {n: 1}, (err, newState) => { + const firstKeyring = this.keyrings[0] + const firstAccount = firstKeyring.getAccounts()[0] + const hexAccount = ethUtil.addHexPrefix(firstAccount) + const seedWords = firstKeyring.serialize().mnemonic + this.configManager.setSelectedAccount(hexAccount) + this.configManager.setSeedWords(seedWords) + autoFaucet(hexAccount) + cb(err, this.getState()) + }) + } else { + return this.submitPassword(password, cb) + } + } + submitPassword(password, cb) { this.loadKey(password) .then((key) => { @@ -139,10 +158,10 @@ module.exports = class KeyringController extends EventEmitter { addNewKeyring(type, opts, cb) { const Keyring = this.getKeyringClassForType(type) const keyring = new Keyring(opts) - const accounts = keyring.addAccounts(1) + const accounts = keyring.getAccounts() - this.setupAccounts(accounts) this.keyrings.push(keyring) + this.setupAccounts(accounts) this.persistAllKeyrings() .then(() => { cb(null, this.getState()) @@ -160,17 +179,21 @@ module.exports = class KeyringController extends EventEmitter { } setupAccounts(accounts) { - const i = this.getAccounts().length accounts.forEach((account) => { - this.loadBalanceAndNickname(account, i) + this.loadBalanceAndNickname(account) }) } // Takes an account address and an iterator representing // the current number of named accounts. - loadBalanceAndNickname(account, i) { + loadBalanceAndNickname(account) { const address = ethUtil.addHexPrefix(account) this.ethStore.addAccount(address) + this.createNickname(address) + } + + createNickname(address) { + var i = Object.keys(this.identities).length const oldNickname = this.configManager.nicknameForWallet(address) const name = oldNickname || `Account ${++i}` this.identities[address] = { diff --git a/app/scripts/keyrings/hd.js b/app/scripts/keyrings/hd.js index 61df8f28e..69b8d25bc 100644 --- a/app/scripts/keyrings/hd.js +++ b/app/scripts/keyrings/hd.js @@ -17,13 +17,22 @@ module.exports = class HdKeyring extends EventEmitter { super() this.type = type this.opts = opts || {} + this.deserialize(opts) + } + + deserialize(opts) { this.wallets = [] this.mnemonic = null - } + this.root = null + + if ('mnemonic' in opts) { + this.initFromMnemonic(opts.mnemonic) + } + + if ('n' in opts) { + this.addAccounts(opts.n) + } - deserialize({ mnemonic, n }) { - this.initFromMnemonic(mnemonic || bip39.generateMnemonic()) - this.addAccounts(n) } initFromMnemonic(mnemonic) { @@ -83,4 +92,3 @@ module.exports = class HdKeyring extends EventEmitter { } } - diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 48c56d915..7ce22b642 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -59,7 +59,8 @@ module.exports = class MetamaskController { setGasMultiplier: this.setGasMultiplier.bind(this), // forward directly to keyringController - createNewVault: keyringController.createNewVault.bind(keyringController), + createNewVaultAndKeychain: keyringController.createNewVaultAndKeychain.bind(keyringController), + createNewVaultAndRestore: keyringController.createNewVaultAndRestore.bind(keyringController), clearSeedWordCache: keyringController.clearSeedWordCache.bind(keyringController), addNewKeyring: keyringController.addNewKeyring.bind(keyringController), addNewAccount: keyringController.addNewAccount.bind(keyringController), -- cgit v1.2.3 From 498b30bddcfa16f587a9f62b74a5d9fceb04cb07 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 1 Nov 2016 11:51:51 -0700 Subject: Fix seed phrase restore --- app/scripts/keyring-controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index f6e71b005..2681b3d48 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -82,7 +82,7 @@ module.exports = class KeyringController extends EventEmitter { if (err) return cb(err) this.addNewKeyring('HD Key Tree', { mnemonic: seed, - n: 0, + n: 1, }, cb) }) } -- cgit v1.2.3 From b5f6ef8c013f2f742546a04e148bac99fbc4691c Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 1 Nov 2016 17:00:17 -0700 Subject: Fixed bugs related to clearing caches when restoring to a new vault --- app/scripts/keyring-controller.js | 51 +++++++++++++++++++++++++++++++++----- app/scripts/keyrings/hd.js | 2 +- app/scripts/metamask-controller.js | 5 ++-- 3 files changed, 48 insertions(+), 10 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 2681b3d48..b93d4a156 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -9,6 +9,7 @@ const BN = ethUtil.BN const Transaction = require('ethereumjs-tx') const createId = require('web3-provider-engine/util/random-id') const autoFaucet = require('./lib/auto-faucet') +const bip39 = require('bip39') // TEMPORARY UNTIL FULL DEPRECATION: const IdStoreMigrator = require('./lib/idStore-migrator') @@ -46,6 +47,8 @@ module.exports = class KeyringController extends EventEmitter { } getState() { + let address = this.configManager.getSelectedAccount() + return { seedWords: this.configManager.getSeedWords(), isInitialized: !!this.configManager.getVault(), @@ -55,7 +58,8 @@ module.exports = class KeyringController extends EventEmitter { transactions: this.configManager.getTxList(), unconfMsgs: messageManager.unconfirmedMsgs(), messages: messageManager.getMsgList(), - selectedAddress: this.configManager.getSelectedAccount(), + selectedAddress: address, + selectedAccount: address, shapeShiftTxList: this.configManager.getShapeShiftTxList(), currentFiat: this.configManager.getCurrentFiat(), conversionRate: this.configManager.getConversionRate(), @@ -78,12 +82,33 @@ module.exports = class KeyringController extends EventEmitter { } createNewVaultAndRestore(password, seed, cb) { + if (typeof password !== 'string') { + return cb('Password must be text.') + } + + if (!bip39.validateMnemonic(seed)) { + return cb('Seed phrase is invalid.') + } + + this.clearKeyrings() + this.createNewVault(password, '', (err) => { if (err) return cb(err) this.addNewKeyring('HD Key Tree', { mnemonic: seed, n: 1, - }, cb) + }, (err) => { + if (err) return cb(err) + const firstKeyring = this.keyrings[0] + const accounts = firstKeyring.getAccounts() + const firstAccount = accounts[0] + const hexAccount = ethUtil.addHexPrefix(firstAccount) + this.configManager.setSelectedAccount(hexAccount) + + this.setupAccounts(accounts) + this.emit('update') + cb(null, this.getState()) + }) }) } @@ -138,6 +163,7 @@ module.exports = class KeyringController extends EventEmitter { return this.unlockKeyrings(key) }) .then(() => { + this.emit('update') cb(null, this.getState()) }) .catch((err) => { @@ -175,6 +201,7 @@ module.exports = class KeyringController extends EventEmitter { const ring = this.keyrings[keyRingNum] const accounts = ring.addAccounts(1) this.setupAccounts(accounts) + this.persistAllKeyrings() cb(null, this.getState()) } @@ -468,10 +495,6 @@ module.exports = class KeyringController extends EventEmitter { cb(null, '0xPrivateKey') } - tryPassword(password, cb) { - cb() - } - getNetwork(err) { if (err) { this.network = 'loading' @@ -503,6 +526,22 @@ module.exports = class KeyringController extends EventEmitter { cb(null, this.configManager.getSelectedAccount()) } + clearKeyrings() { + let accounts + try { + accounts = Object.keys(this.ethStore._currentState.accounts) + } catch (e) { + accounts = [] + } + accounts.forEach((address) => { + this.ethStore.removeAccount(address) + }) + + this.keyrings = [] + this.identities = {} + this.configManager.setSelectedAccount() + } + } function noop () {} diff --git a/app/scripts/keyrings/hd.js b/app/scripts/keyrings/hd.js index 69b8d25bc..90052d9e7 100644 --- a/app/scripts/keyrings/hd.js +++ b/app/scripts/keyrings/hd.js @@ -13,7 +13,7 @@ module.exports = class HdKeyring extends EventEmitter { return type } - constructor(opts) { + constructor(opts = {}) { super() this.type = type this.opts = opts || {} diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 7ce22b642..6dffefe98 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -38,8 +38,8 @@ module.exports = class MetamaskController { return extend( this.state, this.ethStore.getState(), - this.keyringController.getState(), - this.configManager.getConfig() + this.configManager.getConfig(), + this.keyringController.getState() ) } @@ -73,7 +73,6 @@ module.exports = class MetamaskController { setLocked: keyringController.setLocked.bind(keyringController), exportAccount: keyringController.exportAccount.bind(keyringController), saveAccountLabel: keyringController.saveAccountLabel.bind(keyringController), - tryPassword: keyringController.tryPassword.bind(keyringController), // coinbase buyEth: this.buyEth.bind(this), // shapeshift -- cgit v1.2.3 From 8f3db0dbc0bafdc604bd7359bd41370f594c792c Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 1 Nov 2016 22:19:04 -0700 Subject: Add reveal of seed words. --- app/scripts/keyring-controller.js | 10 ++++++++-- app/scripts/metamask-controller.js | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index b93d4a156..e6a7d95b2 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -132,8 +132,6 @@ module.exports = class KeyringController extends EventEmitter { .then((encryptedString) => { this.configManager.setVault(encryptedString) cb(null, serialized) - // NORMAL BEHAVIOR: - // return cb(null, this.getState()) }) .catch((err) => { cb(err) @@ -157,6 +155,14 @@ module.exports = class KeyringController extends EventEmitter { } } + placeSeedWords () { + const firstKeyring = this.keyrings[0] + const seedWords = firstKeyring.serialize().mnemonic + this.configManager.setSeedWords(seedWords) + } + + + submitPassword(password, cb) { this.loadKey(password) .then((key) => { diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 6dffefe98..a165a2e2a 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -59,6 +59,7 @@ module.exports = class MetamaskController { setGasMultiplier: this.setGasMultiplier.bind(this), // forward directly to keyringController + placeSeedWords: keyringController.placeSeedWords.bind(keyringController), createNewVaultAndKeychain: keyringController.createNewVaultAndKeychain.bind(keyringController), createNewVaultAndRestore: keyringController.createNewVaultAndRestore.bind(keyringController), clearSeedWordCache: keyringController.clearSeedWordCache.bind(keyringController), -- cgit v1.2.3 From 4cf1b606e46fa735263b5e1fade5910b572335e3 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 2 Nov 2016 15:04:50 -0700 Subject: Fix handling of migrating old vault style Now old vaults are recognized as an "Initialized" MetaMask instance. Upon logging in, when fetching the initial password-derived key, if there is no new-style vault, but there is an old style vault, it is migrated to the new format before proceeding through the usual unlocking steps. --- app/scripts/keyring-controller.js | 102 ++++++++++++++++++++++-------------- app/scripts/keyrings/hd.js | 7 ++- app/scripts/lib/idStore-migrator.js | 15 ++++-- 3 files changed, 78 insertions(+), 46 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index e6a7d95b2..1b9739b9c 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -47,11 +47,14 @@ module.exports = class KeyringController extends EventEmitter { } getState() { - let address = this.configManager.getSelectedAccount() + const configManager = this.configManager + const address = configManager.getSelectedAccount() + const wallet = configManager.getWallet() // old style vault + const vault = configManager.getVault() // new style vault return { seedWords: this.configManager.getSeedWords(), - isInitialized: !!this.configManager.getVault(), + isInitialized: (!!wallet || !!vault), isUnlocked: !!this.key, isConfirmed: true, // AUDIT this.configManager.getConfirmed(), unconfTxs: this.configManager.unconfirmedTxs(), @@ -77,7 +80,7 @@ module.exports = class KeyringController extends EventEmitter { createNewVaultAndKeychain(password, entropy, cb) { this.createNewVault(password, entropy, (err, serialized) => { if (err) return cb(err) - this.createFirstKeyTree(serialized, password, cb) + this.createFirstKeyTree(password, cb) }) } @@ -112,25 +115,43 @@ module.exports = class KeyringController extends EventEmitter { }) } - createNewVault(password, entropy, cb) { - const salt = this.encryptor.generateSalt() - this.configManager.setSalt(salt) + migrateAndGetKey(password) { + let key + const shouldMigrate = !!this.configManager.getWallet() && !this.configManager.getVault() - let serialized - - this.idStoreMigrator.oldSeedForPassword(password) - .then((oldSerialized) => { - if (oldSerialized) { - serialized = oldSerialized + return this.loadKey(password) + .then((derivedKey) => { + key = derivedKey + return this.idStoreMigrator.oldSeedForPassword(password) + }) + .then((serialized) => { + if (serialized && shouldMigrate) { + const accountLength = this.getAccounts().length + const keyring = this.restoreKeyring(accountLength, serialized) + this.keyrings.push(keyring) + this.configManager.setSelectedAccount(keyring.getAccounts()[0]) + return this.persistAllKeyrings().then(() => { + return key + }) + } else { + return Promise.resolve(key) } - return this.loadKey(password) }) - .then((key) => { - const first = serialized ? [serialized] : [] - return this.encryptor.encryptWithKey(key, first) + } + + createNewVault(password, entropy, cb) { + const configManager = this.configManager + const salt = this.encryptor.generateSalt() + configManager.setSalt(salt) + + return new Promise((res, rej) => { + this.createFirstKeyTree(password, (err, state) => { + if (err) return rej(err) + res(configManager.getVault()) + }) }) .then((encryptedString) => { - this.configManager.setVault(encryptedString) + const serialized = this.keyrings[0].serialize() cb(null, serialized) }) .catch((err) => { @@ -138,21 +159,19 @@ module.exports = class KeyringController extends EventEmitter { }) } - createFirstKeyTree(serialized, password, cb) { - if (!serialized) { - this.addNewKeyring('HD Key Tree', {n: 1}, (err, newState) => { - const firstKeyring = this.keyrings[0] - const firstAccount = firstKeyring.getAccounts()[0] - const hexAccount = ethUtil.addHexPrefix(firstAccount) - const seedWords = firstKeyring.serialize().mnemonic - this.configManager.setSelectedAccount(hexAccount) - this.configManager.setSeedWords(seedWords) - autoFaucet(hexAccount) - cb(err, this.getState()) - }) - } else { - return this.submitPassword(password, cb) - } + createFirstKeyTree(password, cb) { + this.clearKeyrings() + this.addNewKeyring('HD Key Tree', {n: 1}, (err) => { + const firstKeyring = this.keyrings[0] + const firstAccount = firstKeyring.getAccounts()[0] + const hexAccount = ethUtil.addHexPrefix(firstAccount) + const seedWords = firstKeyring.serialize().mnemonic + this.configManager.setSelectedAccount(hexAccount) + this.configManager.setSeedWords(seedWords) + autoFaucet(hexAccount) + this.persistAllKeyrings() + cb(err, this.getState()) + }) } placeSeedWords () { @@ -161,10 +180,8 @@ module.exports = class KeyringController extends EventEmitter { this.configManager.setSeedWords(seedWords) } - - submitPassword(password, cb) { - this.loadKey(password) + this.migrateAndGetKey(password) .then((key) => { return this.unlockKeyrings(key) }) @@ -173,6 +190,7 @@ module.exports = class KeyringController extends EventEmitter { cb(null, this.getState()) }) .catch((err) => { + console.error(err) cb(err) }) } @@ -208,7 +226,12 @@ module.exports = class KeyringController extends EventEmitter { const accounts = ring.addAccounts(1) this.setupAccounts(accounts) this.persistAllKeyrings() - cb(null, this.getState()) + .then(() => { + cb(null, this.getState()) + }) + .catch((reason) => { + cb(reason) + }) } setupAccounts(accounts) { @@ -258,9 +281,6 @@ module.exports = class KeyringController extends EventEmitter { this.configManager.setVault(encryptedString) return true }) - .catch((reason) => { - console.error('Failed to persist keyrings.', reason) - }) } unlockKeyrings(key) { @@ -268,6 +288,9 @@ module.exports = class KeyringController extends EventEmitter { return this.encryptor.decryptWithKey(key, encryptedVault) .then((vault) => { this.keyrings = vault.map(this.restoreKeyring.bind(this, 0)) + return this.persistAllKeyrings() + }) + .then(() => { return this.keyrings }) } @@ -282,6 +305,7 @@ module.exports = class KeyringController extends EventEmitter { this.loadBalanceAndNickname(account, i) }) + this.keyrings.push(keyring) return keyring } diff --git a/app/scripts/keyrings/hd.js b/app/scripts/keyrings/hd.js index 90052d9e7..d0ebee419 100644 --- a/app/scripts/keyrings/hd.js +++ b/app/scripts/keyrings/hd.js @@ -16,11 +16,11 @@ module.exports = class HdKeyring extends EventEmitter { constructor(opts = {}) { super() this.type = type - this.opts = opts || {} this.deserialize(opts) } - deserialize(opts) { + deserialize(opts = {}) { + this.opts = opts || {} this.wallets = [] this.mnemonic = null this.root = null @@ -32,12 +32,11 @@ module.exports = class HdKeyring extends EventEmitter { if ('n' in opts) { this.addAccounts(opts.n) } - } initFromMnemonic(mnemonic) { - const seed = bip39.mnemonicToSeed(mnemonic) this.mnemonic = mnemonic + const seed = bip39.mnemonicToSeed(mnemonic) this.hdWallet = hdkey.fromMasterSeed(seed) this.root = this.hdWallet.derivePath(hdPathString) } diff --git a/app/scripts/lib/idStore-migrator.js b/app/scripts/lib/idStore-migrator.js index c81e7ddfe..2d1826641 100644 --- a/app/scripts/lib/idStore-migrator.js +++ b/app/scripts/lib/idStore-migrator.js @@ -5,12 +5,21 @@ module.exports = class IdentityStoreMigrator { constructor ({ configManager }) { this.configManager = configManager - this.idStore = new IdentityStore({ configManager }) + const hasOldVault = this.hasOldVault() + if (!hasOldVault) { + this.idStore = new IdentityStore({ configManager }) + } } oldSeedForPassword( password ) { - const isOldVault = this.hasOldVault() - if (!isOldVault) { + const hasOldVault = this.hasOldVault() + const configManager = this.configManager + + if (!this.idStore) { + this.idStore = new IdentityStore({ configManager }) + } + + if (!hasOldVault) { return Promise.resolve(null) } -- cgit v1.2.3 From ed1917d71a464c5cf12d3dc283fcc30976134db8 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 2 Nov 2016 16:18:47 -0700 Subject: Fix initial vault creation --- app/scripts/keyring-controller.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 1b9739b9c..f0fb0ad65 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -122,6 +122,7 @@ module.exports = class KeyringController extends EventEmitter { return this.loadKey(password) .then((derivedKey) => { key = derivedKey + this.key = key return this.idStoreMigrator.oldSeedForPassword(password) }) .then((serialized) => { @@ -144,10 +145,13 @@ module.exports = class KeyringController extends EventEmitter { const salt = this.encryptor.generateSalt() configManager.setSalt(salt) - return new Promise((res, rej) => { - this.createFirstKeyTree(password, (err, state) => { - if (err) return rej(err) - res(configManager.getVault()) + return this.migrateAndGetKey(password) + .then((key) => { + return new Promise((res, rej) => { + this.createFirstKeyTree(password, (err, state) => { + if (err) return rej(err) + res(configManager.getVault()) + }) }) }) .then((encryptedString) => { -- cgit v1.2.3 From 185396ff08786dc108cabb57d47925032a9e2d74 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 2 Nov 2016 16:35:46 -0700 Subject: Fix dual vault creation bug --- app/scripts/keyring-controller.js | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index f0fb0ad65..3b59c7890 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -131,12 +131,10 @@ module.exports = class KeyringController extends EventEmitter { const keyring = this.restoreKeyring(accountLength, serialized) this.keyrings.push(keyring) this.configManager.setSelectedAccount(keyring.getAccounts()[0]) - return this.persistAllKeyrings().then(() => { - return key - }) - } else { - return Promise.resolve(key) } + return this.persistAllKeyrings().then(() => { + return key + }) }) } @@ -147,12 +145,7 @@ module.exports = class KeyringController extends EventEmitter { return this.migrateAndGetKey(password) .then((key) => { - return new Promise((res, rej) => { - this.createFirstKeyTree(password, (err, state) => { - if (err) return rej(err) - res(configManager.getVault()) - }) - }) + cb(null, configManager.getVault()) }) .then((encryptedString) => { const serialized = this.keyrings[0].serialize() -- cgit v1.2.3 From 756f56cfee442992c51ac84b042b36dc3f7845ba Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 3 Nov 2016 10:42:34 -0700 Subject: Don't faucet in development --- app/scripts/lib/auto-faucet.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/auto-faucet.js b/app/scripts/lib/auto-faucet.js index 59cf0ec20..ec5e8ed4c 100644 --- a/app/scripts/lib/auto-faucet.js +++ b/app/scripts/lib/auto-faucet.js @@ -1,6 +1,8 @@ -var uri = 'https://faucet.metamask.io/' +const uri = 'https://faucet.metamask.io/' +const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' module.exports = function (address) { + if (METAMASK_DEBUG) return // Don't faucet in development var http = new XMLHttpRequest() var data = address http.open('POST', uri, true) -- cgit v1.2.3 From 4db976ae46352c49e4401eba865081425419efe0 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 3 Nov 2016 11:22:10 -0700 Subject: Don't faucet during tests --- app/scripts/lib/auto-faucet.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/auto-faucet.js b/app/scripts/lib/auto-faucet.js index ec5e8ed4c..1e86f735e 100644 --- a/app/scripts/lib/auto-faucet.js +++ b/app/scripts/lib/auto-faucet.js @@ -1,8 +1,9 @@ const uri = 'https://faucet.metamask.io/' const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' +const env = process.env.METAMASK_ENV module.exports = function (address) { - if (METAMASK_DEBUG) return // Don't faucet in development + if (METAMASK_DEBUG || env === 'test') return // Don't faucet in development or test var http = new XMLHttpRequest() var data = address http.open('POST', uri, true) -- cgit v1.2.3 From 9ca3c57339571c43106306a6b4fadcfad40d3c19 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 3 Nov 2016 11:34:57 -0700 Subject: Fix vault creation bug --- app/scripts/keyring-controller.js | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 3b59c7890..3bc9561e2 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -78,7 +78,7 @@ module.exports = class KeyringController extends EventEmitter { } createNewVaultAndKeychain(password, entropy, cb) { - this.createNewVault(password, entropy, (err, serialized) => { + this.createNewVault(password, entropy, (err) => { if (err) return cb(err) this.createFirstKeyTree(password, cb) }) @@ -107,8 +107,8 @@ module.exports = class KeyringController extends EventEmitter { const firstAccount = accounts[0] const hexAccount = ethUtil.addHexPrefix(firstAccount) this.configManager.setSelectedAccount(hexAccount) - this.setupAccounts(accounts) + this.emit('update') cb(null, this.getState()) }) @@ -127,8 +127,7 @@ module.exports = class KeyringController extends EventEmitter { }) .then((serialized) => { if (serialized && shouldMigrate) { - const accountLength = this.getAccounts().length - const keyring = this.restoreKeyring(accountLength, serialized) + const keyring = this.restoreKeyring(serialized) this.keyrings.push(keyring) this.configManager.setSelectedAccount(keyring.getAccounts()[0]) } @@ -144,12 +143,8 @@ module.exports = class KeyringController extends EventEmitter { configManager.setSalt(salt) return this.migrateAndGetKey(password) - .then((key) => { - cb(null, configManager.getVault()) - }) - .then((encryptedString) => { - const serialized = this.keyrings[0].serialize() - cb(null, serialized) + .then(() => { + cb(null) }) .catch((err) => { cb(err) @@ -160,12 +155,14 @@ module.exports = class KeyringController extends EventEmitter { this.clearKeyrings() this.addNewKeyring('HD Key Tree', {n: 1}, (err) => { const firstKeyring = this.keyrings[0] - const firstAccount = firstKeyring.getAccounts()[0] + const accounts = firstKeyring.getAccounts() + const firstAccount = accounts[0] const hexAccount = ethUtil.addHexPrefix(firstAccount) const seedWords = firstKeyring.serialize().mnemonic - this.configManager.setSelectedAccount(hexAccount) + this.configManager.setSelectedAccount(firstAccount) this.configManager.setSeedWords(seedWords) autoFaucet(hexAccount) + this.setupAccounts(accounts) this.persistAllKeyrings() cb(err, this.getState()) }) @@ -284,7 +281,7 @@ module.exports = class KeyringController extends EventEmitter { const encryptedVault = this.configManager.getVault() return this.encryptor.decryptWithKey(key, encryptedVault) .then((vault) => { - this.keyrings = vault.map(this.restoreKeyring.bind(this, 0)) + this.keyrings = vault.map(this.restoreKeyring.bind(this)) return this.persistAllKeyrings() }) .then(() => { @@ -292,15 +289,14 @@ module.exports = class KeyringController extends EventEmitter { }) } - restoreKeyring(i, serialized) { + restoreKeyring(serialized) { const { type, data } = serialized const Keyring = this.getKeyringClassForType(type) const keyring = new Keyring() keyring.deserialize(data) - keyring.getAccounts().forEach((account) => { - this.loadBalanceAndNickname(account, i) - }) + const accounts = keyring.getAccounts() + this.setupAccounts(accounts) this.keyrings.push(keyring) return keyring -- cgit v1.2.3 From bd2a429a85d27fc82e76115ec136640cbfecf9e1 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 3 Nov 2016 11:59:20 -0700 Subject: Fix account nicknaming bug When nicknaming, we weren't normalizing the input, and so we were retrieving with differently formatted addresses than we were persisting. --- app/scripts/keyring-controller.js | 5 ++++- app/scripts/lib/config-manager.js | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 3bc9561e2..06c1e2761 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -250,7 +250,7 @@ module.exports = class KeyringController extends EventEmitter { address, name, } - this.saveAccountLabel(address, name) + return this.saveAccountLabel(address, name) } saveAccountLabel (account, label, cb) { @@ -259,6 +259,8 @@ module.exports = class KeyringController extends EventEmitter { configManager.setNicknameForWallet(address, label) if (cb) { cb(null, label) + } else { + return label } } @@ -270,6 +272,7 @@ module.exports = class KeyringController extends EventEmitter { data: k.serialize(), } }) + return this.encryptor.encryptWithKey(this.key, serialized) .then((encryptedString) => { this.configManager.setVault(encryptedString) diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index 8f5590738..f50d95c12 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -269,13 +269,15 @@ ConfigManager.prototype.getWalletNicknames = function () { } ConfigManager.prototype.nicknameForWallet = function (account) { + const address = ethUtil.addHexPrefix(account.toLowerCase()) const nicknames = this.getWalletNicknames() - return nicknames[account] + return nicknames[address] } ConfigManager.prototype.setNicknameForWallet = function (account, nickname) { + const address = ethUtil.addHexPrefix(account.toLowerCase()) const nicknames = this.getWalletNicknames() - nicknames[account] = nickname + nicknames[address] = nickname var data = this.getData() data.walletNicknames = nicknames this.setData(data) -- cgit v1.2.3 From e0246975a7a40a72cc68fb3dbe5782c9c219fea2 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 3 Nov 2016 13:44:29 -0700 Subject: Finish fixing nicknaming bug --- app/scripts/keyring-controller.js | 67 +++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 28 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 06c1e2761..505414c88 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -105,7 +105,7 @@ module.exports = class KeyringController extends EventEmitter { const firstKeyring = this.keyrings[0] const accounts = firstKeyring.getAccounts() const firstAccount = accounts[0] - const hexAccount = ethUtil.addHexPrefix(firstAccount) + const hexAccount = normalize(firstAccount) this.configManager.setSelectedAccount(hexAccount) this.setupAccounts(accounts) @@ -157,14 +157,19 @@ module.exports = class KeyringController extends EventEmitter { const firstKeyring = this.keyrings[0] const accounts = firstKeyring.getAccounts() const firstAccount = accounts[0] - const hexAccount = ethUtil.addHexPrefix(firstAccount) + const hexAccount = normalize(firstAccount) const seedWords = firstKeyring.serialize().mnemonic this.configManager.setSelectedAccount(firstAccount) this.configManager.setSeedWords(seedWords) autoFaucet(hexAccount) this.setupAccounts(accounts) this.persistAllKeyrings() - cb(err, this.getState()) + .then(() => { + cb(err, this.getState()) + }) + .catch((reason) => { + cb(reason) + }) }) } @@ -179,7 +184,9 @@ module.exports = class KeyringController extends EventEmitter { .then((key) => { return this.unlockKeyrings(key) }) - .then(() => { + .then((keyrings) => { + this.keyrings = keyrings + this.setupAccounts() this.emit('update') cb(null, this.getState()) }) @@ -229,7 +236,8 @@ module.exports = class KeyringController extends EventEmitter { } setupAccounts(accounts) { - accounts.forEach((account) => { + var arr = accounts || this.getAccounts() + arr.forEach((account) => { this.loadBalanceAndNickname(account) }) } @@ -237,26 +245,28 @@ module.exports = class KeyringController extends EventEmitter { // Takes an account address and an iterator representing // the current number of named accounts. loadBalanceAndNickname(account) { - const address = ethUtil.addHexPrefix(account) + const address = normalize(account) this.ethStore.addAccount(address) this.createNickname(address) } createNickname(address) { + const hexAddress = normalize(address) var i = Object.keys(this.identities).length const oldNickname = this.configManager.nicknameForWallet(address) const name = oldNickname || `Account ${++i}` - this.identities[address] = { - address, + this.identities[hexAddress] = { + address: hexAddress, name, } - return this.saveAccountLabel(address, name) + return this.saveAccountLabel(hexAddress, name) } saveAccountLabel (account, label, cb) { - const address = ethUtil.addHexPrefix(account) + const address = normalize(account) const configManager = this.configManager configManager.setNicknameForWallet(address, label) + this.identities[address].name = label if (cb) { cb(null, label) } else { @@ -268,7 +278,6 @@ module.exports = class KeyringController extends EventEmitter { const serialized = this.keyrings.map((k) => { return { type: k.type, - // keyring.serialize() must return a JSON-encodable object. data: k.serialize(), } }) @@ -284,10 +293,7 @@ module.exports = class KeyringController extends EventEmitter { const encryptedVault = this.configManager.getVault() return this.encryptor.decryptWithKey(key, encryptedVault) .then((vault) => { - this.keyrings = vault.map(this.restoreKeyring.bind(this)) - return this.persistAllKeyrings() - }) - .then(() => { + vault.forEach(this.restoreKeyring.bind(this)) return this.keyrings }) } @@ -325,8 +331,9 @@ module.exports = class KeyringController extends EventEmitter { } setSelectedAddress(address, cb) { - this.configManager.setSelectedAccount(address) - cb(null, address) + var addr = normalize(address) + this.configManager.setSelectedAccount(addr) + cb(null, addr) } addUnconfirmedTransaction(txParams, onTxDoneCb, cb) { @@ -451,7 +458,7 @@ module.exports = class KeyringController extends EventEmitter { signTransaction(txParams, cb) { try { - const address = ethUtil.addHexPrefix(txParams.from.toLowercase()) + const address = normalize(txParams.from) const keyring = this.getKeyringForAccount(address) // Handle gas pricing @@ -461,12 +468,12 @@ module.exports = class KeyringController extends EventEmitter { txParams.gasPrice = ethUtil.intToHex(gasPrice.toNumber()) // normalize values - txParams.to = ethUtil.addHexPrefix(txParams.to.toLowerCase()) - txParams.from = ethUtil.addHexPrefix(txParams.from.toLowerCase()) - txParams.value = ethUtil.addHexPrefix(txParams.value) - txParams.data = ethUtil.addHexPrefix(txParams.data) - txParams.gasLimit = ethUtil.addHexPrefix(txParams.gasLimit || txParams.gas) - txParams.nonce = ethUtil.addHexPrefix(txParams.nonce) + txParams.to = normalize(txParams.to) + txParams.from = normalize(txParams.from) + txParams.value = normalize(txParams.value) + txParams.data = normalize(txParams.data) + txParams.gasLimit = normalize(txParams.gasLimit || txParams.gas) + txParams.nonce = normalize(txParams.nonce) let tx = new Transaction(txParams) tx = keyring.signTransaction(address, tx) @@ -488,7 +495,7 @@ module.exports = class KeyringController extends EventEmitter { signMessage(msgParams, cb) { try { const keyring = this.getKeyringForAccount(msgParams.from) - const address = ethUtil.addHexPrefix(msgParams.from.toLowercase()) + const address = normalize(msgParams.from) const rawSig = keyring.signMessage(address, msgParams.data) cb(null, rawSig) } catch (e) { @@ -497,10 +504,10 @@ module.exports = class KeyringController extends EventEmitter { } getKeyringForAccount(address) { - const hexed = ethUtil.addHexPrefix(address.toLowerCase()) + const hexed = normalize(address) return this.keyrings.find((ring) => { return ring.getAccounts() - .map(acct => ethUtil.addHexPrefix(acct.toLowerCase())) + .map(normalize) .includes(hexed) }) } @@ -544,7 +551,7 @@ module.exports = class KeyringController extends EventEmitter { var gas = new BN(gasHex, 16) var buffer = new BN('100000', 10) var result = gas.add(buffer) - return ethUtil.addHexPrefix(result.toString(16)) + return normalize(result.toString(16)) } clearSeedWordCache(cb) { @@ -570,4 +577,8 @@ module.exports = class KeyringController extends EventEmitter { } +function normalize(address) { + return ethUtil.addHexPrefix(address.toLowerCase()) +} + function noop () {} -- cgit v1.2.3 From 2afc06287dfd1a87bd247234c9a04b92a8394cac Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Thu, 3 Nov 2016 15:40:23 -0700 Subject: Implement private key exporting. --- app/scripts/keyring-controller.js | 9 +++++++-- app/scripts/keyrings/hd.js | 16 +++++++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 505414c88..aa303c43c 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -353,7 +353,6 @@ module.exports = class KeyringController extends EventEmitter { gasMultiplier: configManager.getGasMultiplier() || 1, } - console.log('addUnconfirmedTransaction:', txData) // keep the onTxDoneCb around for after approval/denial (requires user interaction) // This onTxDoneCb fires completion to the Dapp's write operation. @@ -525,7 +524,13 @@ module.exports = class KeyringController extends EventEmitter { } exportAccount(address, cb) { - cb(null, '0xPrivateKey') + try { + const keyring = this.getKeyringForAccount(address) + const privateKey = keyring.exportAccount(normalize(address)) + cb(null, privateKey) + } catch (e) { + cb(e) + } } getNetwork(err) { diff --git a/app/scripts/keyrings/hd.js b/app/scripts/keyrings/hd.js index d0ebee419..4bfc56c15 100644 --- a/app/scripts/keyrings/hd.js +++ b/app/scripts/keyrings/hd.js @@ -48,6 +48,11 @@ module.exports = class HdKeyring extends EventEmitter { } } + exportAccount(address) { + const wallet = this.getWalletForAccount(address) + return wallet.getPrivateKey().toString('hex') + } + addAccounts(n = 1) { if (!this.root) { this.initFromMnemonic(bip39.generateMnemonic()) @@ -87,7 +92,16 @@ module.exports = class HdKeyring extends EventEmitter { } getWalletForAccount(account) { - return this.wallets.find(w => w.getAddress().toString('hex') === account) + return this.wallets.find((w) => { + const address = w.getAddress().toString('hex') + return ((address === account) || (normalize(address) === account)) + }) } + + +} + +function normalize(address) { + return ethUtil.addHexPrefix(address.toLowerCase()) } -- cgit v1.2.3 From ba7d6b437f2e03a9e2bb46dcda846cee1f816ce1 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 3 Nov 2016 16:06:57 -0700 Subject: Fix password validation and persistence issue Was wiping the vault on each successful password attempt... :P --- app/scripts/keyring-controller.js | 9 +++++---- app/scripts/lib/encryptor.js | 3 +++ 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index aa303c43c..81a05e133 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -131,9 +131,7 @@ module.exports = class KeyringController extends EventEmitter { this.keyrings.push(keyring) this.configManager.setSelectedAccount(keyring.getAccounts()[0]) } - return this.persistAllKeyrings().then(() => { - return key - }) + return key }) } @@ -143,6 +141,9 @@ module.exports = class KeyringController extends EventEmitter { configManager.setSalt(salt) return this.migrateAndGetKey(password) + .then(() => { + return this.persistAllKeyrings() + }) .then(() => { cb(null) }) @@ -173,7 +174,7 @@ module.exports = class KeyringController extends EventEmitter { }) } - placeSeedWords () { + placeSeedWords (cb) { const firstKeyring = this.keyrings[0] const seedWords = firstKeyring.serialize().mnemonic this.configManager.setSeedWords(seedWords) diff --git a/app/scripts/lib/encryptor.js b/app/scripts/lib/encryptor.js index 832e6d528..fe83b86dd 100644 --- a/app/scripts/lib/encryptor.js +++ b/app/scripts/lib/encryptor.js @@ -69,6 +69,9 @@ function decryptWithKey (key, text) { const decryptedObj = JSON.parse(decryptedStr) return decryptedObj }) + .catch(function(reason) { + throw new Error('Incorrect password') + }) } function convertStringToArrayBufferView (str) { -- cgit v1.2.3 From abebe51f69ea3ae02ac8d94f7fe739d754eedf7a Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 3 Nov 2016 16:34:55 -0700 Subject: Add tolerance to normalize method --- app/scripts/keyring-controller.js | 1 + 1 file changed, 1 insertion(+) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 81a05e133..1ca34e0f2 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -584,6 +584,7 @@ module.exports = class KeyringController extends EventEmitter { } function normalize(address) { + if (!address) return return ethUtil.addHexPrefix(address.toLowerCase()) } -- cgit v1.2.3 From fc26a0a8991759a54409096d0c7896da86cea4b7 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 4 Nov 2016 12:11:00 -0700 Subject: Fix network checking --- app/scripts/keyring-controller.js | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 1ca34e0f2..fb3091143 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -38,7 +38,7 @@ module.exports = class KeyringController extends EventEmitter { this._unconfTxCbs = {} this._unconfMsgCbs = {} - this.network = null + this.network = opts.network // TEMPORARY UNTIL FULL DEPRECATION: this.idStoreMigrator = new IdStoreMigrator({ @@ -69,7 +69,6 @@ module.exports = class KeyringController extends EventEmitter { conversionDate: this.configManager.getConversionDate(), keyringTypes: this.keyringTypes.map((krt) => krt.type()), identities: this.identities, - network: this.network, } } @@ -534,25 +533,6 @@ module.exports = class KeyringController extends EventEmitter { } } - getNetwork(err) { - if (err) { - this.network = 'loading' - this.emit('update') - } - - this.web3.version.getNetwork((err, network) => { - if (err) { - this.network = 'loading' - return this.emit('update') - } - if (global.METAMASK_DEBUG) { - console.log('web3.getNetwork returned ' + network) - } - this.network = network - this.emit('update') - }) - } - addGasBuffer(gasHex) { var gas = new BN(gasHex, 16) var buffer = new BN('100000', 10) -- cgit v1.2.3 From 553a6da0117d94a6a3be3707266bdc09e67f9103 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 7 Nov 2016 12:00:14 -0800 Subject: Fix 787 gas buffer bug --- app/scripts/keyring-controller.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index fb3091143..3ebf02c44 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -533,11 +533,11 @@ module.exports = class KeyringController extends EventEmitter { } } - addGasBuffer(gasHex) { - var gas = new BN(gasHex, 16) - var buffer = new BN('100000', 10) - var result = gas.add(buffer) - return normalize(result.toString(16)) + addGasBuffer(gas) { + const gasBuffer = new BN('100000', 10) + const bnGas = new BN(ethUtil.stripHexPrefix(gas), 16) + const correct = bnGas.add(gasBuffer) + return ethUtil.addHexPrefix(correct.toString(16)) } clearSeedWordCache(cb) { -- cgit v1.2.3 From 17aac2dbc54b733aeed5f16ef2e7bd8378060ca9 Mon Sep 17 00:00:00 2001 From: Frankie Date: Thu, 10 Nov 2016 19:07:12 -0800 Subject: fix tx data so it has the network id --- app/scripts/keyring-controller.js | 5 +++-- app/scripts/metamask-controller.js | 6 ++++++ 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 3ebf02c44..5d9dd51a4 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -38,7 +38,7 @@ module.exports = class KeyringController extends EventEmitter { this._unconfTxCbs = {} this._unconfMsgCbs = {} - this.network = opts.network + this.getNetwork = opts.getNetwork // TEMPORARY UNTIL FULL DEPRECATION: this.idStoreMigrator = new IdStoreMigrator({ @@ -344,13 +344,14 @@ module.exports = class KeyringController extends EventEmitter { var time = (new Date()).getTime() var txId = createId() txParams.metamaskId = txId - txParams.metamaskNetworkId = this.network + txParams.metamaskNetworkId = this.getNetwork() var txData = { id: txId, txParams: txParams, time: time, status: 'unconfirmed', gasMultiplier: configManager.getGasMultiplier() || 1, + metamaskNetworkId: this.getNetwork(), } diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 4c01b23d8..07d365283 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -17,6 +17,7 @@ module.exports = class MetamaskController { this.configManager = new ConfigManager(opts) this.keyringController = new KeyringController({ configManager: this.configManager, + getNetwork: this.getStateNetwork.bind(this), }) this.provider = this.initializeProvider(opts) this.ethStore = new EthStore(this.provider) @@ -399,4 +400,9 @@ module.exports = class MetamaskController { cb(e) } } + + getStateNetwork () { + return this.state.network + } } + -- cgit v1.2.3 From 23263bec7d5100accd61f7648fd9355fc95e2bb7 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Fri, 11 Nov 2016 10:26:12 -0800 Subject: Linting to the max. --- app/scripts/contentscript.js | 14 ++---- app/scripts/inpage.js | 2 +- app/scripts/keyring-controller.js | 74 ++++++++++++++--------------- app/scripts/keyrings/hd.js | 27 +++++------ app/scripts/keyrings/simple.js | 19 ++++---- app/scripts/lib/auto-reload.js | 5 +- app/scripts/lib/config-manager.js | 3 +- app/scripts/lib/encryptor.js | 10 ++-- app/scripts/lib/idStore-migrator.js | 6 +-- app/scripts/lib/idStore.js | 8 ++-- app/scripts/lib/inpage-provider.js | 8 ++-- app/scripts/lib/is-popup-or-notification.js | 2 +- app/scripts/lib/notifications.js | 12 ++--- app/scripts/metamask-controller.js | 23 +-------- app/scripts/popup-core.js | 4 +- app/scripts/popup.js | 2 +- 16 files changed, 93 insertions(+), 126 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index e2a968ac9..ab64dc9fa 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -6,7 +6,7 @@ const extension = require('./lib/extension') const fs = require('fs') const path = require('path') -const inpageText = fs.readFileSync(path.join(__dirname + '/inpage.js')).toString() +const inpageText = fs.readFileSync(path.join(__dirname, 'inpage.js')).toString() // Eventually this streaming injection could be replaced with: // https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Language_Bindings/Components.utils.exportFunction @@ -20,9 +20,8 @@ if (shouldInjectWeb3()) { setupStreams() } -function setupInjection(){ +function setupInjection () { try { - // inject in-page script var scriptTag = document.createElement('script') scriptTag.src = extension.extension.getURL('scripts/inpage.js') @@ -31,14 +30,12 @@ function setupInjection(){ var container = document.head || document.documentElement // append as first child container.insertBefore(scriptTag, container.children[0]) - } catch (e) { console.error('Metamask injection failed.', e) } } -function setupStreams(){ - +function setupStreams () { // setup communication to page and plugin var pageStream = new LocalMessageDuplexStream({ name: 'contentscript', @@ -65,14 +62,13 @@ function setupStreams(){ mx.ignoreStream('provider') mx.ignoreStream('publicConfig') mx.ignoreStream('reload') - } -function shouldInjectWeb3(){ +function shouldInjectWeb3 () { return isAllowedSuffix(window.location.href) } -function isAllowedSuffix(testCase) { +function isAllowedSuffix (testCase) { var prohibitedTypes = ['xml', 'pdf'] var currentUrl = window.location.href var currentRegex diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index 85dd70b4d..9d6fc96de 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -43,7 +43,7 @@ reloadStream.once('data', triggerReload) var pingChannel = inpageProvider.multiStream.createStream('pingpong') var pingStream = new PingStream({ objectMode: true }) // wait for first successful reponse -metamaskStream.once('_data', function(){ +metamaskStream.once('_data', function () { pingStream.pipe(pingChannel).pipe(pingStream) }) endOfStream(pingStream, triggerReload) diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 5d9dd51a4..b74d6cbfc 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -46,7 +46,7 @@ module.exports = class KeyringController extends EventEmitter { }) } - getState() { + getState () { const configManager = this.configManager const address = configManager.getSelectedAccount() const wallet = configManager.getWallet() // old style vault @@ -72,18 +72,18 @@ module.exports = class KeyringController extends EventEmitter { } } - setStore(ethStore) { + setStore (ethStore) { this.ethStore = ethStore } - createNewVaultAndKeychain(password, entropy, cb) { + createNewVaultAndKeychain (password, entropy, cb) { this.createNewVault(password, entropy, (err) => { if (err) return cb(err) this.createFirstKeyTree(password, cb) }) } - createNewVaultAndRestore(password, seed, cb) { + createNewVaultAndRestore (password, seed, cb) { if (typeof password !== 'string') { return cb('Password must be text.') } @@ -114,7 +114,7 @@ module.exports = class KeyringController extends EventEmitter { }) } - migrateAndGetKey(password) { + migrateAndGetKey (password) { let key const shouldMigrate = !!this.configManager.getWallet() && !this.configManager.getVault() @@ -134,7 +134,7 @@ module.exports = class KeyringController extends EventEmitter { }) } - createNewVault(password, entropy, cb) { + createNewVault (password, entropy, cb) { const configManager = this.configManager const salt = this.encryptor.generateSalt() configManager.setSalt(salt) @@ -151,7 +151,7 @@ module.exports = class KeyringController extends EventEmitter { }) } - createFirstKeyTree(password, cb) { + createFirstKeyTree (password, cb) { this.clearKeyrings() this.addNewKeyring('HD Key Tree', {n: 1}, (err) => { const firstKeyring = this.keyrings[0] @@ -179,7 +179,7 @@ module.exports = class KeyringController extends EventEmitter { this.configManager.setSeedWords(seedWords) } - submitPassword(password, cb) { + submitPassword (password, cb) { this.migrateAndGetKey(password) .then((key) => { return this.unlockKeyrings(key) @@ -196,7 +196,7 @@ module.exports = class KeyringController extends EventEmitter { }) } - loadKey(password) { + loadKey (password) { const salt = this.configManager.getSalt() || this.encryptor.generateSalt() return this.encryptor.keyFromPassword(password + salt) .then((key) => { @@ -206,7 +206,7 @@ module.exports = class KeyringController extends EventEmitter { }) } - addNewKeyring(type, opts, cb) { + addNewKeyring (type, opts, cb) { const Keyring = this.getKeyringClassForType(type) const keyring = new Keyring(opts) const accounts = keyring.getAccounts() @@ -222,7 +222,7 @@ module.exports = class KeyringController extends EventEmitter { }) } - addNewAccount(keyRingNum = 0, cb) { + addNewAccount (keyRingNum = 0, cb) { const ring = this.keyrings[keyRingNum] const accounts = ring.addAccounts(1) this.setupAccounts(accounts) @@ -235,7 +235,7 @@ module.exports = class KeyringController extends EventEmitter { }) } - setupAccounts(accounts) { + setupAccounts (accounts) { var arr = accounts || this.getAccounts() arr.forEach((account) => { this.loadBalanceAndNickname(account) @@ -244,13 +244,13 @@ module.exports = class KeyringController extends EventEmitter { // Takes an account address and an iterator representing // the current number of named accounts. - loadBalanceAndNickname(account) { + loadBalanceAndNickname (account) { const address = normalize(account) this.ethStore.addAccount(address) this.createNickname(address) } - createNickname(address) { + createNickname (address) { const hexAddress = normalize(address) var i = Object.keys(this.identities).length const oldNickname = this.configManager.nicknameForWallet(address) @@ -274,7 +274,7 @@ module.exports = class KeyringController extends EventEmitter { } } - persistAllKeyrings() { + persistAllKeyrings () { const serialized = this.keyrings.map((k) => { return { type: k.type, @@ -289,7 +289,7 @@ module.exports = class KeyringController extends EventEmitter { }) } - unlockKeyrings(key) { + unlockKeyrings (key) { const encryptedVault = this.configManager.getVault() return this.encryptor.decryptWithKey(key, encryptedVault) .then((vault) => { @@ -298,7 +298,7 @@ module.exports = class KeyringController extends EventEmitter { }) } - restoreKeyring(serialized) { + restoreKeyring (serialized) { const { type, data } = serialized const Keyring = this.getKeyringClassForType(type) const keyring = new Keyring() @@ -311,7 +311,7 @@ module.exports = class KeyringController extends EventEmitter { return keyring } - getKeyringClassForType(type) { + getKeyringClassForType (type) { const Keyring = this.keyringTypes.reduce((res, kr) => { if (kr.type() === type) { return kr @@ -322,7 +322,7 @@ module.exports = class KeyringController extends EventEmitter { return Keyring } - getAccounts() { + getAccounts () { const keyrings = this.keyrings || [] return keyrings.map(kr => kr.getAccounts()) .reduce((res, arr) => { @@ -330,13 +330,13 @@ module.exports = class KeyringController extends EventEmitter { }, []) } - setSelectedAddress(address, cb) { + setSelectedAddress (address, cb) { var addr = normalize(address) this.configManager.setSelectedAccount(addr) cb(null, addr) } - addUnconfirmedTransaction(txParams, onTxDoneCb, cb) { + addUnconfirmedTransaction (txParams, onTxDoneCb, cb) { var self = this const configManager = this.configManager @@ -369,7 +369,7 @@ module.exports = class KeyringController extends EventEmitter { ], didComplete) // perform static analyis on the target contract code - function analyzeForDelegateCall(cb){ + function analyzeForDelegateCall (cb) { if (txParams.to) { query.getCode(txParams.to, function (err, result) { if (err) return cb(err) @@ -388,8 +388,8 @@ module.exports = class KeyringController extends EventEmitter { } } - function estimateGas(cb){ - query.estimateGas(txParams, function(err, result){ + function estimateGas (cb) { + query.estimateGas(txParams, function (err, result) { if (err) return cb(err) txData.estimatedGas = self.addGasBuffer(result) cb() @@ -406,7 +406,7 @@ module.exports = class KeyringController extends EventEmitter { } } - addUnconfirmedMessage(msgParams, cb) { + addUnconfirmedMessage (msgParams, cb) { // create txData obj with parameters and meta data var time = (new Date()).getTime() var msgId = createId() @@ -428,7 +428,7 @@ module.exports = class KeyringController extends EventEmitter { return msgId } - approveTransaction(txId, cb) { + approveTransaction (txId, cb) { const configManager = this.configManager var approvalCb = this._unconfTxCbs[txId] || noop @@ -441,7 +441,7 @@ module.exports = class KeyringController extends EventEmitter { this.emit('update') } - cancelTransaction(txId, cb) { + cancelTransaction (txId, cb) { const configManager = this.configManager var approvalCb = this._unconfTxCbs[txId] || noop @@ -456,7 +456,7 @@ module.exports = class KeyringController extends EventEmitter { } } - signTransaction(txParams, cb) { + signTransaction (txParams, cb) { try { const address = normalize(txParams.from) const keyring = this.getKeyringForAccount(address) @@ -492,7 +492,7 @@ module.exports = class KeyringController extends EventEmitter { } } - signMessage(msgParams, cb) { + signMessage (msgParams, cb) { try { const keyring = this.getKeyringForAccount(msgParams.from) const address = normalize(msgParams.from) @@ -503,7 +503,7 @@ module.exports = class KeyringController extends EventEmitter { } } - getKeyringForAccount(address) { + getKeyringForAccount (address) { const hexed = normalize(address) return this.keyrings.find((ring) => { return ring.getAccounts() @@ -512,19 +512,19 @@ module.exports = class KeyringController extends EventEmitter { }) } - cancelMessage(msgId, cb) { + cancelMessage (msgId, cb) { if (cb && typeof cb === 'function') { cb() } } - setLocked(cb) { + setLocked (cb) { this.key = null this.keyrings = [] cb() } - exportAccount(address, cb) { + exportAccount (address, cb) { try { const keyring = this.getKeyringForAccount(address) const privateKey = keyring.exportAccount(normalize(address)) @@ -534,19 +534,19 @@ module.exports = class KeyringController extends EventEmitter { } } - addGasBuffer(gas) { + addGasBuffer (gas) { const gasBuffer = new BN('100000', 10) const bnGas = new BN(ethUtil.stripHexPrefix(gas), 16) const correct = bnGas.add(gasBuffer) return ethUtil.addHexPrefix(correct.toString(16)) } - clearSeedWordCache(cb) { + clearSeedWordCache (cb) { this.configManager.setSeedWords(null) cb(null, this.configManager.getSelectedAccount()) } - clearKeyrings() { + clearKeyrings () { let accounts try { accounts = Object.keys(this.ethStore._currentState.accounts) @@ -564,7 +564,7 @@ module.exports = class KeyringController extends EventEmitter { } -function normalize(address) { +function normalize (address) { if (!address) return return ethUtil.addHexPrefix(address.toLowerCase()) } diff --git a/app/scripts/keyrings/hd.js b/app/scripts/keyrings/hd.js index 4bfc56c15..6df78555d 100644 --- a/app/scripts/keyrings/hd.js +++ b/app/scripts/keyrings/hd.js @@ -9,17 +9,17 @@ const hdPathString = `m/44'/60'/0'/0` module.exports = class HdKeyring extends EventEmitter { - static type() { + static type () { return type } - constructor(opts = {}) { + constructor (opts = {}) { super() this.type = type this.deserialize(opts) } - deserialize(opts = {}) { + deserialize (opts = {}) { this.opts = opts || {} this.wallets = [] this.mnemonic = null @@ -34,26 +34,26 @@ module.exports = class HdKeyring extends EventEmitter { } } - initFromMnemonic(mnemonic) { + initFromMnemonic (mnemonic) { this.mnemonic = mnemonic const seed = bip39.mnemonicToSeed(mnemonic) this.hdWallet = hdkey.fromMasterSeed(seed) this.root = this.hdWallet.derivePath(hdPathString) } - serialize() { + serialize () { return { mnemonic: this.mnemonic, n: this.wallets.length, } } - exportAccount(address) { + exportAccount (address) { const wallet = this.getWalletForAccount(address) return wallet.getPrivateKey().toString('hex') } - addAccounts(n = 1) { + addAccounts (n = 1) { if (!this.root) { this.initFromMnemonic(bip39.generateMnemonic()) } @@ -69,12 +69,12 @@ module.exports = class HdKeyring extends EventEmitter { return newWallets.map(w => w.getAddress().toString('hex')) } - getAccounts() { + getAccounts () { return this.wallets.map(w => w.getAddress().toString('hex')) } // tx is an instance of the ethereumjs-transaction class. - signTransaction(address, tx) { + signTransaction (address, tx) { const wallet = this.getWalletForAccount(address) var privKey = wallet.getPrivateKey() tx.sign(privKey) @@ -82,7 +82,7 @@ module.exports = class HdKeyring extends EventEmitter { } // For eth_sign, we need to sign transactions: - signMessage(withAccount, data) { + signMessage (withAccount, data) { const wallet = this.getWalletForAccount(withAccount) const message = ethUtil.removeHexPrefix(data) var privKey = wallet.getPrivateKey() @@ -91,17 +91,14 @@ module.exports = class HdKeyring extends EventEmitter { return rawMsgSig } - getWalletForAccount(account) { + getWalletForAccount (account) { return this.wallets.find((w) => { const address = w.getAddress().toString('hex') return ((address === account) || (normalize(address) === account)) }) } - - - } -function normalize(address) { +function normalize (address) { return ethUtil.addHexPrefix(address.toLowerCase()) } diff --git a/app/scripts/keyrings/simple.js b/app/scripts/keyrings/simple.js index 9e832f274..ee743bc03 100644 --- a/app/scripts/keyrings/simple.js +++ b/app/scripts/keyrings/simple.js @@ -6,22 +6,22 @@ const sigUtil = require('../lib/sig-util') module.exports = class SimpleKeyring extends EventEmitter { - static type() { + static type () { return type } - constructor(opts) { + constructor (opts) { super() this.type = type this.opts = opts || {} this.wallets = [] } - serialize() { + serialize () { return this.wallets.map(w => w.getPrivateKey().toString('hex')) } - deserialize(wallets = []) { + deserialize (wallets = []) { this.wallets = wallets.map((w) => { var b = new Buffer(w, 'hex') const wallet = Wallet.fromPrivateKey(b) @@ -29,7 +29,7 @@ module.exports = class SimpleKeyring extends EventEmitter { }) } - addAccounts(n = 1) { + addAccounts (n = 1) { var newWallets = [] for (var i = 0; i < n; i++) { newWallets.push(Wallet.generate()) @@ -38,12 +38,12 @@ module.exports = class SimpleKeyring extends EventEmitter { return newWallets.map(w => w.getAddress().toString('hex')) } - getAccounts() { + getAccounts () { return this.wallets.map(w => w.getAddress().toString('hex')) } // tx is an instance of the ethereumjs-transaction class. - signTransaction(address, tx) { + signTransaction (address, tx) { const wallet = this.getWalletForAccount(address) var privKey = wallet.getPrivateKey() tx.sign(privKey) @@ -51,7 +51,7 @@ module.exports = class SimpleKeyring extends EventEmitter { } // For eth_sign, we need to sign transactions: - signMessage(withAccount, data) { + signMessage (withAccount, data) { const wallet = this.getWalletForAccount(withAccount) const message = ethUtil.removeHexPrefix(data) var privKey = wallet.getPrivateKey() @@ -60,9 +60,8 @@ module.exports = class SimpleKeyring extends EventEmitter { return rawMsgSig } - getWalletForAccount(account) { + getWalletForAccount (account) { return this.wallets.find(w => w.getAddress().toString('hex') === account) } } - diff --git a/app/scripts/lib/auto-reload.js b/app/scripts/lib/auto-reload.js index 3c90905db..1302df35f 100644 --- a/app/scripts/lib/auto-reload.js +++ b/app/scripts/lib/auto-reload.js @@ -18,17 +18,16 @@ function setupDappAutoReload (web3) { return handleResetRequest - function handleResetRequest() { + function handleResetRequest () { resetWasRequested = true // ignore if web3 was not used if (!pageIsUsingWeb3) return // reload after short timeout setTimeout(triggerReset, 500) } - } // reload the page function triggerReset () { global.location.reload() -} \ No newline at end of file +} diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index f50d95c12..0c5daa8e6 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -290,7 +290,7 @@ ConfigManager.prototype.getSalt = function () { return ('salt' in data) && data.salt } -ConfigManager.prototype.setSalt = function(salt) { +ConfigManager.prototype.setSalt = function (salt) { var data = this.getData() data.salt = salt this.setData(data) @@ -358,7 +358,6 @@ ConfigManager.prototype.updateConversionRate = function () { this.setConversionPrice(0) this.setConversionDate('N/A') }) - } ConfigManager.prototype.setConversionPrice = function (price) { diff --git a/app/scripts/lib/encryptor.js b/app/scripts/lib/encryptor.js index fe83b86dd..acfb418a1 100644 --- a/app/scripts/lib/encryptor.js +++ b/app/scripts/lib/encryptor.js @@ -42,7 +42,7 @@ function encryptWithKey (key, dataObj) { return global.crypto.subtle.encrypt({ name: 'AES-GCM', iv: vector, - }, key, dataBuffer).then(function(buf){ + }, key, dataBuffer).then(function (buf) { var buffer = new Uint8Array(buf) var vectorStr = encodeBufferToBase64(vector) var vaultStr = encodeBufferToBase64(buffer) @@ -63,13 +63,13 @@ function decryptWithKey (key, text) { const encryptedData = decodeBase64ToBuffer(parts[0]) const vector = decodeBase64ToBuffer(parts[1]) return crypto.subtle.decrypt({name: 'AES-GCM', iv: vector}, key, encryptedData) - .then(function(result){ + .then(function (result) { const decryptedData = new Uint8Array(result) const decryptedStr = convertArrayBufferViewtoString(decryptedData) const decryptedObj = JSON.parse(decryptedStr) return decryptedObj }) - .catch(function(reason) { + .catch(function (reason) { throw new Error('Incorrect password') }) } @@ -95,7 +95,7 @@ function convertArrayBufferViewtoString (buffer) { function keyFromPassword (password) { var passBuffer = convertStringToArrayBufferView(password) return global.crypto.subtle.digest('SHA-256', passBuffer) - .then(function (passHash){ + .then(function (passHash) { return global.crypto.subtle.importKey('raw', passHash, {name: 'AES-GCM'}, false, ['encrypt', 'decrypt']) }) } @@ -135,7 +135,7 @@ function encodeBufferToBase64 (buf) { function decodeBase64ToBuffer (base64) { var buf = new Uint8Array(atob(base64).split('') - .map(function(c) { + .map(function (c) { return c.charCodeAt(0) })) return buf diff --git a/app/scripts/lib/idStore-migrator.js b/app/scripts/lib/idStore-migrator.js index 2d1826641..818364720 100644 --- a/app/scripts/lib/idStore-migrator.js +++ b/app/scripts/lib/idStore-migrator.js @@ -11,7 +11,7 @@ module.exports = class IdentityStoreMigrator { } } - oldSeedForPassword( password ) { + oldSeedForPassword (password) { const hasOldVault = this.hasOldVault() const configManager = this.configManager @@ -35,7 +35,7 @@ module.exports = class IdentityStoreMigrator { }) } - serializeVault() { + serializeVault () { const mnemonic = this.idStore._idmgmt.getSeed() const n = this.idStore._getAddresses().length @@ -45,7 +45,7 @@ module.exports = class IdentityStoreMigrator { } } - hasOldVault() { + hasOldVault () { const wallet = this.configManager.getWallet() return wallet } diff --git a/app/scripts/lib/idStore.js b/app/scripts/lib/idStore.js index 390c8a8ab..2a46b1b5d 100644 --- a/app/scripts/lib/idStore.js +++ b/app/scripts/lib/idStore.js @@ -243,7 +243,7 @@ IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDone ], didComplete) // perform static analyis on the target contract code - function analyzeForDelegateCall(cb){ + function analyzeForDelegateCall (cb) { if (txParams.to) { query.getCode(txParams.to, (err, result) => { if (err) return cb(err) @@ -256,16 +256,16 @@ IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDone } } - function estimateGas(cb){ + function estimateGas (cb) { var estimationParams = extend(txParams) // 1 billion gas for estimation var gasLimit = '0x3b9aca00' estimationParams.gas = gasLimit - query.estimateGas(estimationParams, function(err, result){ + query.estimateGas(estimationParams, function (err, result) { if (err) return cb(err) if (result === estimationParams.gas) { txData.simulationFails = true - query.getBlockByNumber('latest', true, function(err, block){ + query.getBlockByNumber('latest', true, function (err, block) { if (err) return cb(err) txData.estimatedGas = block.gasLimit txData.txParams.gas = block.gasLimit diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index 052a8f5fe..6795f2bd4 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -39,7 +39,7 @@ function MetamaskInpageProvider (connectionStream) { self.idMap = {} // handle sendAsync requests via asyncProvider - self.sendAsync = function(payload, cb){ + self.sendAsync = function (payload, cb) { // rewrite request ids var request = eachJsonMessage(payload, (message) => { var newId = createRandomId() @@ -48,7 +48,7 @@ function MetamaskInpageProvider (connectionStream) { return message }) // forward to asyncProvider - asyncProvider.sendAsync(request, function(err, res){ + asyncProvider.sendAsync(request, function (err, res) { if (err) return cb(err) // transform messages to original ids eachJsonMessage(res, (message) => { @@ -119,7 +119,7 @@ function remoteStoreWithLocalStorageCache (storageKey) { return store } -function createRandomId(){ +function createRandomId () { const extraDigits = 3 // 13 time digits const datePart = new Date().getTime() * Math.pow(10, extraDigits) @@ -129,7 +129,7 @@ function createRandomId(){ return datePart + extraPart } -function eachJsonMessage(payload, transformFn){ +function eachJsonMessage (payload, transformFn) { if (Array.isArray(payload)) { return payload.map(transformFn) } else { diff --git a/app/scripts/lib/is-popup-or-notification.js b/app/scripts/lib/is-popup-or-notification.js index 5c38ac823..693fa8751 100644 --- a/app/scripts/lib/is-popup-or-notification.js +++ b/app/scripts/lib/is-popup-or-notification.js @@ -1,4 +1,4 @@ -module.exports = function isPopupOrNotification() { +module.exports = function isPopupOrNotification () { const url = window.location.href if (url.match(/popup.html$/)) { return 'popup' diff --git a/app/scripts/lib/notifications.js b/app/scripts/lib/notifications.js index cd7535232..3db1ac6b5 100644 --- a/app/scripts/lib/notifications.js +++ b/app/scripts/lib/notifications.js @@ -15,12 +15,9 @@ function show () { if (err) throw err if (popup) { - // bring focus to existing popup extension.windows.update(popup.id, { focused: true }) - } else { - // create new popup extension.windows.create({ url: 'notification.html', @@ -29,12 +26,11 @@ function show () { width, height, }) - } }) } -function getWindows(cb) { +function getWindows (cb) { // Ignore in test environment if (!extension.windows) { return cb() @@ -45,14 +41,14 @@ function getWindows(cb) { }) } -function getPopup(cb) { +function getPopup (cb) { getWindows((err, windows) => { if (err) throw err cb(null, getPopupIn(windows)) }) } -function getPopupIn(windows) { +function getPopupIn (windows) { return windows ? windows.find((win) => { return (win && win.type === 'popup' && win.height === height && @@ -60,7 +56,7 @@ function getPopupIn(windows) { }) : null } -function closePopup() { +function closePopup () { getPopup((err, popup) => { if (err) throw err if (!popup) return diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 07d365283..83220b7b2 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -87,23 +87,6 @@ module.exports = class MetamaskController { } onRpcRequest (stream, originDomain, request) { - - /* Commented out for Parity compliance - * Parity does not permit additional keys, like `origin`, - * and Infura is not currently filtering this key out. - var payloads = Array.isArray(request) ? request : [request] - payloads.forEach(function (payload) { - // Append origin to rpc payload - payload.origin = originDomain - // Append origin to signature request - if (payload.method === 'eth_sendTransaction') { - payload.params[0].origin = originDomain - } else if (payload.method === 'eth_sign') { - payload.params.push({ origin: originDomain }) - } - }) - */ - // handle rpc request this.provider.sendAsync(request, function onPayloadHandled (err, response) { logger(err, request, response) @@ -217,7 +200,7 @@ module.exports = class MetamaskController { newUnsignedTransaction (txParams, onTxDoneCb) { const keyringController = this.keyringController - let err = this.enforceTxValidations(txParams) + const err = this.enforceTxValidations(txParams) if (err) return onTxDoneCb(err) keyringController.addUnconfirmedTransaction(txParams, onTxDoneCb, (err, txData) => { if (err) return onTxDoneCb(err) @@ -291,7 +274,6 @@ module.exports = class MetamaskController { } catch (e) { console.error('Error in checking TOS change.') } - } agreeToDisclaimer (cb) { @@ -373,7 +355,7 @@ module.exports = class MetamaskController { this.configManager.createShapeShiftTx(depositAddress, depositType) } - getNetwork(err) { + getNetwork (err) { if (err) { this.state.network = 'loading' this.sendUpdate() @@ -405,4 +387,3 @@ module.exports = class MetamaskController { return this.state.network } } - diff --git a/app/scripts/popup-core.js b/app/scripts/popup-core.js index 94413a1c4..0c97a5d19 100644 --- a/app/scripts/popup-core.js +++ b/app/scripts/popup-core.js @@ -9,7 +9,7 @@ const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex module.exports = initializePopup -function initializePopup(connectionStream){ +function initializePopup (connectionStream) { // setup app connectToAccountManager(connectionStream, setupApp) } @@ -32,7 +32,7 @@ function setupWeb3Connection (connectionStream) { } function setupControllerConnection (connectionStream, cb) { - // this is a really sneaky way of adding EventEmitter api + // this is a really sneaky way of adding EventEmitter api // to a bi-directional dnode instance var eventEmitter = new EventEmitter() var accountManagerDnode = Dnode({ diff --git a/app/scripts/popup.js b/app/scripts/popup.js index e6f149f96..62db68c10 100644 --- a/app/scripts/popup.js +++ b/app/scripts/popup.js @@ -18,7 +18,7 @@ var portStream = new PortStream(pluginPort) startPopup(portStream) -function closePopupIfOpen(name) { +function closePopupIfOpen (name) { if (name !== 'notification') { notification.closePopup() } -- cgit v1.2.3 From 7012747fb546bc1a95ce65b71bd3f74075150b77 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Fri, 11 Nov 2016 15:37:54 -0800 Subject: Package normalize inside sig util file. --- app/scripts/lib/sig-util.js | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'app/scripts') diff --git a/app/scripts/lib/sig-util.js b/app/scripts/lib/sig-util.js index f8748f535..193dda381 100644 --- a/app/scripts/lib/sig-util.js +++ b/app/scripts/lib/sig-util.js @@ -12,6 +12,11 @@ module.exports = { return ethUtil.addHexPrefix(rStr.concat(sStr, vStr)).toString('hex') }, + normalize: function (address) { + if (!address) return + return ethUtil.addHexPrefix(address.toLowerCase()) + }, + } function padWithZeroes (number, length) { -- cgit v1.2.3 From bfeaae69f2a0c845d8ebfa907a90049f53ba3aea Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Fri, 11 Nov 2016 15:40:12 -0800 Subject: Clarify functions names. Package normalize inside util file. Fix require headers. --- app/scripts/keyrings/hd.js | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyrings/hd.js b/app/scripts/keyrings/hd.js index 6df78555d..b98f29187 100644 --- a/app/scripts/keyrings/hd.js +++ b/app/scripts/keyrings/hd.js @@ -2,9 +2,10 @@ const EventEmitter = require('events').EventEmitter const hdkey = require('ethereumjs-wallet/hdkey') const bip39 = require('bip39') const ethUtil = require('ethereumjs-util') -const type = 'HD Key Tree' const sigUtil = require('../lib/sig-util') +const type = 'HD Key Tree' + const hdPathString = `m/44'/60'/0'/0` module.exports = class HdKeyring extends EventEmitter { @@ -29,8 +30,8 @@ module.exports = class HdKeyring extends EventEmitter { this.initFromMnemonic(opts.mnemonic) } - if ('n' in opts) { - this.addAccounts(opts.n) + if ('numberOfAccounts' in opts) { + this.addAccounts(opts.numberOfAccounts) } } @@ -44,7 +45,7 @@ module.exports = class HdKeyring extends EventEmitter { serialize () { return { mnemonic: this.mnemonic, - n: this.wallets.length, + numberOfAccounts: this.wallets.length, } } @@ -53,14 +54,14 @@ module.exports = class HdKeyring extends EventEmitter { return wallet.getPrivateKey().toString('hex') } - addAccounts (n = 1) { + addAccounts (numberOfAccounts = 1) { if (!this.root) { this.initFromMnemonic(bip39.generateMnemonic()) } const oldLen = this.wallets.length const newWallets = [] - for (let i = oldLen; i < n + oldLen; i++) { + for (let i = oldLen; i < numberOfAccounts + oldLen; i++) { const child = this.root.deriveChild(i) const wallet = child.getWallet() newWallets.push(wallet) @@ -94,11 +95,7 @@ module.exports = class HdKeyring extends EventEmitter { getWalletForAccount (account) { return this.wallets.find((w) => { const address = w.getAddress().toString('hex') - return ((address === account) || (normalize(address) === account)) + return ((address === account) || (sigUtil.normalize(address) === account)) }) } } - -function normalize (address) { - return ethUtil.addHexPrefix(address.toLowerCase()) -} -- cgit v1.2.3 From 20cea5b2f5429cc2574f755fcba0ce5bb12f1a13 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Fri, 11 Nov 2016 15:41:04 -0800 Subject: Various keyring changes - Rearrange the require statements. - Remove unused web3. - Simplify some callbacks and promises. - Clarify certain parameters. --- app/scripts/keyring-controller.js | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index b74d6cbfc..bb1727d7a 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -1,18 +1,18 @@ const async = require('async') -const EventEmitter = require('events').EventEmitter -const encryptor = require('./lib/encryptor') -const messageManager = require('./lib/message-manager') const ethUtil = require('ethereumjs-util') const ethBinToOps = require('eth-bin-to-ops') const EthQuery = require('eth-query') -const BN = ethUtil.BN +const bip39 = require('bip39') const Transaction = require('ethereumjs-tx') +const EventEmitter = require('events').EventEmitter + const createId = require('web3-provider-engine/util/random-id') +const normalize = require('./lib/sig-util').normalize +const encryptor = require('./lib/encryptor') +const messageManager = require('./lib/message-manager') const autoFaucet = require('./lib/auto-faucet') -const bip39 = require('bip39') - -// TEMPORARY UNTIL FULL DEPRECATION: const IdStoreMigrator = require('./lib/idStore-migrator') +const BN = ethUtil.BN // Keyrings: const SimpleKeyring = require('./keyrings/simple') @@ -26,7 +26,6 @@ module.exports = class KeyringController extends EventEmitter { constructor (opts) { super() - this.web3 = opts.web3 this.configManager = opts.configManager this.ethStore = opts.ethStore this.encryptor = encryptor @@ -98,7 +97,7 @@ module.exports = class KeyringController extends EventEmitter { if (err) return cb(err) this.addNewKeyring('HD Key Tree', { mnemonic: seed, - n: 1, + numberOfAccounts: 1, }, (err) => { if (err) return cb(err) const firstKeyring = this.keyrings[0] @@ -143,9 +142,7 @@ module.exports = class KeyringController extends EventEmitter { .then(() => { return this.persistAllKeyrings() }) - .then(() => { - cb(null) - }) + .then(cb) .catch((err) => { cb(err) }) @@ -153,7 +150,7 @@ module.exports = class KeyringController extends EventEmitter { createFirstKeyTree (password, cb) { this.clearKeyrings() - this.addNewKeyring('HD Key Tree', {n: 1}, (err) => { + this.addNewKeyring('HD Key Tree', {numberOfAccounts: 1}, (err) => { const firstKeyring = this.keyrings[0] const accounts = firstKeyring.getAccounts() const firstAccount = accounts[0] @@ -564,9 +561,4 @@ module.exports = class KeyringController extends EventEmitter { } -function normalize (address) { - if (!address) return - return ethUtil.addHexPrefix(address.toLowerCase()) -} - function noop () {} -- cgit v1.2.3 From 4826f7c0a095da8658bfae6a1d7e982cd81ffd3b Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Fri, 11 Nov 2016 17:06:07 -0800 Subject: Revert to previous anonymous function for promise. --- app/scripts/keyring-controller.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index bb1727d7a..c9f7e503e 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -142,7 +142,9 @@ module.exports = class KeyringController extends EventEmitter { .then(() => { return this.persistAllKeyrings() }) - .then(cb) + .then(() => { + cb() + }) .catch((err) => { cb(err) }) -- cgit v1.2.3 From 7de6b12aad4a674bdbb0749d2e61d9fd5f69c536 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Mon, 14 Nov 2016 16:49:16 -0800 Subject: Re-enable disclaimer screen. Rename variables to reflect role more clearly. --- app/scripts/keyring-controller.js | 2 +- app/scripts/lib/config-manager.js | 8 ++++---- app/scripts/lib/idStore.js | 2 +- app/scripts/metamask-controller.js | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index c9f7e503e..c7e3c32a4 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -55,7 +55,7 @@ module.exports = class KeyringController extends EventEmitter { seedWords: this.configManager.getSeedWords(), isInitialized: (!!wallet || !!vault), isUnlocked: !!this.key, - isConfirmed: true, // AUDIT this.configManager.getConfirmed(), + isDisclaimerConfirmed: this.configManager.getConfirmedDisclaimer(), // AUDIT this.configManager.getConfirmedDisclaimer(), unconfTxs: this.configManager.unconfirmedTxs(), transactions: this.configManager.getTxList(), unconfMsgs: messageManager.unconfirmedMsgs(), diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index 0c5daa8e6..faf64bfdc 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -313,15 +313,15 @@ ConfigManager.prototype._emitUpdates = function (state) { }) } -ConfigManager.prototype.setConfirmed = function (confirmed) { +ConfigManager.prototype.setConfirmedDisclaimer = function (confirmed) { var data = this.getData() - data.isConfirmed = confirmed + data.isDisclaimerConfirmed = confirmed this.setData(data) } -ConfigManager.prototype.getConfirmed = function () { +ConfigManager.prototype.getConfirmedDisclaimer = function () { var data = this.getData() - return ('isConfirmed' in data) && data.isConfirmed + return ('isDisclaimerConfirmed' in data) && data.isDisclaimerConfirmed } ConfigManager.prototype.setTOSHash = function (hash) { diff --git a/app/scripts/lib/idStore.js b/app/scripts/lib/idStore.js index 2a46b1b5d..31895b9bc 100644 --- a/app/scripts/lib/idStore.js +++ b/app/scripts/lib/idStore.js @@ -102,7 +102,7 @@ IdentityStore.prototype.getState = function () { isInitialized: !!configManager.getWallet() && !seedWords, isUnlocked: this._isUnlocked(), seedWords: seedWords, - isConfirmed: configManager.getConfirmed(), + isDisclaimerConfirmed: configManager.getConfirmedDisclaimer(), unconfTxs: configManager.unconfirmedTxs(), transactions: configManager.getTxList(), unconfMsgs: messageManager.unconfirmedMsgs(), diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 83220b7b2..3d6c0eb50 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -278,7 +278,7 @@ module.exports = class MetamaskController { agreeToDisclaimer (cb) { try { - this.configManager.setConfirmed(true) + this.configManager.setConfirmedDisclaimer(true) cb() } catch (e) { cb(e) @@ -287,7 +287,7 @@ module.exports = class MetamaskController { resetDisclaimer () { try { - this.configManager.setConfirmed(false) + this.configManager.setConfirmedDisclaimer(false) } catch (e) { console.error(e) } -- cgit v1.2.3 From b1fee2a1d303c28ccedafc4e8c81e07ebf164b36 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 15 Nov 2016 11:07:15 -0800 Subject: Minimize repeated code. --- app/scripts/keyring-controller.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index c7e3c32a4..4acaebba3 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -153,13 +153,12 @@ module.exports = class KeyringController extends EventEmitter { createFirstKeyTree (password, cb) { this.clearKeyrings() this.addNewKeyring('HD Key Tree', {numberOfAccounts: 1}, (err) => { - const firstKeyring = this.keyrings[0] - const accounts = firstKeyring.getAccounts() + const accounts = this.keyrings[0].getAccounts() const firstAccount = accounts[0] const hexAccount = normalize(firstAccount) - const seedWords = firstKeyring.serialize().mnemonic this.configManager.setSelectedAccount(firstAccount) - this.configManager.setSeedWords(seedWords) + + this.placeSeedWords() autoFaucet(hexAccount) this.setupAccounts(accounts) this.persistAllKeyrings() @@ -172,9 +171,11 @@ module.exports = class KeyringController extends EventEmitter { }) } - placeSeedWords (cb) { + placeSeedWords () { const firstKeyring = this.keyrings[0] + console.log(firstKeyring) const seedWords = firstKeyring.serialize().mnemonic + console.log(seedWords) this.configManager.setSeedWords(seedWords) } -- cgit v1.2.3 From a4666de0ce9eaa99242609fdbf518b6a37650ff2 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 15 Nov 2016 11:07:15 -0800 Subject: Minimize repeated code. --- app/scripts/keyring-controller.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index c7e3c32a4..84327b15f 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -153,13 +153,12 @@ module.exports = class KeyringController extends EventEmitter { createFirstKeyTree (password, cb) { this.clearKeyrings() this.addNewKeyring('HD Key Tree', {numberOfAccounts: 1}, (err) => { - const firstKeyring = this.keyrings[0] - const accounts = firstKeyring.getAccounts() + const accounts = this.keyrings[0].getAccounts() const firstAccount = accounts[0] const hexAccount = normalize(firstAccount) - const seedWords = firstKeyring.serialize().mnemonic this.configManager.setSelectedAccount(firstAccount) - this.configManager.setSeedWords(seedWords) + + this.placeSeedWords() autoFaucet(hexAccount) this.setupAccounts(accounts) this.persistAllKeyrings() @@ -172,7 +171,7 @@ module.exports = class KeyringController extends EventEmitter { }) } - placeSeedWords (cb) { + placeSeedWords () { const firstKeyring = this.keyrings[0] const seedWords = firstKeyring.serialize().mnemonic this.configManager.setSeedWords(seedWords) @@ -237,13 +236,13 @@ module.exports = class KeyringController extends EventEmitter { setupAccounts (accounts) { var arr = accounts || this.getAccounts() arr.forEach((account) => { - this.loadBalanceAndNickname(account) + this.getBalanceAndNickname(account) }) } // Takes an account address and an iterator representing // the current number of named accounts. - loadBalanceAndNickname (account) { + getBalanceAndNickname (account) { const address = normalize(account) this.ethStore.addAccount(address) this.createNickname(address) -- cgit v1.2.3 From 585284cb88ec18515b246555a19c745b5bf8de84 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 15 Nov 2016 13:44:22 -0800 Subject: Lints. --- app/scripts/lib/idStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/idStore.js b/app/scripts/lib/idStore.js index eb625987f..d11c38be1 100644 --- a/app/scripts/lib/idStore.js +++ b/app/scripts/lib/idStore.js @@ -261,7 +261,7 @@ IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDone // 1 billion gas for estimation var gasLimit = '0x3b9aca00' estimationParams.gas = gasLimit - query.estimateGas(estimationParams, function(err, result){ + query.estimateGas(estimationParams, function (err, result) { if (err) return cb(err.message || err) if (result === estimationParams.gas) { txData.simulationFails = true -- cgit v1.2.3 From e18109f1eac855a828dc5c6011bbc8a4dbc69f4c Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 15 Nov 2016 13:45:21 -0800 Subject: Fix semantics in comments --- app/scripts/lib/encryptor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/encryptor.js b/app/scripts/lib/encryptor.js index acfb418a1..2af2a1d2b 100644 --- a/app/scripts/lib/encryptor.js +++ b/app/scripts/lib/encryptor.js @@ -26,7 +26,7 @@ module.exports = { generateSalt, } -// Takes a Pojo, returns encrypted text. +// Takes a Pojo, returns cypher text. function encrypt (password, dataObj) { return keyFromPassword(password) .then(function (passwordDerivedKey) { -- cgit v1.2.3 From 5bfb700fa833a415a541a959736d6184d3c07753 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 15 Nov 2016 17:12:13 -0800 Subject: Minimize dispatches by using emitters and relying on state updates. --- app/scripts/keyring-controller.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index e635ad285..280b332a0 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -108,7 +108,7 @@ module.exports = class KeyringController extends EventEmitter { this.setupAccounts(accounts) this.emit('update') - cb(null, this.getState()) + cb() }) }) } @@ -163,7 +163,7 @@ module.exports = class KeyringController extends EventEmitter { this.setupAccounts(accounts) this.persistAllKeyrings() .then(() => { - cb(err, this.getState()) + cb(err) }) .catch((reason) => { cb(reason) @@ -173,9 +173,7 @@ module.exports = class KeyringController extends EventEmitter { placeSeedWords () { const firstKeyring = this.keyrings[0] - console.log(firstKeyring) const seedWords = firstKeyring.serialize().mnemonic - console.log(seedWords) this.configManager.setSeedWords(seedWords) } @@ -188,7 +186,7 @@ module.exports = class KeyringController extends EventEmitter { this.keyrings = keyrings this.setupAccounts() this.emit('update') - cb(null, this.getState()) + cb() }) .catch((err) => { console.error(err) @@ -215,7 +213,7 @@ module.exports = class KeyringController extends EventEmitter { this.setupAccounts(accounts) this.persistAllKeyrings() .then(() => { - cb(null, this.getState()) + cb() }) .catch((reason) => { cb(reason) @@ -228,7 +226,7 @@ module.exports = class KeyringController extends EventEmitter { this.setupAccounts(accounts) this.persistAllKeyrings() .then(() => { - cb(null, this.getState()) + cb() }) .catch((reason) => { cb(reason) @@ -521,6 +519,7 @@ module.exports = class KeyringController extends EventEmitter { setLocked (cb) { this.key = null this.keyrings = [] + this.emit('update') cb() } -- cgit v1.2.3 From 592b64a19fd7001d965aa1a1c329b24f55d2ea90 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 15 Nov 2016 17:13:33 -0800 Subject: Revert one cb to previous state. --- app/scripts/keyring-controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 280b332a0..8ceb2b1ce 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -186,7 +186,7 @@ module.exports = class KeyringController extends EventEmitter { this.keyrings = keyrings this.setupAccounts() this.emit('update') - cb() + cb(null, this.getState()) }) .catch((err) => { console.error(err) -- cgit v1.2.3 From f229d32442f34859be169e38a42ffecdfb8fc48a Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 17 Nov 2016 13:49:46 -0800 Subject: Replace old random-id code with incrementing id generator --- app/scripts/keyring-controller.js | 3 ++- app/scripts/lib/inpage-provider.js | 11 +---------- app/scripts/lib/random-id.js | 9 +++++++++ 3 files changed, 12 insertions(+), 11 deletions(-) create mode 100644 app/scripts/lib/random-id.js (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 3ebf02c44..5b06de690 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -7,7 +7,6 @@ const ethBinToOps = require('eth-bin-to-ops') const EthQuery = require('eth-query') const BN = ethUtil.BN const Transaction = require('ethereumjs-tx') -const createId = require('web3-provider-engine/util/random-id') const autoFaucet = require('./lib/auto-faucet') const bip39 = require('bip39') @@ -22,6 +21,8 @@ const keyringTypes = [ HdKeyring, ] +const createId = require('./lib/random-id') + module.exports = class KeyringController extends EventEmitter { constructor (opts) { diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index 052a8f5fe..f1ba2e0ed 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -2,6 +2,7 @@ const Streams = require('mississippi') const StreamProvider = require('web3-stream-provider') const ObjectMultiplex = require('./obj-multiplex') const RemoteStore = require('./remote-store.js').RemoteStore +const createRandomId = require('./random-id') module.exports = MetamaskInpageProvider @@ -119,16 +120,6 @@ function remoteStoreWithLocalStorageCache (storageKey) { return store } -function createRandomId(){ - const extraDigits = 3 - // 13 time digits - const datePart = new Date().getTime() * Math.pow(10, extraDigits) - // 3 random digits - const extraPart = Math.floor(Math.random() * Math.pow(10, extraDigits)) - // 16 digits - return datePart + extraPart -} - function eachJsonMessage(payload, transformFn){ if (Array.isArray(payload)) { return payload.map(transformFn) diff --git a/app/scripts/lib/random-id.js b/app/scripts/lib/random-id.js new file mode 100644 index 000000000..3c5ae5600 --- /dev/null +++ b/app/scripts/lib/random-id.js @@ -0,0 +1,9 @@ +const MAX = 1000000000 + +let idCounter = Math.round( Math.random() * MAX ) +function createRandomId() { + idCounter = idCounter % MAX + return idCounter++ +} + +module.exports = createRandomId -- cgit v1.2.3 From 39e0a33bba2709971edec0304027f646cb2db3cc Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 17 Nov 2016 14:29:35 -0800 Subject: random-id - use Number.MAX_SAFE_INTEGER as max --- app/scripts/lib/random-id.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/random-id.js b/app/scripts/lib/random-id.js index 3c5ae5600..78d9e34a5 100644 --- a/app/scripts/lib/random-id.js +++ b/app/scripts/lib/random-id.js @@ -1,4 +1,4 @@ -const MAX = 1000000000 +const MAX = Number.MAX_SAFE_INTEGER let idCounter = Math.round( Math.random() * MAX ) function createRandomId() { -- cgit v1.2.3 From cd2442e3e77e50c935b5c84e6ccc8f3c7da45de0 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Fri, 18 Nov 2016 10:48:00 -0800 Subject: Persist keyrings from migration to storage. --- app/scripts/keyring-controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 10d686e23..9046108c0 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -117,7 +117,6 @@ module.exports = class KeyringController extends EventEmitter { migrateAndGetKey (password) { let key const shouldMigrate = !!this.configManager.getWallet() && !this.configManager.getVault() - return this.loadKey(password) .then((derivedKey) => { key = derivedKey @@ -128,6 +127,7 @@ module.exports = class KeyringController extends EventEmitter { if (serialized && shouldMigrate) { const keyring = this.restoreKeyring(serialized) this.keyrings.push(keyring) + this.persistAllKeyrings() this.configManager.setSelectedAccount(keyring.getAccounts()[0]) } return key -- cgit v1.2.3 From ce1c5eb75a17f6a5fca9fce1a6d400e690ecabf7 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 18 Nov 2016 11:37:07 -0800 Subject: Update migration code for new hd wallet param name --- app/scripts/lib/idStore-migrator.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/idStore-migrator.js b/app/scripts/lib/idStore-migrator.js index 818364720..18134b677 100644 --- a/app/scripts/lib/idStore-migrator.js +++ b/app/scripts/lib/idStore-migrator.js @@ -37,11 +37,11 @@ module.exports = class IdentityStoreMigrator { serializeVault () { const mnemonic = this.idStore._idmgmt.getSeed() - const n = this.idStore._getAddresses().length + const numberOfAccounts = this.idStore._getAddresses().length return { type: 'HD Key Tree', - data: { mnemonic, n }, + data: { mnemonic, numberOfAccounts }, } } -- cgit v1.2.3 From bc6312e9e3d3a48b886f53279f13f176c71e4019 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Fri, 18 Nov 2016 15:58:49 -0800 Subject: Promisify persistence of keyrings before returning key Change single letter variables (shame) --- app/scripts/keyring-controller.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 9046108c0..cf761c88c 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -127,8 +127,9 @@ module.exports = class KeyringController extends EventEmitter { if (serialized && shouldMigrate) { const keyring = this.restoreKeyring(serialized) this.keyrings.push(keyring) - this.persistAllKeyrings() this.configManager.setSelectedAccount(keyring.getAccounts()[0]) + return this.persistAllKeyrings() + .then(() => { return key }) } return key }) @@ -274,13 +275,12 @@ module.exports = class KeyringController extends EventEmitter { } persistAllKeyrings () { - const serialized = this.keyrings.map((k) => { + const serialized = this.keyrings.map((keyring) => { return { - type: k.type, - data: k.serialize(), + type: keyring.type, + data: keyring.serialize(), } }) - return this.encryptor.encryptWithKey(this.key, serialized) .then((encryptedString) => { this.configManager.setVault(encryptedString) -- cgit v1.2.3 From d6286cd13aef8b861d84b078b468b02b302ba801 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Fri, 18 Nov 2016 16:27:26 -0800 Subject: Maintain linting. --- app/scripts/lib/inpage-provider.js | 2 +- app/scripts/lib/random-id.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index c9d617996..034812b6a 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -120,7 +120,7 @@ function remoteStoreWithLocalStorageCache (storageKey) { return store } -function eachJsonMessage(payload, transformFn){ +function eachJsonMessage (payload, transformFn) { if (Array.isArray(payload)) { return payload.map(transformFn) } else { diff --git a/app/scripts/lib/random-id.js b/app/scripts/lib/random-id.js index 78d9e34a5..788f3370f 100644 --- a/app/scripts/lib/random-id.js +++ b/app/scripts/lib/random-id.js @@ -1,7 +1,7 @@ const MAX = Number.MAX_SAFE_INTEGER -let idCounter = Math.round( Math.random() * MAX ) -function createRandomId() { +let idCounter = Math.round(Math.random() * MAX) +function createRandomId () { idCounter = idCounter % MAX return idCounter++ } -- cgit v1.2.3