aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wallet/spend.cpp6
-rwxr-xr-xtest/functional/rpc_psbt.py3
2 files changed, 9 insertions, 0 deletions
diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp
index 5771d33b7a..ea910bd5b8 100644
--- a/src/wallet/spend.cpp
+++ b/src/wallet/spend.cpp
@@ -917,6 +917,12 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
const CAmount not_input_fees = coin_selection_params.m_effective_feerate.GetFee(coin_selection_params.m_subtract_fee_outputs ? 0 : coin_selection_params.tx_noinputs_size);
CAmount selection_target = recipients_sum + not_input_fees;
+ // This can only happen if feerate is 0, and requested destinations are value of 0 (e.g. OP_RETURN)
+ // and no pre-selected inputs. This will result in 0-input transaction, which is consensus-invalid anyways
+ if (selection_target == 0 && !coin_control.HasSelected()) {
+ return util::Error{_("Transaction requires one destination of non-0 value, a non-0 feerate, or a pre-selected input")};
+ }
+
// Fetch manually selected coins
PreSelectedInputs preset_inputs;
if (coin_control.HasSelected()) {
diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py
index 58a80e37a2..55322c0745 100755
--- a/test/functional/rpc_psbt.py
+++ b/test/functional/rpc_psbt.py
@@ -931,6 +931,9 @@ class PSBTTest(BitcoinTestFramework):
assert_equal(self.nodes[0].finalizepsbt(psbt.to_base64()),
{'hex': '0200000001dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd0000000000000000000100000000000000000000000000', 'complete': True})
+ self.log.info("Test we don't crash when making a 0-value funded transaction at 0 fee without forcing an input selection")
+ assert_raises_rpc_error(-4, "Transaction requires one destination of non-0 value, a non-0 feerate, or a pre-selected input", self.nodes[0].walletcreatefundedpsbt, [], [{"data": "deadbeef"}], 0, {"fee_rate": "0"})
+
if __name__ == '__main__':
PSBTTest().main()