diff --git a/bit-wallet/bit-address b/bit-wallet/bit-address index fb276bb..c1f6ddc 100644 --- a/bit-wallet/bit-address +++ b/bit-wallet/bit-address @@ -6,8 +6,8 @@ var common = require('./common'); program .version('0.0.1') - .option('-c,--config [file]', 'Wallet config filename') - .option('-v,--verbose', 'be verbose') + .option('-c, --config [file]', 'Wallet config filename') + .option('-v, --verbose', 'be verbose') .parse(process.argv); var args = program.args; diff --git a/bit-wallet/bit-addresses b/bit-wallet/bit-addresses index d01a769..31f2a93 100644 --- a/bit-wallet/bit-addresses +++ b/bit-wallet/bit-addresses @@ -7,8 +7,8 @@ var common = require('./common'); program .version('0.0.1') - .option('-c,--config [file]', 'Wallet config filename') - .option('-v,--verbose', 'be verbose') + .option('-c, --config [file]', 'Wallet config filename') + .option('-v, --verbose', 'be verbose') .parse(process.argv); var args = program.args; diff --git a/bit-wallet/bit-balance b/bit-wallet/bit-balance index 3a9763c..7c95f3e 100644 --- a/bit-wallet/bit-balance +++ b/bit-wallet/bit-balance @@ -6,8 +6,8 @@ var common = require('./common'); program .version('0.0.1') - .option('-c,--config [file]', 'Wallet config filename') - .option('-v,--verbose', 'be verbose') + .option('-c, --config [file]', 'Wallet config filename') + .option('-v, --verbose', 'be verbose') .parse(process.argv); var args = program.args; diff --git a/bit-wallet/bit-create b/bit-wallet/bit-create index 6cdacee..01137a6 100755 --- a/bit-wallet/bit-create +++ b/bit-wallet/bit-create @@ -6,8 +6,8 @@ var common = require('./common'); program .version('0.0.1') - .option('-c,--config [file]', 'Wallet config filename') - .option('-n,--network [networkname]', 'livenet|testnet', String, 'livenet') + .option('-c, --config [file]', 'Wallet config filename') + .option('-n, --network [networkname]', 'livenet|testnet', String, 'livenet') .usage('[options] [copayerName]') .parse(process.argv); diff --git a/bit-wallet/bit-create.js b/bit-wallet/bit-create.js deleted file mode 100644 index 1f02e8c..0000000 --- a/bit-wallet/bit-create.js +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env node - -var program = require('commander'); -var cli = require('../lib/clilib.js'); - -program - .version('0.0.1') - .parse(process.argv); - - diff --git a/bit-wallet/bit-join b/bit-wallet/bit-join index 63f9bc9..4a14659 100644 --- a/bit-wallet/bit-join +++ b/bit-wallet/bit-join @@ -6,7 +6,7 @@ var common = require('./common'); program .version('0.0.1') - .option('-c,--config [file]', 'Wallet config filename') + .option('-c, --config [file]', 'Wallet config filename') .usage('[options] [copayerName]') .parse(process.argv); diff --git a/bit-wallet/bit-send b/bit-wallet/bit-send index e0db849..0fc35d3 100644 --- a/bit-wallet/bit-send +++ b/bit-wallet/bit-send @@ -6,8 +6,8 @@ var common = require('./common'); program .version('0.0.1') -.option('-c,--config [file]', 'Wallet config filename') -.option('-v,--verbose', 'be verbose') +.option('-c, --config [file]', 'Wallet config filename') +.option('-v, --verbose', 'be verbose') .usage('[options]
') .parse(process.argv); diff --git a/bit-wallet/bit-status b/bit-wallet/bit-status index 73ee0b6..6d98416 100644 --- a/bit-wallet/bit-status +++ b/bit-wallet/bit-status @@ -6,8 +6,8 @@ var common = require('./common'); program .version('0.0.1') - .option('-c,--config [file]', 'Wallet config filename') - .option('-v,--verbose', 'be verbose') + .option('-c, --config [file]', 'Wallet config filename') + .option('-v, --verbose', 'be verbose') .parse(process.argv); var args = program.args; diff --git a/lib/clilib.js b/lib/clilib.js index 463672f..9ac09e1 100644 --- a/lib/clilib.js +++ b/lib/clilib.js @@ -72,8 +72,6 @@ CliLib.prototype._loadAndCheck = function() { process.exit(1); } - // TODO - delete data['verified']; if (data.verified == 'corrupt') { log.error('The wallet is tagged as corrupt. Some of the copayers cannot be verified to have known the wallet secret.'); process.exit(1); @@ -143,10 +141,10 @@ CliLib.prototype._joinWallet = function(data, secret, copayerName, cb) { var secretSplit = secret.split(':'); var walletId = secretSplit[0]; - var privKey = Bitcore.PrivateKey.fromString(secretSplit[1]); + var walletPrivKey = Bitcore.PrivateKey.fromString(secretSplit[1]); var xPubKey = new Bitcore.HDPublicKey(data.xPrivKey); - var xPubKeySignature = SignUtils.sign(xPubKey.toString(), privKey); + var xPubKeySignature = SignUtils.sign(xPubKey.toString(), walletPrivKey); var signingPrivKey = (new Bitcore.HDPrivateKey(data.xPrivKey)).derive('m/1/0').privateKey; @@ -171,6 +169,7 @@ CliLib.prototype._joinWallet = function(data, secret, copayerName, cb) { var wallet = body.wallet; data.copayerId = body.copayerId; + data.walletPrivKey = walletPrivKey; data.signingPrivKey = signingPrivKey.toString(); data.m = wallet.m; data.n = wallet.n; diff --git a/lib/server.js b/lib/server.js index c6a727e..4b58469 100644 --- a/lib/server.js +++ b/lib/server.js @@ -332,9 +332,8 @@ CopayServer.prototype._getUtxos = function(cb) { // Get addresses for this wallet self.storage.fetchAddresses(self.walletId, function(err, addresses) { -console.log('[server.js.334:addresses:]',addresses); //TODO if (err) return cb(err); - if (addresses.length == 0) + if (addresses.length == 0) return cb(null, []); var addressStrs = _.pluck(addresses, 'address'); @@ -389,7 +388,6 @@ CopayServer.prototype.getBalance = function(opts, cb) { var self = this; self._getUtxos(function(err, utxos) { -console.log('[server.js.390:utxos:]',utxos); //TODO if (err) return cb(err); var balance = {}; @@ -445,15 +443,13 @@ CopayServer.prototype._selectUtxos = function(txp, utxos) { CopayServer.prototype.createTx = function(opts, cb) { var self = this; - if (!Utils.checkRequired(opts, ['toAddress', 'amount'])) + if (!Utils.checkRequired(opts, ['toAddress', 'amount', 'proposalSignature'])) return cb(new ClientError('Required argument missing')); Utils.runLocked(self.walletId, cb, function(cb) { self.getWallet({}, function(err, wallet) { if (err) return cb(err); if (!wallet.isComplete()) return cb(new ClientError('Wallet is not complete')); - if (wallet.isShared() && !Utils.checkRequired(opts, 'proposalSignature')) - return cb(new ClientError('Proposal signature is required for shared wallets')); var copayer = wallet.getCopayer(self.copayerId); var msg = opts.toAddress + '|' + opts.amount + '|' + opts.message; diff --git a/lib/signutils.js b/lib/signutils.js index 55c8877..c8913c1 100644 --- a/lib/signutils.js +++ b/lib/signutils.js @@ -1,4 +1,3 @@ - var _ = require('lodash'); var Bitcore = require('bitcore'); var PrivateKey = Bitcore.PrivateKey; @@ -8,14 +7,13 @@ var ECDSA = Bitcore.crypto.ECDSA; var Hash = Bitcore.crypto.Hash; var BufferReader = Bitcore.encoding.BufferReader; - -var SignUtils = function () { -}; + +var SignUtils = function() {}; /* TODO: It would be nice to be compatible with bitcoind signmessage. How * the hash is calculated there? */ -SignUtils.hash = function (text) { +SignUtils.hash = function(text) { var buf = new Buffer(text); var ret = Hash.sha256sha256(buf); ret = new BufferReader(ret).readReverse(); @@ -23,14 +21,14 @@ SignUtils.hash = function (text) { }; -SignUtils.sign = function (text, privKey) { +SignUtils.sign = function(text, privKey) { var priv = new PrivateKey(privKey); var hash = SignUtils.hash(text); return ECDSA.sign(hash, priv, 'little').toString(); }; -SignUtils.verify = function (text, signature, pubKey) { +SignUtils.verify = function(text, signature, pubKey) { var pub = new PublicKey(pubKey); var hash = SignUtils.hash(text); diff --git a/test/integration.js b/test/integration.js index 131b32b..f71df22 100644 --- a/test/integration.js +++ b/test/integration.js @@ -167,9 +167,13 @@ helpers.createProposalOpts = function(toAddress, amount, message, signingKey) { toAddress: toAddress, amount: helpers.toSatoshi(amount), message: message, + proposalSignature: null, }; var msg = opts.toAddress + '|' + opts.amount + '|' + opts.message; - opts.proposalSignature = SignUtils.sign(msg, signingKey); + try { + opts.proposalSignature = SignUtils.sign(msg, signingKey); + } catch (ex) {} + return opts; }; @@ -667,6 +671,34 @@ describe('Copay server', function() { }); }); + it('should fail to create tx with invalid proposal signature', function(done) { + helpers.createUtxos(server, wallet, [100, 200], function(utxos) { + helpers.stubBlockExplorer(server, utxos); + var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 80, null, 'dummy'); + + server.createTx(txOpts, function(err, tx) { + should.not.exist(tx); + err.should.exist; + err.message.should.equal('Invalid proposal signature'); + done(); + }); + }); + }); + + it('should fail to create tx with proposal signed by another copayer', function(done) { + helpers.createUtxos(server, wallet, [100, 200], function(utxos) { + helpers.stubBlockExplorer(server, utxos); + var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 80, null, TestData.copayers[1].privKey); + + server.createTx(txOpts, function(err, tx) { + should.not.exist(tx); + err.should.exist; + err.message.should.equal('Invalid proposal signature'); + done(); + }); + }); + }); + it('should fail to create tx for address invalid address', function(done) { helpers.createUtxos(server, wallet, [100, 200], function(utxos) { helpers.stubBlockExplorer(server, utxos);