mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 20:12:57 +01:00
Merge #12909: wallet: Make fee settings to be non-static members
fac0db0
wallet: Make fee settings non-static members (MarcoFalke)
Pull request description:
The wallet header defined some globals (they were called "settings"), that should be class members instead.
This commit is hopefully only refactoring, apart from a multiwallet bugfix: Calling the rpc `settxfee` for one wallet, would set (and change) the fee rate for all loaded wallets. (See added test case)
Tree-SHA512: 4ab6ec2f5c714742396ded5e451ec3b1ceb771e3696492de29889d866de4365b3fbe4a2784d085c8b8bd11b1ebb8a1fec99ab2c62eee716791cfc67c0cf29e1b
This commit is contained in:
parent
716d0cd696
commit
4aca43e24a
@ -112,9 +112,9 @@ CTransactionBuilder::CTransactionBuilder(std::shared_ptr<CWallet> pwalletIn, con
|
||||
tallyItem(tallyItemIn)
|
||||
{
|
||||
// Generate a feerate which will be used to consider if the remainder is dust and will go into fees or not
|
||||
coinControl.m_discard_feerate = ::GetDiscardRate(::feeEstimator);
|
||||
coinControl.m_discard_feerate = ::GetDiscardRate(*pwallet.get(), ::feeEstimator);
|
||||
// Generate a feerate which will be used by calculations of this class and also by CWallet::CreateTransaction
|
||||
coinControl.m_feerate = std::max(::feeEstimator.estimateSmartFee((int)::nTxConfirmTarget, nullptr, true), payTxFee);
|
||||
coinControl.m_feerate = std::max(::feeEstimator.estimateSmartFee((int)pwallet->m_confirm_target, nullptr, true), pwallet->m_pay_tx_fee);
|
||||
// Change always goes back to origin
|
||||
coinControl.destChange = tallyItemIn.txdest;
|
||||
// Only allow tallyItems inputs for tx creation
|
||||
@ -239,7 +239,7 @@ CAmount CTransactionBuilder::GetAmountUsed() const
|
||||
CAmount CTransactionBuilder::GetFee(unsigned int nBytes) const
|
||||
{
|
||||
CAmount nFeeCalc = coinControl.m_feerate->GetFee(nBytes);
|
||||
CAmount nRequiredFee = GetRequiredFee(nBytes);
|
||||
CAmount nRequiredFee = GetRequiredFee(*pwallet.get(), nBytes);
|
||||
if (nRequiredFee > nFeeCalc) {
|
||||
nFeeCalc = nRequiredFee;
|
||||
}
|
||||
|
@ -311,20 +311,6 @@ class NodeImpl : public Node
|
||||
}
|
||||
}
|
||||
bool getNetworkActive() override { return g_connman && g_connman->GetNetworkActive(); }
|
||||
unsigned int getTxConfirmTarget() override { CHECK_WALLET(return ::nTxConfirmTarget); }
|
||||
CAmount getRequiredFee(unsigned int tx_bytes) override { CHECK_WALLET(return GetRequiredFee(tx_bytes)); }
|
||||
CAmount getMinimumFee(unsigned int tx_bytes,
|
||||
const CCoinControl& coin_control,
|
||||
int* returned_target,
|
||||
FeeReason* reason) override
|
||||
{
|
||||
FeeCalculation fee_calc;
|
||||
CAmount result;
|
||||
CHECK_WALLET(result = GetMinimumFee(tx_bytes, coin_control, ::mempool, ::feeEstimator, &fee_calc));
|
||||
if (returned_target) *returned_target = fee_calc.returnedTarget;
|
||||
if (reason) *reason = fee_calc.reason;
|
||||
return result;
|
||||
}
|
||||
CAmount getMaxTxFee() override { return ::maxTxFee; }
|
||||
CFeeRate estimateSmartFee(int num_blocks, bool conservative, int* returned_target = nullptr) override
|
||||
{
|
||||
|
@ -26,11 +26,9 @@ class Coin;
|
||||
class RPCTimerInterface;
|
||||
class UniValue;
|
||||
class proxyType;
|
||||
enum class FeeReason;
|
||||
struct CNodeStateStats;
|
||||
|
||||
namespace interfaces {
|
||||
|
||||
class Handler;
|
||||
class Wallet;
|
||||
|
||||
@ -209,18 +207,6 @@ public:
|
||||
//! Get network active.
|
||||
virtual bool getNetworkActive() = 0;
|
||||
|
||||
//! Get tx confirm target.
|
||||
virtual unsigned int getTxConfirmTarget() = 0;
|
||||
|
||||
//! Get required fee.
|
||||
virtual CAmount getRequiredFee(unsigned int tx_bytes) = 0;
|
||||
|
||||
//! Get minimum fee.
|
||||
virtual CAmount getMinimumFee(unsigned int tx_bytes,
|
||||
const CCoinControl& coin_control,
|
||||
int* returned_target,
|
||||
FeeReason* reason) = 0;
|
||||
|
||||
//! Get max tx fee.
|
||||
virtual CAmount getMaxTxFee() = 0;
|
||||
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include <consensus/validation.h>
|
||||
#include <interfaces/handler.h>
|
||||
#include <net.h>
|
||||
#include <policy/feerate.h>
|
||||
#include <policy/fees.h>
|
||||
#include <policy/policy.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <script/ismine.h>
|
||||
@ -21,6 +23,7 @@
|
||||
#include <ui_interface.h>
|
||||
#include <uint256.h>
|
||||
#include <validation.h>
|
||||
#include <wallet/fees.h>
|
||||
#include <wallet/wallet.h>
|
||||
|
||||
#include <memory>
|
||||
@ -482,6 +485,20 @@ public:
|
||||
}
|
||||
return result;
|
||||
}
|
||||
CAmount getRequiredFee(unsigned int tx_bytes) override { return GetRequiredFee(m_wallet, tx_bytes); }
|
||||
CAmount getMinimumFee(unsigned int tx_bytes,
|
||||
const CCoinControl& coin_control,
|
||||
int* returned_target,
|
||||
FeeReason* reason) override
|
||||
{
|
||||
FeeCalculation fee_calc;
|
||||
CAmount result;
|
||||
result = GetMinimumFee(m_wallet, tx_bytes, coin_control, ::mempool, ::feeEstimator, &fee_calc);
|
||||
if (returned_target) *returned_target = fee_calc.returnedTarget;
|
||||
if (reason) *reason = fee_calc.reason;
|
||||
return result;
|
||||
}
|
||||
unsigned int getConfirmTarget() override { return m_wallet.m_confirm_target; }
|
||||
bool hdEnabled() override { return m_wallet.IsHDEnabled(); }
|
||||
CoinJoin::Client& coinJoin() override { return m_coinjoin; }
|
||||
std::unique_ptr<Handler> handleUnload(UnloadFn fn) override
|
||||
|
@ -23,8 +23,10 @@
|
||||
#include <vector>
|
||||
|
||||
class CCoinControl;
|
||||
class CFeeRate;
|
||||
class CKey;
|
||||
class CWallet;
|
||||
enum class FeeReason;
|
||||
struct CRecipient;
|
||||
|
||||
namespace interfaces {
|
||||
@ -244,6 +246,18 @@ public:
|
||||
//! Return wallet transaction output information.
|
||||
virtual std::vector<WalletTxOut> getCoins(const std::vector<COutPoint>& outputs) = 0;
|
||||
|
||||
//! Get required fee.
|
||||
virtual CAmount getRequiredFee(unsigned int tx_bytes) = 0;
|
||||
|
||||
//! Get minimum fee.
|
||||
virtual CAmount getMinimumFee(unsigned int tx_bytes,
|
||||
const CCoinControl& coin_control,
|
||||
int* returned_target,
|
||||
FeeReason* reason) = 0;
|
||||
|
||||
//! Get tx confirm target.
|
||||
virtual unsigned int getConfirmTarget() = 0;
|
||||
|
||||
// Return whether HD enabled.
|
||||
virtual bool hdEnabled() = 0;
|
||||
|
||||
|
@ -536,7 +536,7 @@ void CoinControlDialog::updateLabels(CCoinControl& m_coin_control, WalletModel *
|
||||
nBytes -= 34;
|
||||
|
||||
// Fee
|
||||
nPayFee = model->node().getMinimumFee(nBytes, m_coin_control, nullptr /* returned_target */, nullptr /* reason */);
|
||||
nPayFee = model->wallet().getMinimumFee(nBytes, m_coin_control, nullptr /* returned_target */, nullptr /* reason */);
|
||||
|
||||
if (nPayAmount > 0)
|
||||
{
|
||||
|
@ -128,7 +128,7 @@ SendCoinsDialog::SendCoinsDialog(bool _fCoinJoin, QWidget* parent) :
|
||||
if (!settings.contains("nSmartFeeSliderPosition"))
|
||||
settings.setValue("nSmartFeeSliderPosition", 0);
|
||||
if (!settings.contains("nTransactionFee"))
|
||||
settings.setValue("nTransactionFee", (qint64)DEFAULT_TRANSACTION_FEE);
|
||||
settings.setValue("nTransactionFee", (qint64)DEFAULT_PAY_TX_FEE);
|
||||
if (!settings.contains("fPayOnlyMinFee"))
|
||||
settings.setValue("fPayOnlyMinFee", false);
|
||||
|
||||
@ -213,7 +213,7 @@ void SendCoinsDialog::setModel(WalletModel *_model)
|
||||
settings.remove("nSmartFeeSliderPosition");
|
||||
}
|
||||
if (settings.value("nConfTarget").toInt() == 0)
|
||||
ui->confTargetSelector->setCurrentIndex(getIndexForConfTarget(model->node().getTxConfirmTarget()));
|
||||
ui->confTargetSelector->setCurrentIndex(getIndexForConfTarget(model->wallet().getConfirmTarget()));
|
||||
else
|
||||
ui->confTargetSelector->setCurrentIndex(getIndexForConfTarget(settings.value("nConfTarget").toInt()));
|
||||
}
|
||||
@ -707,7 +707,7 @@ void SendCoinsDialog::useAvailableBalance(SendCoinsEntry* entry)
|
||||
|
||||
void SendCoinsDialog::setMinimumFee()
|
||||
{
|
||||
ui->customFee->setValue(model->node().getRequiredFee(1000));
|
||||
ui->customFee->setValue(model->wallet().getRequiredFee(1000));
|
||||
}
|
||||
|
||||
void SendCoinsDialog::updateFeeSectionControls()
|
||||
@ -739,7 +739,7 @@ void SendCoinsDialog::updateMinFeeLabel()
|
||||
{
|
||||
if (model && model->getOptionsModel())
|
||||
ui->checkBoxMinimumFee->setText(tr("Pay only the required fee of %1").arg(
|
||||
BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), model->node().getRequiredFee(1000)) + "/kB")
|
||||
BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), model->wallet().getRequiredFee(1000)) + "/kB")
|
||||
);
|
||||
}
|
||||
|
||||
@ -763,7 +763,7 @@ void SendCoinsDialog::updateSmartFeeLabel()
|
||||
m_coin_control->m_feerate.reset(); // Explicitly use only fee estimation rate for smart fee labels
|
||||
int returned_target;
|
||||
FeeReason reason;
|
||||
CFeeRate feeRate = CFeeRate(model->node().getMinimumFee(1000, *m_coin_control, &returned_target, &reason));
|
||||
CFeeRate feeRate = CFeeRate(model->wallet().getMinimumFee(1000, *m_coin_control, &returned_target, &reason));
|
||||
|
||||
ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), feeRate.GetFeePerK()) + "/kB");
|
||||
|
||||
|
@ -39,7 +39,7 @@ public:
|
||||
bool fAllowWatchOnly;
|
||||
//! Override automatic min/max checks on fee, m_feerate must be set if true
|
||||
bool fOverrideFeeRate;
|
||||
//! Override the default payTxFee if set
|
||||
//! Override the wallet's m_pay_tx_fee if set
|
||||
boost::optional<CFeeRate> m_feerate;
|
||||
//! Override the discard feerate estimation with m_discard_feerate in CreateTransaction if set
|
||||
boost::optional<CFeeRate> m_discard_feerate;
|
||||
|
@ -13,14 +13,14 @@
|
||||
#include <wallet/wallet.h>
|
||||
|
||||
|
||||
CAmount GetRequiredFee(unsigned int nTxBytes)
|
||||
CAmount GetRequiredFee(const CWallet& wallet, unsigned int nTxBytes)
|
||||
{
|
||||
return std::max(CWallet::minTxFee.GetFee(nTxBytes), ::minRelayTxFee.GetFee(nTxBytes));
|
||||
return GetRequiredFeeRate(wallet).GetFee(nTxBytes);
|
||||
}
|
||||
|
||||
CAmount GetMinimumFee(unsigned int nTxBytes, const CCoinControl& coin_control, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation *feeCalc)
|
||||
CAmount GetMinimumFee(const CWallet& wallet, unsigned int nTxBytes, const CCoinControl& coin_control, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation* feeCalc)
|
||||
{
|
||||
CAmount fee_needed = GetMinimumFeeRate(coin_control, pool, estimator, feeCalc).GetFee(nTxBytes);
|
||||
CAmount fee_needed = GetMinimumFeeRate(wallet, coin_control, pool, estimator, feeCalc).GetFee(nTxBytes);
|
||||
// Always obey the maximum
|
||||
if (fee_needed > maxTxFee) {
|
||||
fee_needed = maxTxFee;
|
||||
@ -29,34 +29,34 @@ CAmount GetMinimumFee(unsigned int nTxBytes, const CCoinControl& coin_control, c
|
||||
return fee_needed;
|
||||
}
|
||||
|
||||
CFeeRate GetRequiredFeeRate()
|
||||
CFeeRate GetRequiredFeeRate(const CWallet& wallet)
|
||||
{
|
||||
return std::max(CWallet::minTxFee, ::minRelayTxFee);
|
||||
return std::max(wallet.m_min_fee, ::minRelayTxFee);
|
||||
}
|
||||
|
||||
CFeeRate GetMinimumFeeRate(const CCoinControl& coin_control, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation *feeCalc)
|
||||
CFeeRate GetMinimumFeeRate(const CWallet& wallet, const CCoinControl& coin_control, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation* feeCalc)
|
||||
{
|
||||
/* User control of how to calculate fee uses the following parameter precedence:
|
||||
1. coin_control.m_feerate
|
||||
2. coin_control.m_confirm_target
|
||||
3. payTxFee (user-set global variable)
|
||||
4. nTxConfirmTarget (user-set global variable)
|
||||
3. m_pay_tx_fee (user-set member variable of wallet)
|
||||
4. m_confirm_target (user-set member variable of wallet)
|
||||
The first parameter that is set is used.
|
||||
*/
|
||||
CFeeRate feerate_needed ;
|
||||
CFeeRate feerate_needed;
|
||||
if (coin_control.m_feerate) { // 1.
|
||||
feerate_needed = *(coin_control.m_feerate);
|
||||
if (feeCalc) feeCalc->reason = FeeReason::PAYTXFEE;
|
||||
// Allow to override automatic min/max check over coin control instance
|
||||
if (coin_control.fOverrideFeeRate) return feerate_needed;
|
||||
}
|
||||
else if (!coin_control.m_confirm_target && ::payTxFee != CFeeRate(0)) { // 3. TODO: remove magic value of 0 for global payTxFee
|
||||
feerate_needed = ::payTxFee;
|
||||
else if (!coin_control.m_confirm_target && wallet.m_pay_tx_fee != CFeeRate(0)) { // 3. TODO: remove magic value of 0 for wallet member m_pay_tx_fee
|
||||
feerate_needed = wallet.m_pay_tx_fee;
|
||||
if (feeCalc) feeCalc->reason = FeeReason::PAYTXFEE;
|
||||
}
|
||||
else { // 2. or 4.
|
||||
// We will use smart fee estimation
|
||||
unsigned int target = coin_control.m_confirm_target ? *coin_control.m_confirm_target : ::nTxConfirmTarget;
|
||||
unsigned int target = coin_control.m_confirm_target ? *coin_control.m_confirm_target : wallet.m_confirm_target;
|
||||
// By default estimates are economical
|
||||
bool conservative_estimate = true;
|
||||
// Allow to override the default fee estimate mode over the CoinControl instance
|
||||
@ -65,8 +65,8 @@ CFeeRate GetMinimumFeeRate(const CCoinControl& coin_control, const CTxMemPool& p
|
||||
|
||||
feerate_needed = estimator.estimateSmartFee(target, feeCalc, conservative_estimate);
|
||||
if (feerate_needed == CFeeRate(0)) {
|
||||
// if we don't have enough data for estimateSmartFee, then use fallbackFee
|
||||
feerate_needed = CWallet::fallbackFee;
|
||||
// if we don't have enough data for estimateSmartFee, then use fallback fee
|
||||
feerate_needed = wallet.m_fallback_fee;
|
||||
if (feeCalc) feeCalc->reason = FeeReason::FALLBACK;
|
||||
}
|
||||
// Obey mempool min fee when using smart fee estimation
|
||||
@ -77,8 +77,8 @@ CFeeRate GetMinimumFeeRate(const CCoinControl& coin_control, const CTxMemPool& p
|
||||
}
|
||||
}
|
||||
|
||||
// prevent user from paying a fee below minRelayTxFee or minTxFee
|
||||
CFeeRate required_feerate = GetRequiredFeeRate();
|
||||
// prevent user from paying a fee below the required fee rate
|
||||
CFeeRate required_feerate = GetRequiredFeeRate(wallet);
|
||||
if (required_feerate > feerate_needed) {
|
||||
feerate_needed = required_feerate;
|
||||
if (feeCalc) feeCalc->reason = FeeReason::REQUIRED;
|
||||
@ -86,12 +86,12 @@ CFeeRate GetMinimumFeeRate(const CCoinControl& coin_control, const CTxMemPool& p
|
||||
return feerate_needed;
|
||||
}
|
||||
|
||||
CFeeRate GetDiscardRate(const CBlockPolicyEstimator& estimator)
|
||||
CFeeRate GetDiscardRate(const CWallet& wallet, const CBlockPolicyEstimator& estimator)
|
||||
{
|
||||
unsigned int highest_target = estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
|
||||
CFeeRate discard_rate = estimator.estimateSmartFee(highest_target, nullptr /* FeeCalculation */, false /* conservative */);
|
||||
// Don't let discard_rate be greater than longest possible fee estimate if we get a valid fee estimate
|
||||
discard_rate = (discard_rate == CFeeRate(0)) ? CWallet::m_discard_rate : std::min(discard_rate, CWallet::m_discard_rate);
|
||||
discard_rate = (discard_rate == CFeeRate(0)) ? wallet.m_discard_rate : std::min(discard_rate, wallet.m_discard_rate);
|
||||
// Discard rate must be at least dustRelayFee
|
||||
discard_rate = std::max(discard_rate, ::dustRelayFee);
|
||||
return discard_rate;
|
||||
|
@ -12,35 +12,36 @@ class CBlockPolicyEstimator;
|
||||
class CCoinControl;
|
||||
class CFeeRate;
|
||||
class CTxMemPool;
|
||||
class CWallet;
|
||||
struct FeeCalculation;
|
||||
|
||||
/**
|
||||
* Return the minimum required fee taking into account the
|
||||
* floating relay fee and user set minimum transaction fee
|
||||
* Return the minimum required absolute fee for this size
|
||||
* based on the required fee rate
|
||||
*/
|
||||
CAmount GetRequiredFee(unsigned int nTxBytes);
|
||||
CAmount GetRequiredFee(const CWallet& wallet, unsigned int nTxBytes);
|
||||
|
||||
/**
|
||||
* Estimate the minimum fee considering user set parameters
|
||||
* and the required fee
|
||||
*/
|
||||
CAmount GetMinimumFee(unsigned int nTxBytes, const CCoinControl& coin_control, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation *feeCalc);
|
||||
CAmount GetMinimumFee(const CWallet& wallet, unsigned int nTxBytes, const CCoinControl& coin_control, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation* feeCalc);
|
||||
|
||||
/**
|
||||
* Return the minimum required feerate taking into account the
|
||||
* floating relay feerate and user set minimum transaction feerate
|
||||
* minimum relay feerate and user set minimum transaction feerate
|
||||
*/
|
||||
CFeeRate GetRequiredFeeRate();
|
||||
CFeeRate GetRequiredFeeRate(const CWallet& wallet);
|
||||
|
||||
/**
|
||||
* Estimate the minimum fee rate considering user set parameters
|
||||
* and the required fee
|
||||
*/
|
||||
CFeeRate GetMinimumFeeRate(const CCoinControl& coin_control, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation *feeCalc);
|
||||
CFeeRate GetMinimumFeeRate(const CWallet& wallet, const CCoinControl& coin_control, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation* feeCalc);
|
||||
|
||||
/**
|
||||
* Return the maximum feerate for discarding change.
|
||||
*/
|
||||
CFeeRate GetDiscardRate(const CBlockPolicyEstimator& estimator);
|
||||
CFeeRate GetDiscardRate(const CWallet& wallet, const CBlockPolicyEstimator& estimator);
|
||||
|
||||
#endif // BITCOIN_WALLET_FEES_H
|
||||
|
@ -88,7 +88,7 @@ void WalletInit::AddWalletOptions() const
|
||||
gArgs.AddArg("-mintxfee=<amt>", strprintf("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)",
|
||||
CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MINFEE)), false, OptionsCategory::WALLET_FEE);
|
||||
gArgs.AddArg("-paytxfee=<amt>", strprintf("Fee (in %s/kB) to add to transactions you send (default: %s)",
|
||||
CURRENCY_UNIT, FormatMoney(payTxFee.GetFeePerK())), false, OptionsCategory::WALLET_FEE);
|
||||
CURRENCY_UNIT, FormatMoney(CFeeRate{DEFAULT_PAY_TX_FEE}.GetFeePerK())), false, OptionsCategory::WALLET_FEE);
|
||||
gArgs.AddArg("-txconfirmtarget=<n>", strprintf("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)", DEFAULT_TX_CONFIRM_TARGET), false, OptionsCategory::WALLET_FEE);
|
||||
|
||||
gArgs.AddArg("-hdseed=<hex>", "User defined seed for HD wallet (should be in hex). Only has effect during wallet creation/first start (default: randomly generated)", false, OptionsCategory::WALLET_HD);
|
||||
@ -184,52 +184,6 @@ bool WalletInit::ParameterInteraction() const
|
||||
InitWarning(AmountHighWarn("-minrelaytxfee") + " " +
|
||||
_("The wallet will avoid paying less than the minimum relay fee."));
|
||||
|
||||
if (gArgs.IsArgSet("-mintxfee"))
|
||||
{
|
||||
CAmount n = 0;
|
||||
if (!ParseMoney(gArgs.GetArg("-mintxfee", ""), n) || 0 == n)
|
||||
return InitError(AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", "")));
|
||||
if (n > HIGH_TX_FEE_PER_KB)
|
||||
InitWarning(AmountHighWarn("-mintxfee") + " " +
|
||||
_("This is the minimum transaction fee you pay on every transaction."));
|
||||
CWallet::minTxFee = CFeeRate(n);
|
||||
}
|
||||
if (gArgs.IsArgSet("-fallbackfee"))
|
||||
{
|
||||
CAmount nFeePerK = 0;
|
||||
if (!ParseMoney(gArgs.GetArg("-fallbackfee", ""), nFeePerK))
|
||||
return InitError(strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'"), gArgs.GetArg("-fallbackfee", "")));
|
||||
if (nFeePerK > HIGH_TX_FEE_PER_KB)
|
||||
InitWarning(AmountHighWarn("-fallbackfee") + " " +
|
||||
_("This is the transaction fee you may pay when fee estimates are not available."));
|
||||
CWallet::fallbackFee = CFeeRate(nFeePerK);
|
||||
}
|
||||
if (gArgs.IsArgSet("-discardfee"))
|
||||
{
|
||||
CAmount nFeePerK = 0;
|
||||
if (!ParseMoney(gArgs.GetArg("-discardfee", ""), nFeePerK))
|
||||
return InitError(strprintf(_("Invalid amount for -discardfee=<amount>: '%s'"), gArgs.GetArg("-discardfee", "")));
|
||||
if (nFeePerK > HIGH_TX_FEE_PER_KB)
|
||||
InitWarning(AmountHighWarn("-discardfee") + " " +
|
||||
_("This is the transaction fee you may discard if change is smaller than dust at this level"));
|
||||
CWallet::m_discard_rate = CFeeRate(nFeePerK);
|
||||
}
|
||||
if (gArgs.IsArgSet("-paytxfee"))
|
||||
{
|
||||
CAmount nFeePerK = 0;
|
||||
if (!ParseMoney(gArgs.GetArg("-paytxfee", ""), nFeePerK))
|
||||
return InitError(AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", "")));
|
||||
if (nFeePerK > HIGH_TX_FEE_PER_KB)
|
||||
InitWarning(AmountHighWarn("-paytxfee") + " " +
|
||||
_("This is the transaction fee you will pay if you send a transaction."));
|
||||
|
||||
payTxFee = CFeeRate(nFeePerK, 1000);
|
||||
if (payTxFee < ::minRelayTxFee)
|
||||
{
|
||||
return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
|
||||
gArgs.GetArg("-paytxfee", ""), ::minRelayTxFee.ToString()));
|
||||
}
|
||||
}
|
||||
if (gArgs.IsArgSet("-maxtxfee"))
|
||||
{
|
||||
CAmount nMaxFee = 0;
|
||||
@ -244,8 +198,6 @@ bool WalletInit::ParameterInteraction() const
|
||||
gArgs.GetArg("-maxtxfee", ""), ::minRelayTxFee.ToString()));
|
||||
}
|
||||
}
|
||||
nTxConfirmTarget = gArgs.GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
|
||||
bSpendZeroConfChange = gArgs.GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
|
||||
|
||||
if (gArgs.IsArgSet("-walletbackupsdir")) {
|
||||
if (!fs::is_directory(gArgs.GetArg("-walletbackupsdir", ""))) {
|
||||
|
@ -2912,10 +2912,10 @@ UniValue settxfee(const JSONRPCRequest& request)
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
if (request.fHelp || request.params.size() < 1 || request.params.size() > 1)
|
||||
if (request.fHelp || request.params.size() < 1 || request.params.size() > 1) {
|
||||
throw std::runtime_error(
|
||||
"settxfee amount\n"
|
||||
"\nSet the transaction fee per kB. Overwrites the paytxfee parameter.\n"
|
||||
"\nSet the transaction fee per kB for this wallet. Overrides the global -paytxfee command line parameter.\n"
|
||||
"\nArguments:\n"
|
||||
"1. amount (numeric or string, required) The transaction fee in " + CURRENCY_UNIT + "/kB\n"
|
||||
"\nResult:\n"
|
||||
@ -2924,13 +2924,13 @@ UniValue settxfee(const JSONRPCRequest& request)
|
||||
+ HelpExampleCli("settxfee", "0.00001")
|
||||
+ HelpExampleRpc("settxfee", "0.00001")
|
||||
);
|
||||
}
|
||||
|
||||
LOCK2(cs_main, pwallet->cs_wallet);
|
||||
|
||||
// Amount
|
||||
CAmount nAmount = AmountFromValue(request.params[0]);
|
||||
|
||||
payTxFee = CFeeRate(nAmount, 1000);
|
||||
pwallet->m_pay_tx_fee = CFeeRate(nAmount, 1000);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3067,7 +3067,7 @@ UniValue getwalletinfo(const JSONRPCRequest& request)
|
||||
obj.pushKV("keys_left", pwallet->nKeysLeftSinceAutoBackup);
|
||||
if (pwallet->IsCrypted())
|
||||
obj.pushKV("unlocked_until", pwallet->nRelockTime);
|
||||
obj.pushKV("paytxfee", ValueFromAmount(payTxFee.GetFeePerK()));
|
||||
obj.pushKV("paytxfee", ValueFromAmount(pwallet->m_pay_tx_fee.GetFeePerK()));
|
||||
if (fHDEnabled) {
|
||||
obj.pushKV("hdchainid", hdChainCurrent.GetID().GetHex());
|
||||
obj.pushKV("hdaccountcount", (int64_t)hdChainCurrent.CountAccounts());
|
||||
|
@ -92,24 +92,6 @@ std::shared_ptr<CWallet> GetWallet(const std::string& name)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/** Transaction fee set by the user */
|
||||
CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE);
|
||||
unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET;
|
||||
bool bSpendZeroConfChange = DEFAULT_SPEND_ZEROCONF_CHANGE;
|
||||
|
||||
/**
|
||||
* Fees smaller than this (in duffs) are considered zero fee (for transaction creation)
|
||||
* Override with -mintxfee
|
||||
*/
|
||||
CFeeRate CWallet::minTxFee = CFeeRate(DEFAULT_TRANSACTION_MINFEE);
|
||||
/**
|
||||
* If fee estimation does not have enough data to provide estimates, use this fee instead.
|
||||
* Has no effect if not using fee estimation
|
||||
* Override with -fallbackfee
|
||||
*/
|
||||
CFeeRate CWallet::fallbackFee = CFeeRate(DEFAULT_FALLBACK_FEE);
|
||||
|
||||
CFeeRate CWallet::m_discard_rate = CFeeRate(DEFAULT_DISCARD_FEE);
|
||||
|
||||
// Custom deleter for shared_ptr<CWallet>.
|
||||
static void ReleaseWallet(CWallet* wallet)
|
||||
@ -2587,7 +2569,7 @@ bool CWalletTx::IsTrusted() const
|
||||
return false;
|
||||
if (IsLockedByInstantSend())
|
||||
return true;
|
||||
if (!bSpendZeroConfChange || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit
|
||||
if (!pwallet->m_spend_zero_conf_change || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit
|
||||
return false;
|
||||
|
||||
// Don't trust unconfirmed transactions from us unless they are in the mempool.
|
||||
@ -3134,10 +3116,10 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibil
|
||||
FeeCalculation feeCalc;
|
||||
CCoinControl temp;
|
||||
temp.m_confirm_target = 1008;
|
||||
CFeeRate long_term_feerate = GetMinimumFeeRate(temp, ::mempool, ::feeEstimator, &feeCalc);
|
||||
CFeeRate long_term_feerate = GetMinimumFeeRate(*this, temp, ::mempool, ::feeEstimator, &feeCalc);
|
||||
|
||||
// Calculate cost of change
|
||||
CAmount cost_of_change = GetDiscardRate(::feeEstimator).GetFee(coin_selection_params.change_spend_size) + coin_selection_params.effective_fee.GetFee(coin_selection_params.change_output_size);
|
||||
CAmount cost_of_change = GetDiscardRate(*this, ::feeEstimator).GetFee(coin_selection_params.change_spend_size) + coin_selection_params.effective_fee.GetFee(coin_selection_params.change_output_size);
|
||||
|
||||
// Filter by the min conf specs and add to utxo_pool and calculate effective value
|
||||
for (const COutput &output : vCoins)
|
||||
@ -3250,11 +3232,11 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
|
||||
bool res = nTargetValue <= nValueFromPresetInputs ||
|
||||
SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(1, 6, 0), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType) ||
|
||||
SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(1, 1, 0), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType) ||
|
||||
(bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, 2), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType)) ||
|
||||
(bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, std::min((size_t)4, max_ancestors/3), std::min((size_t)4, max_descendants/3)), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType)) ||
|
||||
(bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, max_ancestors/2, max_descendants/2), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType)) ||
|
||||
(bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, max_ancestors-1, max_descendants-1), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType)) ||
|
||||
(bSpendZeroConfChange && !fRejectLongChains && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, std::numeric_limits<uint64_t>::max()), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType));
|
||||
(m_spend_zero_conf_change && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, 2), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType)) ||
|
||||
(m_spend_zero_conf_change && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, std::min((size_t)4, max_ancestors/3), std::min((size_t)4, max_descendants/3)), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType)) ||
|
||||
(m_spend_zero_conf_change && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, max_ancestors/2, max_descendants/2), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType)) ||
|
||||
(m_spend_zero_conf_change && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, max_ancestors-1, max_descendants-1), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType)) ||
|
||||
(m_spend_zero_conf_change && !fRejectLongChains && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, std::numeric_limits<uint64_t>::max()), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType));
|
||||
|
||||
// because SelectCoinsMinConf clears the setCoinsRet, we now add the possible inputs to the coinset
|
||||
setCoinsRet.insert(setPresetCoins.begin(), setPresetCoins.end());
|
||||
@ -3615,7 +3597,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
|
||||
assert(txNew.nLockTime <= (unsigned int)chainActive.Height());
|
||||
assert(txNew.nLockTime < LOCKTIME_THRESHOLD);
|
||||
FeeCalculation feeCalc;
|
||||
CFeeRate discard_rate = coin_control.m_discard_feerate ? *coin_control.m_discard_feerate : GetDiscardRate(::feeEstimator);
|
||||
CFeeRate discard_rate = coin_control.m_discard_feerate ? *coin_control.m_discard_feerate : GetDiscardRate(*this, ::feeEstimator);
|
||||
unsigned int nBytes;
|
||||
{
|
||||
std::vector<CInputCoin> vecCoins;
|
||||
@ -3776,7 +3758,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
|
||||
txin.scriptSig = CScript();
|
||||
}
|
||||
|
||||
nFee = GetMinimumFee(nBytes, coin_control, ::mempool, ::feeEstimator, &feeCalc);
|
||||
nFee = GetMinimumFee(*this, nBytes, coin_control, ::mempool, ::feeEstimator, &feeCalc);
|
||||
|
||||
// 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.
|
||||
@ -5143,6 +5125,66 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const WalletLocation& loc
|
||||
InitWarning(_("Make sure to encrypt your wallet and delete all non-encrypted backups after you have verified that the wallet works!"));
|
||||
}
|
||||
|
||||
if (gArgs.IsArgSet("-mintxfee")) {
|
||||
CAmount n = 0;
|
||||
if (!ParseMoney(gArgs.GetArg("-mintxfee", ""), n) || 0 == n) {
|
||||
InitError(AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", "")));
|
||||
return nullptr;
|
||||
}
|
||||
if (n > HIGH_TX_FEE_PER_KB) {
|
||||
InitWarning(AmountHighWarn("-mintxfee") + " " +
|
||||
_("This is the minimum transaction fee you pay on every transaction."));
|
||||
}
|
||||
walletInstance->m_min_fee = CFeeRate(n);
|
||||
}
|
||||
|
||||
// TODO: enable when IsFallbackFeeEnabled is backported
|
||||
// walletInstance->m_allow_fallback_fee = Params().IsFallbackFeeEnabled();
|
||||
if (gArgs.IsArgSet("-fallbackfee")) {
|
||||
CAmount nFeePerK = 0;
|
||||
if (!ParseMoney(gArgs.GetArg("-fallbackfee", ""), nFeePerK)) {
|
||||
InitError(strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'"), gArgs.GetArg("-fallbackfee", "")));
|
||||
return nullptr;
|
||||
}
|
||||
if (nFeePerK > HIGH_TX_FEE_PER_KB) {
|
||||
InitWarning(AmountHighWarn("-fallbackfee") + " " +
|
||||
_("This is the transaction fee you may pay when fee estimates are not available."));
|
||||
}
|
||||
walletInstance->m_fallback_fee = CFeeRate(nFeePerK);
|
||||
walletInstance->m_allow_fallback_fee = nFeePerK != 0; //disable fallback fee in case value was set to 0, enable if non-null value
|
||||
}
|
||||
if (gArgs.IsArgSet("-discardfee")) {
|
||||
CAmount nFeePerK = 0;
|
||||
if (!ParseMoney(gArgs.GetArg("-discardfee", ""), nFeePerK)) {
|
||||
InitError(strprintf(_("Invalid amount for -discardfee=<amount>: '%s'"), gArgs.GetArg("-discardfee", "")));
|
||||
return nullptr;
|
||||
}
|
||||
if (nFeePerK > HIGH_TX_FEE_PER_KB) {
|
||||
InitWarning(AmountHighWarn("-discardfee") + " " +
|
||||
_("This is the transaction fee you may discard if change is smaller than dust at this level"));
|
||||
}
|
||||
walletInstance->m_discard_rate = CFeeRate(nFeePerK);
|
||||
}
|
||||
if (gArgs.IsArgSet("-paytxfee")) {
|
||||
CAmount nFeePerK = 0;
|
||||
if (!ParseMoney(gArgs.GetArg("-paytxfee", ""), nFeePerK)) {
|
||||
InitError(AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", "")));
|
||||
return nullptr;
|
||||
}
|
||||
if (nFeePerK > HIGH_TX_FEE_PER_KB) {
|
||||
InitWarning(AmountHighWarn("-paytxfee") + " " +
|
||||
_("This is the transaction fee you will pay if you send a transaction."));
|
||||
}
|
||||
walletInstance->m_pay_tx_fee = CFeeRate(nFeePerK, 1000);
|
||||
if (walletInstance->m_pay_tx_fee < ::minRelayTxFee) {
|
||||
InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
|
||||
gArgs.GetArg("-paytxfee", ""), ::minRelayTxFee.ToString()));
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
walletInstance->m_confirm_target = gArgs.GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
|
||||
walletInstance->m_spend_zero_conf_change = gArgs.GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
|
||||
|
||||
LogPrintf(" wallet %15dms\n", GetTimeMillis() - nStart);
|
||||
|
||||
// Try to top up keypool. No-op if the wallet is locked.
|
||||
|
@ -44,19 +44,12 @@ bool HasWallets();
|
||||
std::vector<std::shared_ptr<CWallet>> GetWallets();
|
||||
std::shared_ptr<CWallet> GetWallet(const std::string& name);
|
||||
|
||||
/**
|
||||
* Settings
|
||||
*/
|
||||
extern CFeeRate payTxFee;
|
||||
extern unsigned int nTxConfirmTarget;
|
||||
extern bool bSpendZeroConfChange;
|
||||
|
||||
static const unsigned int DEFAULT_KEYPOOL_SIZE = 1000;
|
||||
//! -paytxfee default
|
||||
static const CAmount DEFAULT_TRANSACTION_FEE = 0;
|
||||
constexpr CAmount DEFAULT_PAY_TX_FEE = 0;
|
||||
//! -fallbackfee default
|
||||
static const CAmount DEFAULT_FALLBACK_FEE = 1000;
|
||||
//! -m_discard_rate default
|
||||
//! -discardfee default
|
||||
static const CAmount DEFAULT_DISCARD_FEE = 10000;
|
||||
//! -mintxfee default
|
||||
static const CAmount DEFAULT_TRANSACTION_MINFEE = 1000;
|
||||
@ -1082,9 +1075,18 @@ public:
|
||||
bool DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut> &txouts) const;
|
||||
bool DummySignInput(CTxIn &tx_in, const CTxOut &txout) const;
|
||||
|
||||
static CFeeRate minTxFee;
|
||||
static CFeeRate fallbackFee;
|
||||
static CFeeRate m_discard_rate;
|
||||
CFeeRate m_pay_tx_fee{DEFAULT_PAY_TX_FEE};
|
||||
unsigned int m_confirm_target{DEFAULT_TX_CONFIRM_TARGET};
|
||||
bool m_spend_zero_conf_change{DEFAULT_SPEND_ZEROCONF_CHANGE};
|
||||
bool m_allow_fallback_fee{true}; //<! will be defined via chainparams
|
||||
CFeeRate m_min_fee{DEFAULT_TRANSACTION_MINFEE}; //!< Override with -mintxfee
|
||||
/**
|
||||
* If fee estimation does not have enough data to provide estimates, use this fee instead.
|
||||
* Has no effect if not using fee estimation
|
||||
* Override with -fallbackfee
|
||||
*/
|
||||
CFeeRate m_fallback_fee{DEFAULT_FALLBACK_FEE};
|
||||
CFeeRate m_discard_rate{DEFAULT_DISCARD_FEE};
|
||||
|
||||
bool NewKeyPool();
|
||||
size_t KeypoolCountExternalKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
@ -163,6 +163,12 @@ class MultiWalletTest(BitcoinTestFramework):
|
||||
assert_equal(batch[0]["result"]["chain"], self.chain)
|
||||
assert_equal(batch[1]["result"]["walletname"], "w1")
|
||||
|
||||
self.log.info('Check for per-wallet settxfee call')
|
||||
assert_equal(w1.getwalletinfo()['paytxfee'], 0)
|
||||
assert_equal(w2.getwalletinfo()['paytxfee'], 0)
|
||||
w2.settxfee(4.0)
|
||||
assert_equal(w1.getwalletinfo()['paytxfee'], 0)
|
||||
assert_equal(w2.getwalletinfo()['paytxfee'], 4.0)
|
||||
|
||||
self.log.info("Test dynamic wallet loading")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user