aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2016-06-03 15:31:49 +0200
committerWladimir J. van der Laan <laanwj@gmail.com>2016-06-03 15:47:48 +0200
commit8c1e49ba13a88917e133c28d35b665967d4c90b0 (patch)
tree52d67112a6dcc8079da634dbf5ee0ca7af3c8a90
parentc141c14c9f5f204b137e42cd8d211d231e090df9 (diff)
parent04eaa9095813b854c4299027c595fb9ebaf6f934 (diff)
downloadbitcoin-8c1e49ba13a88917e133c28d35b665967d4c90b0.tar.xz
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)
-rwxr-xr-xqa/rpc-tests/fundrawtransaction.py8
-rw-r--r--src/coincontrol.h6
-rw-r--r--src/wallet/rpcwallet.cpp17
-rw-r--r--src/wallet/wallet.cpp7
-rw-r--r--src/wallet/wallet.h2
5 files changed, 34 insertions, 6 deletions
diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py
index 57b850a6a9..5c11d3ab18 100755
--- a/qa/rpc-tests/fundrawtransaction.py
+++ b/qa/rpc-tests/fundrawtransaction.py
@@ -678,6 +678,14 @@ class RawTransactionsTest(BitcoinTestFramework):
assert(signedtx["complete"])
self.nodes[0].sendrawtransaction(signedtx["hex"])
+ inputs = []
+ outputs = {self.nodes[2].getnewaddress() : 1}
+ rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
+ result = self.nodes[3].fundrawtransaction(rawtx, )
+ result2 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2000})
+ result3 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 10000})
+ assert_equal(result['fee']*2, result2['fee'])
+ assert_equal(result['fee']*10, result3['fee'])
if __name__ == '__main__':
RawTransactionsTest().main()
diff --git a/src/coincontrol.h b/src/coincontrol.h
index 12fe9ce219..e33adc4d2b 100644
--- a/src/coincontrol.h
+++ b/src/coincontrol.h
@@ -18,6 +18,10 @@ public:
bool fAllowWatchOnly;
//! Minimum absolute fee (not per kilobyte)
CAmount nMinimumTotalFee;
+ //! Override estimated feerate
+ bool fOverrideFeeRate;
+ //! Feerate to use if overrideFeeRate is true
+ CFeeRate nFeeRate;
CCoinControl()
{
@@ -31,6 +35,8 @@ public:
fAllowWatchOnly = false;
setSelected.clear();
nMinimumTotalFee = 0;
+ nFeeRate = CFeeRate(0);
+ fOverrideFeeRate = false;
}
bool HasSelected() const
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 64d4217a09..1aace39106 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -2421,6 +2421,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
" \"changePosition\" (numeric, optional, default random) The index of the change output\n"
" \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n"
" \"lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n"
+ " \"feeRate\" (numeric, optional, default 0=estimate) Set a specific feerate (fee per KB)\n"
" }\n"
" for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}\n"
"\nResult:\n"
@@ -2447,6 +2448,8 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
int changePosition = -1;
bool includeWatching = false;
bool lockUnspents = false;
+ CFeeRate feeRate = CFeeRate(0);
+ bool overrideEstimatedFeerate = false;
if (params.size() > 1) {
if (params[1].type() == UniValue::VBOOL) {
@@ -2458,7 +2461,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
UniValue options = params[1];
- RPCTypeCheckObj(options, boost::assign::map_list_of("changeAddress", UniValue::VSTR)("changePosition", UniValue::VNUM)("includeWatching", UniValue::VBOOL)("lockUnspents", UniValue::VBOOL), true, true);
+ RPCTypeCheckObj(options, boost::assign::map_list_of("changeAddress", UniValue::VSTR)("changePosition", UniValue::VNUM)("includeWatching", UniValue::VBOOL)("lockUnspents", UniValue::VBOOL)("feeRate", UniValue::VNUM), true, true);
if (options.exists("changeAddress")) {
CBitcoinAddress address(options["changeAddress"].get_str());
@@ -2477,6 +2480,12 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
if (options.exists("lockUnspents"))
lockUnspents = options["lockUnspents"].get_bool();
+
+ if (options.exists("feeRate"))
+ {
+ feeRate = CFeeRate(options["feeRate"].get_real());
+ overrideEstimatedFeerate = true;
+ }
}
}
@@ -2492,16 +2501,16 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
throw JSONRPCError(RPC_INVALID_PARAMETER, "changePosition out of bounds");
CMutableTransaction tx(origTx);
- CAmount nFee;
+ CAmount nFeeOut;
string strFailReason;
- if(!pwalletMain->FundTransaction(tx, nFee, changePosition, strFailReason, includeWatching, lockUnspents, changeAddress))
+ if(!pwalletMain->FundTransaction(tx, nFeeOut, overrideEstimatedFeerate, feeRate, changePosition, strFailReason, includeWatching, lockUnspents, changeAddress))
throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);
UniValue result(UniValue::VOBJ);
result.push_back(Pair("hex", EncodeHexTx(tx)));
result.push_back(Pair("changepos", changePosition));
- result.push_back(Pair("fee", ValueFromAmount(nFee)));
+ result.push_back(Pair("fee", ValueFromAmount(nFeeOut)));
return result;
}
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index da0d6f272b..d2b1799632 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -1909,7 +1909,7 @@ bool CWallet::SelectCoins(const vector<COutput>& vAvailableCoins, const CAmount&
return res;
}
-bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const CTxDestination& destChange)
+bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool overrideEstimatedFeeRate, const CFeeRate& specificFeeRate, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const CTxDestination& destChange)
{
vector<CRecipient> vecSend;
@@ -1924,6 +1924,9 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC
coinControl.destChange = destChange;
coinControl.fAllowOtherInputs = true;
coinControl.fAllowWatchOnly = includeWatching;
+ coinControl.fOverrideFeeRate = overrideEstimatedFeeRate;
+ coinControl.nFeeRate = specificFeeRate;
+
BOOST_FOREACH(const CTxIn& txin, tx.vin)
coinControl.Select(txin.prevout);
@@ -2233,6 +2236,8 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
if (coinControl && nFeeNeeded > 0 && coinControl->nMinimumTotalFee > nFeeNeeded) {
nFeeNeeded = coinControl->nMinimumTotalFee;
}
+ if (coinControl && coinControl->fOverrideFeeRate)
+ nFeeNeeded = coinControl->nFeeRate.GetFee(nBytes);
// If we made it here and we aren't even able to meet the relay fee on the next pass, give up
// because we must be at the maximum allowed fee.
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index b2180a5a26..1ed8a0b37c 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -738,7 +738,7 @@ public:
* Insert additional inputs into the transaction by
* calling CreateTransaction();
*/
- bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const CTxDestination& destChange = CNoDestination());
+ bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool overrideEstimatedFeeRate, const CFeeRate& specificFeeRate, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const CTxDestination& destChange = CNoDestination());
/**
* Create a new transaction paying the recipients with a set of coins