From 4ba65dd4e1758ded22b0790c44a613b8e7e765bd Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Fri, 18 Apr 2014 18:25:51 -0300 Subject: [PATCH] automatic peer discovery --- index.html | 6 ++-- js/config.js | 12 ++++---- js/controllers/signin.js | 9 ++++-- js/models/core/PrivateKey.js | 2 +- js/models/core/PublicKeyRing.js | 13 +++++++-- js/models/core/Wallet.js | 35 +++++++++++++++++----- js/models/core/WalletFactory.js | 17 ++++++----- js/models/network/WebRTC.js | 51 ++++++++++++++++++++++++--------- js/services/controllerUtils.js | 2 ++ 9 files changed, 103 insertions(+), 44 deletions(-) diff --git a/index.html b/index.html index 333f9c8b6..ffcc2f018 100644 --- a/index.html +++ b/index.html @@ -61,7 +61,7 @@ One key is - missing. Ask your copayers to join your session: {{$root.wallet.network.peerId}} + missing. Share this secret with your other copayers for them to join your wallet: {{$root.wallet.network.peerId}} @@ -82,7 +82,7 @@

Join Wallet Creation

-
@@ -110,7 +110,7 @@
-

Open a Existing Wallet

+

Open Existing Wallet

diff --git a/js/config.js b/js/config.js index 1ee5a429b..130c3f494 100644 --- a/js/config.js +++ b/js/config.js @@ -3,13 +3,13 @@ var config = { networkName: 'testnet', network: { - key: 'lwjd5qra8257b9', + // key: 'lwjd5qra8257b9', // This is for running local peerJs with params: ./peerjs -p 10009 -k 'sdfjhwefh' - // key: 'sdfjhwefh', - // host: 'localhost', - // port: 10009, - // path: '/', - maxPeers: 3, + key: 'sdfjhwefh', + host: '192.168.1.100', + port: 10009, + path: '/', + maxPeers: 10, debug: 3, }, limits: { diff --git a/js/controllers/signin.js b/js/controllers/signin.js index d977aa106..2607fd611 100644 --- a/js/controllers/signin.js +++ b/js/controllers/signin.js @@ -17,10 +17,11 @@ angular.module('copay.signin').controller('SigninController', $location.path('setup'); }; - $scope.open = function(walletId) { + $scope.open = function(walletId, opts) { $scope.loading = true; - var w = walletFactory.open(walletId); + console.log('OPENING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11 '+walletId+' opts '+opts); + var w = walletFactory.open(walletId, opts); controllerUtils.setupUxHandlers(w); }; @@ -30,7 +31,9 @@ angular.module('copay.signin').controller('SigninController', controllerUtils.onError($scope); $rootScope.$digest(); }); - walletFactory.connectTo(cid, $scope.open.bind($scope)); + walletFactory.connectTo(cid, function(data) { + $scope.open(data.walletId, data.opts); + }); }; diff --git a/js/models/core/PrivateKey.js b/js/models/core/PrivateKey.js index c6e5d5c5f..bf8cfa9de 100644 --- a/js/models/core/PrivateKey.js +++ b/js/models/core/PrivateKey.js @@ -21,7 +21,7 @@ function PrivateKey(opts) { PrivateKey.prototype.getId = function(prefix) { var buf = this.bip.extendedPublicKey; if (prefix) { - buf = Buffer.concat([prefix, this.bip.extendedPublicKey]); + buf = Buffer.concat([prefix, buf]); } return util.ripe160(buf).toString('hex'); }; diff --git a/js/models/core/PublicKeyRing.js b/js/models/core/PublicKeyRing.js index b55d7568b..122fb7da5 100644 --- a/js/models/core/PublicKeyRing.js +++ b/js/models/core/PublicKeyRing.js @@ -9,6 +9,7 @@ var Address = bitcore.Address; var Script = bitcore.Script; var coinUtil = bitcore.util; var Transaction = bitcore.Transaction; +var util = bitcore.util; var Storage = imports.Storage || require('../storage/Base.js'); var storage = Storage.default(); @@ -76,6 +77,14 @@ PublicKeyRing.prototype.serialize = function () { return JSON.stringify(this.toObj()); }; +PublicKeyRing.prototype.getCopayerId = function(i, prefix) { + var buf = this.copayersBIP32[i].extendedPublicKey; + if (prefix) { + buf = Buffer.concat([prefix, buf]); + } + return util.ripe160(buf).toString('hex'); +} + PublicKeyRing.prototype.registeredCopayers = function () { return this.copayersBIP32.length; @@ -225,12 +234,12 @@ PublicKeyRing.prototype._checkInPRK = function(inPKR, ignoreId) { if ( this.requiredCopayers && inPKR.requiredCopayers && (this.requiredCopayers !== inPKR.requiredCopayers)) - throw new Error('inPRK requiredCopayers mismatch'); + throw new Error('inPRK requiredCopayers mismatch '+this.requiredCopayers+'!='+inPKR.requiredCopayers); if ( this.totalCopayers && inPKR.totalCopayers && (this.totalCopayers !== inPKR.totalCopayers)) - throw new Error('inPRK requiredCopayers mismatch'); + throw new Error('inPRK totalCopayers mismatch'+this.totalCopayers+'!='+inPKR.requiredCopayers); }; diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index 254d4e6b1..376e95ebc 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -48,7 +48,9 @@ Wallet.prototype._handlePublicKeyRing = function(senderId, data, isInbound) { var shouldSend = false; var recipients, pkr = this.publicKeyRing; var inPKR = copay.PublicKeyRing.fromObj(data.publicKeyRing); - if (pkr.merge(inPKR, true) && !data.isBroadcast) { + + var hasChanged = pkr.merge(inPKR, true); + if (hasChanged && !data.isBroadcast) { this.log('### BROADCASTING PKR'); recipients = null; shouldSend = true; @@ -115,8 +117,11 @@ Wallet.prototype._handleData = function(senderId, data, isInbound) { Wallet.prototype._handleNetworkChange = function(newPeer) { if (newPeer) { this.log('#### Setting new PEER:', newPeer); + console.log('sending wallet id'); this.sendWalletId(newPeer); + console.log('sending pubkeyring'); this.sendPublicKeyRing(newPeer); + console.log('sending tx proposals'); this.sendTxProposals(newPeer); } this.emit('refresh'); @@ -134,10 +139,16 @@ Wallet.prototype._optsToObj = function () { }; -Wallet.prototype.generatePeerId = function() { - var gen = this.privateKey.getId(new Buffer(this.id)); - console.log(gen); - return gen; +Wallet.prototype.generatePeerId = function(index) { + var idBuf = new Buffer(this.id); + if (typeof index === 'undefined') { + // return my own peerId + var gen = this.privateKey.getId(idBuf); + return gen; + } + // return peer number 'index' peerId + return this.publicKeyRing.getCopayerId(index, idBuf); + }; Wallet.prototype.netStart = function() { @@ -148,17 +159,26 @@ Wallet.prototype.netStart = function() { net.on('data', self._handleData.bind(self) ); net.on('open', function() {}); // TODO net.on('openError', function() { - this.log('[Wallet.js.132:openError:] GOT openError'); //TODO + self.log('[Wallet.js.132:openError:] GOT openError'); //TODO self.emit('openError'); }); net.on('close', function() { self.emit('close'); }); var startOpts = { - peerId: this.generatePeerId() + peerId: self.generatePeerId() } + console.log('STARTING NETWORK WITH PEER ID: '+startOpts.peerId); net.start(function(peerId) { self.emit('created'); + console.log('CREATEEEEEEEEEEEEEEEEEEEEEEd'); + var myId = self.generatePeerId(); + for (var i=0; i= 0) array.splice(pos, 1); - return array; }; Network.prototype._onClose = function(peerId) { this.connectedPeers = Network._arrayRemove(peerId, this.connectedPeers); + console.log('on close peers:'+this.connectedPeers); this._notifyNetworkChange(); }; @@ -106,7 +106,7 @@ Network.prototype._onData = function(data, isInbound) { this._onClose(obj.sender); break; case 'walletId': - this.emit('walletId', obj.data.walletId); + this.emit('walletId', obj.data); break; default: this.emit('data', obj.sender, obj.data, isInbound); @@ -124,8 +124,6 @@ Network.prototype._sendPeers = function(peerIds) { Network.prototype._addPeer = function(peerId, isInbound) { var hasChanged = Network._arrayPushOnce(peerId, this.connectedPeers); - - if (isInbound && hasChanged) { this._sendPeers(); //broadcast peer list } @@ -186,17 +184,15 @@ Network.prototype._setupPeerHandlers = function(openCallback) { var p = this.peer; p.on('open', function(peerId) { + console.log('setup peer handlers open'+peerId); self.peerId = peerId; self.connectedPeers = [peerId]; - self._notifyNetworkChange(); return openCallback(peerId); }); p.on('error', function(err) { console.log('### PEER ERROR:', err); - self.peer.disconnect(); - self.peer.destroy(); - self.peer = null; + //self.disconnect(null, true); // force disconnect self._checkAnyPeer(); }); @@ -217,14 +213,36 @@ Network.prototype._setupPeerHandlers = function(openCallback) { }; Network.prototype.start = function(openCallback, opts) { + console.log('start start'); + opts = opts || {}; // Start PeerJS Peer - if (this.started) return openCallback(); // This is for connectTo-> peer is started before + var self = this; + if (this.started) { + // network already started, restarting network layer + console.log('Restarting network layer'); + opts.connectedPeers = this.connectedPeers; + Network._arrayRemove(this.peerId, opts.connectedPeers); + this.disconnect(function() { + console.log('restart disconnect finished'); + self.start(openCallback, opts); + }, true); // fast disconnect + return; + } + + opts = opts || {}; + opts.connectedPeers = opts.connectedPeers || []; this.peerId = this.peerId || opts.peerId; + console.log('setting up fresh network with id'+this.peerId); this.peer = new Peer(this.peerId, this.opts); this._setupPeerHandlers(openCallback); + console.log('connected peers'+opts.connectedPeers); + for (var i = 0; i