Merge pull request #712 from maraoz/txp/protocol/security2

Improve tx proposal protocol security
This commit is contained in:
Ryan X. Charles 2014-06-23 15:18:56 -07:00
commit 0d54875bf2
5 changed files with 86 additions and 54 deletions

View file

@ -3,6 +3,7 @@
var imports = require('soop').imports();
var preconditions = require('preconditions').instance();
var bitcore = require('bitcore');
var HK = bitcore.HierarchicalKey;
var PrivateKey = require('./PrivateKey');
@ -62,6 +63,7 @@ PublicKeyRing.prototype.toObj = function() {
};
PublicKeyRing.prototype.getCopayerId = function(i) {
preconditions.checkArgument(typeof i !== 'undefined');
return this.copayerIds[i];
};

View file

@ -51,9 +51,9 @@ TxProposal.getSentTs = function() {
return this.sentTs;
};
TxProposal.prototype.merge = function(other) {
TxProposal.prototype.merge = function(other, author) {
var ret = {};
ret.events = this.mergeMetadata(other);
ret.events = this.mergeMetadata(other, author);
ret.hasChanged = this.mergeBuilder(other);
return ret;
};
@ -69,7 +69,7 @@ TxProposal.prototype.mergeBuilder = function(other) {
return after !== before;
};
TxProposal.prototype.mergeMetadata = function(v1) {
TxProposal.prototype.mergeMetadata = function(v1, author) {
var events = [];
var v0 = this;
@ -77,6 +77,7 @@ TxProposal.prototype.mergeMetadata = function(v1) {
Object.keys(v1.seenBy).forEach(function(k) {
if (!v0.seenBy[k]) {
if (k != author) throw new Error('Non authoritative seenBy change by '+author);
v0.seenBy[k] = v1.seenBy[k];
events.push({
type: 'seen',
@ -88,6 +89,7 @@ TxProposal.prototype.mergeMetadata = function(v1) {
Object.keys(v1.signedBy).forEach(function(k) {
if (!v0.signedBy[k]) {
if (k != author) throw new Error('Non authoritative signedBy change by '+author);
v0.signedBy[k] = v1.signedBy[k];
events.push({
type: 'signed',
@ -99,6 +101,7 @@ TxProposal.prototype.mergeMetadata = function(v1) {
Object.keys(v1.rejectedBy).forEach(function(k) {
if (!v0.rejectedBy[k]) {
if (k != author) throw new Error('Non authoritative rejectedBy change by '+author);
v0.rejectedBy[k] = v1.rejectedBy[k];
events.push({
type: 'rejected',
@ -168,7 +171,7 @@ TxProposals.prototype.toObj = function(onlyThisNtxid) {
};
};
TxProposals.prototype.merge = function(inTxp) {
TxProposals.prototype.merge = function(inTxp, author) {
var myTxps = this.txps;
var ntxid = inTxp.getID();
@ -179,7 +182,7 @@ TxProposals.prototype.merge = function(inTxp) {
if (myTxps[ntxid]) {
var v0 = myTxps[ntxid];
var v1 = inTxp;
ret = v0.merge(v1);
ret = v0.merge(v1, author);
} else {
this.txps[ntxid] = inTxp;
ret.hasChanged = true;
@ -192,7 +195,13 @@ TxProposals.prototype.merge = function(inTxp) {
return ret;
};
var preconditions = require('preconditions').instance();
TxProposals.prototype.add = function(data) {
preconditions.checkArgument(data.inputChainPaths);
preconditions.checkArgument(data.signedBy);
preconditions.checkArgument(data.creator);
preconditions.checkArgument(data.createdTs);
preconditions.checkArgument(data.builder);
var txp = new TxProposal(data);
var ntxid = txp.getID();
this.txps[ntxid] = txp;

View file

@ -118,13 +118,18 @@ Wallet.prototype._handlePublicKeyRing = function(senderId, data, isInbound) {
Wallet.prototype._handleTxProposal = function(senderId, data) {
preconditions.checkArgument(senderId);
this.log('RECV TXPROPOSAL:', data);
var inTxp = TxProposals.TxProposal.fromObj(data.txProposal);
var mergeInfo = this.txProposals.merge(inTxp);
var mergeInfo = this.txProposals.merge(inTxp, senderId);
var added = this.addSeenToTxProposals();
if (added) {
this.log('### BROADCASTING txProposals with my seenBy updated.');
this.sendTxProposal(inTxp.getID());
}
this.emit('txProposalsUpdated');
this.store();
@ -499,6 +504,7 @@ Wallet.prototype.reject = function(ntxid) {
Wallet.prototype.sign = function(ntxid, cb) {
preconditions.checkState(typeof this.getMyCopayerId() !== 'undefined');
var self = this;
setTimeout(function() {
var myId = self.getMyCopayerId();
@ -711,7 +717,6 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, comment, utxos
}]);
var selectedUtxos = b.getSelectedUnspent();
var inputChainPaths = selectedUtxos.map(function(utxo) {
return pkr.pathForAddress(utxo.address);
});