add rebroadcast test

This commit is contained in:
Matias Alejo Garcia 2014-08-05 16:25:02 -03:00
commit 5a2dfe690d
5 changed files with 131 additions and 66 deletions

View file

@ -2,6 +2,7 @@
var imports = require('soop').imports();
var bitcore = require('bitcore');
var coinUtil = bitcore.util;
var preconditions = require('preconditions').singleton();
var http;
@ -39,9 +40,9 @@ function _asyncForEach(array, fn, callback) {
function removeRepeatedElements(ar) {
var ya = false,
v = "",
aux = [].concat(ar),
r = Array();
v = "",
aux = [].concat(ar),
r = Array();
for (var i in aux) { //
v = aux[i];
ya = false;
@ -78,6 +79,25 @@ Insight.prototype._getOptions = function(method, path, data) {
};
};
// This is vulneable to txid maneability
// TODO: if ret = false,
// check output address from similar transactions.
//
Insight.prototype.checkSentTx = function(tx, cb) {
var hash = coinUtil.formatHashFull(tx.getHash());
var options = this._getOptions('GET', '/api/tx/' + hash);
this._request(options, function(err, res) {
if (err) return cb(err);
var ret = false;
if (res && res.txid === hash) {
ret = hash;
}
return cb(err, ret);
});
};
Insight.prototype.getTransactions = function(addresses, cb) {
preconditions.shouldBeArray(addresses);
preconditions.shouldBeFunction(cb);
@ -164,8 +184,8 @@ Insight.prototype.checkActivity = function(addresses, cb) {
var getOutputs = function(t) {
return flatArray(
t.vout.map(function(vout) {
return vout.scriptPubKey.addresses;
})
return vout.scriptPubKey.addresses;
})
);
};

View file

@ -74,7 +74,7 @@ TxProposals.prototype.merge = function(inObj, builderOpts) {
} else {
// Create a new one
ret.new = 1;
ret.new = ret.hasChanged = 1;
this.txps[ntxid] = incomingTx;
}
@ -91,16 +91,16 @@ TxProposals.prototype.add = function(txp) {
};
TxProposals.prototype._getTxp = function(ntxid) {
TxProposals.prototype.get = function(ntxid) {
var ret = this.txps[ntxid];
if (!ret)
throw new Error('Could not find txp: '+ntxid);
throw new Error('Unknown TXP: '+ntxid);
return ret;
};
TxProposals.prototype.getTxProposal = function(ntxid, copayers) {
var txp = this._getTxp(ntxid);
var txp = this.get(ntxid);
var i = JSON.parse(JSON.stringify(txp));
i.builder = txp.builder;
@ -139,12 +139,12 @@ TxProposals.prototype.getTxProposal = function(ntxid, copayers) {
TxProposals.prototype.reject = function(ntxid, copayerId) {
var txp = this._getTxp(ntxid);
var txp = this.get(ntxid);
txp.setRejected(copayerId);
};
TxProposals.prototype.seen = function(ntxid, copayerId) {
var txp = this._getTxp(ntxid);
var txp = this.get(ntxid);
txp.setSeen(copayerId);
};

View file

@ -138,10 +138,10 @@ Wallet.prototype._processProposalEvents = function(senderId, m) {
type: 'new',
cid: senderId
}
} else if(m.newCopayer){
ev={
} else if (m.newCopayer) {
ev = {
type: 'signed',
cid: m.newCopayer
cid: m.newCopayer
};
}
} else {
@ -187,29 +187,54 @@ Wallet.prototype._getKeyMap = function(txp) {
};
Wallet.prototype._checkSentTx = function(ntxid, cb) {
var txp = this.txProposals.get(ntxid);
var tx = txp.builder.build();
this.blockchain.checkSentTx(tx, function(err, txid) {
var ret = false;
if (txid) {
txp.setSent(txid);
ret = txid;
}
return cb(ret);
});
};
Wallet.prototype._handleTxProposal = function(senderId, data) {
var self = this;
this.log('RECV TXPROPOSAL: ', data);
var m;
try {
m = this.txProposals.merge(data.txProposal, Wallet.builderOpts);
var keyMap = this._getKeyMap(m.txp);
ret.newCopayer = m.txp.setCopayers(senderId, keyMap);
m = this.txProposals.merge(data.txProposal, Wallet.builderOpts);
var keyMap = this._getKeyMap(m.txp);
ret.newCopayer = m.txp.setCopayers(senderId, keyMap);
} catch (e) {
this.log('Corrupt TX proposal received from:', senderId, e);
}
if (m) {
if (m.hasChanged) {
this.sendSeen(m.ntxid);
var tx = m.txp.builder.build();
if (tx.isComplete()) {
this._checkSentTx(m.ntxid, function(ret) {
if (ret) {
self.emit('txProposalsUpdated');
self.store();
}
});
} else {
this.sendTxProposal(m.ntxid);
}
}
this.emit('txProposalsUpdated');
this.store();
this.sendSeen(m.ntxid);
if (m.hasChanged)
this.sendTxProposal(m.ntxid);
}
this._processProposalEvents(senderId, m);
};
@ -218,7 +243,7 @@ Wallet.prototype._handleReject = function(senderId, data, isInbound) {
preconditions.checkState(data.ntxid);
this.log('RECV REJECT:', data);
var txp = this.txProposals.txps[data.ntxid];
var txp = this.txProposals.get(data.ntxid);
if (!txp)
throw new Error('Received Reject for an unknown TX from:' + senderId);
@ -241,11 +266,7 @@ Wallet.prototype._handleSeen = function(senderId, data, isInbound) {
preconditions.checkState(data.ntxid);
this.log('RECV SEEN:', data);
var txp = this.txProposals.txps[data.ntxid];
if (!txp)
throw new Error('Received Reject for an unknown TX from:' + senderId);
var txp = this.txProposals.get(data.ntxid);
txp.setSeen(senderId);
this.store();
this.emit('txProposalsUpdated');
@ -524,12 +545,11 @@ Wallet.prototype.sendAllTxProposals = function(recipients) {
Wallet.prototype.sendTxProposal = function(ntxid, recipients) {
preconditions.checkArgument(ntxid);
preconditions.checkState(this.txProposals.txps[ntxid]);
this.log('### SENDING txProposal ' + ntxid + ' TO:', recipients || 'All', this.txProposals);
this.send(recipients, {
type: 'txProposal',
txProposal: this.txProposals.txps[ntxid].toObjTrim(),
txProposal: this.txProposals.get(ntxid).toObjTrim(),
walletId: this.id,
});
};
@ -644,7 +664,7 @@ Wallet.prototype.getTxProposals = function() {
Wallet.prototype.reject = function(ntxid) {
var txp = this.txProposals.reject(ntxid, this.getMyCopayerId()) ;
var txp = this.txProposals.reject(ntxid, this.getMyCopayerId());
this.sendReject(ntxid);
this.store();
this.emit('txProposalsUpdated');
@ -655,7 +675,7 @@ Wallet.prototype.sign = function(ntxid, cb) {
var self = this;
setTimeout(function() {
var myId = self.getMyCopayerId();
var txp = self.txProposals.txps[ntxid];
var txp = self.txProposals.get(ntxid);
// if (!txp || txp.rejectedBy[myId] || txp.signedBy[myId]) {
// if (cb) cb(false);
// }
@ -678,14 +698,13 @@ Wallet.prototype.sign = function(ntxid, cb) {
}, 10);
};
Wallet.prototype.sendTx = function(ntxid, cb) {
var txp = this.txProposals.txps[ntxid];
if (!txp) return;
var txp = this.txProposals.get(ntxid);
var tx = txp.builder.build();
if (!tx.isComplete()) return;
if (!tx.isComplete())
throw new Error('Tx is not complete. Can not broadcast');
this.log('Broadcasting Transaction');
var scriptSig = tx.ins[0].getScript();
var size = scriptSig.serialize().length;
@ -696,28 +715,23 @@ Wallet.prototype.sendTx = function(ntxid, cb) {
this.blockchain.sendRawTransaction(txHex, function(txid) {
self.log('BITCOIND txid:', txid);
if (txid) {
self.txProposals.txps[ntxid].setSent(txid);
self.txProposals.get(ntxid).setSent(txid);
self.sendTxProposal(ntxid);
self.store();
return cb(txid);
} else {
self.log('Sent failed. Checking is the TX was sent already');
self._checkSentTx(ntxid, function(txid) {
console.log('[Wallet.js.730:txid:]', txid); //TODO
if (txid)
self.store();
return cb(txid);
});
}
return cb(txid);
});
};
// Wallet.prototype.addSeenToTxProposals = function() {
// var ret = false;
// var myId = this.getMyCopayerId();
//
// for (var k in this.txProposals.txps) {
// var txp = this.txProposals.txps[k];
// if (!txp.seenBy[myId]) {
//
// txp.seenBy[myId] = Date.now();
// ret = true;
// }
// }
// return ret;
// };
// TODO: remove this method and use getAddressesInfo everywhere
Wallet.prototype.getAddresses = function(opts) {
@ -840,7 +854,7 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, comment, utxos
preconditions.checkArgument(new Address(toAddress).network().name === this.getNetworkName(), 'networkname mismatch');
preconditions.checkState(pkr.isComplete(), 'pubkey ring incomplete');
preconditions.checkState(priv,'no private key');
preconditions.checkState(priv, 'no private key');
if (comment) preconditions.checkArgument(comment.length <= 100);
if (!opts.remainderOut) {

View file

@ -678,10 +678,10 @@ describe('Wallet model', function() {
w.blockchain.fixUnspent(utxo);
w.createTx(toAddress, amountSatStr, null, function(ntxid) {
var s = sinon.stub(w, 'getMyCopayerId').returns('213');
Object.keys(w.txProposals._getTxp(ntxid).rejectedBy).length.should.equal(0);
Object.keys(w.txProposals.get(ntxid).rejectedBy).length.should.equal(0);
w.reject(ntxid);
Object.keys(w.txProposals._getTxp(ntxid).rejectedBy).length.should.equal(1);
w.txProposals._getTxp(ntxid).rejectedBy['213'].should.gt(1);
Object.keys(w.txProposals.get(ntxid).rejectedBy).length.should.equal(1);
w.txProposals.get(ntxid).rejectedBy['213'].should.gt(1);
s.restore();
done();
});
@ -1169,7 +1169,7 @@ describe('Wallet model', function() {
w._handleReject(1, {
ntxid: 1
}, 1);
}).should.throw('unknown TX');
}).should.throw('Unknown TXP');
});
it('should fail to reject a signed tx', function() {
var w = cachedCreateW();
@ -1223,7 +1223,7 @@ describe('Wallet model', function() {
w._handleReject(1, {
ntxid: 1
}, 1);
}).should.throw('unknown TX');
}).should.throw('Unknown TXP');
});
it('should set seen a tx', function() {
var w = cachedCreateW();

View file

@ -82,9 +82,9 @@ describe('Insight model', function() {
sinon
.stub(http, 'request')
.returns(req)
.yields(request);
.stub(http, 'request')
.returns(req)
.yields(request);
i.getUnspent(['2MuD5LnZSViZZYwZbpVsagwrH8WWvCztdmV', '2NBSLoMvsHsf2Uv3LA17zV4beH6Gze6RovA'], function(e, ret) {
should.not.exist(e);
@ -113,9 +113,9 @@ describe('Insight model', function() {
req.end = function() {};
sinon
.stub(http, 'request')
.returns(req)
.yields(request);
.stub(http, 'request')
.returns(req)
.yields(request);
i.sendRawTransaction(rawtx, function(a) {
should.exist(a);
@ -200,5 +200,36 @@ describe('Insight model', function() {
});
});
describe("#checkSentTx", function() {
it('should return true if Tx is found', function(done) {
var w = new Insight();
w._request = sinon.stub().yields(null, {
txid: "414142",
});
var tx = function() {};
tx.prototype.getHash = function(){return new Buffer('BAA')};
w.checkSentTx(new tx(), function(err, ret) {
should.not.exist(err);
ret.should.equal('414142');
done();
});
});
it('should return false if Tx is not found', function(done) {
var w = new Insight();
w._request = sinon.stub().yields(null, {
txid: "414142",
});
var tx = function() {};
tx.prototype.getHash = function(){return new Buffer('ABC')};
w.checkSentTx(new tx(), function(err, ret) {
should.not.exist(err);
ret.should.equal(false);
done();
});
});
});
});