diff --git a/js/controllers/setup.js b/js/controllers/setup.js index 4f8030434..6020b4acb 100644 --- a/js/controllers/setup.js +++ b/js/controllers/setup.js @@ -1,5 +1,37 @@ 'use strict'; + +var valid_pairs = { + '1,1': 112, + '1,2': 147, + '2,2': 220, + '1,3': 182, + '2,3': 256, + '3,3': 329, + '1,4': 216, + '2,4': 290, + '3,4': 363, + '4,4': 436, + '1,5': 250, + '2,5': 324, + '3,5': 398, + '4,5': 470, + '1,6': 284, + '2,6': 358, + '3,6': 432, + '1,7': 318, + '2,7': 392, + '3,7': 465, + '1,8': 353, + '2,8': 427, + '1,9': 387, + '2,9': 461, + '1,10': 421, + '2,10': 495, + '1,11': 455, + '1,12': 489 +}; + angular.module('copay.setup').controller('SetupController', function($scope, $rootScope, $location, $timeout, walletFactory, controllerUtils, Passphrase) { @@ -9,7 +41,7 @@ angular.module('copay.setup').controller('SetupController', // ng-repeat defined number of times instead of repeating over array? $scope.getNumber = function(num) { - return new Array(num); + return new Array(num); } $scope.totalCopayers = config.wallet.totalCopayers; @@ -18,10 +50,11 @@ angular.module('copay.setup').controller('SetupController', $scope.TCValues.push(n); var updateRCSelect = function(n) { - $scope.requiredCopayers = parseInt(Math.min(n / 2 + 1, config.limits.mPlusN-n)); + $scope.requiredCopayers = (valid_pairs[[parseInt(n / 2 + 1), n]] > 0 || config.networkName === 'testnet') ? + parseInt(n / 2 + 1) : 1; $scope.RCValues = []; for (var m = 1; m <= n; m++) { - if (n + m <= config.limits.mPlusN) { + if (valid_pairs[[m, n]] > 0 || config.networkName === 'testnet') { $scope.RCValues.push(m); } } @@ -35,15 +68,18 @@ angular.module('copay.setup').controller('SetupController', $scope.create = function(form) { if (form && form.$invalid) { - $rootScope.$flashMessage = { message: 'Please, enter required fields', type: 'error'}; + $rootScope.$flashMessage = { + message: 'Please, enter required fields', + type: 'error' + }; return; } $scope.loading = true; - Passphrase.getBase64Async($scope.walletPassword, function(passphrase){ + Passphrase.getBase64Async($scope.walletPassword, function(passphrase) { var opts = { requiredCopayers: $scope.requiredCopayers, totalCopayers: $scope.totalCopayers, - name: $scope.walletName, + name: $scope.walletName, nickname: $scope.myNickname, passphrase: passphrase, }; diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index f221378ad..9bba3a6c0 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -426,7 +426,10 @@ Wallet.prototype.sign = function(ntxid, cb) { setTimeout(function() { var myId = self.getMyCopayerId(); var txp = self.txProposals.txps[ntxid]; - if (!txp || txp.rejectedBy[myId] || txp.signedBy[myId]) return; + if (!txp || txp.rejectedBy[myId] || txp.signedBy[myId]) { + if (cb) cb(false); + return; + } var pkr = self.publicKeyRing; var keys = self.privateKey.getAll(pkr.addressIndex, pkr.changeAddressIndex); @@ -455,6 +458,10 @@ Wallet.prototype.sendTx = function(ntxid, cb) { if (!tx.isComplete()) return; this.log('[Wallet.js.231] BROADCASTING TX!!!'); //TODO + var scriptSig = tx.ins[0].getScript(); + var size = scriptSig.serialize().length; + alert('\t scriptSig size: '+size); + var txHex = tx.serialize().toString('hex'); this.log('[Wallet.js.261:txHex:]', txHex); //TODO diff --git a/test/find_m_n.js b/test/find_m_n.js deleted file mode 100755 index 4ea1c7518..000000000 --- a/test/find_m_n.js +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env node - -'use strict'; - -var async = require('async'); -var bitcore = require('bitcore'); -var PublicKeyRing = require('../js/models/core/PublicKeyRing'); -var PrivateKey = require('../js/models/core/PrivateKey'); - -var FakeNetwork = require('./mocks/FakeNetwork'); -var Insight = require('../js/models/blockchain/Insight'); -var FakeStorage = require('./mocks/FakeStorage'); - -var WalletFactory = require('soop').load('../js/models/core/WalletFactory', { - Network: FakeNetwork, - Blockchain: Insight, - Storage: FakeStorage, -}); -var Key = bitcore.Key; - - -var N_LIMIT = 20; -var nn = 'livenet'; - -for (var n = 1; n <= N_LIMIT; n++) { - var end = false; - for (var m = 1; m <= n; m++) { - // case m-of-n - console.log('case ' + m + '-of-' + n); - // create full pkr - var publicKeyRing = new PublicKeyRing({ - networkName: nn, - requiredCopayers: m, - totalCopayers: n, - }); - var privateKey = null; - var pks = []; - for (var i = 0; i < n; i++) { - var pk = new PrivateKey({ - networkName: nn - }); - if (i === 0) { - privateKey = pk; - } else { - publicKeyRing.addCopayer(pk.getExtendedPublicKeyString(), 'dummy'); - } - pks.push(pk); - } - - var opts = {}; - opts.publicKeyRing = publicKeyRing; - opts.privateKey = privateKey; - opts.requiredCopayers = m; - opts.totalCopayers = n; - opts.spendUnconfirmed = true; - opts.version = 'script' - - var w = new WalletFactory(opts).create(opts); - var addr = w.generateAddress(); - console.log('\t receive addr=' + addr); - - - var toAddress = 'msj42CCGruhRsFrGATiUuh25dtxYtnpbTx'; - var amount = '5000000'; - // create fake utxo - var utxos = [{ - 'address': addr, - 'txid': '82a974b72d3135152043989652e687e2966c651ba4822274926221017ea072d2', - 'vout': 1, - 'ts': 1400696213, - 'scriptPubKey': 'a914b2562c950498ff48ad3479ca1c2dfda2b0273e2287', - 'amount': 10.0, - 'confirmations': 2 - }]; - var ntxid = w.createTxSync(toAddress, amount, utxos); - console.log('\t ntxid =' + ntxid); - var txp = w.txProposals.txps[ntxid]; - var tx = txp.builder.build(); - var scriptSig = tx.ins[0].getScript(); - var size = scriptSig.serialize().length; - console.log('\t scriptSig size: '+size); - if (size > 500) { - if (m === 1) { - end = true; - } - break; - } - } - if (end) break; -} diff --git a/util/find_m_n.js b/util/find_m_n.js new file mode 100755 index 000000000..88364fe6d --- /dev/null +++ b/util/find_m_n.js @@ -0,0 +1,123 @@ +#!/usr/bin/env node + +'use strict'; + +var async = require('async'); +var bitcore = require('bitcore'); +var chai = require('chai'); +var should = chai.should(); +var PublicKeyRing = require('../js/models/core/PublicKeyRing'); +var PrivateKey = require('../js/models/core/PrivateKey'); + +var FakeNetwork = require('../test/mocks/FakeNetwork'); +var Insight = require('../js/models/blockchain/Insight'); +var FakeStorage = require('../test/mocks/FakeStorage'); + +var WalletFactory = require('soop').load('../js/models/core/WalletFactory', { + Network: FakeNetwork, + Blockchain: Insight, + Storage: FakeStorage, +}); +var Key = bitcore.Key; + + +var N_LIMIT = 50; +var ITERS = 5; +var nn = 'livenet'; + +var maxs = {}; +var valid = {}; + +for (var n = 1; n <= N_LIMIT; n++) { + var end = false; + for (var m = 1; m <= n; m++) { + // case m-of-n + console.log('case ' + m + '-of-' + n); + var pair = [m, n]; + for (var iter = 0; iter <= ITERS*n; iter++) { + // create full pkr + var publicKeyRing = new PublicKeyRing({ + networkName: nn, + requiredCopayers: m, + totalCopayers: n, + }); + var privateKey = null; + var others_pks = []; + for (var i = 0; i < n; i++) { + var pk = new PrivateKey({ + networkName: nn + }); + if (i === 0) { + privateKey = pk; + } else { + publicKeyRing.addCopayer(pk.getExtendedPublicKeyString(), 'dummy'); + others_pks.push(pk); + } + } + + others_pks.length.should.equal(n - 1); + + var opts = {}; + opts.publicKeyRing = publicKeyRing; + opts.privateKey = privateKey; + opts.requiredCopayers = m; + opts.totalCopayers = n; + opts.spendUnconfirmed = true; + opts.version = 'script' + + var w = new WalletFactory(opts).create(opts); + var addr = w.generateAddress(); + + var toAddress = 'msj42CCGruhRsFrGATiUuh25dtxYtnpbTx'; + var amount = '5000000'; + // create fake utxo + var utxos = [{ + 'address': addr, + 'txid': '82a974b72d3135152043989652e687e2966c651ba4822274926221017ea072d2', + 'vout': 1, + 'ts': 1400696213, + 'scriptPubKey': 'a914b2562c950498ff48ad3479ca1c2dfda2b0273e2287', + 'amount': 10.0, + 'confirmations': 2 + }]; + var ntxid = w.createTxSync(toAddress, amount, utxos); + var txp = w.txProposals.txps[ntxid]; + + var signTx = function(pk, cb) { + var pkr = publicKeyRing; + var keys = pk.getAll(pkr.addressIndex, pkr.changeAddressIndex); + + var b = txp.builder; + var before = b.signaturesAdded; + b.sign(keys); + + return cb(); + } + + async.eachSeries(others_pks, signTx, function(err) { + if (err) { + throw err; + } else { + var tx = txp.builder.build(); + var scriptSig = tx.ins[0].getScript(); + var size = scriptSig.serialize().length; + + maxs[pair] = Math.max(maxs[pair] || 0, size) + } + }); + + } + var size = maxs[pair]; + console.log('\tmax size: '+size); + var m_valid = false; + if (size < 500) { + m_valid = true; + valid[[m,n]] = size; + } + if (!m_valid) break; + } + if (!m_valid && m === 1) break; +} + + +console.log(valid);