Skip to content

Commit 5dc5cd5

Browse files
committed
[rpc] return feereason from send* wallet rpcs
1 parent 171f4a5 commit 5dc5cd5

File tree

7 files changed

+45
-15
lines changed

7 files changed

+45
-15
lines changed

src/interfaces/wallet.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,10 @@ class WalletImpl : public Wallet
225225
bilingual_str& fail_reason) override
226226
{
227227
LOCK(m_wallet->cs_wallet);
228-
CTransactionRef tx;
228+
CTransactionRef tx;
229+
std::string feeReason;
229230
if (!m_wallet->CreateTransaction(recipients, tx, fee, change_pos,
230-
fail_reason, coin_control, sign)) {
231+
fail_reason, coin_control, feeReason, sign)) {
231232
return {};
232233
}
233234
return tx;

src/qt/walletmodel.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,10 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
198198
CAmount nFeeRequired = 0;
199199
int nChangePosRet = -1;
200200
bilingual_str error;
201+
std::string feeReason;
201202

202203
auto& newTx = transaction.getWtx();
203-
newTx = m_wallet->createTransaction(vecSend, coinControl, !wallet().privateKeysDisabled() /* sign */, nChangePosRet, nFeeRequired, error);
204+
newTx = m_wallet->createTransaction(vecSend, coinControl, !wallet().privateKeysDisabled() /* sign */, nChangePosRet, nFeeRequired, error, feeReason);
204205
transaction.setTransactionFee(nFeeRequired);
205206
if (fSubtractFeeFromAmount && newTx)
206207
transaction.reassignAmounts(nChangePosRet);

src/wallet/feebumper.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,9 @@ Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCo
218218
CTransactionRef tx_new = MakeTransactionRef();
219219
CAmount fee_ret;
220220
int change_pos_in_out = -1; // No requested location for change
221+
std::string feeReason;
221222
bilingual_str fail_reason;
222-
if (!wallet.CreateTransaction(recipients, tx_new, fee_ret, change_pos_in_out, fail_reason, new_coin_control, false)) {
223+
if (!wallet.CreateTransaction(recipients, tx_new, fee_ret, change_pos_in_out, fail_reason, new_coin_control, feeReason, false)) {
223224
errors.push_back(Untranslated("Unable to create transaction.") + Untranslated(" ") + fail_reason);
224225
return Result::WALLET_ERROR;
225226
}

src/wallet/rpcwallet.cpp

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ static UniValue setlabel(const JSONRPCRequest& request)
360360
}
361361

362362

