From aa69ca971d1535f9fb7e4e4a8d7ec5fabbdd2349 Mon Sep 17 00:00:00 2001 From: dthorpe Date: Sat, 3 May 2014 18:03:40 -0700 Subject: [PATCH 01/13] Fix concat.sh failure when building copay on Windows. (and silent? bug in Linux builds - build.js attempts to cd to js/browser subdir, but there is no such directory in the copay project, and concat.sh resides in the project root) --- util/build.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/build.js b/util/build.js index fd587da26..14855bbe8 100755 --- a/util/build.js +++ b/util/build.js @@ -30,7 +30,7 @@ var createBundle = function(opts) { opts.dir = opts.dir || 'js/'; // concat browser vendor files - exec('cd ' + opts.dir + 'browser; sh concat.sh', puts); + exec('sh concat.sh', puts); var bopts = { pack: pack, From 79492f02efa36e425e5286c4022f751d5d1bdea3 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Sun, 4 May 2014 16:41:17 -0300 Subject: [PATCH 02/13] Minor spelling fixes in README.md --- README.md | 59 +++++++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index dd6106226..71b7dc353 100644 --- a/README.md +++ b/README.md @@ -36,19 +36,19 @@ About Copay General ------- -*Copay* implements a multisig wallet using p2sh addresses. It support multiple wallet configurations, like 3-of-5 -(3 required signatures from 5 participant peers) or 2-of-3. To generate addresses to receive coins, -*Copay* needs the public keys of all the participat peers in the wallet. Those public keys, among the +*Copay* implements a multisig wallet using p2sh addresses. It supports multiple wallet configurations, like +3-of-5 (3 required signatures from 5 participant peers) or 2-of-3. To generate addresses to receive coins, +*Copay* needs the public keys of all the participant peers in the wallet. Those public keys, among the wallet configuration, are combined to generate a single address to receive a payment. -To unlock the payment, and spend the wallet's funds, the needed signatures need to be collected an put togheter -in the transaction. Each peer manage her own private key, and that key is never transmited to other -peers. Once a transaction proposal is created, the proposal is distributed among the peers and each peer -can sign the transaction locally. Once the transaction is complete, the last signing peer will broadcast the +To unlock the payment, and spend the wallet's funds, the needed signatures need to be collected and put +togheter in the transaction. Each peer manages her own private key, and that key is never transmited to +other peers. Once a transaction proposal is created, the proposal is distributed among the peers and each peer +can sign the transaction locally. Once the signing is complete, the last signing peer will broadcast the transaction to the bitcoin network, using a public API for that (Insight API by default in *Copay*).. -*Copay* also implements BIP32 to generate new addresses for the peers. This mean that the actual piece of -information shared between the peers is an extended public key, from which is possible to derive more +*Copay* also implements BIP32 to generate new addresses for the peers. This means that the actual piece of +information shared between the peers is an extended public key, from which it is possible to derive more public keys so the wallet can use them. Each peer holds for himself his extended private key, to be able to sign the incoming transaction proposals. @@ -57,41 +57,40 @@ Serverless web *Copay* software does not need an application server to run. All the software is implemented in client-side Javascript. For persistent storage, the client browser's *localStorage* is used. This information is stored encryped using the peer's password. Also it is possible (and recommended) to backup that information -with using one of the options provided by *Copay*, like file downloading. Without a proper backup, all +with using one of the options provided by *Copay*, like file downloading. Without a proper backup, all wallets funds can be lost if the browser's localStorage is deleted, or the browser installation deleted. Peer communications ------------------- -*Copay* use peer-to-peer (p2p) networking to comunicate the parties. Parties exchange transaction -proposals, public keys, nicknames and some wallet options. As mentioned above, private keys are *no* +*Copay* use peer-to-peer (p2p) networking for comunication between the parties. Parties exchange transaction +proposals, public keys, nicknames and some wallet options. As mentioned above, private keys are *not* sent to the network. -webRTC is the used protocol. A p2p facilitator server is needed to allow the peers to find each other. - *Copay* uses the open-sourced *peerjs* -server implementation. Wallet participants can use a public peerjs server or install their own. Once the peers -find each other, a true p2p connection is established and there is no flow of information to the -server, only between the peers. +webRTC is the used protocol for p2p communication. A p2p facilitator server is needed to allow the peers +to find each other. *Copay* uses the open-sourced *peerjs* server implementation. Wallet participants +can use a public peerjs server or install their own. Once the peers find each other, a true p2p +connection is established and there is no flow of information to the server, only between the peers. -webRTC uses DTLS to secure communications between the peers, and each peer use a self-signed +webRTC uses DTLS to secure communications between the peers, and each peer uses a self-signed certificate. Security model -------------- -On top of webRTC, *Copay* peers authenticate as part of the "wallet ring"(WR) by 2 factors: An identity +On top of webRTC, *Copay* peers authenticate as part of the "wallet ring"(WR) by 2 factors: An identity key and a network key. -The *identity key* is a ECDSA public key derived from their extended public -key using a specific BIP32 branch. This special public key is never used for Bitcoin address creation, and -should only be know by members of the WR. -In *Copay* this special public key is named *copayerId*. To register into the peerjs server, while not -reveling its copayerId to an entity outside the WR, each peer hash the copayerId and pass a SIN -to the server. peer discovery is then entirely done using peer's SINs. Note that all copayers in the WR -know the complete copayerIDs of the peers. +The *identity key* is a ECDSA public key derived from peers' extended public key using a specific BIP32 +branch. This special public key is never used for Bitcoin address creation, and should only be know by +members of the WR. +In *Copay* this special public key is named *copayerId*. To register into the peerjs server, while not +reveling its copayerId to an entity outside the WR, each peer hashes the copayerId and sends a SIN +to the server. peer discovery is then entirely done using the peer's SINs. Note that all copayers in +the WR know the complete copayerIDs of the peers. The *network key* is a random key generated when the wallet is created an shared in the initial 'secret string' that peers distribute while the wallet is been created. The network key is then stored -by each peer on the wallet configuration. The network key is used for establishing a CCM/AES -authenticated encrypted channel between all peers, on top of webRTC. The main reason of implementing +by each peer in their wallet configuration. The network key is used for establishing a CCM/AES +authenticated encrypted channel between all peers, on top of webRTC. The main reason for implementing the *network key* is to prevent man-in-the-middle attacks from a compromised peerjs server. Secret String @@ -99,7 +98,7 @@ Secret String When a wallet is created, a secret string is provided to invite new peers to the new wallet. This string has the following format: - - CopayerId of the peer generating the string. This is a 33 bytes ECDSA public key, as explained above. + - CopayerId of the peer generating the string. This is a 33 byte ECDSA public key, as explained above. This allow the receiving peer to locate the generating peer. - Network Key. A 8 byte string to encrypt and sign the peers communication. @@ -109,7 +108,7 @@ Peer authentication ------------------- It is important to note that all data in the wallet is shared between *all peers*, with the exception of each -peer's private key, with are never transmited throught the network. There is not private messages or, in general, +peer's private key, which are never transmited throught the network. There are no private messages or, in general, information that belongs to a subset of the WR. From af4a11c26d40ad3837b8b95bb823f443e42267af Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Mon, 5 May 2014 13:16:56 -0300 Subject: [PATCH 03/13] Improve restore forms --- index.html | 31 ++++++++++++++++++++++--------- js/controllers/import.js | 32 +++++++++++++++++++++++++------- 2 files changed, 47 insertions(+), 16 deletions(-) diff --git a/index.html b/index.html index 9994794a6..51dffc4cd 100644 --- a/index.html +++ b/index.html @@ -176,7 +176,7 @@ Create a new wallet · - Import from file + Restore a backup @@ -185,14 +185,27 @@ diff --git a/js/controllers/import.js b/js/controllers/import.js index d04fd54fc..1f6174892 100644 --- a/js/controllers/import.js +++ b/js/controllers/import.js @@ -21,13 +21,31 @@ angular.module('copay.import').controller('ImportController', }; }; - $scope.import = function() { - if ($scope.password) { - if ($scope.backupText) { - _importBackup($scope.backupText); - } else { - reader.readAsBinaryString($scope.file); - } + $scope.import = function(form) { + if (form.$invalid) { + $rootScope.flashMessage = { message: 'There is an error in the form. Please, try again', type: 'error'}; + return; } + + var backupFile = $scope.file; + var backupText = form.backupText.$modelValue; + var password = form.password.$modelValue; + + if (!backupFile && !backupText) { + $rootScope.flashMessage = { message: 'Please, select your backup file or paste the text', type: 'error'}; + return; + } + + $scope.loading = true; + + if (backupFile) { + reader.readAsBinaryString(backupFile); + } + else { + _importBackup(backupText); + } + + $scope.loading = false; + }; }); From 33e824a64c8855cee04ae1fc089958a7eab1828d Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Mon, 5 May 2014 15:54:17 -0300 Subject: [PATCH 04/13] STUN/TURN in default config --- config.template.js | 28 +++++++++++++++++++--------- js/models/network/WebRTC.js | 7 ++----- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/config.template.js b/config.template.js index b297a068b..c3326df2d 100644 --- a/config.template.js +++ b/config.template.js @@ -9,18 +9,29 @@ var config = { //host: 'localhost', //port: 10009, //path: '/', - // + // key: 'g23ihfh82h35rf', // api key for the peerjs server - host:'162.242.219.26', // peerjs server - port:10009, + host: '162.242.219.26', // peerjs server + port: 10009, path: '/', maxPeers: 15, -// debug: 3, + debug: 3, sjclParams: { salt: 'mjuBtGybi/4=', // choose your own salt (base64) - iter:1000, - mode:'ccm', - ts:parseInt(64), + iter: 1000, + mode: 'ccm', + ts: parseInt(64), + }, + config: { + 'iceServers': [ + // Pass in STUN and TURN server for maximum network compatibility + { + url: 'stun:stun.l.google.com:19302' + }, { + url: 'turn:homeo@turn.bistri.com:80', + credential: 'homeo' + } + ] } }, limits: { @@ -47,7 +58,6 @@ var config = { storageSalt: 'mjuBtGybi/4=', // choose your own salt (base64) }; -var log = function () { +var log = function() { if (config.verbose) console.log(arguments); } - diff --git a/js/models/network/WebRTC.js b/js/models/network/WebRTC.js index 62b308d77..6f9eeaefd 100644 --- a/js/models/network/WebRTC.js +++ b/js/models/network/WebRTC.js @@ -28,11 +28,8 @@ function Network(opts) { mode:'ccm', ts:parseInt(64), }; - - - // For using your own peerJs server - self.opts = {}; - ['port', 'host', 'path', 'debug', 'key'].forEach(function(k) { + this.opts = {}; + ['config', 'port', 'host', 'path', 'debug', 'key'].forEach(function(k) { if (opts[k]) self.opts[k] = opts[k]; }); this.cleanUp(); From c46e7bf2d1bcb4b389880af4b18358916d6466d6 Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Mon, 5 May 2014 15:59:57 -0300 Subject: [PATCH 05/13] Replaced accordion by standard angularjs directives. --- index.html | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/index.html b/index.html index 51dffc4cd..4ade128b3 100644 --- a/index.html +++ b/index.html @@ -185,19 +185,15 @@ diff --git a/js/controllers/setup.js b/js/controllers/setup.js index 1da4404e4..bd5116dad 100644 --- a/js/controllers/setup.js +++ b/js/controllers/setup.js @@ -32,7 +32,12 @@ angular.module('copay.setup').controller('SetupController', updateRCSelect(tc); }); - $scope.create = function() { + $scope.create = function(form) { + if (form && form.$invalid) { + $rootScope.flashMessage = { message: 'Please, enter required fields', type: 'error'}; + return; + } + $scope.loading = true; var passphrase = Passphrase.getBase64($scope.walletPassword); From 20b0b6e9c7301fa672ab6e1f178b67fef117d79a Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Tue, 6 May 2014 16:21:56 -0300 Subject: [PATCH 13/13] fix refresh button --- js/controllers/header.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/controllers/header.js b/js/controllers/header.js index 3d17ec7a7..1c0dc56e9 100644 --- a/js/controllers/header.js +++ b/js/controllers/header.js @@ -44,6 +44,7 @@ angular.module('copay.header').controller('HeaderController', }; $scope.refresh = function() { + var w = $rootScope.wallet; controllerUtils.updateBalance(function() { w.connectToAll(); $rootScope.$digest();