check available utxos when sending temporary txp
This commit is contained in:
parent
30c8072b8b
commit
8ef05c8841
|
@ -26,6 +26,7 @@ var errors = {
|
|||
TX_NOT_ACCEPTED: 'The transaction proposal is not accepted',
|
||||
TX_NOT_FOUND: 'Transaction proposal not found',
|
||||
TX_NOT_PENDING: 'The transaction proposal is not pending',
|
||||
UNAVAILABLE_UTXOS: 'Unavailable unspent outputs',
|
||||
UPGRADE_NEEDED: 'Client app needs to be upgraded',
|
||||
WALLET_ALREADY_EXISTS: 'Wallet already exists',
|
||||
WALLET_FULL: 'Wallet full',
|
||||
|
|
|
@ -1436,6 +1436,10 @@ WalletService.prototype.createTx2 = function(opts, cb) {
|
|||
WalletService.prototype.sendTx = function(opts, cb) {
|
||||
var self = this;
|
||||
|
||||
function utxoKey(utxo) {
|
||||
return utxo.txid + '|' + utxo.vout
|
||||
};
|
||||
|
||||
if (!Utils.checkRequired(opts, ['txProposalId', 'proposalSignature', 'proposalSignaturePubKey', 'proposalSignaturePubKeySig']))
|
||||
return cb(new ClientError('Required argument missing'));
|
||||
|
||||
|
@ -1445,6 +1449,18 @@ WalletService.prototype.sendTx = function(opts, cb) {
|
|||
if (!txp) return cb(Errors.TX_NOT_FOUND);
|
||||
if (!txp.isTemporary()) return cb();
|
||||
|
||||
// Verify UTXOs are still available
|
||||
self.getUtxos({}, function(err, utxos) {
|
||||
if (err) return cb(err);
|
||||
|
||||
var txpInputs = _.map(txp.inputs, utxoKey);
|
||||
var lockedUtxoIndex = _.indexBy(_.filter(utxos, 'locked'), utxoKey);
|
||||
var unavailable = _.any(txpInputs, function(i) {
|
||||
return lockedUtxoIndex[i];
|
||||
});
|
||||
|
||||
if (unavailable) return cb(Errors.UNAVAILABLE_UTXOS);
|
||||
|
||||
txp.status = 'pending';
|
||||
self.storage.storeTx(self.walletId, txp, function(err) {
|
||||
if (err) return cb(err);
|
||||
|
@ -1452,6 +1468,7 @@ WalletService.prototype.sendTx = function(opts, cb) {
|
|||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -2409,6 +2409,84 @@ describe('Wallet service', function() {
|
|||
});
|
||||
});
|
||||
});
|
||||
it('should fail to send a temporary tx proposal if utxos are unavailable', function(done) {
|
||||
var txp1, txp2;
|
||||
var txOpts = helpers.createProposalOpts2([{
|
||||
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
|
||||
amount: 0.8
|
||||
}], {
|
||||
message: 'some message',
|
||||
});
|
||||
|
||||
async.waterfall([
|
||||
|
||||
function(next) {
|
||||
helpers.stubUtxos(server, wallet, [1, 2], function() {
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
server.createTx2(txOpts, next);
|
||||
},
|
||||
function(txp, next) {
|
||||
txp1 = txp;
|
||||
server.createTx2(txOpts, next);
|
||||
},
|
||||
function(txp, next) {
|
||||
txp2 = txp;
|
||||
should.exist(txp1);
|
||||
should.exist(txp2);
|
||||
server.sendTx({
|
||||
txProposalId: txp1.id,
|
||||
proposalSignature: 'dummy',
|
||||
proposalSignaturePubKey: 'dummy',
|
||||
proposalSignaturePubKeySig: 'dummy',
|
||||
}, next);
|
||||
},
|
||||
function(next) {
|
||||
server.sendTx({
|
||||
txProposalId: txp2.id,
|
||||
proposalSignature: 'dummy',
|
||||
proposalSignaturePubKey: 'dummy',
|
||||
proposalSignaturePubKeySig: 'dummy',
|
||||
}, function(err) {
|
||||
should.exist(err);
|
||||
err.code.should.equal('UNAVAILABLE_UTXOS');
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
server.getPendingTxs({}, function(err, txs) {
|
||||
should.not.exist(err);
|
||||
txs.length.should.equal(1);
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
// A new tx proposal should use the next available UTXO
|
||||
server.createTx2(txOpts, next);
|
||||
},
|
||||
function(txp3, next) {
|
||||
should.exist(txp3);
|
||||
server.sendTx({
|
||||
txProposalId: txp3.id,
|
||||
proposalSignature: 'dummy',
|
||||
proposalSignaturePubKey: 'dummy',
|
||||
proposalSignaturePubKeySig: 'dummy',
|
||||
}, next);
|
||||
},
|
||||
function(next) {
|
||||
server.getPendingTxs({}, function(err, txs) {
|
||||
should.not.exist(err);
|
||||
txs.length.should.equal(2);
|
||||
next();
|
||||
});
|
||||
},
|
||||
], function(err) {
|
||||
should.not.exist(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('#createTx backoff time', function(done) {
|
||||
var server, wallet, txid;
|
||||
|
|
Loading…
Reference in New Issue