add rebroadcast test
This commit is contained in:
parent
91829f8410
commit
5a2dfe690d
5 changed files with 131 additions and 66 deletions
|
|
@ -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;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue