mirror of https://github.com/BTCPrivate/copay.git
automatic peer discovery
This commit is contained in:
parent
d62dbeffca
commit
4ba65dd4e1
|
@ -61,7 +61,7 @@
|
|||
<span ng-show="$root.wallet.publicKeyRing.totalCopayers - $root.wallet.publicKeyRing.registeredCopayers()==1">
|
||||
One key is
|
||||
</span>
|
||||
missing. Ask your copayers to join your session: <b>{{$root.wallet.network.peerId}}</b>
|
||||
missing. Share this secret with your other copayers for them to join your wallet: <b>{{$root.wallet.network.peerId}}</b>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -82,7 +82,7 @@
|
|||
<div class="row">
|
||||
<div class="large-6 columns">
|
||||
<h3>Join Wallet Creation</h3>
|
||||
<input type="text" class="form-control" placeholder="Paste wallet ID here"
|
||||
<input type="text" class="form-control" placeholder="Paste secret here"
|
||||
ng-model="connectionId" autofocus>
|
||||
</div>
|
||||
<div class="large-3 columns">
|
||||
|
@ -110,7 +110,7 @@
|
|||
<div ng-show="walletIds.length>0">
|
||||
<div class="row">
|
||||
<div class="large-6 columns">
|
||||
<h3>Open a Existing Wallet</h3>
|
||||
<h3>Open Existing Wallet</h3>
|
||||
<select class="form-control" ng-model="selectedWalletId" ng-options="walletId for walletId in walletIds">
|
||||
</select>
|
||||
</div>
|
||||
|
|
12
js/config.js
12
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: {
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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');
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
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<self.publicKeyRing.registeredCopayers(); i++) {
|
||||
var otherPeerId = self.generatePeerId(i);
|
||||
if (otherPeerId !== myId) {
|
||||
net.connectTo(otherPeerId);
|
||||
}
|
||||
}
|
||||
}, startOpts);
|
||||
};
|
||||
|
||||
|
@ -217,6 +237,7 @@ Wallet.prototype.sendWalletId = function(recipients) {
|
|||
this.network.send(recipients, {
|
||||
type: 'walletId',
|
||||
walletId: this.id,
|
||||
opts: this._optsToObj()
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -75,7 +75,6 @@ WalletFactory.prototype.read = function(walletId) {
|
|||
this.log('NOT NECCESARY AN ERROR:', e); //TODO
|
||||
}
|
||||
this.log('### WALLET OPENED:', w.id);
|
||||
w.netStart();
|
||||
return w;
|
||||
};
|
||||
|
||||
|
@ -113,16 +112,16 @@ WalletFactory.prototype.create = function(opts) {
|
|||
opts.totalCopayers = totalCopayers;
|
||||
var w = new Wallet(opts);
|
||||
w.store();
|
||||
w.netStart();
|
||||
return w;
|
||||
};
|
||||
|
||||
WalletFactory.prototype.open = function(walletId) {
|
||||
WalletFactory.prototype.open = function(walletId, opts) {
|
||||
this.log('Opening walletId:' + walletId);
|
||||
var w = this.read(walletId) || this.create({
|
||||
id: walletId,
|
||||
verbose: this.verbose,
|
||||
});
|
||||
opts = opts || {};
|
||||
opts.id = walletId;
|
||||
opts.verbose = this.verbose;
|
||||
var w = this.read(walletId) || this.create(opts);
|
||||
w.store();
|
||||
return w;
|
||||
};
|
||||
|
||||
|
@ -139,8 +138,8 @@ WalletFactory.prototype.connectTo = function(peerId, cb) {
|
|||
var self=this;
|
||||
self.network.start(function() {
|
||||
self.network.connectTo(peerId)
|
||||
self.network.on('walletId', function(walletId) {
|
||||
return cb(walletId);
|
||||
self.network.on('walletId', function(data) {
|
||||
return cb(data);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
@ -21,7 +21,7 @@ function Network(opts) {
|
|||
this.peerId = opts.peerId;
|
||||
this.apiKey = opts.apiKey || 'lwjd5qra8257b9';
|
||||
this.debug = opts.debug || 3;
|
||||
this.maxPeers = opts.maxPeers || 5;
|
||||
this.maxPeers = opts.maxPeers || 10;
|
||||
this.opts = { key: opts.key };
|
||||
|
||||
// For using your own peerJs server
|
||||
|
@ -65,12 +65,12 @@ Network._arrayPushOnce = function(el, array) {
|
|||
Network._arrayRemove = function(el, array) {
|
||||
var pos = array.indexOf(el);
|
||||
if (pos >= 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<opts.connectedPeers.length; i++) {
|
||||
var otherPeerId = opts.connectedPeers[i];
|
||||
this.connectTo(otherPeerId);
|
||||
}
|
||||
this.started = true;
|
||||
};
|
||||
|
||||
|
@ -284,11 +302,12 @@ Network.prototype.connectTo = function(peerId) {
|
|||
};
|
||||
|
||||
|
||||
Network.prototype.disconnect = function(cb) {
|
||||
Network.prototype.disconnect = function(cb, forced) {
|
||||
var self = this;
|
||||
self.closing = 1;
|
||||
this.send(null, { type: 'disconnect' }, function() {
|
||||
var cleanUp = function() {
|
||||
self.connectedPeers = [];
|
||||
self.started = false;
|
||||
self.peerId = null;
|
||||
if (self.peer) {
|
||||
self.peer.disconnect();
|
||||
|
@ -296,8 +315,14 @@ Network.prototype.disconnect = function(cb) {
|
|||
self.peer = null;
|
||||
}
|
||||
self.closing = 0;
|
||||
console.log('cleanup after disconnect finished');
|
||||
if (typeof cb === 'function') cb();
|
||||
});
|
||||
};
|
||||
if (!forced) {
|
||||
this.send(null, { type: 'disconnect' }, cleanUp);
|
||||
} else {
|
||||
cleanUp();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = require('soop')(Network);
|
||||
|
|
|
@ -43,6 +43,8 @@ angular.module('copay.controllerUtils').factory('controllerUtils', function ($ro
|
|||
});
|
||||
w.on('openError', root.onErrorDigest);
|
||||
w.on('close', root.onErrorDigest);
|
||||
|
||||
w.netStart();
|
||||
};
|
||||
|
||||
root.handleTransactionByAddress = function(scope, cb) {
|
||||
|
|
Loading…
Reference in New Issue