363-
static CTransactionRef SendMoney(CWallet* const pwallet, const CTxDestination& address, CAmount nValue, bool fSubtractFeeFromAmount, const CCoinControl& coin_control, mapValue_t mapValue)
363+
static CTransactionRef SendMoney(CWallet* const pwallet, const CTxDestination& address, CAmount nValue, bool fSubtractFeeFromAmount, const CCoinControl& coin_control, mapValue_t mapValue, std::string& feeReason)
364364
{
365365
CAmount curBalance = pwallet->GetBalance(0, coin_control.m_avoid_address_reuse).m_mine_trusted;
366366

@@ -381,8 +381,8 @@ static CTransactionRef SendMoney(CWallet* const pwallet, const CTxDestination& a
381381
int nChangePosRet = -1;
382382
CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
383383
vecSend.push_back(recipient);
384-
CTransactionRef tx;
385-
if (!pwallet->CreateTransaction(vecSend, tx, nFeeRequired, nChangePosRet, error, coin_control)) {
384+
CTransactionRef tx;
385+
if (!pwallet->CreateTransaction(vecSend, tx, nFeeRequired, nChangePosRet, error, coin_control, feeReason)) {
386386
if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance)
387387
error = strprintf(Untranslated("Error: This transaction requires a transaction fee of at least %s"), FormatMoney(nFeeRequired));
388388
throw JSONRPCError(RPC_WALLET_ERROR, error.original);
@@ -412,6 +412,8 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
412412
" \"" + FeeModes("\"\n\"") + "\""},
413413
{"avoid_reuse", RPCArg::Type::BOOL, /* default */ "true", "(only available if avoid_reuse wallet flag is set) Avoid spending from dirty addresses; addresses are considered\n"
414414
" dirty if they have previously been used in a transaction."},
415+
{"verbose", RPCArg::Type::BOOL, /* default */ "false",
416+
"Whether to display the fee reason or not."},
415417
},
416418
RPCResult{
417419
RPCResult::Type::STR_HEX, "txid", "The transaction id."
@@ -470,8 +472,17 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
470472
SetFeeEstimateMode(pwallet, coin_control, request.params[7], request.params[6]);
471473

472474
EnsureWalletIsUnlocked(pwallet);
475+
UniValue entry(UniValue::VOBJ);
476+
std::string feeReason;
477+
CTransactionRef tx = SendMoney(pwallet, dest, nAmount, fSubtractFeeFromAmount, coin_control, std::move(mapValue), feeReason);
478+
479+
bool verbose = request.params[9].isNull() ? false : request.params[9].get_bool();
480+
if(verbose){
481+
entry.pushKV("hex", tx->GetHash().GetHex());
482+
entry.pushKV("Fee Reason", feeReason);
483+
return entry;
484+
}
473485

474-
CTransactionRef tx = SendMoney(pwallet, dest, nAmount, fSubtractFeeFromAmount, coin_control, std::move(mapValue));
475486
return tx->GetHash().GetHex();
476487
}
477488

@@ -813,6 +824,8 @@ static UniValue sendmany(const JSONRPCRequest& request)
813824
{"conf_target", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks), or fee rate (for " + CURRENCY_UNIT + "/kB or " + CURRENCY_ATOM + "/B estimate modes)"},
814825
{"estimate_mode", RPCArg::Type::STR, /* default */ "unset", std::string() + "The fee estimate mode, must be one of (case insensitive):\n"
815826
" \"" + FeeModes("\"\n\"") + "\""},
827+
{"verbose", RPCArg::Type::BOOL, /* default */ "false",
828+
"Whether to display the fee reason or not."},
816829
},
817830
RPCResult{
818831
RPCResult::Type::STR_HEX, "txid", "The transaction id for the send. Only 1 transaction is created regardless of\n"
@@ -901,10 +914,21 @@ static UniValue sendmany(const JSONRPCRequest& request)
901914
int nChangePosRet = -1;
902915
bilingual_str error;
903916
CTransactionRef tx;
904-
bool fCreated = pwallet->CreateTransaction(vecSend, tx, nFeeRequired, nChangePosRet, error, coin_control);
917+
UniValue entry(UniValue::VOBJ);
918+
std::string feeReason;
919+
bool fCreated = pwallet->CreateTransaction(vecSend, tx, nFeeRequired, nChangePosRet, error, coin_control, feeReason);
905920
if (!fCreated)
906921
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, error.original);
907922
pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */);
923+
924+
bool verbose = request.params[8].isNull() ? false : request.params[8].get_bool();
925+
926+
if(verbose){
927+
entry.pushKV("hex", tx->GetHash().GetHex());
928+
entry.pushKV("Fee Reason", feeReason);
929+
return entry;
930+
}
931+
908932
return tx->GetHash().GetHex();
909933
}
910934

@@ -4198,8 +4222,8 @@ static const CRPCCommand commands[] =
41984222
{ "wallet", "lockunspent", &lockunspent, {"unlock","transactions"} },
41994223
{ "wallet", "removeprunedfunds", &removeprunedfunds, {"txid"} },
42004224
{ "wallet", "rescanblockchain", &rescanblockchain, {"start_height", "stop_height"} },
4201-
{ "wallet", "sendmany", &sendmany, {"dummy","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode"} },
4202-
{ "wallet", "sendtoaddress", &sendtoaddress, {"address","amount","comment","comment_to","subtractfeefromamount","replaceable","conf_target","estimate_mode","avoid_reuse"} },
4225+
{ "wallet", "sendmany", &sendmany, {"dummy","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode", "verbose"} },
4226+
{ "wallet", "sendtoaddress", &sendtoaddress, {"address","amount","comment","comment_to","subtractfeefromamount","replaceable","conf_target","estimate_mode","avoid_reuse", "verbose"} },
42034227
{ "wallet", "sethdseed", &sethdseed, {"newkeypool","seed"} },
42044228
{ "wallet", "setlabel", &setlabel, {"address","label"} },
42054229
{ "wallet", "settxfee", &settxfee, {"amount"} },

