Skip to content

Commit 8c1e49b

Browse files
committed
Merge #7967: [RPC] add feerate option to fundrawtransaction
04eaa90 Add more clear interface for CoinControl.h regarding individual feerate (Jonas Schnelli) 3b35e48 [RPC] add feerate option to fundrawtransaction (Jonas Schnelli)
2 parents c141c14 + 04eaa90 commit 8c1e49b

File tree

5 files changed

+34
-6
lines changed

5 files changed

+34
-6
lines changed

qa/rpc-tests/fundrawtransaction.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,14 @@ def run_test(self):
678678
assert(signedtx["complete"])
679679
self.nodes[0].sendrawtransaction(signedtx["hex"])
680680

681+
inputs = []
682+
outputs = {self.nodes[2].getnewaddress() : 1}
683+
rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
684+
result = self.nodes[3].fundrawtransaction(rawtx, )
685+
result2 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2000})
686+
result3 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 10000})
687+
assert_equal(result['fee']*2, result2['fee'])
688+
assert_equal(result['fee']*10, result3['fee'])
681689

682690
if __name__ == '__main__':
683691
RawTransactionsTest().main()

src/coincontrol.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ class CCoinControl
1818
bool fAllowWatchOnly;
1919
//! Minimum absolute fee (not per kilobyte)
2020
CAmount nMinimumTotalFee;
21+
//! Override estimated feerate
22+
bool fOverrideFeeRate;
23+
//! Feerate to use if overrideFeeRate is true
24+
CFeeRate nFeeRate;
2125

2226
CCoinControl()
2327
{
@@ -31,6 +35,8 @@ class CCoinControl
3135
fAllowWatchOnly = false;
3236
setSelected.clear();
3337
nMinimumTotalFee = 0;
38+
nFeeRate = CFeeRate(0);
39+
fOverrideFeeRate = false;
3440
}
3541

3642
bool HasSelected() const

src/wallet/rpcwallet.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2421,6 +2421,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
24212421
" \"changePosition\" (numeric, optional, default random) The index of the change output\n"
24222422
" \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n"
24232423
" \"lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n"
2424+
" \"feeRate\" (numeric, optional, default 0=estimate) Set a specific feerate (fee per KB)\n"
24242425
" }\n"
24252426
" for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}\n"
24262427
"\nResult:\n"
@@ -2447,6 +2448,8 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
24472448
int changePosition = -1;
24482449
bool includeWatching = false;
24492450
bool lockUnspents = false;
2451+
CFeeRate feeRate = CFeeRate(0);
2452+
bool overrideEstimatedFeerate = false;
24502453

24512454
if (params.size() > 1) {
24522455
if (params[1].type() == UniValue::VBOOL) {
@@ -2458,7 +2461,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
24582461

24592462
UniValue options = params[1];
24602463

2461-
RPCTypeCheckObj(options, boost::assign::map_list_of("changeAddress", UniValue::VSTR)("changePosition", UniValue::VNUM)("includeWatching", UniValue::VBOOL)("lockUnspents", UniValue::VBOOL), true, true);
2464+
RPCTypeCheckObj(options, boost::assign::map_list_of("changeAddress", UniValue::VSTR)("changePosition", UniValue::VNUM)("includeWatching", UniValue::VBOOL)("lockUnspents", UniValue::VBOOL)("feeRate", UniValue::VNUM), true, true);
24622465

24632466
if (options.exists("changeAddress")) {
24642467
CBitcoinAddress address(options["changeAddress"].get_str());
@@ -2477,6 +2480,12 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
24772480

24782481
if (options.exists("lockUnspents"))
24792482
lockUnspents = options["lockUnspents"].get_bool();
2483+
2484+
if (options.exists("feeRate"))
2485+
{
2486+
feeRate = CFeeRate(options["feeRate"].get_real());
2487+
overrideEstimatedFeerate = true;
2488+
}
24802489
}
24812490
}
24822491

@@ -2492,16 +2501,16 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
24922501
throw JSONRPCError(RPC_INVALID_PARAMETER, "changePosition out of bounds");
24932502

24942503
CMutableTransaction tx(origTx);
2495-
CAmount nFee;
2504+
CAmount nFeeOut;
24962505
string strFailReason;
24972506

2498-
if(!pwalletMain->FundTransaction(tx, nFee, changePosition, strFailReason, includeWatching, lockUnspents, changeAddress))
2507+
if(!pwalletMain->FundTransaction(tx, nFeeOut, overrideEstimatedFeerate, feeRate, changePosition, strFailReason, includeWatching, lockUnspents, changeAddress))
24992508
throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);
25002509

25012510
UniValue result(UniValue::VOBJ);
25022511
result.push_back(Pair("hex", EncodeHexTx(tx)));
25032512
result.push_back(Pair("changepos", changePosition));
2504-
result.push_back(Pair("fee", ValueFromAmount(nFee)));
2513+
result.push_back(Pair("fee", ValueFromAmount(nFeeOut)));
25052514

25062515
return result;
25072516
}

src/wallet/wallet.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1909,7 +1909,7 @@ bool CWallet::SelectCoins(const vector<COutput>& vAvailableCoins, const CAmount&
19091909
return res;
19101910
}
19111911

1912-
bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const CTxDestination& destChange)
1912+
bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool overrideEstimatedFeeRate, const CFeeRate& specificFeeRate, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const CTxDestination& destChange)
19131913
{
19141914
vector<CRecipient> vecSend;
19151915

@@ -1924,6 +1924,9 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC
19241924
coinControl.destChange = destChange;
19251925
coinControl.fAllowOtherInputs = true;
19261926
coinControl.fAllowWatchOnly = includeWatching;
1927+
coinControl.fOverrideFeeRate = overrideEstimatedFeeRate;
1928+
coinControl.nFeeRate = specificFeeRate;
1929+
19271930
BOOST_FOREACH(const CTxIn& txin, tx.vin)
19281931
coinControl.Select(txin.prevout);
19291932

@@ -2233,6 +2236,8 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
22332236
if (coinControl && nFeeNeeded > 0 && coinControl->nMinimumTotalFee > nFeeNeeded) {
22342237
nFeeNeeded = coinControl->nMinimumTotalFee;
22352238
}
2239+
if (coinControl && coinControl->fOverrideFeeRate)
2240+
nFeeNeeded = coinControl->nFeeRate.GetFee(nBytes);
22362241

22372242
// If we made it here and we aren't even able to meet the relay fee on the next pass, give up
22382243
// because we must be at the maximum allowed fee.

src/wallet/wallet.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -738,7 +738,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
738738
* Insert additional inputs into the transaction by
739739
* calling CreateTransaction();
740740
*/
741-
bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const CTxDestination& destChange = CNoDestination());
741+
bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool overrideEstimatedFeeRate, const CFeeRate& specificFeeRate, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const CTxDestination& destChange = CNoDestination());
742742

743743
/**
744744
* Create a new transaction paying the recipients with a set of coins

0 commit comments

Comments
 (0)