diff --git a/lib/model/address.js b/lib/model/address.js index 8ef4db0..a5da342 100644 --- a/lib/model/address.js +++ b/lib/model/address.js @@ -1,6 +1,6 @@ 'use strict'; -var Bitcore = require('bitcore'); +var Bitcore = require('bitcore-wallet-utils').Bitcore; function Address() { this.version = '1.0.0'; diff --git a/lib/model/copayer.js b/lib/model/copayer.js index 1cfffd4..830a55f 100644 --- a/lib/model/copayer.js +++ b/lib/model/copayer.js @@ -4,12 +4,11 @@ var $ = require('preconditions').singleton(); var _ = require('lodash'); var util = require('util'); -var Bitcore = require('bitcore'); -var HDPublicKey = Bitcore.HDPublicKey; var Uuid = require('uuid'); var AddressManager = require('./addressmanager'); var WalletUtils = require('bitcore-wallet-utils'); - +var Bitcore = WalletUtils.Bitcore; +var HDPublicKey = Bitcore.HDPublicKey; function Copayer() { this.version = '1.0.0'; diff --git a/lib/model/txproposal.js b/lib/model/txproposal.js index ef77ec4..1846e50 100644 --- a/lib/model/txproposal.js +++ b/lib/model/txproposal.js @@ -2,7 +2,8 @@ var _ = require('lodash'); var Uuid = require('uuid'); -var Bitcore = require('bitcore'); +var WalletUtils = require('bitcore-wallet-utils'); +var Bitcore = WalletUtils.Bitcore; var Address = Bitcore.Address; var TxProposalAction = require('./txproposalaction'); @@ -31,6 +32,7 @@ TxProposal.create = function(opts) { x.requiredRejections = opts.requiredRejections; x.status = 'pending'; x.actions = []; + x.outputOrder = _.shuffle(_.range(2)); return x; }; @@ -57,6 +59,7 @@ TxProposal.fromObj = function(obj) { x.actions = _.map(obj.actions, function(action) { return TxProposalAction.fromObj(action); }); + x.outputOrder = obj.outputOrder; return x; }; @@ -89,16 +92,7 @@ TxProposal.prototype._getCurrentSignatures = function() { TxProposal.prototype.getBitcoreTx = function() { var self = this; - var t = new Bitcore.Transaction(); - - _.each(this.inputs, function(i) { - t.from(i, i.publicKeys, self.requiredSignatures) - }); - - t.to(this.toAddress, this.amount) - .change(this.changeAddress.address); - - t._updateChangeOutput(); + var t = WalletUtils.buildTx(this); var sigs = this._getCurrentSignatures(); _.each(sigs, function(x) { diff --git a/lib/server.js b/lib/server.js index 4481849..1b4e707 100644 --- a/lib/server.js +++ b/lib/server.js @@ -8,7 +8,8 @@ var inherits = require('inherits'); var events = require('events'); var nodeutil = require('util'); -var Bitcore = require('bitcore'); +var WalletUtils = require('bitcore-wallet-utils'); +var Bitcore = WalletUtils.Bitcore; var PublicKey = Bitcore.PublicKey; var HDPublicKey = Bitcore.HDPublicKey; var Address = Bitcore.Address; @@ -17,7 +18,6 @@ var Explorers = require('bitcore-explorers'); var ClientError = require('./clienterror'); var Utils = require('./utils'); var Storage = require('./storage'); -var WalletUtils = require('bitcore-wallet-utils'); var Wallet = require('./model/wallet'); var Copayer = require('./model/copayer'); diff --git a/package.json b/package.json index a2c6aba..4638121 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "bitcore-wallet-service", "description": "A service for Mutisig HD Bitcoin Wallets", "author": "BitPay Inc", - "version": "0.0.5", + "version": "0.0.6", "keywords": [ "bitcoin", "copay", @@ -19,8 +19,7 @@ }, "dependencies": { "async": "^0.9.0", - "bitcore": "^0.11.2", - "bitcore-wallet-utils": "0.0.3", + "bitcore-wallet-utils": "^0.0.4", "bitcore-explorers": "^0.9.1", "body-parser": "^1.11.0", "coveralls": "^2.11.2", diff --git a/test/integration/server.js b/test/integration/server.js index 6b49596..3a5ae14 100644 --- a/test/integration/server.js +++ b/test/integration/server.js @@ -11,10 +11,10 @@ var levelup = require('levelup'); var memdown = require('memdown'); var log = require('npmlog'); log.debug = log.verbose; -var Bitcore = require('bitcore'); var Utils = require('../../lib/utils'); var WalletUtils = require('bitcore-wallet-utils'); +var Bitcore = WalletUtils.Bitcore; var Storage = require('../../lib/storage'); var Wallet = require('../../lib/model/wallet'); @@ -168,38 +168,7 @@ helpers.stubHistory = function(txs) { blockExplorer.getTransactions = sinon.stub().callsArgWith(1, null, txs); }; -helpers.clientSign = function(txp, xprivHex) { - //Derive proper key to sign, for each input - var privs = [], - derived = {}; - var xpriv = new Bitcore.HDPrivateKey(xprivHex); - - _.each(txp.inputs, function(i) { - if (!derived[i.path]) { - derived[i.path] = xpriv.derive(i.path).privateKey; - privs.push(derived[i.path]); - } - }); - - var t = new Bitcore.Transaction(); - - _.each(txp.inputs, function(i) { - t.from(i, i.publicKeys, txp.requiredSignatures); - }); - - t.to(txp.toAddress, txp.amount) - .change(txp.changeAddress.address); - - var signatures = _.map(privs, function(priv, i) { - return t.getSignatures(priv); - }); - - signatures = _.map(_.sortBy(_.flatten(signatures), 'inputIndex'), function(s) { - return s.signature.toDER().toString('hex'); - }); - - return signatures; -}; +helpers.clientSign = WalletUtils.signTxp; helpers.createProposalOpts = function(toAddress, amount, message, signingKey) { var opts = { @@ -1236,7 +1205,7 @@ describe('Copay server', function() { var tx = txs[0]; tx.id.should.equal(txid); - var signatures = helpers.clientSign(tx, TestData.copayers[0].xPrivKey_45H); + var signatures = helpers.clientSign(tx, TestData.copayers[0].xPrivKey); server.signTx({ txProposalId: txid, signatures: signatures, @@ -1263,7 +1232,7 @@ describe('Copay server', function() { server.getPendingTxs({}, function(err, txs) { var tx = txs[0]; tx.id.should.equal(txid); - var signatures = helpers.clientSign(tx, TestData.copayers[1].xPrivKey_45H); + var signatures = helpers.clientSign(tx, TestData.copayers[1].xPrivKey); server.signTx({ txProposalId: txid, signatures: signatures, @@ -1279,7 +1248,7 @@ describe('Copay server', function() { var tx = txs[0]; tx.id.should.equal(txid); - var signatures = helpers.clientSign(tx, TestData.copayers[0].xPrivKey_45H); + var signatures = helpers.clientSign(tx, TestData.copayers[0].xPrivKey); signatures[0] = 1; server.signTx({ @@ -1314,7 +1283,7 @@ describe('Copay server', function() { var tx = txs[0]; tx.id.should.equal(txid); - var signatures = _.take(helpers.clientSign(tx, TestData.copayers[0].xPrivKey_45H), 2); + var signatures = _.take(helpers.clientSign(tx, TestData.copayers[0].xPrivKey), 2); server.signTx({ txProposalId: txid, signatures: signatures, @@ -1331,7 +1300,7 @@ describe('Copay server', function() { var tx = txs[0]; tx.id.should.equal(txid); - var signatures = helpers.clientSign(tx, TestData.copayers[0].xPrivKey_45H); + var signatures = helpers.clientSign(tx, TestData.copayers[0].xPrivKey); server.signTx({ txProposalId: txid, signatures: signatures, @@ -1354,7 +1323,7 @@ describe('Copay server', function() { server.rejectTx({ txProposalId: txid, }, function(err) { - var signatures = helpers.clientSign(tx, TestData.copayers[0].xPrivKey_45H); + var signatures = helpers.clientSign(tx, TestData.copayers[0].xPrivKey); server.signTx({ txProposalId: txid, signatures: signatures, @@ -1402,7 +1371,7 @@ describe('Copay server', function() { txProposalId: txid }, function(err, tx) { should.not.exist(err); - var signatures = helpers.clientSign(tx, TestData.copayers[2].xPrivKey_45H); + var signatures = helpers.clientSign(tx, TestData.copayers[2].xPrivKey); server.signTx({ txProposalId: txid, signatures: signatures, @@ -1429,7 +1398,7 @@ describe('Copay server', function() { server.createTx(txOpts, function(err, txp) { should.not.exist(err); should.exist(txp); - var signatures = helpers.clientSign(txp, TestData.copayers[0].xPrivKey_45H); + var signatures = helpers.clientSign(txp, TestData.copayers[0].xPrivKey); server.signTx({ txProposalId: txp.id, signatures: signatures, @@ -1571,7 +1540,7 @@ describe('Copay server', function() { }); }, function(txp, next) { - var signatures = helpers.clientSign(txp, TestData.copayers[0].xPrivKey_45H); + var signatures = helpers.clientSign(txp, TestData.copayers[0].xPrivKey); server.signTx({ txProposalId: txpId, signatures: signatures, @@ -1602,7 +1571,7 @@ describe('Copay server', function() { }, function(txp, next) { helpers.getAuthServer(wallet.copayers[1].id, function(server, wallet) { - var signatures = helpers.clientSign(txp, TestData.copayers[1].xPrivKey_45H); + var signatures = helpers.clientSign(txp, TestData.copayers[1].xPrivKey); server.signTx({ txProposalId: txpId, signatures: signatures, @@ -1917,7 +1886,7 @@ describe('Copay server', function() { server.getPendingTxs({}, function(err, txs) { helpers.stubBroadcastFail(); var tx = txs[0]; - var signatures = helpers.clientSign(tx, TestData.copayers[0].xPrivKey_45H); + var signatures = helpers.clientSign(tx, TestData.copayers[0].xPrivKey); server.signTx({ txProposalId: tx.id, signatures: signatures, @@ -1959,7 +1928,7 @@ describe('Copay server', function() { it('should notify sign, acceptance, and broadcast, and emit', function(done) { server.getPendingTxs({}, function(err, txs) { var tx = txs[2]; - var signatures = helpers.clientSign(tx, TestData.copayers[0].xPrivKey_45H); + var signatures = helpers.clientSign(tx, TestData.copayers[0].xPrivKey); sinon.spy(server, 'emit'); server.signTx({ txProposalId: tx.id, @@ -2102,7 +2071,7 @@ describe('Copay server', function() { }); it('should allow creator to remove an signed TX by himself', function(done) { - var signatures = helpers.clientSign(txp, TestData.copayers[0].xPrivKey_45H); + var signatures = helpers.clientSign(txp, TestData.copayers[0].xPrivKey); server.signTx({ txProposalId: txp.id, signatures: signatures, @@ -2124,7 +2093,7 @@ describe('Copay server', function() { async.waterfall([ function(next) { - var signatures = helpers.clientSign(txp, TestData.copayers[0].xPrivKey_45H); + var signatures = helpers.clientSign(txp, TestData.copayers[0].xPrivKey); server.signTx({ txProposalId: txp.id, signatures: signatures, @@ -2188,7 +2157,7 @@ describe('Copay server', function() { it('should not allow creator copayer to remove an TX signed by other copayer', function(done) { helpers.getAuthServer(wallet.copayers[1].id, function(server2) { - var signatures = helpers.clientSign(txp, TestData.copayers[1].xPrivKey_45H); + var signatures = helpers.clientSign(txp, TestData.copayers[1].xPrivKey); server2.signTx({ txProposalId: txp.id, signatures: signatures, @@ -2325,7 +2294,7 @@ describe('Copay server', function() { should.not.exist(err); should.exist(tx); - var signatures = helpers.clientSign(tx, TestData.copayers[0].xPrivKey_45H); + var signatures = helpers.clientSign(tx, TestData.copayers[0].xPrivKey); server.signTx({ txProposalId: tx.id, signatures: signatures, diff --git a/test/models/txproposal.js b/test/models/txproposal.js index 119ab88..9b864f3 100644 --- a/test/models/txproposal.js +++ b/test/models/txproposal.js @@ -5,7 +5,7 @@ var chai = require('chai'); var sinon = require('sinon'); var should = chai.should(); var TXP = require('../../lib/model/txproposal'); -var Bitcore = require('bitcore'); +var Bitcore = require('bitcore-wallet-utils').Bitcore; describe('TXProposal', function() { @@ -22,6 +22,17 @@ describe('TXProposal', function() { var t = txp.getBitcoreTx(); should.exist(t); }); + it('should order ouputs as specified by outputOrder', function() { + var txp = TXP.fromObj(aTXP()); + + txp.outputOrder = [0, 1]; + var t = txp.getBitcoreTx(); + t.getChangeOutput().should.deep.equal(t.outputs[1]); + + txp.outputOrder = [1, 0]; + var t = txp.getBitcoreTx(); + t.getChangeOutput().should.deep.equal(t.outputs[0]); + }); }); @@ -108,6 +119,7 @@ var aTXP = function() { "requiredSignatures": 2, "requiredRejections": 1, "status": "pending", - "actions": [] + "actions": [], + "outputOrder": [0, 1], } };