From d379c47032c84d12a3374af1c96a80dc6e8b9b2e Mon Sep 17 00:00:00 2001 From: Mario Colque Date: Mon, 21 Apr 2014 17:01:24 -0300 Subject: [PATCH 1/6] removed unnecessary peers files --- index.html | 3 +-- js/app.js | 4 +--- js/controllers/peer.js | 6 ------ 3 files changed, 2 insertions(+), 11 deletions(-) delete mode 100644 js/controllers/peer.js diff --git a/index.html b/index.html index 52c9ff94e..04288084e 100644 --- a/index.html +++ b/index.html @@ -178,7 +178,7 @@ - diff --git a/js/app.js b/js/app.js index c955f458e..1b6ef9813 100644 --- a/js/app.js +++ b/js/app.js @@ -13,8 +13,7 @@ angular.module('copay',[ 'copay.signin', 'copay.socket', 'copay.controllerUtils', - 'copay.setup', - 'copay.peer' + 'copay.setup' ]); angular.module('copay.header', []); @@ -26,6 +25,5 @@ angular.module('copay.walletFactory', []); angular.module('copay.controllerUtils', []); angular.module('copay.signin', []); angular.module('copay.setup', []); -angular.module('copay.peer', []); angular.module('copay.socket', []); diff --git a/js/controllers/peer.js b/js/controllers/peer.js deleted file mode 100644 index 5ae619020..000000000 --- a/js/controllers/peer.js +++ /dev/null @@ -1,6 +0,0 @@ -'use strict'; - -angular.module('copay.peer').controller('PeerController', - function($scope, $rootScope, $location, $routeParams) { - }); - From d4b12c82d9a814d224e8666592a46107ae1e5b8f Mon Sep 17 00:00:00 2001 From: "Ryan X. Charles" Date: Tue, 22 Apr 2014 18:18:08 -0300 Subject: [PATCH 2/6] make PrivateKey tests pass by updating length with new correct length --- test/test.PrivateKey.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test.PrivateKey.js b/test/test.PrivateKey.js index f3cec474f..9eafd5794 100644 --- a/test/test.PrivateKey.js +++ b/test/test.PrivateKey.js @@ -70,7 +70,7 @@ describe('PrivateKey model', function() { it('should calculate .id', function () { var w1 = new PrivateKey(config); should.exist(w1.getId()); - w1.getId().length.should.equal(40); + w1.getId().length.should.equal(32); }); it('fromObj toObj roundtrip', function () { var w1 = new PrivateKey(config); From 4092f0cb9de29a437abe1ca529456674cadbbf49 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 21 Apr 2014 20:28:57 -0300 Subject: [PATCH 3/6] works sometimes --- js/controllers/transactions.js | 13 +++--- js/models/core/PrivateKey.js | 2 + js/models/core/PublicKeyRing.js | 1 + js/models/core/Wallet.js | 7 ++-- js/services/controllerUtils.js | 2 +- test/test.TxProposals.js | 70 +++++++++++++++++++++++++++++---- 6 files changed, 78 insertions(+), 17 deletions(-) diff --git a/js/controllers/transactions.js b/js/controllers/transactions.js index d4356a62a..6f29bdd40 100644 --- a/js/controllers/transactions.js +++ b/js/controllers/transactions.js @@ -51,17 +51,20 @@ console.log('[transactions.js.68:txid:] SENTTX CALLBACK',txid); //TODO $scope.sign = function (ntxid) { var w = $rootScope.wallet; var ret = w.sign(ntxid); - _updateTxs(); + if (!ret) { + $rootScope.flashMessage = {type:'error', message: 'There was an error signing the Transaction'}; + _updateTxs(); + $rootScope.$digest(); + return; + } var p = w.getTxProposal(ntxid); if (p.txp.builder.isFullySigned()) { $scope.send(ntxid); + _updateTxs(); + $rootScope.$digest(); } else { - $rootScope.flashMessage = ret - ? {type:'success', message: 'Transactions signed'} - : {type:'error', message: 'There was an error signing the Transaction'} - ; _updateTxs(); $rootScope.$digest(); } diff --git a/js/models/core/PrivateKey.js b/js/models/core/PrivateKey.js index 2002a14b6..5e7ab06cf 100644 --- a/js/models/core/PrivateKey.js +++ b/js/models/core/PrivateKey.js @@ -71,6 +71,8 @@ PrivateKey.prototype.get = function(index,isChange) { PrivateKey.prototype.getAll = function(addressIndex, changeAddressIndex) { var ret = []; +console.log('[PrivateKey.js.75:addressIndex:]',addressIndex); //TODO +console.log('[PrivateKey.js.79:changeAddressIndex:]',changeAddressIndex); //TODO for(var i=0;i Date: Tue, 22 Apr 2014 22:07:18 -0300 Subject: [PATCH 4/6] small fixes --- js/models/core/PrivateKey.js | 3 --- js/models/core/PublicKeyRing.js | 20 +++++++++++++------- js/models/core/Wallet.js | 17 ++++++----------- js/models/network/WebRTC.js | 1 - test/test.TxProposals.js | 19 +++++++++---------- 5 files changed, 28 insertions(+), 32 deletions(-) diff --git a/js/models/core/PrivateKey.js b/js/models/core/PrivateKey.js index 5e7ab06cf..0e2d87631 100644 --- a/js/models/core/PrivateKey.js +++ b/js/models/core/PrivateKey.js @@ -71,9 +71,6 @@ PrivateKey.prototype.get = function(index,isChange) { PrivateKey.prototype.getAll = function(addressIndex, changeAddressIndex) { var ret = []; -console.log('[PrivateKey.js.75:addressIndex:]',addressIndex); //TODO -console.log('[PrivateKey.js.79:changeAddressIndex:]',changeAddressIndex); //TODO - for(var i=0;i Date: Tue, 22 Apr 2014 23:07:20 -0300 Subject: [PATCH 5/6] fix ux issues. tx sending working --- index.html | 15 ++++++++++----- js/controllers/transactions.js | 8 ++++---- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/index.html b/index.html index 15af8e066..a88a9fb03 100644 --- a/index.html +++ b/index.html @@ -249,11 +249,13 @@
- - {{o.value}} - - {{o.address}} + + + + + +
{{out.value}} {{out.address}}
created at {{tx.createdTs | date:'medium'}}
@@ -266,7 +268,10 @@ - Proposal ID: {{tx.ntxid}} + + Fee: {{tx.fee}} + Proposal ID: {{tx.ntxid}} +
diff --git a/js/controllers/transactions.js b/js/controllers/transactions.js index 6f29bdd40..7cc47598e 100644 --- a/js/controllers/transactions.js +++ b/js/controllers/transactions.js @@ -5,8 +5,9 @@ angular.module('copay.transactions').controller('TransactionsController', function($scope, $rootScope, $location) { $scope.title = 'Transactions'; var _updateTxs = function() { -console.log('[transactions.js.10:_updateTxs:]'); //TODO var w =$rootScope.wallet; + if (!w) return; + var inT = w.getTxProposals(); var txs = []; @@ -25,11 +26,10 @@ console.log('[transactions.js.10:_updateTxs:]'); //TODO }); // extra fields i.outs = outs; - i.fee = i.feeSat/bitcore.util.COIN; + i.fee = i.builder.feeSat/bitcore.util.COIN; i.missingSignatures = tx.countInputMissingSignatures(0); txs.push(i); }); -console.log('[transactions.js.35:txs:]',txs); //TODO $scope.txs = txs; w.removeListener('txProposalsUpdated',_updateTxs) w.once('txProposalsUpdated',_updateTxs); @@ -38,7 +38,7 @@ console.log('[transactions.js.35:txs:]',txs); //TODO $scope.send = function (ntxid) { var w = $rootScope.wallet; w.sendTx(ntxid, function(txid) { -console.log('[transactions.js.68:txid:] SENTTX CALLBACK',txid); //TODO + console.log('[transactions.js.68:txid:] SENTTX CALLBACK',txid); //TODO $rootScope.flashMessage = txid ? {type:'success', message: 'Transactions SENT! txid:' + txid} : {type:'error', message: 'There was an error sending the Transaction'} From b6280348e56f2c038c72907c71791570c758637e Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 23 Apr 2014 02:01:54 -0300 Subject: [PATCH 6/6] reject button working --- index.html | 17 ++++++---- js/controllers/send.js | 15 ++++----- js/controllers/transactions.js | 9 +++++ js/models/core/PublicKeyRing.js | 3 +- js/models/core/TxProposals.js | 44 ++++++++++++++++++++++-- js/models/core/Wallet.js | 60 +++++++++++++++------------------ 6 files changed, 99 insertions(+), 49 deletions(-) diff --git a/index.html b/index.html index a88a9fb03..16b278635 100644 --- a/index.html +++ b/index.html @@ -244,7 +244,7 @@
-

Pending transactions ({{txs.length}})

+

Transactions proposals ({{txs.length}})

@@ -284,6 +284,7 @@ + @@ -301,16 +302,20 @@
Signed by you already
-
+
-
+ + Transaction finally rejected + + Transaction ready.
diff --git a/js/controllers/send.js b/js/controllers/send.js index 276468464..46000b937 100644 --- a/js/controllers/send.js +++ b/js/controllers/send.js @@ -23,16 +23,15 @@ angular.module('copay.send').controller('SendController', var w = $rootScope.wallet; w.createTx( address, amount,function() { + + // reset fields + $scope.address = null; + $scope.amount = null; + form.address.$pristine = true; + form.amount.$pristine = true; + $rootScope.flashMessage = { message: 'The transaction proposal has been created', type: 'success'}; $rootScope.$digest(); }); - // reset fields - $scope.address = null; - $scope.amount = null; - form.address.$pristine = true; - form.amount.$pristine = true; - - // TODO: check if createTx has an error. - $rootScope.flashMessage = { message: 'Your transaction proposal has been sent successfully', type: 'success'}; }; }); diff --git a/js/controllers/transactions.js b/js/controllers/transactions.js index 7cc47598e..59f58f150 100644 --- a/js/controllers/transactions.js +++ b/js/controllers/transactions.js @@ -70,5 +70,14 @@ angular.module('copay.transactions').controller('TransactionsController', } }; + + $scope.reject = function (ntxid) { + var w = $rootScope.wallet; + w.reject(ntxid); + $rootScope.flashMessage = {type:'warning', message: 'Transaction rejected by you'}; + _updateTxs(); + $rootScope.$digest(); + }; + _updateTxs(); }); diff --git a/js/models/core/PublicKeyRing.js b/js/models/core/PublicKeyRing.js index 14f611d8b..a9a1327d5 100644 --- a/js/models/core/PublicKeyRing.js +++ b/js/models/core/PublicKeyRing.js @@ -274,6 +274,8 @@ PublicKeyRing.prototype._mergePubkeys = function(inPKR) { var self = this; var hasChanged = false; var l= self.copayersBIP32.length; + if (self.isComplete()) + return; inPKR.copayersBIP32.forEach( function(b) { var haveIt = false; @@ -286,7 +288,6 @@ 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)); diff --git a/js/models/core/TxProposals.js b/js/models/core/TxProposals.js index 772faefe4..bbef94908 100644 --- a/js/models/core/TxProposals.js +++ b/js/models/core/TxProposals.js @@ -18,6 +18,7 @@ function TxProposal(opts) { this.createdTs = opts.createdTs; this.seenBy = opts.seenBy || {}; this.signedBy = opts.signedBy || {}; + this.rejectedBy = opts.rejectedBy || {}; this.builder = opts.builder; this.sentTs = opts.sentTs || null; this.sentTxid = opts.sentTxid || null; @@ -120,6 +121,7 @@ TxProposals.prototype._startMerge = function(myTxps, theirTxps) { }; }; +// TODO add signatures. TxProposals.prototype._mergeMetadata = function(myTxps, theirTxps, mergeInfo) { var toMerge = mergeInfo.toMerge; @@ -130,7 +132,7 @@ TxProposals.prototype._mergeMetadata = function(myTxps, theirTxps, mergeInfo) { var v1 = toMerge[hash]; Object.keys(v1.seenBy).forEach(function(k) { - if (!v0.seenBy[k] || v0.seenBy[k] !== v1.seenBy[k]) { + if (!v0.seenBy[k]) { v0.seenBy[k] = v1.seenBy[k]; hasChanged++; } @@ -143,6 +145,13 @@ TxProposals.prototype._mergeMetadata = function(myTxps, theirTxps, mergeInfo) { } }); + Object.keys(v1.rejectedBy).forEach(function(k) { + if (!v0.rejectedBy[k]) { + v0.rejectedBy[k] = v1.rejectedBy[k]; + hasChanged++; + } + }); + if (!v0.sentTxid && v1.sentTxid) { v0.sentTs = v1.sentTs; v0.sentTxid = v1.sentTxid; @@ -181,10 +190,41 @@ TxProposals.prototype.setSent = function(ntxid,txid) { this.txps[ntxid].setSent(txid); }; -TxProposals.prototype.getUsedUnspent = function() { + +TxProposals.prototype.getTxProposal = function(ntxid) { + var txp = this.txps[ntxid]; + var i = JSON.parse(JSON.stringify(txp)); + i.builder = txp.builder; + i.ntxid = ntxid; + i.peerActions = {}; + for(var p in txp.seenBy){ + i.peerActions[p]={seen: txp.seenBy[p]}; + } + for(var p in txp.signedBy){ + i.peerActions[p]= i.peerActions[p] || {}; + i.peerActions[p].sign = txp.signedBy[p]; + } + var r=0; + for(var p in txp.rejectedBy){ + i.peerActions[p]= i.peerActions[p] || {}; + i.peerActions[p].rejected = txp.rejectedBy[p]; + r++; + } + i.rejectCount=r; + + var c = txp.creator; + i.peerActions[c] = i.peerActions[c] || {}; + i.peerActions[c].create = txp.createdTs; + return i; +}; + +TxProposals.prototype.getUsedUnspent = function(maxRejectCount) { var ret = []; for(var i in this.txps) { var u = this.txps[i].builder.getSelectedUnspent(); + if (this.getTxProposal(i).rejectCount>maxRejectCount) + continue; + for (var j in u){ ret.push(u[j].txid); } diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index b966e295a..b90b71040 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -274,46 +274,38 @@ Wallet.prototype.generateAddress = function(isChange) { return addr; }; -// TODO : sort by time... / signed. + Wallet.prototype.getTxProposals = function() { var ret = []; for(var k in this.txProposals.txps) { - var txp = this.txProposals.txps[k]; - var i = JSON.parse(JSON.stringify(txp)); - i.builder = txp.builder; - i.ntxid = k; - i.signedByUs = txp.signedBy[this.getMyPeerId()]?true:false; - - i.peerActions = {}; - for(var p in txp.seenBy){ - i.peerActions[p]={seen: txp.seenBy[p]}; - } - for(var p in txp.signedBy){ - i.peerActions[p]= i.peerActions[p] || {}; - i.peerActions[p].sign = txp.signedBy[p]; - } - var c = txp.creator; - i.peerActions[c] = i.peerActions[c] || {}; - i.peerActions[c].create = txp.createdTs; - + var i = this.txProposals.getTxProposal(k); + i.signedByUs = i.signedBy[this.getMyPeerId()]?true:false; + i.rejectedByUs = i.rejectedBy[this.getMyPeerId()]?true:false; + if (this.totalCopayers-i.rejectCount < this.requiredCopayers) + i.finallyRejected=true; ret.push(i); } return ret; }; -Wallet.prototype.getTxProposal = function(ntxid) { + +Wallet.prototype.reject = function(ntxid) { + var myId=this.getMyPeerId(); var txp = this.txProposals.txps[ntxid]; - var i = {txp:txp}; - i.ntxid = ntxid; - i.signedByUs = txp.signedBy[this.getMyPeerId()]?true:false; - return i; + if (!txp || txp.rejectedBy[myId] || txp.signedBy[myId]) return; + + txp.rejectedBy[myId] = Date.now(); + this.sendTxProposals(); + this.store(true); }; + Wallet.prototype.sign = function(ntxid) { var self = this; + var myId=this.getMyPeerId(); var txp = self.txProposals.txps[ntxid]; - if (!txp) return; + if (!txp || txp.rejectedBy[myId] || txp.signedBy[myId]) return; var pkr = self.publicKeyRing; var keys = self.privateKey.getAll(pkr.addressIndex, pkr.changeAddressIndex); @@ -324,7 +316,7 @@ Wallet.prototype.sign = function(ntxid) { var ret = false; if (b.signaturesAdded > before) { - txp.signedBy[self.getMyPeerId()] = Date.now(); + txp.signedBy[myId] = Date.now(); this.sendTxProposals(); this.store(true); ret = true; @@ -371,7 +363,6 @@ Wallet.prototype.addSeenToTxProposals = function() { return ret; }; - Wallet.prototype.getAddresses = function(onlyMain) { return this.publicKeyRing.getAddresses(onlyMain); }; @@ -438,7 +429,8 @@ Wallet.prototype.getSafeUnspent = function(cb) { this.blockchain.getUnspent(this.getAddressesStr(), function(unspentList) { var ret=[]; - var uu = self.txProposals.getUsedUnspent(); + var maxRejectCount = self.totalCopayers - self.requiredCopayers; + var uu = self.txProposals.getUsedUnspent(maxRejectCount); for(var i in unspentList){ if (uu.indexOf(unspentList[i].txid) === -1) @@ -497,21 +489,25 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, utxos, opts) { if (priv) { b.sign( priv.getAll(pkr.addressIndex, pkr.changeAddressIndex) ); } - var me = {}; var myId = this.getMyPeerId(); var now = Date.now(); - if (priv) me[myId] = now; + var me = {}; + if (priv && b.signaturesAdded) me[myId] = now; + + var meSeen = {}; + if (priv) meSeen[myId] = now; var data = { - signedBy: (priv && b.signaturesAdded ? me : {}), - seenBy: (priv ? me : {}), + signedBy: me, + seenBy: meSeen, creator: myId, createdTs: now, builder: b, }; this.txProposals.add(data); + return true; }; Wallet.prototype.connectTo = function(peerId) {