on reject / seen checks

This commit is contained in:
Matias Alejo Garcia 2014-11-25 16:41:56 -03:00
commit fb891d3f89
3 changed files with 99 additions and 86 deletions

View file

@ -197,7 +197,8 @@ Identity.prototype.storeWallet = function(wallet, cb) {
this.storage.setItem(key, val, function(err) { this.storage.setItem(key, val, function(err) {
if (err) { if (err) {
log.debug('Wallet:' + wallet.getName() + ' couldnt be stored:', err); log.error('Wallet:' + wallet.getName() + ' couldnt be stored:', err);
log.error('Wallet:' + wallet.getName() + ' Size:', JSON.stringify(wallet.sizes()));
} }
if (cb) if (cb)
return cb(err); return cb(err);

View file

@ -1,6 +1,5 @@
'use strict'; 'use strict';
var EventEmitter = require('events').EventEmitter;
var _ = require('lodash'); var _ = require('lodash');
var preconditions = require('preconditions').singleton(); var preconditions = require('preconditions').singleton();
var inherits = require('inherits'); var inherits = require('inherits');
@ -358,12 +357,9 @@ Wallet.prototype._processProposalEvents = function(senderId, m) {
type: 'signed', type: 'signed',
cId: m.newCopayer[0] cId: m.newCopayer[0]
}; };
} else {
log.error('unknown tx proposal event:', m)
} }
} else {
ev = {
type: 'corrupt',
cId: senderId
};
} }
if (ev) if (ev)
this.emitAndKeepAlive('txProposalEvent', ev); this.emitAndKeepAlive('txProposalEvent', ev);
@ -557,30 +553,33 @@ Wallet.prototype._onTxProposal = function(senderId, data) {
var m; var m;
try { try {
m = this.txProposals.merge(data.txProposal, Wallet.builderOpts); m = self.txProposals.merge(data.txProposal, Wallet.builderOpts);
var keyMap = this._getKeyMap(m.txp); var keyMap = self._getKeyMap(m.txp);
m.newCopayer = m.txp.setCopayers(senderId, keyMap); m.newCopayer = m.txp.setCopayers(senderId, keyMap);
} catch (e) { } catch (e) {
log.error('Corrupt TX proposal received from:', senderId, e.toString()); log.error('Corrupt TX proposal received from:', senderId, e.toString());
if (m && m.ntxid) if (m && m.ntxid)
this.txProposals.deleteOne(m.ntxid); self.txProposals.deleteOne(m.ntxid);
m = null; m = null;
} }
this._processIncomingTxProposal(m, function(err) { if (m) {
if (err) { self._processIncomingTxProposal(m, function(err) {
log.error('Corrupt TX proposal received from:', senderId, err.toString());
if (m && m.ntxid)
self.txProposals.deleteOne(m.ntxid);
m = null;
} else {
if (m && m.hasChanged)
self.sendTxProposal(m.ntxid);
}
self._processProposalEvents(senderId, m); if (err) {
}); log.error('Corrupt TX proposal received from:', senderId, err.toString());
if (m && m.ntxid)
self.txProposals.deleteOne(m.ntxid);
m = null;
} else {
if (m && m.hasChanged)
self.sendTxProposal(m.ntxid);
}
self._processProposalEvents(senderId, m);
});
}
}; };
/** /**
@ -597,20 +596,21 @@ Wallet.prototype._onReject = function(senderId, data) {
preconditions.checkState(data.ntxid); preconditions.checkState(data.ntxid);
log.debug('Wallet:' + this.id + ' RECV REJECT:', data); log.debug('Wallet:' + this.id + ' RECV REJECT:', data);
var txp = this.txProposals.get(data.ntxid); try {
var txp = this.txProposals.get(data.ntxid);
} catch (e) {};
if (!txp) if (txp) {
throw new Error('Received Reject for an unknown TX from:' + senderId); if (txp.signedBy[senderId])
throw new Error('Received Reject for an already signed TX from:' + senderId);
if (txp.signedBy[senderId]) txp.setRejected(senderId);
throw new Error('Received Reject for an already signed TX from:' + senderId); this.emitAndKeepAlive('txProposalEvent', {
type: 'rejected',
txp.setRejected(senderId); cId: senderId,
this.emitAndKeepAlive('txProposalEvent', { txId: data.ntxid
type: 'rejected', });
cId: senderId, }
txId: data.ntxid
});
}; };
/** /**
@ -625,14 +625,17 @@ Wallet.prototype._onReject = function(senderId, data) {
*/ */
Wallet.prototype._onSeen = function(senderId, data) { Wallet.prototype._onSeen = function(senderId, data) {
preconditions.checkState(data.ntxid); preconditions.checkState(data.ntxid);
var txp = this.txProposals.get(data.ntxid); try {
txp.setSeen(senderId); var txp = this.txProposals.get(data.ntxid);
this.emitAndKeepAlive('txProposalEvent', { } catch (e) {};
type: 'seen', if (txp) {
cId: senderId, txp.setSeen(senderId);
txId: data.ntxid this.emitAndKeepAlive('txProposalEvent', {
}); type: 'seen',
cId: senderId,
txId: data.ntxid
});
}
}; };
/** /**
@ -1083,6 +1086,23 @@ Wallet.prototype.toObj = function() {
return walletObj; return walletObj;
}; };
/**
* @desc: returns the sizes, by component, of a wallet, in bytes.
*
* @return {object} sizes by component name and 'total' for the total wallet size.
*/
Wallet.prototype.sizes = function() {
var obj = this.toObj();
var sizes = {},
total = 0;
_.each(obj, function(val, key) {
var s = JSON.stringify(val).length;
sizes[key] = s;
total += s;
});
sizes.total = total;
return sizes;
};
Wallet.fromUntrustedObj = function(obj, readOpts) { Wallet.fromUntrustedObj = function(obj, readOpts) {
obj = _.clone(obj); obj = _.clone(obj);
@ -1638,33 +1658,33 @@ Wallet.prototype.fetchPaymentRequest = function(options, cb) {
if (self.paymentRequestsCache[options.url]) if (self.paymentRequestsCache[options.url])
return cb(null, self.paymentRequestsCache[options.url]); return cb(null, self.paymentRequestsCache[options.url]);
this.httpUtil.request({ this.httpUtil.request({
method: 'GET', method: 'GET',
url: options.url, url: options.url,
headers: { headers: {
'Accept': PayPro.PAYMENT_REQUEST_CONTENT_TYPE 'Accept': PayPro.PAYMENT_REQUEST_CONTENT_TYPE
}, },
responseType: 'arraybuffer' responseType: 'arraybuffer'
})
.success(function(rawData) {
log.info('PayPro Request done successfully. Parsing response')
var merchantData, err;
try {
merchantData = self.parsePaymentRequest(options, rawData);
} catch (e) {
err = e
};
log.debug('PayPro request data', merchantData);
self.paymentRequestsCache[options.url] = merchantData;
return cb(err, merchantData);
}) })
.error(function(data, status) { .success(function(rawData) {
log.debug('Server did not return PaymentRequest.\nXHR status: ' + status); log.info('PayPro Request done successfully. Parsing response')
return cb(new Error('Status: ' + status));
}); var merchantData, err;
try {
merchantData = self.parsePaymentRequest(options, rawData);
} catch (e) {
err = e
};
log.debug('PayPro request data', merchantData);
self.paymentRequestsCache[options.url] = merchantData;
return cb(err, merchantData);
})
.error(function(data, status) {
log.debug('Server did not return PaymentRequest.\nXHR status: ' + status);
return cb(new Error('Status: ' + status));
});
}; };
@ -2232,7 +2252,7 @@ Wallet.prototype.spend = function(opts, cb) {
log.debug('TXP Added: ', ntxid); log.debug('TXP Added: ', ntxid);
console.log('[Wallet.js.2233]'); //TODO console.log('[Wallet.js.2233]'); //TODO
self.sendIndexes(); self.sendIndexes();
// Needs only one signature? Broadcast it! // Needs only one signature? Broadcast it!
if (!self.requiresMultipleSignatures()) { if (!self.requiresMultipleSignatures()) {
@ -2573,8 +2593,8 @@ Wallet.prototype.getTransactionHistory = function(opts, cb) {
var proposals = self.getTxProposals(); var proposals = self.getTxProposals();
var satToUnit = 1 / self.settings.unitToSatoshi; var satToUnit = 1 / self.settings.unitToSatoshi;
var indexedProposals = _.indexBy(proposal,'sentTxid'); var indexedProposals = _.indexBy(proposals, 'sentTxid');
function extractInsOuts(tx) { function extractInsOuts(tx) {
// Inputs // Inputs

View file

@ -1674,15 +1674,12 @@ describe('Wallet model', function() {
}); });
it('should handle corrupt tx', function(done) { it('should handle corrupt tx', function() {
w.txProposals.merge = sinon.stub().throws(new Error('test error')); w.txProposals.merge = sinon.stub().throws(new Error('test error'));
w.on('txProposalEvent', function(e) { sinon.stub(w, 'on');
e.type.should.equal('corrupt');
w.txProposals.deleteOne.calledOnce.should.equal(false);
done();
});
w._onTxProposal('senderID', data); w._onTxProposal('senderID', data);
w.on.called.should.equal(false);
}); });
it('should call _processIncomingTxProposal', function(done) { it('should call _processIncomingTxProposal', function(done) {
@ -1705,19 +1702,14 @@ describe('Wallet model', function() {
w._onTxProposal('senderID', data); w._onTxProposal('senderID', data);
}); });
it('should handle corrupt tx, case2', function(done) { it('should handle corrupt tx, case2', function() {
sinon.stub(w.txProposals, 'merge').returns({ sinon.stub(w.txProposals, 'merge').returns({
ntxid: '1' ntxid: '1'
}); });
sinon.stub(w, 'on');
sinon.stub(w, '_getKeyMap').throws(new Error('test error')); sinon.stub(w, '_getKeyMap').throws(new Error('test error'));
w.on('txProposalEvent', function(e) {
e.type.should.equal('corrupt');
w.txProposals.deleteOne.calledWith('1').should.equal(true);
w._getKeyMap.restore();
done();
});
w._onTxProposal('senderID', data); w._onTxProposal('senderID', data);
w.on.called.should.equal(false);
}); });
}); });