From d7cc503843769b789dc5f031b4ddc75d555ba980 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 16 Mar 2023 14:58:41 -0400 Subject: [PATCH] Fix fund transaction case at 0-value, 0-fee --- src/wallet/spend.cpp | 6 ++++++ test/functional/rpc_psbt.py | 3 +++ 2 files changed, 9 insertions(+) diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp index 5771d33b7a88f..ea910bd5b8545 100644 --- a/src/wallet/spend.cpp +++ b/src/wallet/spend.cpp @@ -917,6 +917,12 @@ static util::Result 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 58a80e37a200c..55322c074547c 100755 --- a/test/functional/rpc_psbt.py +++ b/test/functional/rpc_psbt.py @@ -931,6 +931,9 @@ def test_psbt_input_keys(psbt_input, keys): 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()