@@ -488,13 +488,13 @@ static std::vector<RPCArg> FundTxDoc(bool solving_data = true)
488488 return args;
489489}
490490
491- void FundTransaction (CWallet& wallet, CMutableTransaction& tx, CAmount& fee_out, int & change_position , const UniValue& options, CCoinControl& coinControl, bool override_min_fee)
491+ CreatedTransactionResult FundTransaction (CWallet& wallet, const CMutableTransaction& tx, const UniValue& options, CCoinControl& coinControl, bool override_min_fee)
492492{
493493 // Make sure the results are valid at least up to the most recent block
494494 // the user could have gotten from another RPC command prior to now
495495 wallet.BlockUntilSyncedToCurrentChain ();
496496
497- change_position = - 1 ;
497+ std::optional< unsigned int > change_position ;
498498 bool lockUnspents = false ;
499499 UniValue subtractFeeFromOutputs;
500500 std::set<int > setSubtractFeeFromOutputs;
@@ -552,7 +552,11 @@ void FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& fee_out,
552552 }
553553
554554 if (options.exists (" changePosition" ) || options.exists (" change_position" )) {
555- change_position = (options.exists (" change_position" ) ? options[" change_position" ] : options[" changePosition" ]).getInt <int >();
555+ int pos = (options.exists (" change_position" ) ? options[" change_position" ] : options[" changePosition" ]).getInt <int >();
556+ if (pos < 0 || (unsigned int )pos > tx.vout .size ()) {
557+ throw JSONRPCError (RPC_INVALID_PARAMETER, " changePosition out of bounds" );
558+ }
559+ change_position = (unsigned int )pos;
556560 }
557561
558562 if (options.exists (" change_type" )) {
@@ -702,9 +706,6 @@ void FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& fee_out,
702706 if (tx.vout .size () == 0 )
703707 throw JSONRPCError (RPC_INVALID_PARAMETER, " TX must have at least one output" );
704708
705- if (change_position != -1 && (change_position < 0 || (unsigned int )change_position > tx.vout .size ()))
706- throw JSONRPCError (RPC_INVALID_PARAMETER, " changePosition out of bounds" );
707-
708709 for (unsigned int idx = 0 ; idx < subtractFeeFromOutputs.size (); idx++) {
709710 int pos = subtractFeeFromOutputs[idx].getInt <int >();
710711 if (setSubtractFeeFromOutputs.count (pos))
@@ -716,11 +717,11 @@ void FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& fee_out,
716717 setSubtractFeeFromOutputs.insert (pos);
717718 }
718719
719- bilingual_str error;
720-
721- if (!FundTransaction (wallet, tx, fee_out, change_position, error, lockUnspents, setSubtractFeeFromOutputs, coinControl)) {
722- throw JSONRPCError (RPC_WALLET_ERROR, error.original );
720+ auto txr = FundTransaction (wallet, tx, change_position, lockUnspents, setSubtractFeeFromOutputs, coinControl);
721+ if (!txr) {
722+ throw JSONRPCError (RPC_WALLET_ERROR, ErrorString (txr).original );
723723 }
724+ return *txr;
724725}
725726
726727static void SetOptionsInputWeights (const UniValue& inputs, UniValue& options)
@@ -843,17 +844,15 @@ RPCHelpMan fundrawtransaction()
843844 throw JSONRPCError (RPC_DESERIALIZATION_ERROR, " TX decode failed" );
844845 }
845846
846- CAmount fee;
847- int change_position;
848847 CCoinControl coin_control;
849848 // Automatically select (additional) coins. Can be overridden by options.add_inputs.
850849 coin_control.m_allow_other_inputs = true ;
851- FundTransaction (*pwallet, tx, fee, change_position , request.params [1 ], coin_control, /* override_min_fee=*/ true );
850+ auto txr = FundTransaction (*pwallet, tx, request.params [1 ], coin_control, /* override_min_fee=*/ true );
852851
853852 UniValue result (UniValue::VOBJ);
854- result.pushKV (" hex" , EncodeHexTx (CTransaction (tx) ));
855- result.pushKV (" fee" , ValueFromAmount (fee));
856- result.pushKV (" changepos" , change_position );
853+ result.pushKV (" hex" , EncodeHexTx (*txr. tx ));
854+ result.pushKV (" fee" , ValueFromAmount (txr. fee ));
855+ result.pushKV (" changepos" , txr. change_pos ? ( int )*txr. change_pos : - 1 );
857856
858857 return result;
859858},
@@ -1275,18 +1274,16 @@ RPCHelpMan send()
12751274 PreventOutdatedOptions (options);
12761275
12771276
1278- CAmount fee;
1279- int change_position;
12801277 bool rbf{options.exists (" replaceable" ) ? options[" replaceable" ].get_bool () : pwallet->m_signal_rbf };
12811278 CMutableTransaction rawTx = ConstructTransaction (options[" inputs" ], request.params [0 ], options[" locktime" ], rbf);
12821279 CCoinControl coin_control;
12831280 // Automatically select coins, unless at least one is manually selected. Can
12841281 // be overridden by options.add_inputs.
12851282 coin_control.m_allow_other_inputs = rawTx.vin .size () == 0 ;
12861283 SetOptionsInputWeights (options[" inputs" ], options);
1287- FundTransaction (*pwallet, rawTx, fee, change_position , options, coin_control, /* override_min_fee=*/ false );
1284+ auto txr = FundTransaction (*pwallet, rawTx, options, coin_control, /* override_min_fee=*/ false );
12881285
1289- return FinishTransaction (pwallet, options, rawTx );
1286+ return FinishTransaction (pwallet, options, CMutableTransaction (*txr. tx ) );
12901287 }
12911288 };
12921289}
@@ -1711,8 +1708,6 @@ RPCHelpMan walletcreatefundedpsbt()
17111708
17121709 UniValue options{request.params [3 ].isNull () ? UniValue::VOBJ : request.params [3 ]};
17131710
1714- CAmount fee;
1715- int change_position;
17161711 const UniValue &replaceable_arg = options[" replaceable" ];
17171712 const bool rbf{replaceable_arg.isNull () ? wallet.m_signal_rbf : replaceable_arg.get_bool ()};
17181713 CMutableTransaction rawTx = ConstructTransaction (request.params [0 ], request.params [1 ], request.params [2 ], rbf);
@@ -1721,10 +1716,10 @@ RPCHelpMan walletcreatefundedpsbt()
17211716 // be overridden by options.add_inputs.
17221717 coin_control.m_allow_other_inputs = rawTx.vin .size () == 0 ;
17231718 SetOptionsInputWeights (request.params [0 ], options);
1724- FundTransaction (wallet, rawTx, fee, change_position , options, coin_control, /* override_min_fee=*/ true );
1719+ auto txr = FundTransaction (wallet, rawTx, options, coin_control, /* override_min_fee=*/ true );
17251720
17261721 // Make a blank psbt
1727- PartiallySignedTransaction psbtx (rawTx );
1722+ PartiallySignedTransaction psbtx (CMutableTransaction (*txr. tx ) );
17281723
17291724 // Fill transaction with out data but don't sign
17301725 bool bip32derivs = request.params [4 ].isNull () ? true : request.params [4 ].get_bool ();
@@ -1740,8 +1735,8 @@ RPCHelpMan walletcreatefundedpsbt()
17401735
17411736 UniValue result (UniValue::VOBJ);
17421737 result.pushKV (" psbt" , EncodeBase64 (ssTx.str ()));
1743- result.pushKV (" fee" , ValueFromAmount (fee));
1744- result.pushKV (" changepos" , change_position );
1738+ result.pushKV (" fee" , ValueFromAmount (txr. fee ));
1739+ result.pushKV (" changepos" , txr. change_pos ? ( int )*txr. change_pos : - 1 );
17451740 return result;
17461741},
17471742 };
0 commit comments