diff --git a/lib/common/defaults.js b/lib/common/defaults.js index f51efc1..8dded64 100644 --- a/lib/common/defaults.js +++ b/lib/common/defaults.js @@ -7,6 +7,7 @@ Defaults.MIN_FEE_PER_KB = 0; Defaults.MAX_FEE_PER_KB = 1000000; Defaults.MIN_TX_FEE = 0; Defaults.MAX_TX_FEE = 0.1 * 1e8; +Defaults.MAX_TX_SIZE_IN_KB = 100; Defaults.MAX_KEYS = 100; diff --git a/lib/errors/errordefinitions.js b/lib/errors/errordefinitions.js index 180f53b..62f0081 100644 --- a/lib/errors/errordefinitions.js +++ b/lib/errors/errordefinitions.js @@ -24,6 +24,7 @@ var errors = { TX_ALREADY_BROADCASTED: 'The transaction proposal is already broadcasted', TX_CANNOT_CREATE: 'Cannot create TX proposal during backoff time', TX_CANNOT_REMOVE: 'Cannot remove this tx proposal during locktime', + TX_MAX_SIZE_EXCEEDED: 'TX exceeds maximum allowed size', 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', diff --git a/lib/server.js b/lib/server.js index 60c0be6..af90246 100644 --- a/lib/server.js +++ b/lib/server.js @@ -1305,21 +1305,23 @@ WalletService.prototype._selectTxInputs = function(txp, utxosToExclude, cb) { var bitcoreTx, bitcoreError; - while (i < inputs.length) { - selected.push(inputs[i]); - total += inputs[i].satoshis; - i++; + function select() { + if (i >= inputs.length) return cb(bitcoreError || new Error('Could not select tx inputs')); + var input = inputs[i++]; + selected.push(input); + total += input.satoshis; if (total >= txp.getTotalAmount()) { txp.setInputs(selected); bitcoreError = self._checkTxAndEstimateFee(txp); - if (!bitcoreError) { - return cb(); - } + if (!bitcoreError) return cb(); + if (txp.getEstimatedSize() / 1000 > Defaults.MAX_TX_SIZE_IN_KB) + return cb(Errors.TX_MAX_SIZE_EXCEEDED); } - } + setTimeout(select, 0); + }; - return cb(bitcoreError || new Error('Could not select tx inputs')); + select(); }); }; diff --git a/test/integration/server.js b/test/integration/server.js index 6dc14a6..1aa8028 100644 --- a/test/integration/server.js +++ b/test/integration/server.js @@ -2287,6 +2287,20 @@ describe('Wallet service', function() { }); }); + it('should fail to create a tx exceeding max size in kb', function(done) { + helpers.stubUtxos(server, wallet, _.range(1, 10, 0), function() { + var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 9, TestData.copayers[0].privKey_1H_0); + var _oldDefault = Defaults.MAX_TX_SIZE_IN_KB; + Defaults.MAX_TX_SIZE_IN_KB = 1; + server.createTxLegacy(txOpts, function(err, tx) { + should.exist(err); + err.code.should.equal('TX_MAX_SIZE_EXCEEDED'); + Defaults.MAX_TX_SIZE_IN_KB = _oldDefault; + done(); + }); + }); + }); + it('should fail to create tx for dust amount', function(done) { helpers.stubUtxos(server, wallet, [1], function() { var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 0.00000001, TestData.copayers[0].privKey_1H_0);