@@ -2464,7 +2464,8 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
2464
2464
throw runtime_error (
2465
2465
" fundrawtransaction \" hexstring\" ( options )\n "
2466
2466
" \n Add inputs to a transaction until it has enough in value to meet its out value.\n "
2467
- " This will not modify existing inputs, and will add one change output to the outputs.\n "
2467
+ " This will not modify existing inputs, and will add at most one change output to the outputs.\n "
2468
+ " No existing outputs will be modified unless \" subtractFeeFromOutputs\" is specified.\n "
2468
2469
" Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n "
2469
2470
" The inputs added will not be signed, use signrawtransaction for that.\n "
2470
2471
" Note that all existing inputs must have their previous output transaction be in the wallet.\n "
@@ -2476,11 +2477,17 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
2476
2477
" 1. \" hexstring\" (string, required) The hex string of the raw transaction\n "
2477
2478
" 2. options (object, optional)\n "
2478
2479
" {\n "
2479
- " \" changeAddress\" (string, optional, default pool address) The bitcoin address to receive the change\n "
2480
- " \" changePosition\" (numeric, optional, default random) The index of the change output\n "
2481
- " \" includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n "
2482
- " \" lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n "
2483
- " \" feeRate\" (numeric, optional, default not set: makes wallet determine the fee) Set a specific feerate (" + CURRENCY_UNIT + " per KB)\n "
2480
+ " \" changeAddress\" (string, optional, default pool address) The bitcoin address to receive the change\n "
2481
+ " \" changePosition\" (numeric, optional, default random) The index of the change output\n "
2482
+ " \" includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n "
2483
+ " \" lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n "
2484
+ " \" feeRate\" (numeric, optional, default not set: makes wallet determine the fee) Set a specific feerate (" + CURRENCY_UNIT + " per KB)\n "
2485
+ " \" subtractFeeFromOutputs\" (array, optional) A json array of integers.\n "
2486
+ " The fee will be equally deducted from the amount of each specified output.\n "
2487
+ " The outputs are specified by their zero-based index, before any change output is added.\n "
2488
+ " Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n "
2489
+ " If no outputs are specified here, the sender pays the fee.\n "
2490
+ " [vout_index,...]\n "
2484
2491
" }\n "
2485
2492
" for backward compatibility: passing in a true instead of an object will result in {\" includeWatching\" :true}\n "
2486
2493
" \n Result:\n "
@@ -2509,6 +2516,8 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
2509
2516
bool lockUnspents = false ;
2510
2517
CFeeRate feeRate = CFeeRate (0 );
2511
2518
bool overrideEstimatedFeerate = false ;
2519
+ UniValue subtractFeeFromOutputs;
2520
+ set<int > setSubtractFeeFromOutputs;
2512
2521
2513
2522
if (request.params .size () > 1 ) {
2514
2523
if (request.params [1 ].type () == UniValue::VBOOL) {
@@ -2527,6 +2536,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
2527
2536
{" includeWatching" , UniValueType (UniValue::VBOOL)},
2528
2537
{" lockUnspents" , UniValueType (UniValue::VBOOL)},
2529
2538
{" feeRate" , UniValueType ()}, // will be checked below
2539
+ {" subtractFeeFromOutputs" , UniValueType (UniValue::VARR)},
2530
2540
},
2531
2541
true , true );
2532
2542
@@ -2553,6 +2563,9 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
2553
2563
feeRate = CFeeRate (AmountFromValue (options[" feeRate" ]));
2554
2564
overrideEstimatedFeerate = true ;
2555
2565
}
2566
+
2567
+ if (options.exists (" subtractFeeFromOutputs" ))
2568
+ subtractFeeFromOutputs = options[" subtractFeeFromOutputs" ].get_array ();
2556
2569
}
2557
2570
}
2558
2571
@@ -2567,10 +2580,21 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
2567
2580
if (changePosition != -1 && (changePosition < 0 || (unsigned int )changePosition > tx.vout .size ()))
2568
2581
throw JSONRPCError (RPC_INVALID_PARAMETER, " changePosition out of bounds" );
2569
2582
2583
+ for (unsigned int idx = 0 ; idx < subtractFeeFromOutputs.size (); idx++) {
2584
+ int pos = subtractFeeFromOutputs[idx].get_int ();
2585
+ if (setSubtractFeeFromOutputs.count (pos))
2586
+ throw JSONRPCError (RPC_INVALID_PARAMETER, strprintf (" Invalid parameter, duplicated position: %d" , pos));
2587
+ if (pos < 0 )
2588
+ throw JSONRPCError (RPC_INVALID_PARAMETER, strprintf (" Invalid parameter, negative position: %d" , pos));
2589
+ if (pos >= int (tx.vout .size ()))
2590
+ throw JSONRPCError (RPC_INVALID_PARAMETER, strprintf (" Invalid parameter, position too large: %d" , pos));
2591
+ setSubtractFeeFromOutputs.insert (pos);
2592
+ }
2593
+
2570
2594
CAmount nFeeOut;
2571
2595
string strFailReason;
2572
2596
2573
- if (!pwalletMain->FundTransaction (tx, nFeeOut, overrideEstimatedFeerate, feeRate, changePosition, strFailReason, includeWatching, lockUnspents, changeAddress))
2597
+ if (!pwalletMain->FundTransaction (tx, nFeeOut, overrideEstimatedFeerate, feeRate, changePosition, strFailReason, includeWatching, lockUnspents, setSubtractFeeFromOutputs, changeAddress))
2574
2598
throw JSONRPCError (RPC_INTERNAL_ERROR, strFailReason);
2575
2599
2576
2600
UniValue result (UniValue::VOBJ);
0 commit comments