mirror of https://github.com/BTCPrivate/copay.git
complete validation tests for txProposal SIGHASH
This commit is contained in:
parent
d7650f30ff
commit
b5c144d48c
|
@ -5,10 +5,11 @@ var imports = require('soop').imports();
|
||||||
var bitcore = require('bitcore');
|
var bitcore = require('bitcore');
|
||||||
var util = bitcore.util;
|
var util = bitcore.util;
|
||||||
var Transaction = bitcore.Transaction;
|
var Transaction = bitcore.Transaction;
|
||||||
var Builder = bitcore.TransactionBuilder;
|
|
||||||
var BuilderMockV0 = require('./BuilderMockV0');;
|
var BuilderMockV0 = require('./BuilderMockV0');;
|
||||||
|
var TransactionBuilder = bitcore.TransactionBuilder;
|
||||||
var Script = bitcore.Script;
|
var Script = bitcore.Script;
|
||||||
var buffertools = bitcore.buffertools;
|
var buffertools = bitcore.buffertools;
|
||||||
|
var preconditions = require('preconditions').instance();
|
||||||
|
|
||||||
function TxProposal(opts) {
|
function TxProposal(opts) {
|
||||||
this.creator = opts.creator;
|
this.creator = opts.creator;
|
||||||
|
@ -44,7 +45,7 @@ TxProposal.prototype.setSent = function(sentTxid) {
|
||||||
TxProposal.fromObj = function(o) {
|
TxProposal.fromObj = function(o) {
|
||||||
var t = new TxProposal(o);
|
var t = new TxProposal(o);
|
||||||
try {
|
try {
|
||||||
t.builder = new Builder.fromObj(o.builderObj);
|
t.builder = new TransactionBuilder.fromObj(o.builderObj);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (!o.version) {
|
if (!o.version) {
|
||||||
t.builder = new BuilderMockV0(o.builderObj);
|
t.builder = new BuilderMockV0(o.builderObj);
|
||||||
|
@ -54,6 +55,14 @@ TxProposal.fromObj = function(o) {
|
||||||
return t;
|
return t;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
TxProposal.prototype.isValid = function() {
|
||||||
|
if (this.builder.signhash !== Transaction.SIGHASH_ALL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
TxProposal.getSentTs = function() {
|
TxProposal.getSentTs = function() {
|
||||||
return this.sentTs;
|
return this.sentTs;
|
||||||
};
|
};
|
||||||
|
@ -218,7 +227,6 @@ TxProposals.prototype.merge = function(inTxp, author) {
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
var preconditions = require('preconditions').instance();
|
|
||||||
TxProposals.prototype.add = function(data) {
|
TxProposals.prototype.add = function(data) {
|
||||||
preconditions.checkArgument(data.inputChainPaths);
|
preconditions.checkArgument(data.inputChainPaths);
|
||||||
preconditions.checkArgument(data.signedBy);
|
preconditions.checkArgument(data.signedBy);
|
||||||
|
|
|
@ -125,6 +125,15 @@ Wallet.prototype._handleTxProposal = function(senderId, data) {
|
||||||
this.log('RECV TXPROPOSAL:', data);
|
this.log('RECV TXPROPOSAL:', data);
|
||||||
|
|
||||||
var inTxp = TxProposals.TxProposal.fromObj(data.txProposal);
|
var inTxp = TxProposals.TxProposal.fromObj(data.txProposal);
|
||||||
|
var valid = inTxp.isValid();
|
||||||
|
if (!valid) {
|
||||||
|
var corruptEvent = {
|
||||||
|
type: 'corrupt',
|
||||||
|
cId: inTxp.creator
|
||||||
|
};
|
||||||
|
this.emit('txProposalEvent', corruptEvent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
var mergeInfo = this.txProposals.merge(inTxp, senderId);
|
var mergeInfo = this.txProposals.merge(inTxp, senderId);
|
||||||
var added = this.addSeenToTxProposals();
|
var added = this.addSeenToTxProposals();
|
||||||
|
|
||||||
|
|
|
@ -149,15 +149,17 @@ angular.module('copayApp.services')
|
||||||
}, 3000);
|
}, 3000);
|
||||||
});
|
});
|
||||||
w.on('txProposalEvent', function(e) {
|
w.on('txProposalEvent', function(e) {
|
||||||
|
var user = w.publicKeyRing.nicknameForCopayer(e.cId);
|
||||||
switch (e.type) {
|
switch (e.type) {
|
||||||
case 'signed':
|
case 'signed':
|
||||||
var user = w.publicKeyRing.nicknameForCopayer(e.cId);
|
|
||||||
notification.info('Transaction Update', 'A transaction was signed by ' + user);
|
notification.info('Transaction Update', 'A transaction was signed by ' + user);
|
||||||
break;
|
break;
|
||||||
case 'rejected':
|
case 'rejected':
|
||||||
var user = w.publicKeyRing.nicknameForCopayer(e.cId);
|
|
||||||
notification.info('Transaction Update', 'A transaction was rejected by ' + user);
|
notification.info('Transaction Update', 'A transaction was rejected by ' + user);
|
||||||
break;
|
break;
|
||||||
|
case 'corrupt':
|
||||||
|
notification.error('Transaction Error', 'Received corrupt transaction from '+user);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
w.on('addressBookUpdated', function(dontDigest) {
|
w.on('addressBookUpdated', function(dontDigest) {
|
||||||
|
|
|
@ -16,6 +16,8 @@ var Network = require('./mocks/FakeNetwork');
|
||||||
var Blockchain = require('./mocks/FakeBlockchain');
|
var Blockchain = require('./mocks/FakeBlockchain');
|
||||||
var bitcore = bitcore || require('bitcore');
|
var bitcore = bitcore || require('bitcore');
|
||||||
var TransactionBuilder = bitcore.TransactionBuilder;
|
var TransactionBuilder = bitcore.TransactionBuilder;
|
||||||
|
var Transaction = bitcore.Transaction;
|
||||||
|
var Address = bitcore.Address;
|
||||||
|
|
||||||
var addCopayers = function(w) {
|
var addCopayers = function(w) {
|
||||||
for (var i = 0; i < 4; i++) {
|
for (var i = 0; i < 4; i++) {
|
||||||
|
@ -1011,4 +1013,75 @@ describe('Wallet model', function() {
|
||||||
copayConfig.forceNetwork = backup;
|
copayConfig.forceNetwork = backup;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('validate txProposals', function() {
|
||||||
|
var a1 = 'n1pKARYYUnZwxBuGj3y7WqVDu6VLN7n971';
|
||||||
|
var a2 = 'mtxYYJXZJmQc2iJRHQ4RZkfxU5K7TE2qMJ';
|
||||||
|
var utxos = [{
|
||||||
|
address: a1,
|
||||||
|
txid: '2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc1',
|
||||||
|
vout: 1,
|
||||||
|
scriptPubKey: Address.getScriptPubKeyFor(a1).serialize().toString('hex'),
|
||||||
|
amount: 0.5,
|
||||||
|
confirmations: 200
|
||||||
|
}, {
|
||||||
|
address: a2,
|
||||||
|
txid: '88c4520ffd97ea565578afe0b40919120be704b36561c71ba4e450e83cb3c9fd',
|
||||||
|
vout: 1,
|
||||||
|
scriptPubKey: Address.getScriptPubKeyFor(a2).serialize().toString('hex'),
|
||||||
|
amount: 0.5001,
|
||||||
|
confirmations: 200
|
||||||
|
}];
|
||||||
|
var destAddress = 'myuAQcCc1REUgXGsCTiYhZvPPc3XxZ36G1';
|
||||||
|
var outs = [{
|
||||||
|
address: destAddress,
|
||||||
|
amount: 1.0
|
||||||
|
}];
|
||||||
|
|
||||||
|
var testValidate = function(signhash, result, done) {
|
||||||
|
var w = cachedCreateW();
|
||||||
|
var spy = sinon.spy();
|
||||||
|
w.on('txProposalEvent', spy);
|
||||||
|
w.on('txProposalEvent', function(e) {
|
||||||
|
e.type.should.equal(result);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
var opts = {};
|
||||||
|
opts.signhash = signhash;
|
||||||
|
var txb = new TransactionBuilder(opts)
|
||||||
|
.setUnspent(utxos)
|
||||||
|
.setOutputs(outs)
|
||||||
|
.sign(['cVBtNonMyTydnS3NnZyipbduXo9KZfF1aUZ3uQHcvJB6UARZbiWG',
|
||||||
|
'cRVF68hhZp1PUQCdjr2k6aVYb2cn6uabbySDPBizAJ3PXF7vDXTL'
|
||||||
|
]);
|
||||||
|
var txp = {
|
||||||
|
'txProposal': {
|
||||||
|
'builderObj': txb.toObj()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
w._handleTxProposal('senderID', txp, true);
|
||||||
|
spy.callCount.should.equal(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
it('should validate for SIGHASH_ALL', function(done) {
|
||||||
|
var result = 'new';
|
||||||
|
var signhash = Transaction.SIGHASH_ALL;
|
||||||
|
testValidate(signhash, result, done);
|
||||||
|
});
|
||||||
|
it('should not validate for different SIGHASH_NONE', function(done) {
|
||||||
|
var result = 'corrupt';
|
||||||
|
var signhash = Transaction.SIGHASH_NONE;
|
||||||
|
testValidate(signhash, result, done);
|
||||||
|
});
|
||||||
|
it('should not validate for different SIGHASH_SINGLE', function(done) {
|
||||||
|
var result = 'corrupt';
|
||||||
|
var signhash = Transaction.SIGHASH_SINGLE;
|
||||||
|
testValidate(signhash, result, done);
|
||||||
|
});
|
||||||
|
it('should not validate for different SIGHASH_ANYONECANPAY', function(done) {
|
||||||
|
var result = 'corrupt';
|
||||||
|
var signhash = Transaction.SIGHASH_ANYONECANPAY;
|
||||||
|
testValidate(signhash, result, done);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue