add paypro checks

This commit is contained in:
Matias Alejo Garcia 2014-11-21 11:06:47 -03:00
commit 32f281fb82
5 changed files with 222 additions and 352 deletions

View file

@ -788,132 +788,6 @@ describe('PayPro (in Wallet) model', function() {
});
});
it('#try to sign a tampered payment request (raw)', function(done) {
var w = createWallet();
should.exist(w);
var address = 'bitcoin:2NBzZdFBoQymDgfzH2Pmnthser1E71MmU47?amount=0.00003&r=' + server.uri + '/request';
var commentText = 'Hello, server. I\'d like to make a payment.';
w.createPaymentTx({
uri: address,
memo: commentText
}, function(err, ntxid, merchantData) {
should.equal(err, null);
should.exist(ntxid);
should.exist(merchantData);
// Tamper with payment request in its raw form:
var data = new Buffer(merchantData.raw, 'hex');
data = PayPro.PaymentRequest.decode(data);
var pr = new PayPro();
pr = pr.makePaymentRequest(data);
var details = pr.get('serialized_payment_details');
details = PayPro.PaymentDetails.decode(details);
var pd = new PayPro();
pd = pd.makePaymentDetails(details);
var outputs = pd.get('outputs');
outputs[outputs.length - 1].set('amount', 1000000000);
pd.set('outputs', outputs);
pr.set('serialized_payment_details', pd.serialize());
merchantData.raw = pr.serialize().toString('hex');
var myId = w.getMyCopayerId();
var txp = w.txProposals.get(ntxid);
should.exist(txp);
should.exist(txp.signedBy[myId]);
should.not.exist(txp.rejectedBy[myId]);
w.verifyPaymentRequest(ntxid).should.equal(false);
return done();
});
});
it('#try to sign a tampered payment request (abstract)', function(done) {
var w = createWallet();
should.exist(w);
var address = 'bitcoin:2NBzZdFBoQymDgfzH2Pmnthser1E71MmU47?amount=0.00003&r=' + server.uri + '/request';
var commentText = 'Hello, server. I\'d like to make a payment.';
w.createPaymentTx({
uri: address,
memo: commentText
}, function(err, ntxid, merchantData) {
should.equal(err, null);
should.exist(ntxid);
should.exist(merchantData);
// Tamper with payment request in its abstract form:
var outputs = merchantData.pr.pd.outputs;
var output = outputs[outputs.length - 1];
var amount = output.amount;
amount.low = 2;
var myId = w.getMyCopayerId();
var txp = w.txProposals.get(ntxid);
should.exist(txp);
should.exist(txp.signedBy[myId]);
should.not.exist(txp.rejectedBy[myId]);
w.verifyPaymentRequest(ntxid).should.equal(false);
return done();
});
});
it('#try to sign a tampered txp tx (abstract)', function(done) {
var w = createWallet();
should.exist(w);
var address = 'bitcoin:2NBzZdFBoQymDgfzH2Pmnthser1E71MmU47?amount=0.00003&r=' + server.uri + '/request';
var commentText = 'Hello, server. I\'d like to make a payment.';
w.createPaymentTx({
uri: address,
memo: commentText
}, function(err, ntxid, merchantData) {
should.equal(err, null);
should.exist(ntxid);
should.exist(merchantData);
// Tamper with payment request in its abstract form:
var txp = w.txProposals.get(ntxid);
var tx = txp.builder.tx || txp.builder.build();
tx.outs[0].v = new Buffer([2, 0, 0, 0, 0, 0, 0, 0]);
var myId = w.getMyCopayerId();
var txp = w.txProposals.get(ntxid);
should.exist(txp);
should.exist(txp.signedBy[myId]);
should.not.exist(txp.rejectedBy[myId]);
w.verifyPaymentRequest(ntxid).should.equal(false);
return done();
});
});
it('#sign an untampered payment request', function(done) {
var w = createWallet();
should.exist(w);
var address = 'bitcoin:2NBzZdFBoQymDgfzH2Pmnthser1E71MmU47?amount=0.00003&r=' + server.uri + '/request';
var commentText = 'Hello, server. I\'d like to make a payment.';
w.createPaymentTx({
uri: address,
memo: commentText
}, function(err, ntxid, merchantData) {
should.equal(err, null);
should.exist(ntxid);
should.exist(merchantData);
var myId = w.getMyCopayerId();
var txp = w.txProposals.get(ntxid);
should.exist(txp);
should.exist(txp.signedBy[myId]);
should.not.exist(txp.rejectedBy[myId]);
w.verifyPaymentRequest(ntxid).should.equal(true);
return done();
});
});
it('#close payment server', function(done) {
server.close(function() {
return done();

View file

@ -11,12 +11,12 @@ var networks = bitcore.networks;
var FakeBuilder = requireMock('FakeBuilder');
var TxProposal = copay.TxProposal;
var dummyProposal = new TxProposal({
creator: 1,
var dummyProposal = function() { return new TxProposal({
creator: 'creator',
createdTs: 1,
builder: new FakeBuilder(),
inputChainPaths: ['m/1'],
});
})};
var someKeys = ["03b39d61dc9a504b13ae480049c140dcffa23a6cc9c09d12d6d1f332fee5e18ca5", "022929f515c5cf967474322468c3bd945bb6f281225b2c884b465680ef3052c07e"];
@ -208,8 +208,8 @@ describe('TxProposal', function() {
});
it('#_verifyScriptSig, two signatures', function() {
// Data taken from bitcore's TransactionBuilder test
var txp = dummyProposal;
var tx = dummyProposal.builder.build();
var txp = dummyProposal();
var tx = dummyProposal().builder.build();
var ret = TxProposal._verifySignatures(pubkeys, validScriptSig, tx.hashForSignature());
ret.should.deep.equal(['03197599f6e209cefef07da2fddc6fe47715a70162c531ffff8e611cef23dfb70d', '03a94351fecc4328bb683bf93a1aa67378374904eac5980c7966723a51897c56e3']);
});
@ -223,13 +223,13 @@ describe('TxProposal', function() {
Buffer.isBuffer(info.script.getBuffer()).should.equal(true);
});
it('#_updateSignedBy', function() {
var txp = dummyProposal;
var txp = dummyProposal();
txp._inputSigners.should.deep.equal([
['03197599f6e209cefef07da2fddc6fe47715a70162c531ffff8e611cef23dfb70d', '03a94351fecc4328bb683bf93a1aa67378374904eac5980c7966723a51897c56e3']
]);
});
describe('#_check', function() {
var txp = dummyProposal;
var txp = dummyProposal();
var backup = txp.builder.tx.ins;
it('OK', function() {
@ -272,8 +272,96 @@ describe('TxProposal', function() {
txp.builder.tx.ins[0].s = backup;
});
});
describe('#_checkPayPro', function() {
var txp, md;
beforeEach(function() {
txp = dummyProposal();
txp.paymentProtocolURL = '123';
md = {
request_url: '123',
pr: {
pd: {
expires: 123,
memo: 'memo',
},
},
total: '1230',
outs: [{
address: '2NDJbzwzsmRgD2o5HHXPhuq5g6tkKTjYkd6',
amountSatStr: "123"
}],
expires: 92345678900,
};
});
it('OK no merchant data', function() {
txp._checkPayPro();
});
it('OK merchant data', function() {
txp.addMerchantData(md);
});
it('NOK URL', function() {
txp.paymentProtocolURL = '1234';
(function() {
txp.addMerchantData(md);
}).should.throw('Mismatch');
});
it('NOK OUTS', function() {
md.outs = [];
(function() {
txp.addMerchantData(md);
}).should.throw('outputs');
});
it('NOK OUTS (case 2)', function() {
md.outs = [{}, {}];
(function() {
txp.addMerchantData(md);
}).should.throw('outputs');
});
it('NOK OUTS (case 3)', function() {
md.outs = [{}, {}];
(function() {
txp.addMerchantData(md);
}).should.throw('outputs');
});
it('NOK Amount', function() {
md.total = undefined;
(function() {
txp.addMerchantData(md);
}).should.throw('amount');
});
it('NOK Outs case 4', function() {
md.outs[0].address = 'aaa';
(function() {
txp.addMerchantData(md);
}).should.throw('address');
});
it('NOK Outs case 5', function() {
md.outs[0].amountSatStr = '432';
(function() {
txp.addMerchantData(md);
}).should.throw('amount');
});
it('NOK Expired', function() {
md.expires = 1;
(function() {
txp.addMerchantData(md);
}).should.throw('expired');
});
it('OK Expired but sent', function() {
md.expires = 2;
txp.sentTs = 1;
txp.addMerchantData(md);
});
});
describe('#merge', function() {
var txp = dummyProposal;
var txp = dummyProposal();
var backup = txp.builder.tx.ins;
it('with self', function() {
var hasChanged = txp.merge(txp);
@ -307,7 +395,7 @@ describe('TxProposal', function() {
});
describe('#setCopayers', function() {
it("should fails if Tx has no creator", function() {
var txp = dummyProposal;
var txp = dummyProposal();
txp.signedBy = {
'hugo': 1
};
@ -319,7 +407,7 @@ describe('TxProposal', function() {
}).should.throw('no creator');
});
it("should fails if Tx is not signed by creator", function() {
var txp = dummyProposal;
var txp = dummyProposal();
txp.creator = 'creator';
txp.signedBy = {
'hugo': 1
@ -336,7 +424,7 @@ describe('TxProposal', function() {
it("should fails if Tx has unmapped signatures", function() {
var txp = dummyProposal;
var txp = dummyProposal();
txp.creator = 'creator';
txp.signedBy = {
creator: 1
@ -353,7 +441,7 @@ describe('TxProposal', function() {
// This was disabled. Unnecessary to check this.
it.skip("should be signed by sender", function() {
var txp = dummyProposal;
var txp = dummyProposal();
var ts = Date.now();
txp._inputSigners = [
['pk1', 'pk0']
@ -372,7 +460,7 @@ describe('TxProposal', function() {
it("should set signedBy (trivial case)", function() {
var txp = dummyProposal;
var txp = dummyProposal();
var ts = Date.now();
txp._inputSigners = [
['pk1', 'pk0']
@ -390,7 +478,7 @@ describe('TxProposal', function() {
txp.signedBy['creator'].should.gte(ts);
});
it("should assign creator", function() {
var txp = dummyProposal;
var txp = dummyProposal();
var ts = Date.now();
txp._inputSigners = [
['pk0']
@ -409,7 +497,7 @@ describe('TxProposal', function() {
txp.seenBy['creator'].should.equal(txp.createdTs);
})
it("New tx should have only 1 signature", function() {
var txp = dummyProposal;
var txp = dummyProposal();
var ts = Date.now();
txp.signedBy = {};
delete txp['creator'];
@ -431,7 +519,7 @@ describe('TxProposal', function() {
})
it("if signed, should not change ts", function() {
var txp = dummyProposal;
var txp = dummyProposal();
var ts = Date.now();
txp._inputSigners = [
['pk0', 'pk1']
@ -456,25 +544,25 @@ describe('TxProposal', function() {
describe('micelaneous functions', function() {
it('should report rejectCount', function() {
var txp = dummyProposal;
var txp = dummyProposal();
txp.rejectCount().should.equal(0);
txp.setRejected(['juan'])
txp.rejectCount().should.equal(1);
});
it('should report isPending 1', function() {
var txp = dummyProposal;
var txp = dummyProposal();
txp.rejectedBy = [];
txp.sentTxid = 1;
txp.isPending(3).should.equal(false);
});
it('should report isPending 2', function() {
var txp = dummyProposal;
var txp = dummyProposal();
txp.rejectedBy = [];
txp.sentTxid = null;
txp.isPending(3).should.equal(true);
});
it('should report isPending 3', function() {
var txp = dummyProposal;
var txp = dummyProposal();
txp.rejectedBy = [1, 2, 3, 4];
txp.sentTxid = null;
txp.isPending(3).should.equal(false);

View file

@ -2,10 +2,12 @@
var bitcore = bitcore || require('bitcore');
var Script = bitcore.Script;
var VALID_SCRIPTSIG_BUF = new Buffer('0048304502200708a381dde585ef7fdfaeaeb5da9b451d3e22b01eac8a5e3d03b959e24a7478022100c90e76e423523a54a9e9c43858337ebcef1a539a7fc685c2698dd8648fcf1b9101473044022030a77c9613d6ee010717c1abc494668d877e3fa0ae4c520f65cc3b308754c98c02205219d387bcb291bd44805b9468439e4168b02a6a180cdbcc24d84d71d696c1ae014cad532103197599f6e209cefef07da2fddc6fe47715a70162c531ffff8e611cef23dfb70d210380a29968851f93af55e581c43d9ef9294577a439a3ca9fc2bc47d1ca2b3e9127210392dccb2ed470a45984811d6402fdca613c175f8f3e4eb8e2306e8ccd7d0aed032103a94351fecc4328bb683bf93a1aa67378374904eac5980c7966723a51897c56e32103e085eb6fa1f20b2722c16161144314070a2c316a9cae2489fd52ce5f63fff6e455ae','hex');
var VALID_SCRIPTSIG_BUF = new Buffer('0048304502200708a381dde585ef7fdfaeaeb5da9b451d3e22b01eac8a5e3d03b959e24a7478022100c90e76e423523a54a9e9c43858337ebcef1a539a7fc685c2698dd8648fcf1b9101473044022030a77c9613d6ee010717c1abc494668d877e3fa0ae4c520f65cc3b308754c98c02205219d387bcb291bd44805b9468439e4168b02a6a180cdbcc24d84d71d696c1ae014cad532103197599f6e209cefef07da2fddc6fe47715a70162c531ffff8e611cef23dfb70d210380a29968851f93af55e581c43d9ef9294577a439a3ca9fc2bc47d1ca2b3e9127210392dccb2ed470a45984811d6402fdca613c175f8f3e4eb8e2306e8ccd7d0aed032103a94351fecc4328bb683bf93a1aa67378374904eac5980c7966723a51897c56e32103e085eb6fa1f20b2722c16161144314070a2c316a9cae2489fd52ce5f63fff6e455ae', 'hex');
function Tx() {
this.ins = [{s: VALID_SCRIPTSIG_BUF }];
this.ins = [{
s: VALID_SCRIPTSIG_BUF
}];
};
Tx.prototype.getHashType = function() {
@ -23,26 +25,32 @@ function FakeBuilder() {
this.test = 1;
this.tx = new Tx();
this.signhash = 1;
this.inputMap = [{ address: '2NDJbzwzsmRgD2o5HHXPhuq5g6tkKTjYkd6',
this.inputMap = [{
address: '2NDJbzwzsmRgD2o5HHXPhuq5g6tkKTjYkd6',
scriptPubKey: new Script(new Buffer('a914dc0623476aefb049066b09b0147a022e6eb8429187', 'hex')),
scriptType: 4,
i: 0 }];
i: 0
}];
this.vanilla = {
scriptSig: [VALID_SCRIPTSIG_BUF],
}
this.vanilla = {
scriptSig: [VALID_SCRIPTSIG_BUF],
outs: [{
address: '2NDJbzwzsmRgD2o5HHXPhuq5g6tkKTjYkd6',
amountSatStr: '123',
}]
}
}
FakeBuilder.prototype.merge = function() {
};
FakeBuilder.prototype.merge = function() {};
FakeBuilder.prototype.build = function() {
FakeBuilder.prototype.build = function() {
return this.tx;
};
FakeBuilder.prototype.toObj = function() {
FakeBuilder.prototype.toObj = function() {
return this;
};
FakeBuilder.VALID_SCRIPTSIG_BUF = VALID_SCRIPTSIG_BUF;