aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatt Corallo <git@bluematt.me>2017-07-10 14:29:06 -0400
committerMatt Corallo <git@bluematt.me>2017-07-18 11:20:47 -0400
commitcf82a9e704f56d245cf512d76ba9d0e6b178f3b0 (patch)
treefa413cbf28fae3f278a28a6ef72582930b9d50c6 /src
parent7b6e8bc4424006119dc537699c8b3b3121e0b3c3 (diff)
Do not allow users to get keys from keypool without reserving them
fundrawtransaction allows users to add a change output and then not have it removed from keypool. While it would be nice to have users follow the normal CreateTransaction/CommitTransaction process we use internally, there isnt much benefit in exposing this option, especially with HD wallets, while there is ample room for users to misunderstand or misuse this option. This could be particularly nasty in some use-cases (especially pre-HD-split) - eg a user might fundrawtransaction, then call getnewaddress, hand out the address for someone to pay them, then sendrawtransaction. This may result in the user thinking they have received payment, even though it was really just their own change! This could obviously result in needless key-reuse.
Diffstat (limited to 'src')
-rw-r--r--src/wallet/rpcwallet.cpp9
-rw-r--r--src/wallet/wallet.cpp12
-rw-r--r--src/wallet/wallet.h2
3 files changed, 10 insertions, 13 deletions
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index ee8c7548fc..26fcfea95c 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -2693,7 +2693,6 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
" \"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"
- " \"reserveChangeKey\" (boolean, optional, default true) Reserves the change output key from the keypool\n"
" \"feeRate\" (numeric, optional, default not set: makes wallet determine the fee) Set a specific feerate (" + CURRENCY_UNIT + " per KB)\n"
" \"subtractFeeFromOutputs\" (array, optional) A json array of integers.\n"
" The fee will be equally deducted from the amount of each specified output.\n"
@@ -2732,7 +2731,6 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
CCoinControl coinControl;
int changePosition = -1;
bool lockUnspents = false;
- bool reserveChangeKey = true;
UniValue subtractFeeFromOutputs;
std::set<int> setSubtractFeeFromOutputs;
@@ -2752,7 +2750,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
{"changePosition", UniValueType(UniValue::VNUM)},
{"includeWatching", UniValueType(UniValue::VBOOL)},
{"lockUnspents", UniValueType(UniValue::VBOOL)},
- {"reserveChangeKey", UniValueType(UniValue::VBOOL)},
+ {"reserveChangeKey", UniValueType(UniValue::VBOOL)}, // DEPRECATED (and ignored), should be removed in 0.16 or so.
{"feeRate", UniValueType()}, // will be checked below
{"subtractFeeFromOutputs", UniValueType(UniValue::VARR)},
{"replaceable", UniValueType(UniValue::VBOOL)},
@@ -2779,9 +2777,6 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
if (options.exists("lockUnspents"))
lockUnspents = options["lockUnspents"].get_bool();
- if (options.exists("reserveChangeKey"))
- reserveChangeKey = options["reserveChangeKey"].get_bool();
-
if (options.exists("feeRate"))
{
coinControl.m_feerate = CFeeRate(AmountFromValue(options["feeRate"]));
@@ -2830,7 +2825,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
CAmount nFeeOut;
std::string strFailReason;
- if (!pwallet->FundTransaction(tx, nFeeOut, changePosition, strFailReason, lockUnspents, setSubtractFeeFromOutputs, coinControl, reserveChangeKey)) {
+ if (!pwallet->FundTransaction(tx, nFeeOut, changePosition, strFailReason, lockUnspents, setSubtractFeeFromOutputs, coinControl)) {
throw JSONRPCError(RPC_WALLET_ERROR, strFailReason);
}
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 5317502589..c56fd05d7e 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -2471,7 +2471,7 @@ bool CWallet::SignTransaction(CMutableTransaction &tx)
return true;
}
-bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl coinControl, bool keepReserveKey)
+bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl coinControl)
{
std::vector<CRecipient> vecSend;
@@ -2493,8 +2493,13 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC
if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosInOut, strFailReason, coinControl, false)) {
return false;
}
- if (nChangePosInOut != -1)
+
+ if (nChangePosInOut != -1) {
tx.vout.insert(tx.vout.begin() + nChangePosInOut, wtx.tx->vout[nChangePosInOut]);
+ // we dont have the normal Create/Commit cycle, and dont want to risk reusing change,
+ // so just remove the key from the keypool here.
+ reservekey.KeepKey();
+ }
// Copy output sizes from new transaction; they may have had the fee subtracted from them
for (unsigned int idx = 0; idx < tx.vout.size(); idx++)
@@ -2515,9 +2520,6 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC
}
}
- // optionally keep the change output key
- if (keepReserveKey)
- reservekey.KeepKey();
return true;
}
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 574fd8710d..bf09b040f6 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -949,7 +949,7 @@ public:
* Insert additional inputs into the transaction by
* calling CreateTransaction();
*/
- bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl, bool keepReserveKey = true);
+ bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl);
bool SignTransaction(CMutableTransaction& tx);
/**