From 0758c2e84277f20b2358f9a8234fc2473c40217d Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 4 Feb 2015 16:18:36 -0300 Subject: [PATCH] signing test --- lib/server.js | 54 ++++++++++++++++++++-------------- package.json | 2 +- test/integration.js | 71 +++++++++++++++++++++++++++------------------ 3 files changed, 76 insertions(+), 51 deletions(-) diff --git a/lib/server.js b/lib/server.js index 20c70f5..44ad8b4 100644 --- a/lib/server.js +++ b/lib/server.js @@ -184,10 +184,10 @@ CopayServer.prototype.createAddress = function(opts, cb) { self.storage.storeAddress(wallet.id, address, function(err) { if (err) return cb(err); - + self.storage.storeWallet(wallet, function(err) { if (err) { - self.storage.removeAddress(wallet.id, address, function () { + self.storage.removeAddress(wallet.id, address, function() { return cb(err); }); } else { @@ -205,7 +205,7 @@ CopayServer.prototype.createAddress = function(opts, cb) { * @param {string} opts.walletId - The wallet id. * @returns {Address[]} */ -CopayServer.prototype.getAddresses = function (opts, cb) { +CopayServer.prototype.getAddresses = function(opts, cb) { var self = this; self.storage.fetchAddresses(opts.walletId, function(err, addresses) { @@ -291,7 +291,7 @@ CopayServer.prototype._getUtxos = function(opts, cb) { }) .value(); - var dictionary = _.reduce(utxos, function (memo, utxo) { + var dictionary = _.reduce(utxos, function(memo, utxo) { memo[utxo.txid + '|' + utxo.vout] = utxo; return memo; }, {}); @@ -333,13 +333,13 @@ CopayServer.prototype.getBalance = function(opts, cb) { var balance = {}; balance.totalAmount = Utils.strip(_.reduce(utxos, function(sum, utxo) { - return sum + utxo.amount; + return sum + self._inputSatoshis(utxo); }, 0)); balance.lockedAmount = Utils.strip(_.reduce(_.filter(utxos, { locked: true }), function(sum, utxo) { - return sum + utxo.amount; + return sum + self._inputSatoshis(utxo); }, 0)); return cb(null, balance); @@ -348,7 +348,7 @@ CopayServer.prototype.getBalance = function(opts, cb) { CopayServer.prototype._createRawTx = function(txp) { -console.log('[server.js.320:txp:]',txp.inputs, txp.toAddress, txp.amount, txp.changeAddress); //TODO + console.log('[server.js.320:txp:]', txp.inputs, txp.toAddress, txp.amount, txp.changeAddress); //TODO var rawTx = new Bitcore.Transaction() @@ -356,10 +356,15 @@ console.log('[server.js.320:txp:]',txp.inputs, txp.toAddress, txp.amount, txp.ch .to(txp.toAddress, txp.amount) .change(txp.changeAddress); -console.log('[server.js.324:rawTx:]',rawTx); //TODO + console.log('[server.js.324:rawTx:]', rawTx); //TODO return rawTx; }; + +CopayServer.prototype._inputSatoshis = function(i) { + return i.amount ? Utils.strip(i.amount * 1e8) : i.satoshis; +}; + CopayServer.prototype._selectUtxos = function(txp, utxos) { var i = 0; var total = 0; @@ -368,13 +373,15 @@ CopayServer.prototype._selectUtxos = function(txp, utxos) { while (i < inputs.length) { selected.push(inputs[i]); - total += inputs[i].amount; + total += this._inputSatoshis(inputs[i]); + if (total >= txp.amount) { + break; } i++; }; - return total >= txp.amount ? selected : null; + return total >= txp.amount ? selected : null; }; @@ -428,7 +435,7 @@ CopayServer.prototype.createTx = function(opts, cb) { return cb(new ClientError('INSUFFICIENTFUNDS', 'Insufficient funds')); } - txp.inputPaths = _.pluck(txp.inputs,'path'); + txp.inputPaths = _.pluck(txp.inputs, 'path'); // no need to do this now: // TODO remove this comment //self._createRawTx(txp); @@ -471,12 +478,12 @@ CopayServer.prototype._broadcastTx = function(rawTx, cb) { * @param {string} opts.walletId - The wallet id. * @param {string} opts.copayerId - The wallet id. * @param {string} opts.txProposalId - The identifier of the transaction. - * @param {string} opts.signature - The signature of the tx for this copayer. + * @param {string} opts.signatures - The signatures of the inputs of this tx for this copayer (in apperance order) */ CopayServer.prototype.signTx = function(opts, cb) { var self = this; - Utils.checkRequired(opts, ['walletId', 'copayerId', 'txProposalId', 'signature']); + Utils.checkRequired(opts, ['walletId', 'copayerId', 'txProposalId', 'signatures']); self.fetchTx(opts.walletId, opts.txProposalId, function(err, txp) { if (err) return cb(err); @@ -487,22 +494,25 @@ CopayServer.prototype.signTx = function(opts, cb) { if (action) return cb(new ClientError('CVOTED', 'Copayer already voted on this transaction proposal')); if (txp.status != 'pending') return cb(new ClientError('TXNOTPENDING', 'The transaction proposal is not pending')); - txp.sign(opts.copayerId, opts.signature); + txp.sign(opts.copayerId, opts.signatures); self.storage.storeTx(opts.walletId, txp, function(err) { if (err) return cb(err); - if (txp.status == 'accepted'); - self._broadcastTx(txp.rawTx, function(err, txid) { - if (err) return cb(err); - - tx.setBroadcasted(txid); - self.storage.storeTx(opts.walletId, txp, function(err) { + if (txp.status == 'accepted') { + self._broadcastTx(txp.rawTx, function(err, txid) { if (err) return cb(err); - return cb(); + tx.setBroadcasted(txid); + self.storage.storeTx(opts.walletId, txp, function(err) { + if (err) return cb(err); + + return cb(null,txp); + }); }); - }); + } else { + return cb(null, txp); + } }); }); }; diff --git a/package.json b/package.json index 68214c8..8a82314 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ }, "dependencies": { "async": "^0.9.0", - "bitcore": "^0.8.6", + "bitcore": "*", "bitcore-explorers": "^0.9.1", "express": "^4.10.0", "inherits": "^2.0.1", diff --git a/test/integration.js b/test/integration.js index 6849289..c849e96 100644 --- a/test/integration.js +++ b/test/integration.js @@ -10,6 +10,7 @@ var levelup = require('levelup'); var memdown = require('memdown'); var Bitcore = require('bitcore'); +var Utils = require('../lib/utils'); var SignUtils = require('../lib/signutils'); var Storage = require('../lib/storage'); @@ -100,9 +101,20 @@ helpers.randomTXID = function() { return Bitcore.crypto.Hash.sha256(new Buffer(Math.random() * 100000)).toString('hex');; }; + +helpers.toSatoshi = function(btc) { + if (_.isArray(btc)) { + return _.map(btc, helpers.toSatoshi); + } else { + return Utils.strip(btc * 1e8); + } +}; + +// Amounts in satoshis helpers.createUtxos = function(server, wallet, amounts, cb) { var addresses = []; + async.each(amounts, function(a, next) { server.createAddress({ walletId: wallet.id, @@ -120,7 +132,7 @@ helpers.createUtxos = function(server, wallet, amounts, cb) { return { txid: helpers.randomTXID(), vout: Math.floor((Math.random() * 10) + 1), - amount: amount, + satoshis: amount, scriptPubKey: addresses[i].getScriptPubKey(wallet.m).toBuffer().toString('hex'), address: addresses[i].address, }; @@ -158,12 +170,11 @@ helpers.clientSign = function(tx, xpriv, n) { .sign(privs); var signatures = []; - console.log('Bitcore Transaction:', t); //TODO + //console.log('Bitcore Transaction:', t); //TODO _.each(privs, function(p) { var s = t.getSignatures(p)[0].signature.toDER().toString('hex'); - - console.log('\n## Priv key:', p); - console.log('\t\t->> signature ->>', s); //TODO + // console.log('\n## Priv key:', p); + // console.log('\t\t->> signature ->>', s); //TODO signatures.push(s); }); @@ -767,13 +778,13 @@ describe('Copay server', function() { it('should create tx', function(done) { - helpers.createUtxos(server, wallet, [100, 200], function(utxos) { + helpers.createUtxos(server, wallet, helpers.toSatoshi([100, 200]), function(utxos) { var txOpts = { copayerId: '1', walletId: '123', toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', - amount: 80, + amount: helpers.toSatoshi(80), message: 'some message', otToken: 'dummy', requestSignature: 'dummy', @@ -793,8 +804,8 @@ describe('Copay server', function() { walletId: '123' }, function(err, balance) { should.not.exist(err); - balance.totalAmount.should.equal(300); - balance.lockedAmount.should.equal(100); + balance.totalAmount.should.equal(helpers.toSatoshi(300)); + balance.lockedAmount.should.equal(helpers.toSatoshi(100)); done(); }); }); @@ -804,13 +815,13 @@ describe('Copay server', function() { it('should fail to create tx when insufficient funds', function(done) { - helpers.createUtxos(server, wallet, [100], function(utxos) { + helpers.createUtxos(server, wallet, helpers.toSatoshi([100]), function() { var txOpts = { copayerId: '1', walletId: '123', toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', - amount: 120, + amount: helpers.toSatoshi(120), message: 'some message', otToken: 'dummy', requestSignature: 'dummy', @@ -829,7 +840,7 @@ describe('Copay server', function() { }, function(err, balance) { should.not.exist(err); balance.lockedAmount.should.equal(0); - balance.totalAmount.should.equal(100); + balance.totalAmount.should.equal(10000000000); done(); }); }); @@ -839,13 +850,13 @@ describe('Copay server', function() { it('should create tx when there is a pending tx and enough UTXOs', function(done) { - helpers.createUtxos(server, wallet, [10.1, 10.2, 10.3], function(utxos) { + helpers.createUtxos(server, wallet, helpers.toSatoshi([10.1, 10.2, 10.3]), function(utxos) { var txOpts = { copayerId: '1', walletId: '123', toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', - amount: 12, + amount: helpers.toSatoshi(12), message: 'some message', otToken: 'dummy', requestSignature: 'dummy', @@ -875,8 +886,8 @@ describe('Copay server', function() { walletId: '123' }, function(err, balance) { should.not.exist(err); - balance.totalAmount.should.equal(30.6); - balance.lockedAmount.should.equal(30.6); + balance.totalAmount.should.equal(3060000000); + balance.lockedAmount.should.equal(3060000000); done(); }); }); @@ -886,13 +897,13 @@ describe('Copay server', function() { }); it('should fail to create tx when there is a pending tx and not enough UTXOs', function(done) { - helpers.createUtxos(server, wallet, [10.1, 10.2, 10.3], function(utxos) { + helpers.createUtxos(server, wallet, helpers.toSatoshi([10.1, 10.2, 10.3]), function(utxos) { var txOpts = { copayerId: '1', walletId: '123', toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', - amount: 12, + amount: helpers.toSatoshi(12), message: 'some message', otToken: 'dummy', requestSignature: 'dummy', @@ -905,7 +916,7 @@ describe('Copay server', function() { copayerId: '1', walletId: '123', toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', - amount: 24, + amount: helpers.toSatoshi(24), message: 'some message 2', otToken: 'dummy', requestSignature: 'dummy', @@ -923,8 +934,8 @@ describe('Copay server', function() { walletId: '123' }, function(err, balance) { should.not.exist(err); - balance.totalAmount.should.equal(30.6); - balance.lockedAmount.should.equal(20.3); + balance.totalAmount.should.equal(helpers.toSatoshi(30.6)); + balance.lockedAmount.should.equal(helpers.toSatoshi(20.3)); done(); }); }); @@ -935,7 +946,7 @@ describe('Copay server', function() { }); }); - describe.only('#signTx', function() { + describe('#signTx', function() { var wallet, txid; beforeEach(function(done) { @@ -948,12 +959,12 @@ describe('Copay server', function() { walletId: '123', isChange: false, }, function(err, address) { - helpers.createUtxos(server, wallet, [10, 20, 30], function(utxos) { + helpers.createUtxos(server, wallet, helpers.toSatoshi([1, 2, 3, 4, 5, 6, 7, 8]), function(utxos) { var txOpts = { copayerId: '1', walletId: '123', toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', - amount: 10, + amount: helpers.toSatoshi(10), message: 'some message', otToken: 'dummy', requestSignature: 'dummy', @@ -978,11 +989,15 @@ describe('Copay server', function() { // var signatures = helpers.clientSign(tx, someXPrivKey[0], wallet.n); + server.signTx({ + walletId: '123', + copayerId: '1', + txProposalId: txid, + signatures: signatures, + }, function(err) { + done(); + }); - // TODO send signatures - - - done(); }); });