src/wallet/test/wallet_tests.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,11 +513,12 @@ class ListCoinsTestingSetup : public TestChain100Setup
513513
{
514514
CTransactionRef tx;
515515
CAmount fee;
516+
std::string feeReason;
516517
int changePos = -1;
517518
bilingual_str error;
518519
CCoinControl dummy;
519520
{
520-
BOOST_CHECK(wallet->CreateTransaction({recipient}, tx, fee, changePos, error, dummy));
521+
BOOST_CHECK(wallet->CreateTransaction({recipient}, tx, fee, changePos, error, dummy, feeReason));
521522
}
522523
wallet->CommitTransaction(tx, {}, {});
523524
CMutableTransaction blocktx;

src/wallet/wallet.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2576,7 +2576,8 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC
25762576
LOCK(cs_wallet);
25772577

25782578
CTransactionRef tx_new;
2579-
if (!CreateTransaction(vecSend, tx_new, nFeeRet, nChangePosInOut, error, coinControl, false)) {
2579+
std::string feeReason;
2580+
if (!CreateTransaction(vecSend, tx_new, nFeeRet, nChangePosInOut, error, coinControl, feeReason, false)) {
25802581
return false;
25812582
}
25822583

@@ -2692,7 +2693,7 @@ OutputType CWallet::TransactionChangeType(const Optional<OutputType>& change_typ
26922693
return m_default_address_type;
26932694
}
26942695

2695-
bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CAmount& nFeeRet, int& nChangePosInOut, bilingual_str& error, const CCoinControl& coin_control, bool sign)
2696+
bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CAmount& nFeeRet, int& nChangePosInOut, bilingual_str& error, const CCoinControl& coin_control, std::string& feeReason, bool sign)
26962697
{
26972698
CAmount nValue = 0;
26982699
const OutputType change_type = TransactionChangeType(coin_control.m_change_type ? *coin_control.m_change_type : m_default_change_type, vecSend);
@@ -3035,6 +3036,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
30353036
// Before we return success, we assume any change key will be used to prevent
30363037
// accidental re-use.
30373038
reservedest.KeepDestination();
3039+
feeReason = StringForFeeReason(feeCalc.reason);
30383040

30393041
WalletLogPrintf("Fee Calculation: Fee:%d Bytes:%u Needed:%d Tgt:%d (requested %d) Reason:\"%s\" Decay %.5f: Estimation: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out) Fail: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out)\n",
30403042
nFeeRet, nBytes, nFeeNeeded, feeCalc.returnedTarget, feeCalc.desiredTarget, StringForFeeReason(feeCalc.reason), feeCalc.est.decay,

src/wallet/wallet.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,7 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
969969
* selected by SelectCoins(); Also create the change output, when needed
970970
* @note passing nChangePosInOut as -1 will result in setting a random position
971971
*/
972-
bool CreateTransaction(const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CAmount& nFeeRet, int& nChangePosInOut, bilingual_str& error, const CCoinControl& coin_control, bool sign = true);
972+
bool CreateTransaction(const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CAmount& nFeeRet, int& nChangePosInOut, bilingual_str& error, const CCoinControl& coin_control, std::string& feeReason, bool sign = true);
973973
/**
974974
* Submit the transaction to the node's mempool and then relay to peers.
975975
* Should be called after CreateTransaction unless you want to abort

0 commit comments

Comments
 (0)