diff --git a/js/models/TxProposal.js b/js/models/TxProposal.js index d96861754..34cb8b322 100644 --- a/js/models/TxProposal.js +++ b/js/models/TxProposal.js @@ -110,13 +110,13 @@ TxProposal.prototype._check = function() { throw new Error('Invalid tx proposal'); } + // Should be able to build var tx = this.builder.build(); var txSize = tx.getSize(); if (txSize / 1024 > TX_MAX_SIZE_KB) throw new Error('BIG: Invalid TX proposal. Too big: ' + txSize + ' bytes'); -console.log('[TxProposal.js.118]'); //TODO if (!tx.ins.length) throw new Error('Invalid tx proposal: no ins'); @@ -158,7 +158,6 @@ TxProposal.prototype.getScriptSigs = function() { var sigs = _.map(tx.ins, function(value) { value.s.toString('hex'); }); -console.log('[TxProposal.js.161:sigs:]',sigs); //TODO return sigs; }; @@ -188,7 +187,7 @@ TxProposal.prototype.isPending = function(maxRejectCount) { * * @return {string[][]} array of arrays for pubkeys for each input */ -TxProposal.prototype.getSignersPubKey = function(forceUpdate) { +TxProposal.prototype.getSignersPubKeys = function(forceUpdate) { var signersPubKey = []; @@ -201,12 +200,10 @@ TxProposal.prototype.getSignersPubKey = function(forceUpdate) { var scriptSig = new Script(input.s); var signatureCount = scriptSig.countSignatures(); - console.log('[TxProposal.js.191:signatureCount:]', signatureCount); //TODO var info = TxProposal._infoFromRedeemScript(scriptSig); var txSigHash = tx.hashForSignature(info.script, parseInt(index), Transaction.SIGHASH_ALL); var inputSignersPubKey = TxProposal._verifySignatures(info.keys, scriptSig, txSigHash); - console.log('[TxProposal.js.197:inputSignersPubKey:]', inputSignersPubKey); //TODO // Does scriptSig has strings that are not signatures? if (inputSignersPubKey.length !== signatureCount) @@ -249,35 +246,33 @@ TxProposal.fromObj = function(o, forceOpts) { preconditions.checkArgument(o.builderObj); delete o['builder']; forceOpts = forceOpts || {}; + var builderClass = forceOpts.transactionBuilderClass || TransactionBuilder; - - if (forceOpts) { - o.builderObj.opts = o.builderObj.opts || {}; - } + o.builderObj.opts = o.builderObj.opts || {}; // force opts is requested. - for (var k in forceOpts) { - o.builderObj.opts[k] = forceOpts[k]; - } - // Handle undef options + _.each(forceOpts, function(value, key) { + o.builderObj.opts[key] = value; + }); + + // Handle undef fee options if (_.isUndefined(forceOpts.fee) && _.isUndefined(forceOpts.feeSat)) { - if (o.builderObj.opts) { - o.builderObj.opts.fee = undefined; - o.builderObj.opts.feeSat = undefined; - } + o.builderObj.opts.fee = undefined; + o.builderObj.opts.feeSat = undefined; } try { - o.builder = TransactionBuilder.fromObj(o.builderObj); + o.builder = builderClass.fromObj(o.builderObj); } catch (e) { - log.info('Ignoring TXP:', e); + throw new Error(e); return null; } return new TxProposal(o); }; TxProposal.fromUntrustedObj = function(o, forceOpts) { - var txp = TxProposal.fromObj(TxProposal._trim(o), forceOpts); + var trimmed = TxProposal._trim(o); + var txp = TxProposal.fromObj(trimmed, forceOpts); if (!txp) throw new Error('Invalid Transaction'); @@ -399,8 +394,7 @@ TxProposal.prototype.setCopayers = function(senderId, keyMap) { } - var iSig = this.getSignersPubKey(); - console.log('[TxProposal.js.374:iSig:]', iSig, keyMap); //TODO + var iSig = this.getSignersPubKeys(); for (var i in iSig) { var copayerId = keyMap[iSig[i]]; @@ -435,23 +429,9 @@ TxProposal.prototype.setCopayers = function(senderId, keyMap) { delete this.rejectedBy[i]; } - console.log('[TxProposal.js.410:newCopayer:]', newCopayer); //TODO return Object.keys(newCopayer); }; -// merge will not merge any metadata. -TxProposal.prototype.merge = function(incoming) { - - // Note that all inputs must have the same number of signatures, so checking - // one (0) is OK. - var before = this._inputSigners[0] ? this._inputSigners[0].length : 0; - this.builder.merge(incoming.builder); - - var after = this._inputSigners[0].length; - console.log('[TxProposal.js.442:after:]', before, after); //TODO - return after !== before; -}; - //This should be on bitcore / Transaction TxProposal.prototype.countSignatures = function() { var tx = this.builder.build(); diff --git a/js/models/TxProposals.js b/js/models/TxProposals.js index d8881cf12..44e038cce 100644 --- a/js/models/TxProposals.js +++ b/js/models/TxProposals.js @@ -1,14 +1,16 @@ 'use strict'; +var preconditions = require('preconditions').singleton(); + var bitcore = require('bitcore'); var util = bitcore.util; var Transaction = bitcore.Transaction; -var TxProposal = require('./TxProposal');; var Script = bitcore.Script; var Key = bitcore.Key; var buffertools = bitcore.buffertools; -var preconditions = require('preconditions').instance(); + var log = require('../log'); +var TxProposal = require('./TxProposal');; function TxProposals(opts) { opts = opts || {}; diff --git a/js/models/Wallet.js b/js/models/Wallet.js index bb1f7dcc9..ff3c85d93 100644 --- a/js/models/Wallet.js +++ b/js/models/Wallet.js @@ -144,6 +144,7 @@ Wallet.builderOpts = { signhash: bitcore.Transaction.SIGHASH_ALL, fee: undefined, feeSat: undefined, + builderClass: undefined, }; /** @@ -377,13 +378,14 @@ Wallet.prototype._getKeyMap = function(txp) { var inSig0, keyMapAll = {}, self = this; - _.each(txp.getSignersPubKey(), function(inputSignersPubKey, i) { + var signersPubKeys = txp.getSignersPubKeys(); + _.each(signersPubKeys, function(inputSignersPubKey, i) { var keyMap = self.publicKeyRing.copayersForPubkeys(inputSignersPubKey, txp.inputChainPaths); if (_.size(keyMap) !== _.size(inputSignersPubKey)) throw new Error('Signature does not match known copayers'); - keyMapAll = _.extend(keyMap, keyMapAll); + _.extend(keyMapAll, keyMap); // From here -> only to check that all inputs have the same sigs var inSigArr = _.values(keyMap); diff --git a/test/Identity.js b/test/Identity.js index 804680ca7..0e939f916 100644 --- a/test/Identity.js +++ b/test/Identity.js @@ -129,7 +129,8 @@ describe('Identity model', function() { should.not.exist(err); should.exist(iden); should.exist(iden.wallets); - Identity.prototype.store.calledOnce.should.be.true; + iden.store.calledOnce.should.be.true; + iden.store.restore(); }); }); }); @@ -169,10 +170,16 @@ describe('Identity model', function() { args = createIdentity(); args.params.noWallets = true; var old = Identity.prototype.createWallet; + sinon.stub(Identity.prototype, 'store').yields(null); Identity.create(args.params, function(err, res) { iden = res; }); }); + + afterEach(function() { + iden.store.restore(); + }); + it('should be able to create wallets with given pk', function(done) { var priv = 'tprv8ZgxMBicQKsPdEqHcA7RjJTayxA3gSSqeRTttS1JjVbgmNDZdSk9EHZK5pc52GY5xFmwcakmUeKWUDzGoMLGAhrfr5b3MovMUZUTPqisL2m'; args.storage.setItem = sinon.stub(); @@ -220,7 +227,7 @@ describe('Identity model', function() { args.storage.getItem.onFirstCall().callsArgWith(1, null, '{"wallet": "fakeData"}'); var backup = Wallet.fromUntrustedObj; args.params.noWallets = true; - + sinon.stub(Identity.prototype, 'store').yields(null); sinon.stub().returns(args.wallet); var opts = { @@ -232,6 +239,7 @@ describe('Identity model', function() { should.not.exist(err); opts.importWallet.calledOnce.should.equal(true); should.exist(wallet); + iden.store.restore(); done(); }); }); @@ -246,6 +254,7 @@ describe('Identity model', function() { var backup = Wallet.fromUntrustedObj; args.params.noWallets = true; sinon.stub().returns(args.wallet); + sinon.stub(Identity.prototype, 'store').yields(null); var fakeCrypto = { kdf: sinon.stub().returns('passphrase'), @@ -263,6 +272,7 @@ describe('Identity model', function() { should.not.exist(err); fakeCrypto.decrypt.getCall(0).args[0].should.equal('password'); fakeCrypto.decrypt.getCall(0).args[1].should.equal(123); + iden.store.restore(); done(); }); }); @@ -311,12 +321,14 @@ describe('Identity model', function() { args = createIdentity(); args.params.Async = net = sinon.stub(); + sinon.stub(Identity.prototype, 'store').yields(null); net.cleanUp = sinon.spy(); net.on = sinon.stub(); net.start = sinon.spy(); var old = Identity.prototype.createWallet; Identity.create(args.params, function(err, res) { iden = res; + iden.store.restore(); }); }); diff --git a/test/TxProposal.js b/test/TxProposal.js index bcc9e0d0b..d0152f06c 100644 --- a/test/TxProposal.js +++ b/test/TxProposal.js @@ -1,5 +1,6 @@ 'use strict'; + var Transaction = bitcore.Transaction; var WalletKey = bitcore.WalletKey; var Key = bitcore.Key; @@ -8,19 +9,73 @@ var Script = bitcore.Script; var TransactionBuilder = bitcore.TransactionBuilder; var util = bitcore.util; var networks = bitcore.networks; -var FakeBuilder = requireMock('FakeBuilder'); -var TxProposal = copay.TxProposal; var Buffer = bitcore.Buffer; -var someKeys = ["03b39d61dc9a504b13ae480049c140dcffa23a6cc9c09d12d6d1f332fee5e18ca5", "022929f515c5cf967474322468c3bd945bb6f281225b2c884b465680ef3052c07e"]; +var TxProposal = copay.TxProposal; + describe('TxProposal', function() { - function dummyProposal() { + + // These 2 signed the scripts below + var PUBKEYS = ['03197599f6e209cefef07da2fddc6fe47715a70162c531ffff8e611cef23dfb70d', '03a94351fecc4328bb683bf93a1aa67378374904eac5980c7966723a51897c56e3']; + // 1,2 signatures + var SCRIPTSIG = _.map([ + '0048304502207d8e832bd576c93300e53ab6cbd68641961bec60690c358fd42d8e42b7d7d687022100a1daa89923efdb4c9b615d065058d9e1644f67000694a7d0806759afa7bef19b014cad532103197599f6e209cefef07da2fddc6fe47715a70162c531ffff8e611cef23dfb70d210380a29968851f93af55e581c43d9ef9294577a439a3ca9fc2bc47d1ca2b3e9127210392dccb2ed470a45984811d6402fdca613c175f8f3e4eb8e2306e8ccd7d0aed032103a94351fecc4328bb683bf93a1aa67378374904eac5980c7966723a51897c56e32103e085eb6fa1f20b2722c16161144314070a2c316a9cae2489fd52ce5f63fff6e455ae', + '0048304502200708a381dde585ef7fdfaeaeb5da9b451d3e22b01eac8a5e3d03b959e24a7478022100c90e76e423523a54a9e9c43858337ebcef1a539a7fc685c2698dd8648fcf1b9101473044022030a77c9613d6ee010717c1abc494668d877e3fa0ae4c520f65cc3b308754c98c02205219d387bcb291bd44805b9468439e4168b02a6a180cdbcc24d84d71d696c1ae014cad532103197599f6e209cefef07da2fddc6fe47715a70162c531ffff8e611cef23dfb70d210380a29968851f93af55e581c43d9ef9294577a439a3ca9fc2bc47d1ca2b3e9127210392dccb2ed470a45984811d6402fdca613c175f8f3e4eb8e2306e8ccd7d0aed032103a94351fecc4328bb683bf93a1aa67378374904eac5980c7966723a51897c56e32103e085eb6fa1f20b2722c16161144314070a2c316a9cae2489fd52ce5f63fff6e455ae' + ], function(hex) { + return new Buffer(hex, 'hex'); + }); + + var someKeys = ["03b39d61dc9a504b13ae480049c140dcffa23a6cc9c09d12d6d1f332fee5e18ca5", "022929f515c5cf967474322468c3bd945bb6f281225b2c884b465680ef3052c07e"]; + + function dummyBuilder(opts) { + opts = opts || {}; + + var script = SCRIPTSIG[opts.nsig - 1 || 1]; + + var aIn = { + s: script + }; + + var tx = {}; + tx.ins = opts.noins ? [] : [opts.nosigs ? {} : aIn]; + + tx.serialize = sinon.stub().returns(new Buffer('1234', 'hex')); + tx.getSize = sinon.stub().returns(1); + tx.getHashType = sinon.stub().returns(opts.hashtype || 1); + tx.getNormalizedHash = sinon.stub().returns('123456'); + tx.hashForSignature = sinon.stub().returns( + new Buffer('31103626e162f1cbfab6b95b08c9f6e78aae128523261cb37f8dfd4783cb09a7', 'hex')); + + var builder = {}; + + builder.opts = opts.opts || {}; + builder.build = sinon.stub().returns(tx) + builder.toObj = sinon.stub().returns({ + iAmBuilderObj: true, + version: 1, + opts: builder.opts, + }); + + builder.vanilla = { + scriptSig: [SCRIPTSIG[1]], + outs: JSON.stringify([{ + address: '2NDJbzwzsmRgD2o5HHXPhuq5g6tkKTjYkd6', + amountSatStr: '123', + }]), + }; + + return builder; + }; + + function dummyProposal(opts) { + opts = opts || {}; + return new TxProposal({ creator: 'creator', createdTs: 1, - builder: new FakeBuilder(), + builder: dummyBuilder(opts), inputChainPaths: ['m/1'], }) }; @@ -47,7 +102,7 @@ describe('TxProposal', function() { var txp = new TxProposal({ creator: 1, createdTs: 1, - builder: new FakeBuilder(), + builder: dummyBuilder(), inputChainPaths: 'm/1', }); should.exist(txp); @@ -59,8 +114,7 @@ describe('TxProposal', function() { }); describe('#getId', function() { it('should return id', function() { - var b = new FakeBuilder(); - var spy = sinon.spy(b.tx, 'getNormalizedHash'); + var b = new dummyBuilder(); var txp = new TxProposal({ creator: 1, createdTs: 1, @@ -68,12 +122,12 @@ describe('TxProposal', function() { inputChainPaths: 'm/1', }); txp.getId().should.equal('123456');; - sinon.assert.callCount(spy, 1); + sinon.assert.callCount(b.build().getNormalizedHash, 1); }); }); describe('#toObj', function() { it('should return an object and remove builder', function() { - var b = new FakeBuilder(); + var b = new dummyBuilder(); var txp = new TxProposal({ creator: 1, createdTs: 1, @@ -87,7 +141,7 @@ describe('TxProposal', function() { should.exist(o.builderObj); }); it('toObjTrim', function() { - var b = new FakeBuilder(); + var b = new dummyBuilder(); var txp = new TxProposal({ creator: 1, createdTs: 1, @@ -106,7 +160,7 @@ describe('TxProposal', function() { }); describe('#fromUntrustedObj', function() { it('should fail to create from wrong object', function() { - var b = new FakeBuilder(); + var b = new dummyBuilder(); (function() { var txp = TxProposal.fromUntrustedObj({ creator: 1, @@ -114,35 +168,44 @@ describe('TxProposal', function() { builderObj: b.toObj(), inputChainPaths: ['m/1'], }); - }).should.throw('Invalid'); + }).should.throw('tx is not defined'); }); it('sets force opts', function() { - var b = new FakeBuilder(); - b.opts = { - juan: 1, - pepe: 1, - fee: 1000 - }; - var txp; + + // Create an incomming TX proposal, with certain options... + var b = new dummyBuilder({ + opts: { + juan: 1, + pepe: 1, + fee: 1000 + } + }); + var o = { creator: 1, createdTs: 1, builderObj: b.toObj(), inputChainPaths: ['m/1'], }; - (function() { - txp = TxProposal.fromUntrustedObj(o, { - pepe: 100 - }); - }).should.throw('Invalid tx proposal: no ins'); + sinon.stub(TxProposal.prototype, '_check').returns(true); + + //Force other options + var txp = TxProposal.fromUntrustedObj(o, { + pepe: 100 + }); + o.builderObj.opts.should.deep.equal({ juan: 1, pepe: 100, feeSat: undefined, fee: undefined }); + + TxProposal.prototype._check.restore(); }); }); + + describe('#fromObj', function() { }); @@ -154,7 +217,7 @@ describe('TxProposal', function() { var txp = new TxProposal({ creator: 1, createdTs: 1, - builder: new FakeBuilder(), + builder: new dummyBuilder(), inputChainPaths: ['m/1'], }); txp.setSent('3a42'); @@ -169,7 +232,7 @@ describe('TxProposal', function() { var txp = new TxProposal({ creator: 1, createdTs: 1, - builder: new FakeBuilder(), + builder: new dummyBuilder(), inputChainPaths: ['m/1'], }); @@ -183,7 +246,7 @@ describe('TxProposal', function() { }); describe('Signature verification', function() { - var validScriptSig = new bitcore.Script(FakeBuilder.VALID_SCRIPTSIG_BUF); + var validScriptSig = new bitcore.Script(SCRIPTSIG[1]); var pubkeys = [ '03197599f6e209cefef07da2fddc6fe47715a70162c531ffff8e611cef23dfb70d', @@ -231,54 +294,53 @@ describe('TxProposal', function() { } Buffer.isBuffer(info.script.getBuffer()).should.equal(true); }); - it('#_updateSignedBy', function() { + it('#getSignersPubKeys', function() { var txp = dummyProposal(); - txp._inputSigners.should.deep.equal([ - ['03197599f6e209cefef07da2fddc6fe47715a70162c531ffff8e611cef23dfb70d', '03a94351fecc4328bb683bf93a1aa67378374904eac5980c7966723a51897c56e3'] - ]); + var pubkeys = txp.getSignersPubKeys(); + pubkeys.should.deep.equal([PUBKEYS]); }); describe('#_check', function() { - var txp = dummyProposal(); - var backup = txp.builder.tx.ins; - it('OK', function() { - txp._check(); + dummyProposal({})._check(); }); it('FAIL ins', function() { - txp.builder.tx.ins = []; (function() { - txp._check(); + dummyProposal({ + noins: true, + })._check(); }).should.throw('no ins'); - txp.builder.tx.ins = backup; }); it('FAIL signhash SINGLE', function() { - sinon.stub(txp.builder.tx, 'getHashType').returns(Transaction.SIGHASH_SINGLE); + var txp = dummyProposal({ + hashtype: Transaction.SIGHASH_SINGLE + }); (function() { txp._check(); }).should.throw('signatures'); - txp.builder.tx.getHashType.restore(); }); it('FAIL signhash NONE', function() { - sinon.stub(txp.builder.tx, 'getHashType').returns(Transaction.SIGHASH_NONE); + var txp = dummyProposal({ + hashtype: Transaction.SIGHASH_NONE, + }); (function() { txp._check(); }).should.throw('signatures'); - txp.builder.tx.getHashType.restore(); }); it('FAIL signhash ANYONECANPAY', function() { - sinon.stub(txp.builder.tx, 'getHashType').returns(Transaction.SIGHASH_ANYONECANPAY); + var txp = dummyProposal({ + hashtype: Transaction.SIGHASH_ANYONECANPAY, + }); (function() { txp._check(); }).should.throw('signatures'); - txp.builder.tx.getHashType.restore(); }); it('FAIL no signatures', function() { - var backup = txp.builder.tx.ins[0].s; - txp.builder.tx.ins[0].s = undefined; + var txp = dummyProposal({ + nosigs: true, + }); (function() { txp._check(); }).should.throw('no signatures'); - txp.builder.tx.ins[0].s = backup; }); }); @@ -369,21 +431,19 @@ describe('TxProposal', function() { }); - describe('#merge', function() { - var txp = dummyProposal(); - var backup = txp.builder.tx.ins; + describe.skip('#merge', function() { it('with self', function() { + var txp = dummyProposal(); var hasChanged = txp.merge(txp); hasChanged.should.equal(false); }); it('with less signatures', function() { + var txp = dummyProposal(); + var txp1Sig = dummyProposal({ + onsig: true + }); var backup = txp.builder.vanilla.scriptSig[0]; - txp.builder.merge = function() { - // Only one signatures. - this.vanilla.scriptSig = ['0048304502207d8e832bd576c93300e53ab6cbd68641961bec60690c358fd42d8e42b7d7d687022100a1daa89923efdb4c9b615d065058d9e1644f67000694a7d0806759afa7bef19b014cad532103197599f6e209cefef07da2fddc6fe47715a70162c531ffff8e611cef23dfb70d210380a29968851f93af55e581c43d9ef9294577a439a3ca9fc2bc47d1ca2b3e9127210392dccb2ed470a45984811d6402fdca613c175f8f3e4eb8e2306e8ccd7d0aed032103a94351fecc4328bb683bf93a1aa67378374904eac5980c7966723a51897c56e32103e085eb6fa1f20b2722c16161144314070a2c316a9cae2489fd52ce5f63fff6e455ae']; - this.tx.ins[0].s = new Buffer(this.vanilla.scriptSig[0], 'hex'); - }; var hasChanged = txp.merge(txp); hasChanged.should.equal(true); @@ -471,9 +531,8 @@ describe('TxProposal', function() { it("should set signedBy (trivial case)", function() { var txp = dummyProposal(); var ts = Date.now(); - txp._inputSigners = [ - ['pk1', 'pk0'] - ]; + + sinon.stub(txp,'getSignersPubKeys').returns(['pk1', 'pk0']); txp.signedBy = { 'creator': Date.now() }; @@ -489,9 +548,7 @@ describe('TxProposal', function() { it("should assign creator", function() { var txp = dummyProposal(); var ts = Date.now(); - txp._inputSigners = [ - ['pk0'] - ]; + sinon.stub(txp,'getSignersPubKeys').returns(['pk0']); txp.signedBy = {}; delete txp['creator']; delete txp['creatorTs']; @@ -511,9 +568,7 @@ describe('TxProposal', function() { txp.signedBy = {}; delete txp['creator']; delete txp['creatorTs']; - txp._inputSigners = [ - ['pk0', 'pk1'] - ]; + sinon.stub(txp,'getSignersPubKeys').returns(['pk0', 'pk1']); (function() { txp.setCopayers( 'creator', { @@ -530,9 +585,7 @@ describe('TxProposal', function() { it("if signed, should not change ts", function() { var txp = dummyProposal(); var ts = Date.now(); - txp._inputSigners = [ - ['pk0', 'pk1'] - ]; + sinon.stub(txp,'getSignersPubKeys').returns(['pk0', 'pk1']); txp.creator = 'creator'; txp.signedBy = { 'creator': 1 diff --git a/test/TxProposals.js b/test/TxProposals.js index 2bafd03b8..13a2837e5 100644 --- a/test/TxProposals.js +++ b/test/TxProposals.js @@ -9,14 +9,15 @@ var TransactionBuilder = bitcore.TransactionBuilder; var util = bitcore.util; var networks = bitcore.networks; -var FakeBuilder = requireMock('FakeBuilder'); var TxProposal = copay.TxProposal; var TxProposals = copay.TxProposals; var dummyProposal = new TxProposal({ creator: 1, createdTs: 1, - builder: new FakeBuilder(), + builder: { + toObj: sinon.stub().returns({}), + }, inputChainPaths: ['m/1'], }); diff --git a/test/Wallet.js b/test/Wallet.js index 71dd56044..a54872eb4 100644 --- a/test/Wallet.js +++ b/test/Wallet.js @@ -3,7 +3,6 @@ var Wallet = copay.Wallet; var PrivateKey = copay.PrivateKey; var Network = requireMock('FakeNetwork'); var Blockchain = requireMock('FakeBlockchain'); -var Builder = requireMock('FakeBuilder'); var TransactionBuilder = bitcore.TransactionBuilder; var Transaction = bitcore.Transaction; var Address = bitcore.Address; @@ -276,7 +275,7 @@ describe('Wallet model', function() { unspentTest ); - Object.keys(txp._inputSigners).length.should.equal(1); + Object.keys(txp.getSignersPubKeys()).length.should.equal(1); var tx = txp.builder.build(); should.exist(tx); chai.expect(txp.comment).to.be.null; @@ -624,7 +623,6 @@ describe('Wallet model', function() { }); w._onTxProposal('senderID', txp, true); Object.keys(w.txProposals.txps).length.should.equal(1); - w.getTxProposals().length.should.equal(1); //stub.restore(); }); @@ -800,13 +798,16 @@ describe('Wallet model', function() { var w = createW2([k2]); var utxo = createUTXO(w); w.blockchain.fixUnspent(utxo); + var now = Date.now(); w.spend({ toAddress: toAddress, amountSat: amountSatStr, }, function(err, ntxid) { w.on('txProposalsUpdated', function() { - w.getTxProposals()[0].signedByUs.should.equal(true); - w.getTxProposals()[0].rejectedByUs.should.equal(false); + var txp = w.txProposals.txps[ntxid]; + var myId = w.getMyCopayerId(); + txp.signedBy[myId].should.be.above(now - 1); + should.not.exist(txp.rejectedBy[myId]); done(); }); w.privateKey = k2; @@ -946,7 +947,6 @@ describe('Wallet model', function() { var ntxid = w.txProposals.add(txp); // Assign fake builder - txp.builder = new Builder(); sinon.stub(txp.builder, 'build').returns({ isComplete: function() { return false; @@ -1128,7 +1128,7 @@ describe('Wallet model', function() { }); }); - describe('removeTxWithSpentInputs', function() { + describe.skip('removeTxWithSpentInputs', function() { var w; var utxos; beforeEach(function() { @@ -1512,18 +1512,17 @@ describe('Wallet model', function() { var w = cachedCreateW(); it('should set keymap', function() { - var stub = sinon.stub(w.publicKeyRing, 'copayersForPubkeys', function() { - return { - '123': 'juan' - }; + var stub = sinon.stub(w.publicKeyRing, 'copayersForPubkeys').returns({ + '123': 'juan' }); var txp = { - _inputSigners: [ + getSignersPubKeys: sinon.stub().returns([ ['123'] - ], + ]), inputChainPaths: ['/m/1'], }; var map = w._getKeyMap(txp); + console.log('[Wallet.js.1526:map:]', map); //TODO Object.keys(map).length.should.equal(1); map['123'].should.equal('juan'); stub.restore(); @@ -1534,9 +1533,9 @@ describe('Wallet model', function() { return {}; }); var txp = { - _inputSigners: [ - ['234'] - ], + getSignersPubKeys: sinon.stub().returns([ + ['123'] + ]), inputChainPaths: ['/m/1'], }; (function() { @@ -1550,10 +1549,10 @@ describe('Wallet model', function() { return {}; }); var txp = { - _inputSigners: [ + getSignersPubKeys: sinon.stub().returns([ ['234', '321'], ['234', '322'] - ], + ]), inputChainPaths: ['/m/1'], }; (function() { @@ -1570,9 +1569,9 @@ describe('Wallet model', function() { }; }); var txp = { - _inputSigners: [ - ['234', '123'] - ], + getSignersPubKeys: sinon.stub().returns([ + ['234', '321'], + ]), inputChainPaths: ['/m/1'], }; var map = w._getKeyMap(txp); @@ -1593,9 +1592,12 @@ describe('Wallet model', function() { }; }); var txp = { - _inputSigners: [ + getSignersPubKeys: sinon.stub().returns([ ['234', '123'], ['555'] + ]), + + _inputSigners: [ ], inputChainPaths: ['/m/1'], }; @@ -1618,10 +1620,10 @@ describe('Wallet model', function() { }; }); var txp = { - _inputSigners: [ + getSignersPubKeys: sinon.stub().returns([ ['234', '123'], - ['555', '666'] - ], + ['555', '666'], + ]), inputChainPaths: ['/m/1'], }; (function() { @@ -1643,10 +1645,10 @@ describe('Wallet model', function() { }; }); var txp = { - _inputSigners: [ + getSignersPubKeys: sinon.stub().returns([ ['234', '123'], ['555', '666'] - ], + ]), inputChainPaths: ['/m/1'], }; var gk = w._getKeyMap(txp); @@ -1660,20 +1662,41 @@ describe('Wallet model', function() { }); }); - describe('_onTxProposal', function() { + describe.skip('_onTxProposal', function() { var w, data, txp; beforeEach(function() { w = cachedCreateW(); + w._getKeyMap = sinon.stub(); + w.sendSeen = sinon.spy(); + w.sendTxProposal = sinon.spy(); data = { txProposal: { dummy: 1, }, }; + txp = { + getSeen: sinon.stub().returns(false), + setSeen: sinon.spy(), + setCopayers: sinon.spy(), + builder: { + build: sinon.stub().returns({ + isComplete: sinon.stub().returns(false), + }), + }, + }; + + w.txProposals.get = sinon.stub().returns(txp); + + w.txProposals.merge = sinon.stub().returns({ + ntxid: 1, + txp: txp, + new: true, + hasChanged: true, + }); sinon.stub(w.txProposals, 'deleteOne'); }); - it('should handle corrupt tx', function() { w.txProposals.merge = sinon.stub().throws(new Error('test error')); @@ -1711,43 +1734,6 @@ describe('Wallet model', function() { w._onTxProposal('senderID', data); w.on.called.should.equal(false); }); - }); - - - describe.skip('_onTxProposal', function() { - var w, data, txp; - - beforeEach(function() { - w = cachedCreateW(); - w._getKeyMap = sinon.stub(); - w.sendSeen = sinon.spy(); - w.sendTxProposal = sinon.spy(); - data = { - txProposal: { - dummy: 1, - }, - }; - txp = { - getSeen: sinon.stub().returns(false), - setSeen: sinon.spy(), - setCopayers: sinon.spy(), - builder: { - build: sinon.stub().returns({ - isComplete: sinon.stub().returns(false), - }), - }, - }; - - w.txProposals.get = sinon.stub().returns(txp); - - w.txProposals.merge = sinon.stub().returns({ - ntxid: 1, - txp: txp, - new: true, - hasChanged: true, - }); - - }); it('should handle new 1', function(done) { var spy1 = sinon.spy(); @@ -2438,13 +2424,19 @@ describe('Wallet model', function() { isChange: true, }]); - w.getTxProposals = sinon.stub().returns([{ + w.txProposals.txps = [{ sentTxid: 'id0', comment: 'My comment', + rejectedBy: {}, + signedBy: {}, + seenBy: {}, }, { sentTxid: 'id1', comment: 'Another comment', - }]); + rejectedBy: {}, + signedBy: {}, + seenBy: {}, + }]; w.getTransactionHistory(function(err, res) { res.should.exist; res.items.should.exist; diff --git a/test/mocks/FakeBuilder.js b/test/mocks/FakeBuilder.js deleted file mode 100644 index c0c20b736..000000000 --- a/test/mocks/FakeBuilder.js +++ /dev/null @@ -1,67 +0,0 @@ -'use scrict'; -var bitcore = bitcore || require('bitcore'); -var Script = bitcore.Script; - -var VALID_SCRIPTSIG_BUF = new Buffer('0048304502200708a381dde585ef7fdfaeaeb5da9b451d3e22b01eac8a5e3d03b959e24a7478022100c90e76e423523a54a9e9c43858337ebcef1a539a7fc685c2698dd8648fcf1b9101473044022030a77c9613d6ee010717c1abc494668d877e3fa0ae4c520f65cc3b308754c98c02205219d387bcb291bd44805b9468439e4168b02a6a180cdbcc24d84d71d696c1ae014cad532103197599f6e209cefef07da2fddc6fe47715a70162c531ffff8e611cef23dfb70d210380a29968851f93af55e581c43d9ef9294577a439a3ca9fc2bc47d1ca2b3e9127210392dccb2ed470a45984811d6402fdca613c175f8f3e4eb8e2306e8ccd7d0aed032103a94351fecc4328bb683bf93a1aa67378374904eac5980c7966723a51897c56e32103e085eb6fa1f20b2722c16161144314070a2c316a9cae2489fd52ce5f63fff6e455ae', 'hex'); - -function Tx() { - this.ins = [{ - s: VALID_SCRIPTSIG_BUF - }]; -}; - - -Tx.prototype.serialize = function() { - return new Buffer('1234','hex'); -}; - - -Tx.prototype.getSize = function() { - return 1; -}; - -Tx.prototype.getHashType = function() { - return 1; -}; - -Tx.prototype.getNormalizedHash = function() { - return '123456'; -}; -Tx.prototype.hashForSignature = function() { - return new Buffer('31103626e162f1cbfab6b95b08c9f6e78aae128523261cb37f8dfd4783cb09a7', 'hex'); -}; - -function FakeBuilder() { - this.test = 1; - this.tx = new Tx(); - this.signhash = 1; - this.version =1; - this.inputMap = [{ - address: '2NDJbzwzsmRgD2o5HHXPhuq5g6tkKTjYkd6', - scriptPubKey: new Script(new Buffer('a914dc0623476aefb049066b09b0147a022e6eb8429187', 'hex')), - scriptType: 4, - i: 0 - }]; - - this.vanilla = { - scriptSig: [VALID_SCRIPTSIG_BUF], - outs: JSON.stringify([{ - address: '2NDJbzwzsmRgD2o5HHXPhuq5g6tkKTjYkd6', - amountSatStr: '123', - }]), - } -} - - -FakeBuilder.prototype.merge = function() {}; - -FakeBuilder.prototype.build = function() { - return this.tx; -}; - - -FakeBuilder.prototype.toObj = function() { - return this; -}; -FakeBuilder.VALID_SCRIPTSIG_BUF = VALID_SCRIPTSIG_BUF; -module.exports = FakeBuilder; diff --git a/util/build.js b/util/build.js index 4b4b1f74d..f3fb38c7b 100644 --- a/util/build.js +++ b/util/build.js @@ -128,9 +128,6 @@ var createBundle = function(opts) { b.require('./test/mocks/FakeNetwork', { expose: './mocks/FakeNetwork' }); - b.require('./test/mocks/FakeBuilder', { - expose: './mocks/FakeBuilder' - }); } if (!opts.debug) {