From f9fad5d62f758b24ce30c1932770f963e9d07994 Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Mon, 7 Jul 2014 17:09:24 -0300 Subject: [PATCH 1/8] Add partial backup at create and join --- js/controllers/setup.js | 1 + js/controllers/signin.js | 1 + js/services/backupService.js | 10 ++++++---- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/js/controllers/setup.js b/js/controllers/setup.js index 3ac730299..f2409c204 100644 --- a/js/controllers/setup.js +++ b/js/controllers/setup.js @@ -81,6 +81,7 @@ angular.module('copayApp.controllers').controller('SetupController', passphrase: passphrase, }; var w = walletFactory.create(opts); + backupService.download(w); controllerUtils.startNetwork(w, $scope); }); }; diff --git a/js/controllers/signin.js b/js/controllers/signin.js index 6503d46ab..e01292886 100644 --- a/js/controllers/signin.js +++ b/js/controllers/signin.js @@ -70,6 +70,7 @@ angular.module('copayApp.controllers').controller('SigninController', notification.error('Unknown error'); controllerUtils.onErrorDigest(); } else { + backupService.download(w); controllerUtils.startNetwork(w, $scope); } }); diff --git a/js/services/backupService.js b/js/services/backupService.js index 689604e47..0b7375c0e 100644 --- a/js/services/backupService.js +++ b/js/services/backupService.js @@ -11,10 +11,12 @@ BackupService.prototype.getName = function(wallet) { BackupService.prototype.download = function(wallet) { var ew = wallet.toEncryptedObj(); - var timestamp = +(new Date()); - var walletName = this.getName(wallet); - var filename = walletName + '-' + timestamp + '-keybackup.json.aes'; - this.notifications.success('Backup created', 'Encrypted backup file saved.'); + var partial = !wallet.publicKeyRing.isComplete(); + var walletName = this.getName(wallet) + (partial ? '-Partial' : ''); + var filename = walletName + '-keybackup.json.aes'; + + var notify = partial ? 'Partial backup created' : 'Backup created'; + this.notifications.success(notify, 'Encrypted backup file saved.'); var blob = new Blob([ew], { type: 'text/plain;charset=utf-8' }); From 49ac6dfcf487f7033037eabdc6884cd2dd7c5658 Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Mon, 7 Jul 2014 18:35:44 -0300 Subject: [PATCH 2/8] Hold on backup page until all copayers made a full backup --- index.html | 13 ++++++++----- js/controllers/header.js | 4 ++-- js/models/core/PublicKeyRing.js | 34 +++++++++++++++++++++++++++++++++ js/models/core/Wallet.js | 8 ++++---- 4 files changed, 48 insertions(+), 11 deletions(-) diff --git a/index.html b/index.html index cac7012c4..ec93c6212 100644 --- a/index.html +++ b/index.html @@ -140,10 +140,11 @@
- +
diff --git a/js/controllers/header.js b/js/controllers/header.js index 1b61dc518..1a7c8fe66 100644 --- a/js/controllers/header.js +++ b/js/controllers/header.js @@ -87,10 +87,10 @@ angular.module('copayApp.controllers').controller('HeaderController', window.onbeforeunload = undefined; }); - $scope.backupAndOpen = function() { + $scope.backup = function() { var w = $rootScope.wallet; - w.offerBackup(); backupService.download(w); + w.setBackupReady(); }; $scope.getVideoURL = function(copayer) { diff --git a/js/models/core/PublicKeyRing.js b/js/models/core/PublicKeyRing.js index ea56d20f8..8bf663d6d 100644 --- a/js/models/core/PublicKeyRing.js +++ b/js/models/core/PublicKeyRing.js @@ -30,6 +30,7 @@ function PublicKeyRing(opts) { this.publicKeysCache = opts.publicKeysCache || {}; this.nicknameFor = opts.nicknameFor || {}; this.copayerIds = []; + this.copayersBackup = opts.copayersBackup || []; this.addressToPath = {}; } @@ -59,6 +60,7 @@ PublicKeyRing.prototype.toObj = function() { requiredCopayers: this.requiredCopayers, totalCopayers: this.totalCopayers, indexes: AddressIndex.serialize(this.indexes), + copayersBackup: this.copayersBackup, copayersExtPubKeys: this.copayersHK.map(function(b) { return b.extendedPublicKeyString(); @@ -350,12 +352,30 @@ PublicKeyRing.prototype._mergePubkeys = function(inPKR) { return hasChanged; }; +PublicKeyRing.prototype.setBackupReady = function(copayerId) { + if (this.isBackupReady()) return false; + + var cid = this.myCopayerId(); + this.copayersBackup.push(cid); + return true; +} + +PublicKeyRing.prototype.isBackupReady = function(copayerId) { + var cid = this.myCopayerId(); + return this.copayersBackup.indexOf(cid) != -1; +} + +PublicKeyRing.prototype.isFullyBackup = function(copayerId) { + return this.copayersBackup.length == this.totalCopayers; +} + PublicKeyRing.prototype.merge = function(inPKR, ignoreId) { this._checkInPKR(inPKR, ignoreId); var hasChanged = false; hasChanged |= this.mergeIndexes(inPKR.indexes); hasChanged |= this._mergePubkeys(inPKR); + hasChanged |= this.mergeBackups(inPKR.copayersBackup); return !!hasChanged; }; @@ -372,4 +392,18 @@ PublicKeyRing.prototype.mergeIndexes = function(indexes) { return !!hasChanged } +PublicKeyRing.prototype.mergeBackups = function(backups) { + var self = this; + var hasChanged = false; + + backups.forEach(function(cid) { + var isNew = self.copayersBackup.indexOf(cid) == -1; + if (isNew) self.copayersBackup.push(cid); + hasChanged |= isNew; + }); + + return !!hasChanged +} + + module.exports = require('soop')(PublicKeyRing); diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index 5e0be4c44..fa7c8be57 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -879,13 +879,13 @@ Wallet.prototype.toggleAddressBookEntry = function(key) { }; Wallet.prototype.isReady = function() { - var ret = this.publicKeyRing.isComplete() && this.backupOffered; + var ret = this.publicKeyRing.isComplete() && this.publicKeyRing.isFullyBackup(); return ret; }; -Wallet.prototype.offerBackup = function() { - this.backupOffered = true; - this.store(); +Wallet.prototype.setBackupReady = function() { + this.publicKeyRing.setBackupReady(); + this.emit('publicKeyRingUpdated', false); }; Wallet.prototype.signJson = function(payload) { From c1452901671f40f568e422853c5929946615338e Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Tue, 8 Jul 2014 10:43:10 -0300 Subject: [PATCH 3/8] Add full backup stage with user feedback --- index.html | 25 +++++++++++++++---------- js/models/core/PublicKeyRing.js | 14 +++++++++++--- js/models/core/Wallet.js | 4 +++- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/index.html b/index.html index ec93c6212..9d88b89c2 100644 --- a/index.html +++ b/index.html @@ -121,11 +121,9 @@ src="./img/satoshi.gif" /> - -

you

-
- -

{{c.nick}}

+ +

you{{c.nick}} + Backup ready

[SIN: {{c.peerId}}]
@@ -144,13 +142,13 @@ ng-show="!$root.wallet.publicKeyRing.isBackupReady()" ng-disabled="!$root.wallet.publicKeyRing.isComplete()"> - Backup keys + Backup the wallet - - {{$root.wallet.publicKeyRing.totalCopayers - $root.wallet.publicKeyRing.registeredCopayers() }} people have + + {{ $root.wallet.publicKeyRing.remainingCopayers() }} people have - + One person has yet to join. @@ -159,7 +157,14 @@ diff --git a/js/models/core/PublicKeyRing.js b/js/models/core/PublicKeyRing.js index 8bf663d6d..423c083eb 100644 --- a/js/models/core/PublicKeyRing.js +++ b/js/models/core/PublicKeyRing.js @@ -80,7 +80,11 @@ PublicKeyRing.prototype.registeredCopayers = function() { }; PublicKeyRing.prototype.isComplete = function() { - return this.registeredCopayers() === this.totalCopayers; + return this.remainingCopayers() == 0; +}; + +PublicKeyRing.prototype.remainingCopayers = function() { + return this.totalCopayers - this.registeredCopayers(); }; PublicKeyRing.prototype.getAllCopayerIds = function() { @@ -361,14 +365,18 @@ PublicKeyRing.prototype.setBackupReady = function(copayerId) { } PublicKeyRing.prototype.isBackupReady = function(copayerId) { - var cid = this.myCopayerId(); + var cid = copayerId || this.myCopayerId(); return this.copayersBackup.indexOf(cid) != -1; } PublicKeyRing.prototype.isFullyBackup = function(copayerId) { - return this.copayersBackup.length == this.totalCopayers; + return this.remainingBackups() == 0; } +PublicKeyRing.prototype.remainingBackups = function() { + return this.totalCopayers - this.copayersBackup.length; +}; + PublicKeyRing.prototype.merge = function(inPKR, ignoreId) { this._checkInPKR(inPKR, ignoreId); diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index fa7c8be57..8c530d90e 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -327,6 +327,7 @@ Wallet.prototype.getRegisteredPeerIds = function() { var pid = this.network.peerFromCopayer(cid); this.registeredPeerIds.push({ peerId: pid, + copayerId: cid, nick: this.publicKeyRing.nicknameForCopayer(cid), index: i, }); @@ -885,7 +886,8 @@ Wallet.prototype.isReady = function() { Wallet.prototype.setBackupReady = function() { this.publicKeyRing.setBackupReady(); - this.emit('publicKeyRingUpdated', false); + this.sendPublicKeyRing(); + this.store(); }; Wallet.prototype.signJson = function(payload) { From 37b3543da2b8849dd2b825fd3f1e0bc554007d11 Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Tue, 8 Jul 2014 10:45:20 -0300 Subject: [PATCH 4/8] Change SIN to ID --- index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index 9d88b89c2..569adb873 100644 --- a/index.html +++ b/index.html @@ -124,7 +124,7 @@

you{{c.nick}} Backup ready

- [SIN: {{c.peerId}}] + [ID: {{c.peerId}}]
@@ -229,7 +229,7 @@
-
+