From 5864afd8c08db91528f77e37fe1cd371407f3bd1 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 29 Aug 2016 11:58:23 -0300 Subject: [PATCH] BWC 4.0 WIP --- app-template/package.json | 2 +- package.json | 2 +- public/views/preferences.html | 23 +++-- src/js/controllers/backup.js | 35 +++---- src/js/controllers/preferences.js | 52 ++++------- src/js/services/walletService.js | 148 ++++++++++++++++-------------- 6 files changed, 122 insertions(+), 140 deletions(-) diff --git a/app-template/package.json b/app-template/package.json index 369729f80..1b9235f8c 100644 --- a/app-template/package.json +++ b/app-template/package.json @@ -42,7 +42,7 @@ "url": "https://github.com/bitpay/copay/issues" }, "dependencies": { - "bitcore-wallet-client": "2.11.0", + "bitcore-wallet-client": "4.0.0", "coveralls": "^2.11.9", "express": "^4.11.2", "fs": "0.0.2", diff --git a/package.json b/package.json index f7955d753..dbd5438d2 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "url": "https://github.com/bitpay/copay/issues" }, "dependencies": { - "bitcore-wallet-client": "2.11.0", + "bitcore-wallet-client": "4.0.0", "coveralls": "^2.11.9", "express": "^4.11.2", "fs": "0.0.2", diff --git a/public/views/preferences.html b/public/views/preferences.html index 0a3f1260a..075194522 100644 --- a/public/views/preferences.html +++ b/public/views/preferences.html @@ -20,18 +20,12 @@
- Devices + Wallet Type - 1 + wallet.m-of-wallet.n
-
- Required number of signatures - - 1 - -
-
+
Hardware wallet {{wallet.externalSource}} @@ -56,15 +50,20 @@
Security
-
+
Backup
-
- +
+ Request Spending Password
+
+ + Request Fingerprint + +
Delete recovery phrase diff --git a/src/js/controllers/backup.js b/src/js/controllers/backup.js index 65ab2a89f..3d8045df4 100644 --- a/src/js/controllers/backup.js +++ b/src/js/controllers/backup.js @@ -4,6 +4,7 @@ angular.module('copayApp.controllers').controller('backupController', function($rootScope, $scope, $timeout, $log, $state, $stateParams, $ionicPopup, uxLanguage, lodash, fingerprintService, platformInfo, configService, profileService, gettext, bwcService, walletService, ongoingProcess) { var wallet = profileService.getWallet($stateParams.walletId); + var xPriv6; $scope.walletName = wallet.credentials.walletName; $scope.n = wallet.n; @@ -15,36 +16,17 @@ angular.module('copayApp.controllers').controller('backupController', return false; }; - var handleEncryptedWallet = function(client, cb) { - if (!walletService.isEncrypted(client)) { - return cb(); - } - - $rootScope.$emit('Local/NeedsPassword', false, function(err, password) { - if (err) return cb(err); - return cb(walletService.unlock(client, password)); - }); - }; - $scope.init = function() { $scope.deleted = isDeletedSeed(); if ($scope.deleted) return; - fingerprintService.check(wallet, function(err) { + walletService.getKey(wallet, function(err, mnemonics, xpriv) { if (err) { $state.go('preferences'); return; } - - handleEncryptedWallet(wallet, function(err) { - if (err) { - $log.warn('Error decrypting credentials:', $scope.error); - $state.go('preferences'); - return; - } - $scope.credentialsEncrypted = false; - $scope.initFlow(); - }); + $scope.credentialsEncrypted = false; + $scope.initFlow(mnemonics, xpriv); }); }; @@ -61,7 +43,8 @@ angular.module('copayApp.controllers').controller('backupController', $scope.initFlow = function() { var words = wallet.getMnemonic(); - $scope.xPrivKey = wallet.credentials.xPrivKey; + xPriv6 = wallet.credentials.xPrivKey.substr(wallet.credentials.xPrivKey.length - 6); + $scope.mnemonicWords = words.split(/[\u3000\s]+/); $scope.shuffledMnemonicWords = shuffledWords($scope.mnemonicWords); $scope.mnemonicHasPassphrase = wallet.mnemonicHasPassphrase(); @@ -72,6 +55,7 @@ angular.module('copayApp.controllers').controller('backupController', $scope.selectComplete = false; $scope.backupError = false; + words = lodash.repeat('x', 300); $timeout(function() { $scope.$apply(); }, 10); @@ -139,10 +123,12 @@ angular.module('copayApp.controllers').controller('backupController', account: wallet.credentials.account }); } catch (err) { + walletClient.credentials.xPrivKey = lodash.repeat('x', 64); return cb(err); } - if (walletClient.credentials.xPrivKey != $scope.xPrivKey) { + if (walletClient.credentials.xPrivKey.substr(walletClient.credentials.xPrivKey-6) != xPriv6) { + walletClient.credentials.xPrivKey = lodash.repeat('x', 64); return cb('Private key mismatch'); } } @@ -155,6 +141,7 @@ angular.module('copayApp.controllers').controller('backupController', var finalStep = function() { ongoingProcess.set('validatingWords', true); confirm(function(err) { + xPriv6 = lodash.repeat('x', 6); ongoingProcess.set('validatingWords', false); if (err) { backupError(err); diff --git a/src/js/controllers/preferences.js b/src/js/controllers/preferences.js index 4a72ae416..5118d70ef 100644 --- a/src/js/controllers/preferences.js +++ b/src/js/controllers/preferences.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('copayApp.controllers').controller('preferencesController', - function($scope, $rootScope, $timeout, $log, $stateParams, configService, profileService, fingerprintService, walletService) { + function($scope, $rootScope, $timeout, $log, $stateParams, configService, profileService, fingerprintService, walletService, $state) { var wallet = profileService.getWallet($stateParams.walletId); var walletId = wallet.credentials.walletId; @@ -10,22 +10,20 @@ angular.module('copayApp.controllers').controller('preferencesController', $scope.init = function() { $scope.externalSource = null; - if (wallet) { - var config = configService.getSync(); - config.aliasFor = config.aliasFor || {}; - $scope.alias = config.aliasFor[walletId] || wallet.credentials.walletName; - $scope.color = config.colorFor[walletId] || '#4A90E2'; + if (!wallet) + return $state.go('tabs.home'); - $scope.encryptEnabled = walletService.isEncrypted(wallet); - if (wallet.isPrivKeyExternal) - $scope.externalSource = wallet.getPrivKeyExternalSourceName() == 'ledger' ? 'Ledger' : 'Trezor'; + var config = configService.getSync(); + config.aliasFor = config.aliasFor || {}; + $scope.alias = config.aliasFor[walletId] || wallet.credentials.walletName; + $scope.color = config.colorFor[walletId] || '#4A90E2'; - // TODO externalAccount - //this.externalIndex = wallet.getExternalIndex(); - } + $scope.encryptEnabled = walletService.isEncrypted(wallet); + if (wallet.isPrivKeyExternal) + $scope.externalSource = wallet.getPrivKeyExternalSourceName() == 'ledger' ? 'Ledger' : 'Trezor'; - $scope.touchidAvailable = fingerprintService.isAvailable(); - $scope.touchidEnabled = config.touchIdFor ? config.touchIdFor[walletId] : null; + $scope.touchIdAvailable = fingerprintService.isAvailable(); + $scope.touchIdEnabled = config.touchIdFor ? config.touchIdFor[walletId] : null; $scope.deleted = false; if (wallet.credentials && !wallet.credentials.mnemonicEncrypted && !wallet.credentials.mnemonic) { @@ -101,29 +99,15 @@ angular.module('copayApp.controllers').controller('preferencesController', } }; - $scope.touchidChange = function() { - - var opts = { - touchIdFor: {} - }; - opts.touchIdFor[walletId] = $scope.touchidEnabled; - - fingerprintService.check(wallet, function(err) { + $scope.touchIdChange = function() { + var newStatus = $scope.touchIdEnabled; + walletService.setTouchId(wallet, newStatus, function(err) { if (err) { - $log.debug(err); - $timeout(function() { - $scope.touchidError = true; - $scope.touchidEnabled = true; - }, 100); + $log.warn(err); + $scope.touchIdEnabled = !newStatus; return; } - configService.set(opts, function(err) { - if (err) { - $log.debug(err); - $scope.touchidError = true; - $scope.touchidEnabled = false; - } - }); + $log.debug('Touch Id status changed: ' + newStatus); }); }; }); diff --git a/src/js/services/walletService.js b/src/js/services/walletService.js index b8b006e7e..5d3cbaf4c 100644 --- a/src/js/services/walletService.js +++ b/src/js/services/walletService.js @@ -547,27 +547,6 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim return isEncrypted; }; - root.lock = function(wallet) { - try { - wallet.lock(); - } catch (e) { - $log.warn('Encrypting wallet:', e); - }; - }; - - root.unlock = function(wallet, password) { - if (lodash.isEmpty(wallet)) - return 'MISSING_PARAMETER'; - if (lodash.isEmpty(password)) - return 'NO_PASSWORD_GIVEN'; - try { - wallet.unlock(password); - } catch (e) { - $log.warn('Decrypting wallet:', e); - return 'PASSWORD_INCORRECT'; - } - }; - root.createTx = function(wallet, txp, cb) { if (lodash.isEmpty(txp) || lodash.isEmpty(wallet)) return cb('MISSING_PARAMETER'); @@ -619,8 +598,8 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim }); }; - root.signTx = function(wallet, txp, cb) { - if (lodash.isEmpty(txp) || lodash.isEmpty(wallet)) + root.signTx = function(wallet, txp, password, cb) { + if (lodash.isEmpty(txp) || lodash.isEmpty(wallet) || lodash.isEmpty(cb)) return cb('MISSING_PARAMETER'); if (wallet.isPrivKeyExternal()) { @@ -637,8 +616,8 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim } else { try { - wallet.signTxProposal(txp, function(err, signedTxp) { - $log.debug('Transaction signed'); + wallet.signTxProposal(txp, password, function(err, signedTxp) { + $log.debug('Transaction signed err:' + err); return cb(err, signedTxp); }); } catch (e) { @@ -896,7 +875,8 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim askPassword(wallet.name, function(password) { if (!password) return cb('no password'); - return cb(root.unlock(wallet, password)); + + return cb(null, password); }); }; @@ -932,6 +912,19 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim }); }; + + root.prepare = function(wallet, cb) { + fingerprintService.check(wallet, function(err) { + if (err) return cb(err); + + root.handleEncryptedWallet(wallet, function(err, password) { + if (err) return cb(err); + + return cb(null, password); + }); + }); + }; + root.publishAndSign = function(wallet, txp, cb) { var publishFn = root.publishTx; @@ -943,56 +936,50 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim }; } - fingerprintService.check(wallet, function(err) { + root.prepare(wallet, function(err, password) { if (err) return cb(err); - root.handleEncryptedWallet(wallet, function(err) { + ongoingProcess.set('sendingTx', true); + publishFn(wallet, txp, function(err, publishedTxp) { + ongoingProcess.set('sendingTx', false); if (err) return cb(err); - ongoingProcess.set('sendingTx', true); - publishFn(wallet, txp, function(err, publishedTxp) { - ongoingProcess.set('sendingTx', false); - if (err) return cb(err); - - ongoingProcess.set('signingTx', true); - root.signTx(wallet, publishedTxp, function(err, signedTxp) { - root.lock(wallet); - - ongoingProcess.set('signingTx', false); - root.invalidateCache(wallet); + ongoingProcess.set('signingTx', true); + root.signTx(wallet, publishedTxp, password, function(err, signedTxp) { + ongoingProcess.set('signingTx', false); + root.invalidateCache(wallet); - if (err) { - // TODO? - var msg = err.message ? - err.message : - gettext('The payment was created but could not be completed. Please try again from home screen'); - $rootScope.$emit('Local/TxAction', wallet.id); - return cb(err); - } + if (err) { + // TODO? + var msg = err.message ? + err.message : + gettext('The payment was created but could not be completed. Please try again from home screen'); + $rootScope.$emit('Local/TxAction', wallet.id); + return cb(err); + } - if (signedTxp.status == 'accepted') { - ongoingProcess.set('broadcastingTx', true); - root.broadcastTx(wallet, signedTxp, function(err, broadcastedTxp) { - ongoingProcess.set('broadcastingTx', false); - if (err) return cb(err); + if (signedTxp.status == 'accepted') { + ongoingProcess.set('broadcastingTx', true); + root.broadcastTx(wallet, signedTxp, function(err, broadcastedTxp) { + ongoingProcess.set('broadcastingTx', false); + if (err) return cb(err); - var type = txStatus.notify(broadcastedTxp); - root.openStatusModal(type, broadcastedTxp, function() { - $rootScope.$emit('Local/TxAction', wallet.id); - }); - - return cb(null, broadcastedTxp) - }); - } else { - var type = txStatus.notify(signedTxp); - root.openStatusModal(type, signedTxp, function() { - root.invalidateCache(wallet); + var type = txStatus.notify(broadcastedTxp); + root.openStatusModal(type, broadcastedTxp, function() { $rootScope.$emit('Local/TxAction', wallet.id); }); - return cb(null, signedTxp); - } - }); + + return cb(null, broadcastedTxp) + }); + } else { + var type = txStatus.notify(signedTxp); + root.openStatusModal(type, signedTxp, function() { + root.invalidateCache(wallet); + $rootScope.$emit('Local/TxAction', wallet.id); + }); + return cb(null, signedTxp); + } }); }); }); @@ -1004,7 +991,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim if (err) return cb(err); notifications = lodash.filter(notifications, function(x) { - return x.type != 'NewBlock' && x.type != 'BalanceUpdated' && x.type !='NewOutgoingTxByThirdParty'; + return x.type != 'NewBlock' && x.type != 'BalanceUpdated' && x.type != 'NewOutgoingTxByThirdParty'; }); var idToName = {}; @@ -1110,7 +1097,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim } }); - // messsages... + // messages... var u = bwcService.getUtils(); lodash.each(finale, function(x) { @@ -1124,6 +1111,31 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim }; + root.setTouchId = function(wallet, enabled, cb) { + fingerprintService.check(wallet, function(err) { + if (err) return cb(err); { + $log.debug(err); + return; + } + configService.set(opts, cb); + }); + }; + + root.getKey = function(wallet, cb) { + root.prepare(wallet, function(err, password) { + if (err) return cb(err); + var keys; + + try { + keys = wallet.getKeys(password); + } catch (e) { + return cb(err); + } + + return cb(null, keys); + }); + }; + return root; });