mirror of https://github.com/BTCPrivate/copay.git
txproposal comuninication between peers. Still WIP
This commit is contained in:
parent
c255c27e5f
commit
ac784ad9ae
10
index.html
10
index.html
|
@ -23,6 +23,7 @@
|
|||
</div>
|
||||
|
||||
<nav class="top-bar" data-topbar ng-show="$root.peerId">
|
||||
<!-- TODO : porque el repeat en UL y no en LI?? -->
|
||||
<ul class="title-area" data-ng-repeat="item in menu" ui-route="/{{item.link}}" data-ng-class="{active: isActive(item)}">
|
||||
<li class="name"></li>
|
||||
<li class="toggle-topbar menu-icon">
|
||||
|
@ -32,8 +33,8 @@
|
|||
|
||||
<section class="top-bar-section">
|
||||
<!-- Right Nav Section -->
|
||||
<ul data-ng-repeat="item in menu" ui-route="/{{item.link}}">
|
||||
<li class="large-3 text-center" data-ng-class="{active: isActive(item)}">
|
||||
<ul>
|
||||
<li data-ng-repeat="item in menu" ui-route="/{{item.link}}" class="large-2 text-center" data-ng-class="{active: isActive(item)}">
|
||||
<a href="{{item.link}}"> <i class="fi-home size-16"></i> {{item.title}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -110,14 +111,14 @@
|
|||
|
||||
<ul class="no-bullet">
|
||||
<li> [DEBUG] Pubkeys that you have: {{$root.publicKeyRing.registeredCopayers()}}
|
||||
<li> [DEBUG] WalletId: {{$root.walletId}}
|
||||
<li class="panel" style="word-wrap: break-word;" ng-repeat="pub in $root.publicKeyRing.copayersBIP32">
|
||||
${{pub.extendedPublicKeyString()}}
|
||||
</li>
|
||||
</ul>
|
||||
<h3 class="panel-title">Copayers ({{$root.connectedPeers.length}}/5)</h3>
|
||||
</div>
|
||||
<div class="large-6 columns">
|
||||
<h3 class="panel-title">Copayers ({{$root.connectedPeers.length}}/5)</h3>
|
||||
<h3 class="panel-title">Copayers ({{$root.connectedPeers.length}}/{{$root.publicKeyRing.requiredCopayers}})</h3>
|
||||
<ul class="no-bullet">
|
||||
<li class="panel" ng-repeat="copayer in $root.connectedPeers">
|
||||
<span ng-if="copayer == $root.peerId"> You ({{$root.peerId}})<i class="fi-check size-24"></i></span>
|
||||
|
@ -222,6 +223,7 @@
|
|||
<script type="text/ng-template" id="send.html">
|
||||
<div class="send" data-ng-controller="SendController">
|
||||
<h2>{{title}}</h2>
|
||||
<button class="button primary expand round" type="button" ng-click="sendTest()">sendTest</button>
|
||||
<form>
|
||||
<label for="address">To
|
||||
<input type="text" id="address" placeholder="Send to">
|
||||
|
|
|
@ -5,4 +5,6 @@ var config = {
|
|||
p2pApiKey: 'lwjd5qra8257b9',
|
||||
p2pDebug: 3,
|
||||
maxPeers: 5,
|
||||
requiredCopayers: 2,
|
||||
totalCopayers: 3
|
||||
};
|
||||
|
|
|
@ -5,6 +5,9 @@ angular.module('copay.header').controller('HeaderController',
|
|||
$scope.menu = [{
|
||||
'title': 'Home',
|
||||
'link': '#/home'
|
||||
}, {
|
||||
'title': 'Copayers',
|
||||
'link': '#/peer'
|
||||
}, {
|
||||
'title': 'Transactions',
|
||||
'link': '#/transactions'
|
||||
|
|
|
@ -1,11 +1,43 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copay.send').controller('SendController',
|
||||
function($scope, $rootScope, $location) {
|
||||
function($scope, $rootScope, $location, Network, Storage) {
|
||||
$scope.title = 'Send';
|
||||
|
||||
if (!$rootScope.peerId) {
|
||||
$location.path('signin');
|
||||
}
|
||||
|
||||
|
||||
$scope.sendTest = function() {
|
||||
var pkr = $rootScope.publicKeyRing;
|
||||
var txp = $rootScope.txProposals;
|
||||
var opts = {remainderOut: { address: pkr.generateAddress(true).toString() }};
|
||||
|
||||
// From @cmgustavo's wallet
|
||||
var unspentTest = [{
|
||||
"txid": "2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc1",
|
||||
"vout": 1,
|
||||
"amount": 10,
|
||||
"confirmations":7
|
||||
}];
|
||||
|
||||
unspentTest[0].address = pkr.generateAddress(false).toString();
|
||||
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(false);
|
||||
|
||||
console.log('[send.js.29:txp:] BEFORE',txp); //TODO
|
||||
|
||||
txp.create(
|
||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||
'123456789',
|
||||
unspentTest,
|
||||
$rootScope.privateKey,
|
||||
opts
|
||||
);
|
||||
console.log('[send.js.29:txp:] READY:',txp); //TODO
|
||||
|
||||
Network.storeOpenWallet();
|
||||
Network.sendTxProposals();
|
||||
$rootScope.$digest;
|
||||
};
|
||||
});
|
||||
|
|
|
@ -25,6 +25,7 @@ angular.module('copay.signin').controller('SigninController',
|
|||
$scope.open = function(walletId) {
|
||||
$scope.loading = true;
|
||||
|
||||
console.log('[signin.js.28:walletId:]',walletId); //TODO
|
||||
if (Network.openWallet(walletId)) {
|
||||
Network.init(function() {
|
||||
$location.path('peer');
|
||||
|
|
|
@ -12,7 +12,9 @@ var PublicKeyRing = require('./PublicKeyRing');
|
|||
function PrivateKey(opts) {
|
||||
this.network = opts.networkName === 'testnet' ?
|
||||
networks.testnet : networks.livenet;
|
||||
this.BIP32 = opts.BIP32 || new BIP32(opts.extendedPrivateKeyString || this.network.name);
|
||||
var init = opts.extendedPrivateKeyString || this.network.name;
|
||||
console.log('[PrivateKey.js.15:init:]',init); //TODO
|
||||
this.BIP32 = opts.BIP32 || new BIP32(init);
|
||||
this._calcId();
|
||||
};
|
||||
|
||||
|
|
|
@ -50,7 +50,8 @@ PublicKeyRing.ChangeBranch = function (index) {
|
|||
};
|
||||
|
||||
PublicKeyRing.getRandomId = function () {
|
||||
return buffertools.toHex(coinUtil.generateNonce());
|
||||
var r = buffertools.toHex(coinUtil.generateNonce());
|
||||
return r;
|
||||
};
|
||||
|
||||
PublicKeyRing.decrypt = function (passphrase, encPayload) {
|
||||
|
@ -64,6 +65,9 @@ PublicKeyRing.encrypt = function (passphrase, payload) {
|
|||
};
|
||||
|
||||
PublicKeyRing.fromObj = function (data) {
|
||||
if (!data.ts) {
|
||||
throw new Error('bad data format: Did you use .toObj()?');
|
||||
}
|
||||
var config = { networkName: data.networkName || 'livenet' };
|
||||
|
||||
var w = new PublicKeyRing(config);
|
||||
|
@ -73,11 +77,11 @@ PublicKeyRing.fromObj = function (data) {
|
|||
w.addressIndex = data.addressIndex;
|
||||
w.changeAddressIndex = data.changeAddressIndex;
|
||||
|
||||
// this.bip32 = ;
|
||||
w.copayersBIP32 = data.copayersExtPubKeys.map( function (pk) {
|
||||
return new BIP32(pk);
|
||||
});
|
||||
|
||||
w.ts = data.ts;
|
||||
return w;
|
||||
};
|
||||
|
||||
|
@ -258,16 +262,11 @@ PublicKeyRing.prototype.getRedeemScriptMap = function () {
|
|||
|
||||
PublicKeyRing.prototype._checkInPRK = function(inPKR, ignoreId) {
|
||||
|
||||
|
||||
if (!inPKR.ts) {
|
||||
throw new Error('inPRK bad format: Did you use .toObj()?');
|
||||
}
|
||||
|
||||
if (!ignoreId && this.id !== inPKR.id) {
|
||||
throw new Error('inPRK id mismatch');
|
||||
}
|
||||
|
||||
if (this.network.name !== inPKR.networkName)
|
||||
if (this.network.name !== inPKR.network.name)
|
||||
throw new Error('inPRK network mismatch');
|
||||
|
||||
if (
|
||||
|
@ -279,9 +278,6 @@ PublicKeyRing.prototype._checkInPRK = function(inPKR, ignoreId) {
|
|||
this.totalCopayers && inPKR.totalCopayers &&
|
||||
(this.totalCopayers !== inPKR.totalCopayers))
|
||||
throw new Error('inPRK requiredCopayers mismatch');
|
||||
|
||||
if (! inPKR.ts)
|
||||
throw new Error('no ts at inPRK');
|
||||
};
|
||||
|
||||
|
||||
|
@ -302,13 +298,13 @@ PublicKeyRing.prototype._mergeIndexes = function(inPKR) {
|
|||
};
|
||||
|
||||
PublicKeyRing.prototype._mergePubkeys = function(inPKR) {
|
||||
var hasChanged = false;
|
||||
var l= this.copayersBIP32.length;
|
||||
|
||||
var self = this;
|
||||
var hasChanged = false;
|
||||
var l= self.copayersBIP32.length;
|
||||
|
||||
inPKR.copayersExtPubKeys.forEach( function(epk) {
|
||||
inPKR.copayersBIP32.forEach( function(b) {
|
||||
var haveIt = false;
|
||||
var epk = b.extendedPublicKeyString();
|
||||
for(var j=0; j<l; j++) {
|
||||
if (self.copayersBIP32[j].extendedPublicKeyString() === epk) {
|
||||
haveIt=true;
|
||||
|
@ -316,6 +312,10 @@ PublicKeyRing.prototype._mergePubkeys = function(inPKR) {
|
|||
}
|
||||
}
|
||||
if (!haveIt) {
|
||||
if (self.isComplete()) {
|
||||
console.log('[PublicKeyRing.js.318] REPEATED KEY', epk); //TODO
|
||||
throw new Error('trying to add more pubkeys, when PKR isComplete at merge');
|
||||
}
|
||||
self.copayersBIP32.push(new BIP32(epk));
|
||||
hasChanged=true;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ module.exports = require('soop')(TxProposal);
|
|||
|
||||
function TxProposals(opts) {
|
||||
opts = opts || {};
|
||||
this.walletId = opts.walletId;
|
||||
this.network = opts.networkName === 'livenet' ?
|
||||
bitcore.networks.livenet : bitcore.networks.testnet;
|
||||
this.publicKeyRing = opts.publicKeyRing;
|
||||
|
@ -32,10 +33,11 @@ function TxProposals(opts) {
|
|||
TxProposals.fromObj = function(o) {
|
||||
var ret = new TxProposals({
|
||||
networkName: o.networkName,
|
||||
walletId: o.walletId,
|
||||
});
|
||||
o.txps.forEach(function(t) {
|
||||
var tx = new Transaction;
|
||||
tx.parse(t.txHex);
|
||||
tx.parse(new Buffer(t.txHex,'hex'));
|
||||
ret.txps.push({
|
||||
seenBy: t.seenBy,
|
||||
signedBy: t.signedBy,
|
||||
|
@ -45,6 +47,7 @@ TxProposals.fromObj = function(o) {
|
|||
return ret;
|
||||
};
|
||||
|
||||
|
||||
TxProposals.prototype.toObj = function() {
|
||||
var ret = [];
|
||||
this.txps.forEach(function(t) {
|
||||
|
@ -56,6 +59,7 @@ TxProposals.prototype.toObj = function() {
|
|||
});
|
||||
return {
|
||||
txps: ret,
|
||||
walletId: this.walletId,
|
||||
networkName: this.network.name,
|
||||
};
|
||||
};
|
||||
|
@ -140,7 +144,7 @@ TxProposals.prototype._chunkIsEmpty = function(chunk) {
|
|||
// this assumes that the same signature can not be v0 / v1 (which shouldnt be!)
|
||||
TxProposals.prototype._mergeInputSig = function(s0buf, s1buf) {
|
||||
if (buffertools.compare(s0buf,s1buf) === 0) {
|
||||
console.log('BUFFERS .s MATCH'); //TODO
|
||||
// console.log('BUFFERS .s MATCH'); //TODO
|
||||
return s0buf;
|
||||
}
|
||||
// Is multisig?
|
||||
|
@ -225,7 +229,7 @@ TxProposals.prototype._mergeSignatures = function(myTxps, theirTxps, mergeInfo)
|
|||
|
||||
TxProposals.prototype.merge = function(t) {
|
||||
if (this.network.name !== t.network.name)
|
||||
throw new Error('network mismatch');
|
||||
throw new Error('network mismatch in:', t);
|
||||
|
||||
var res = [];
|
||||
|
||||
|
@ -244,10 +248,12 @@ TxProposals.prototype.merge = function(t) {
|
|||
return mergeInfo.stats;
|
||||
};
|
||||
|
||||
TxProposals.prototype.create = function(toAddress, amountSat, utxos, priv, opts) {
|
||||
TxProposals.prototype.create = function(toAddress, amountSatStr, utxos, priv, opts) {
|
||||
var pkr = this.publicKeyRing;
|
||||
opts = opts || {};
|
||||
|
||||
var amountSat = bitcore.bignum(amountSatStr);
|
||||
|
||||
if (! pkr.isComplete() ) {
|
||||
throw new Error('publicKeyRing is not complete');
|
||||
}
|
||||
|
|
|
@ -20,14 +20,14 @@ angular.module('copay.network')
|
|||
});
|
||||
};
|
||||
|
||||
|
||||
// set new inbound connections
|
||||
var _setNewPeer = function(newPeer) {
|
||||
var cp = $rootScope.cp;
|
||||
console.log('#### SENDING PKR 1111 ');
|
||||
cp.send(newPeer, {
|
||||
type: 'publicKeyRing',
|
||||
publicKeyRing: $rootScope.publicKeyRing.toObj(),
|
||||
});
|
||||
console.log('#### Setting new PEER:', newPeer);
|
||||
sendPublicKeyRing(newPeer);
|
||||
sendTxProposals(newPeer);
|
||||
|
||||
};
|
||||
|
||||
var _handleNetworkChange = function(newPeer) {
|
||||
|
@ -40,6 +40,16 @@ angular.module('copay.network')
|
|||
_refreshUx();
|
||||
};
|
||||
|
||||
// TODO -> probably not in network.js
|
||||
var storeOpenWallet = function() {
|
||||
var id = $rootScope.walletId;
|
||||
Storage.addWalletId(id);
|
||||
Storage.set(id, 'publicKeyRing',$rootScope.publicKeyRing.toObj());
|
||||
Storage.set(id, 'privateKey', $rootScope.privateKey.toObj());
|
||||
Storage.set(id, 'txProposals', $rootScope.txProposals.toObj());
|
||||
console.log('\t### Wallet Stored');
|
||||
};
|
||||
|
||||
// TODO -> probably not in network.js
|
||||
var createWallet = function(walletId) {
|
||||
|
||||
|
@ -47,48 +57,67 @@ angular.module('copay.network')
|
|||
|
||||
var priv = new copay.PrivateKey({networkName: config.networkName});
|
||||
console.log('\t### PrivateKey Initialized');
|
||||
|
||||
//TODO
|
||||
console.log('[PRIVATE]',priv.toObj()); //TODO
|
||||
|
||||
//TODO create a wallet and WalletId, not only pkr
|
||||
var pkr = new copay.PublicKeyRing({
|
||||
networkName: config.networkName,
|
||||
id: walletId,
|
||||
requiredCopayers: config.requiredCopayers || 3, // TODO set per wallet
|
||||
totalCopayers: config.totalCopayers || 5,
|
||||
});
|
||||
|
||||
console.log('[network.js.70] WALLET ID IS:', pkr.id); //TODO
|
||||
|
||||
// Add self to the ring.
|
||||
pkr.addCopayer(priv.getBIP32().extendedPublicKeyString());
|
||||
|
||||
console.log('\t### PublicKeyRing Initialized');
|
||||
|
||||
var txp = new copay.TxProposals({
|
||||
networkName: config.networkName,
|
||||
publicKeyRing: pkr,
|
||||
walletId: pkr.id,
|
||||
});
|
||||
console.log('\t### TxProposals Initialized');
|
||||
|
||||
Storage.addWalletId(pkr.id);
|
||||
Storage.set(pkr.id, 'publicKeyRing', pkr.toObj());
|
||||
Storage.set(pkr.id, 'privateKey', priv.toObj());
|
||||
Storage.set(pkr.id, 'txProposals', txp.toObj());
|
||||
console.log('\t### Wallet Stored');
|
||||
|
||||
// Store it on rootScope
|
||||
$rootScope.priv = priv; // TODO secure this.
|
||||
$rootScope.walletId = pkr.id;
|
||||
$rootScope.publicKeyRing = pkr;
|
||||
$rootScope.txProposals = txp;
|
||||
$rootScope.walletId = pkr.id;
|
||||
$rootScope.privateKey = priv; // TODO secure this.
|
||||
$rootScope.publicKeyRing = pkr;
|
||||
$rootScope.txProposals = txp;
|
||||
|
||||
storeOpenWallet();
|
||||
};
|
||||
|
||||
var openWallet = function (walletId) {
|
||||
var ret = false;
|
||||
var pkr = Storage.get(walletId, 'publicKeyRing');
|
||||
var priv = Storage.get(walletId, 'privateKey');
|
||||
var txp = Storage.get(walletId, 'txProposals');
|
||||
console.log('[network.js.90:openWallet:]',walletId); //TODO
|
||||
|
||||
if (pkr) {
|
||||
var ret = false;
|
||||
var pkr = Storage.get(walletId, 'publicKeyRing');
|
||||
var priv = Storage.get(walletId, 'privateKey');
|
||||
var txp = Storage.get(walletId, 'txProposals');
|
||||
|
||||
console.log('[network.js.96:pkr:]',pkr); //TODO
|
||||
console.log('[network.js.97:priv:]',priv); //TODO
|
||||
|
||||
|
||||
if (pkr && pkr.copayersExtPubKeys.length && priv) {
|
||||
console.log('### WALLET OPENED:', walletId, pkr);
|
||||
$rootScope.walletId = walletId;
|
||||
$rootScope.walletId = walletId;
|
||||
$rootScope.publicKeyRing = new copay.PublicKeyRing.fromObj(pkr);
|
||||
$rootScope.txProposals = new copay.TxProposals.fromObj(txp);
|
||||
$rootScope.priv = new copay.PrivateKey.fromObj(priv); //TODO secure
|
||||
$rootScope.txProposals = new copay.TxProposals.fromObj(txp);
|
||||
$rootScope.PrivateKey = new copay.PrivateKey.fromObj(priv); //TODO secure
|
||||
|
||||
// Add our key JIC
|
||||
try {
|
||||
$rootScope.publicKeyRing.addCopayer(
|
||||
$rootScope.PrivateKey.getBIP32().extendedPublicKeyString()
|
||||
);
|
||||
} catch (e) {
|
||||
console.log('[network.js.103]', e); //TODO
|
||||
};
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
|
@ -101,52 +130,112 @@ angular.module('copay.network')
|
|||
//TODO
|
||||
};
|
||||
|
||||
var _checkWallet = function(walletId) {
|
||||
var _checkWallet = function(walletId, allowChange) {
|
||||
console.log('[network.js.79:_checkWallet:]',walletId); //TODO
|
||||
|
||||
if ($rootScope.walletId && $rootScope.walletId !== walletId)
|
||||
closeWallet();
|
||||
|
||||
if ($rootScope.walletId)
|
||||
return;
|
||||
if ($rootScope.walletId && $rootScope.walletId === walletId)
|
||||
return;
|
||||
|
||||
if ($rootScope.walletId && $rootScope.walletId !== walletId) {
|
||||
if (allowChange)
|
||||
closeWallet();
|
||||
else
|
||||
throw new Error('message to wrong walletID');
|
||||
}
|
||||
|
||||
|
||||
if (!openWallet(walletId)) {
|
||||
createWallet(walletId);
|
||||
}
|
||||
};
|
||||
|
||||
var _handleData = function(senderId, data, isInbound) {
|
||||
|
||||
var _handlePublicKeyRing = function(senderId, data, isInbound) {
|
||||
var cp = $rootScope.cp;
|
||||
_checkWallet(data.publicKeyRing.id, true);
|
||||
var shouldSend = false;
|
||||
|
||||
var recipients, pkr = $rootScope.publicKeyRing;
|
||||
var inPKR = copay.PublicKeyRing.fromObj(data.publicKeyRing);
|
||||
if (pkr.merge(inPKR, true) && !data.isBroadcast) {
|
||||
console.log('### BROADCASTING PKR');
|
||||
recipients = null;
|
||||
shouldSend = true;
|
||||
}
|
||||
else if (isInbound && !data.isBroadcast) {
|
||||
// always replying to connecting peer
|
||||
console.log('### REPLYING PKR TO:', senderId);
|
||||
recipients = senderId;
|
||||
shouldSend = true;
|
||||
}
|
||||
|
||||
if (shouldSend) {
|
||||
console.log('### SENDING PKR TO:', recipients);
|
||||
cp.send( recipients, {
|
||||
type: 'publicKeyRing',
|
||||
publicKeyRing: $rootScope.publicKeyRing.toObj(),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var sendTxProposals = function(recipients) {
|
||||
var cp = $rootScope.cp;
|
||||
console.log('### SENDING txProposals TO:', recipients||'All');
|
||||
cp.send( recipients, {
|
||||
type: 'txProposals',
|
||||
txProposals: $rootScope.txProposals.toObj(),
|
||||
walletId: $rootScope.walletId,
|
||||
});
|
||||
};
|
||||
var sendPublicKeyRing = function(recipients) {
|
||||
var cp = $rootScope.cp;
|
||||
console.log('### SENDING publicKeyRing TO:', recipients||'All');
|
||||
|
||||
cp.send(recipients, {
|
||||
type: 'publicKeyRing',
|
||||
publicKeyRing: $rootScope.publicKeyRing.toObj(),
|
||||
});
|
||||
};
|
||||
|
||||
var _handleTxProposals = function(senderId, data, isInbound) {
|
||||
var cp = $rootScope.cp;
|
||||
_checkWallet(data.txProposals.walletId, false);
|
||||
|
||||
var shouldSend = false;
|
||||
console.log('RECV TXPROPOSAL:',data); //TODO
|
||||
var recipients, pkr = $rootScope.txProposals;
|
||||
|
||||
var inTxProposals = copay.TxProposals.fromObj(data.txProposals);
|
||||
var mergeInfo = pkr.merge(inTxProposals, true);
|
||||
if ( mergeInfo.merged && !data.isBroadcast) {
|
||||
console.log('### BROADCASTING txProposals');
|
||||
recipients = null;
|
||||
shouldSend = true;
|
||||
}
|
||||
else if (isInbound && !data.isBroadcast) {
|
||||
// always replying to connecting peer
|
||||
console.log('### REPLYING txProposals TO:', senderId);
|
||||
recipients = senderId;
|
||||
shouldSend = true;
|
||||
}
|
||||
|
||||
if (shouldSend) {
|
||||
this.sendTxProposals(recipients);
|
||||
}
|
||||
};
|
||||
|
||||
var _handleData = function(senderId, data, isInbound) {
|
||||
|
||||
switch(data.type) {
|
||||
case 'publicKeyRing':
|
||||
_checkWallet(data.publicKeyRing.id);
|
||||
var shouldSend = false;
|
||||
|
||||
var recipients, pkr = $rootScope.publicKeyRing;
|
||||
if (pkr.merge(data.publicKeyRing, true) && !data.isBroadcast) {
|
||||
console.log('### BROADCASTING PKR');
|
||||
recipients = null;
|
||||
shouldSend = true;
|
||||
}
|
||||
else if (isInbound && !data.isBroadcast) {
|
||||
// always replying to connecting peer
|
||||
console.log('### REPLYING PKR TO:', senderId);
|
||||
recipients = senderId;
|
||||
shouldSend = true;
|
||||
}
|
||||
|
||||
if (shouldSend) {
|
||||
console.log('### SENDING PKR TO:', recipients);
|
||||
cp.send( recipients, {
|
||||
type: 'publicKeyRing',
|
||||
publicKeyRing: $rootScope.publicKeyRing.toObj(),
|
||||
});
|
||||
}
|
||||
|
||||
_refreshUx();
|
||||
_handlePublicKeyRing(senderId, data, isInbound);
|
||||
break;
|
||||
case 'txProposals':
|
||||
_handleTxProposals(senderId, data, isInbound);
|
||||
break;
|
||||
|
||||
}
|
||||
_refreshUx();
|
||||
};
|
||||
var _setupHandlers = function () {
|
||||
var cp = $rootScope.cp;
|
||||
|
@ -192,8 +281,12 @@ angular.module('copay.network')
|
|||
init: init,
|
||||
connect: connect,
|
||||
disconnect: disconnect,
|
||||
sendTxProposals: sendTxProposals,
|
||||
|
||||
// TODO Move to Wallet.
|
||||
createWallet: createWallet,
|
||||
openWallet: openWallet,
|
||||
storeOpenWallet: storeOpenWallet,
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -41,6 +41,13 @@ angular.module('copay.storage')
|
|||
},
|
||||
addWalletId: function(walletId) {
|
||||
var ids = localStorage.getItem('walletIds');
|
||||
if (ids) {
|
||||
var list = ids.split(',');
|
||||
var l = list.length;
|
||||
for(var i=0; i<l; i++)
|
||||
if (walletId === list[i])
|
||||
return;
|
||||
}
|
||||
localStorage.setItem('walletIds', (ids?ids+',':'') + walletId);
|
||||
},
|
||||
delWalletId: function(walletId) {
|
||||
|
|
|
@ -158,65 +158,71 @@ describe('PublicKeyRing model', function() {
|
|||
networkName: 'livenet',
|
||||
id: w.id,
|
||||
});
|
||||
w2.merge(w.toObj()).should.equal(true);
|
||||
w2.merge(w).should.equal(true);
|
||||
w2.requiredCopayers.should.equal(3);
|
||||
w2.totalCopayers.should.equal(5);
|
||||
w2.changeAddressIndex.should.equal(2);
|
||||
w2.addressIndex.should.equal(3);
|
||||
|
||||
//
|
||||
w2.merge(w.toObj()).should.equal(false);
|
||||
w2.merge(w).should.equal(false);
|
||||
});
|
||||
|
||||
|
||||
it('#merge check tests', function () {
|
||||
var k = createW();
|
||||
var w = k.w;
|
||||
|
||||
for(var i=0; i<2; i++)
|
||||
w.generateAddress(true);
|
||||
for(var i=0; i<3; i++)
|
||||
w.generateAddress(false);
|
||||
|
||||
|
||||
|
||||
var w2 = new PublicKeyRing({
|
||||
var config = {
|
||||
networkName: 'livenet',
|
||||
});
|
||||
(function() { w2.merge(w.toObj());}).should.throw();
|
||||
(function() { w2.merge(w,true);}).should.throw();
|
||||
w2.merge(w.toObj(),true).should.equal(true);
|
||||
};
|
||||
|
||||
var w = new PublicKeyRing(config);
|
||||
var w2 = new PublicKeyRing({
|
||||
networkName: 'testnet', //wrong
|
||||
id: w.id,
|
||||
});
|
||||
(function() { w2.merge(w);}).should.throw();
|
||||
|
||||
var w3 = new PublicKeyRing({
|
||||
networkName: 'livenet',
|
||||
id: w.id,
|
||||
requiredCopayers: 2,
|
||||
requiredCopayers: 2, // wrong
|
||||
});
|
||||
(function() { w3.merge(w.toObj());}).should.throw();
|
||||
(function() { w3.merge(w);}).should.throw();
|
||||
|
||||
var w4 = new PublicKeyRing({
|
||||
networkName: 'testnet',
|
||||
id: w.id,
|
||||
});
|
||||
(function() { w4.merge(w.toObj());}).should.throw();
|
||||
|
||||
var w5 = new PublicKeyRing({
|
||||
networkName: 'livenet',
|
||||
id: w.id,
|
||||
totalCopayers: 4,
|
||||
totalCopayers: 3, // wrong
|
||||
});
|
||||
(function() { w5.merge(w.toObj());}).should.throw();
|
||||
(function() { w4.merge(w);}).should.throw();
|
||||
|
||||
|
||||
var w6 = new PublicKeyRing({
|
||||
networkName: 'livenet',
|
||||
id: w.id,
|
||||
});
|
||||
(function() { w6.merge(w);}).should.throw();
|
||||
w.networkName= 'livenet';
|
||||
(function() { w6.merge(w);}).should.throw();
|
||||
|
||||
|
||||
var w0 = new PublicKeyRing({
|
||||
networkName: 'livenet',
|
||||
});
|
||||
w0.addCopayer();
|
||||
w0.addCopayer();
|
||||
w0.addCopayer();
|
||||
w0.addCopayer();
|
||||
w0.addCopayer();
|
||||
(function() { w0.merge(w);}).should.throw();
|
||||
w.merge(w0,true).should.equal(true);
|
||||
w.isComplete().should.equal(true);
|
||||
|
||||
var wx = new PublicKeyRing({
|
||||
networkName: 'livenet',
|
||||
});
|
||||
wx.addCopayer();
|
||||
(function() { w.merge(wx, true);}).should.throw();
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
@ -239,14 +245,14 @@ describe('PublicKeyRing model', function() {
|
|||
w2.isComplete().should.equal(false);
|
||||
w2.addCopayer();
|
||||
}
|
||||
w2.merge(w.toObj()).should.equal(true);
|
||||
w2.merge(w).should.equal(true);
|
||||
w2.isComplete().should.equal(true);
|
||||
w2.merge(w.toObj()).should.equal(false);
|
||||
w2.merge(w).should.equal(false);
|
||||
|
||||
w.isComplete().should.equal(false);
|
||||
w.merge(w2.toObj()).should.equal(true);
|
||||
w.merge(w2).should.equal(true);
|
||||
w.isComplete().should.equal(true);
|
||||
w.merge(w2.toObj()).should.equal(false);
|
||||
w.merge(w2).should.equal(false);
|
||||
});
|
||||
|
||||
it('#merge pubkey tests (case 2)', function () {
|
||||
|
@ -260,7 +266,7 @@ describe('PublicKeyRing model', function() {
|
|||
id: w.id,
|
||||
});
|
||||
w2.addCopayer();
|
||||
w.merge(w2.toObj()).should.equal(true);
|
||||
w.merge(w2).should.equal(true);
|
||||
}
|
||||
w.isComplete().should.equal(true);
|
||||
});
|
||||
|
|
|
@ -81,7 +81,7 @@ describe('TxProposals model', function() {
|
|||
|
||||
var tx = w.create(
|
||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||
bignum('123456789'),
|
||||
'123456789',
|
||||
unspentTest
|
||||
);
|
||||
should.exist(tx);
|
||||
|
@ -105,7 +105,7 @@ describe('TxProposals model', function() {
|
|||
var priv = new PrivateKey(config);
|
||||
var tx = w.create(
|
||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||
bignum('123456789'),
|
||||
'123456789',
|
||||
unspentTest,
|
||||
priv
|
||||
);
|
||||
|
@ -131,7 +131,7 @@ describe('TxProposals model', function() {
|
|||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange);
|
||||
var tx = w.create(
|
||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||
bignum('123456789'),
|
||||
'123456789',
|
||||
unspentTest,
|
||||
priv
|
||||
);
|
||||
|
@ -161,7 +161,7 @@ describe('TxProposals model', function() {
|
|||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange);
|
||||
var tx = w.create(
|
||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||
bignum('123456789'),
|
||||
'123456789',
|
||||
unspentTest,
|
||||
priv
|
||||
);
|
||||
|
@ -204,7 +204,7 @@ describe('TxProposals model', function() {
|
|||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange);
|
||||
w.create(
|
||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||
bignum('123456789'),
|
||||
'123456789',
|
||||
unspentTest,
|
||||
priv2,
|
||||
opts
|
||||
|
@ -225,7 +225,7 @@ describe('TxProposals model', function() {
|
|||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange);
|
||||
w2.create(
|
||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||
bignum('123456789'),
|
||||
'123456789',
|
||||
unspentTest,
|
||||
priv,
|
||||
opts
|
||||
|
@ -274,7 +274,7 @@ var _dumpChunks = function (scriptSig, label) {
|
|||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange);
|
||||
w.create(
|
||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||
bignum('123456789'),
|
||||
'123456789',
|
||||
unspentTest,
|
||||
priv3,
|
||||
opts
|
||||
|
@ -295,7 +295,7 @@ var _dumpChunks = function (scriptSig, label) {
|
|||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange);
|
||||
w2.create(
|
||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||
bignum('123456789'),
|
||||
'123456789',
|
||||
unspentTest,
|
||||
priv,
|
||||
opts
|
||||
|
@ -322,7 +322,7 @@ var _dumpChunks = function (scriptSig, label) {
|
|||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange);
|
||||
w3.create(
|
||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||
bignum('123456789'),
|
||||
'123456789',
|
||||
unspentTest,
|
||||
priv2,
|
||||
opts
|
||||
|
@ -365,7 +365,7 @@ var _dumpChunks = function (scriptSig, label) {
|
|||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange);
|
||||
w.create(
|
||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||
bignum('123456789'),
|
||||
'123456789',
|
||||
unspentTest,
|
||||
priv,
|
||||
opts
|
||||
|
@ -384,7 +384,7 @@ var _dumpChunks = function (scriptSig, label) {
|
|||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange);
|
||||
w2.create(
|
||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||
bignum('123456789'),
|
||||
'123456789',
|
||||
unspentTest,
|
||||
priv2,
|
||||
opts
|
||||
|
@ -403,7 +403,7 @@ var _dumpChunks = function (scriptSig, label) {
|
|||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange);
|
||||
w3.create(
|
||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||
bignum('123456789'),
|
||||
'123456789',
|
||||
unspentTest,
|
||||
priv3,
|
||||
opts
|
||||
|
@ -441,6 +441,7 @@ var _dumpChunks = function (scriptSig, label) {
|
|||
|
||||
var priv = new PrivateKey(config);
|
||||
var w = new TxProposals({
|
||||
walletId: 'qwerty',
|
||||
networkName: config.networkName,
|
||||
publicKeyRing: createPKR([priv.getBIP32()]),
|
||||
});
|
||||
|
@ -452,7 +453,7 @@ var _dumpChunks = function (scriptSig, label) {
|
|||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange);
|
||||
var tx = w.create(
|
||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||
bignum('123456789'),
|
||||
'123456789',
|
||||
unspentTest,
|
||||
priv
|
||||
);
|
||||
|
@ -470,11 +471,14 @@ var _dumpChunks = function (scriptSig, label) {
|
|||
should.exist(o.txps[0].signedBy[priv.id]);
|
||||
|
||||
var w2 = TxProposals.fromObj(o);
|
||||
w2.walletId.should.equal(w.walletId);
|
||||
var tx2 = w2.txps[0].tx;
|
||||
tx2.isComplete().should.equal(false);
|
||||
tx2.countInputMissingSignatures(0).should.equal(2);
|
||||
(w2.txps[0].signedBy[priv.id] - ts > 0).should.equal(true);
|
||||
(w2.txps[0].seenBy[priv.id] - ts > 0).should.equal(true);
|
||||
|
||||
w2.merge(w);
|
||||
});
|
||||
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue