mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 04:22:55 +01:00
wallet: Make fee settings non-static members
This commit is contained in:
parent
d5b2e98250
commit
fac0db0ff8
@ -191,20 +191,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;
|
||||
|
||||
@ -152,18 +150,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;
|
||||
|
||||
|
@ -9,6 +9,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>
|
||||
@ -20,6 +22,7 @@
|
||||
#include <uint256.h>
|
||||
#include <validation.h>
|
||||
#include <wallet/feebumper.h>
|
||||
#include <wallet/fees.h>
|
||||
#include <wallet/wallet.h>
|
||||
|
||||
namespace interfaces {
|
||||
@ -403,6 +406,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(); }
|
||||
OutputType getDefaultAddressType() override { return m_wallet.m_default_address_type; }
|
||||
OutputType getDefaultChangeType() override { return m_wallet.m_default_change_type; }
|
||||
|
@ -22,8 +22,10 @@
|
||||
#include <vector>
|
||||
|
||||
class CCoinControl;
|
||||
class CFeeRate;
|
||||
class CKey;
|
||||
class CWallet;
|
||||
enum class FeeReason;
|
||||
enum class OutputType;
|
||||
struct CRecipient;
|
||||
|
||||
@ -218,6 +220,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;
|
||||
|
||||
|
@ -509,7 +509,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
|
||||
nBytes -= 34;
|
||||
|
||||
// Fee
|
||||
nPayFee = model->node().getMinimumFee(nBytes, *coinControl(), nullptr /* returned_target */, nullptr /* reason */);
|
||||
nPayFee = model->wallet().getMinimumFee(nBytes, *coinControl(), nullptr /* returned_target */, nullptr /* reason */);
|
||||
|
||||
if (nPayAmount > 0)
|
||||
{
|
||||
|
@ -114,7 +114,7 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *p
|
||||
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);
|
||||
ui->groupFee->setId(ui->radioSmartFee, 0);
|
||||
@ -175,7 +175,7 @@ void SendCoinsDialog::setModel(WalletModel *_model)
|
||||
connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(coinControlUpdateLabels()));
|
||||
connect(ui->optInRBF, SIGNAL(stateChanged(int)), this, SLOT(updateSmartFeeLabel()));
|
||||
connect(ui->optInRBF, SIGNAL(stateChanged(int)), this, SLOT(coinControlUpdateLabels()));
|
||||
ui->customFee->setSingleStep(model->node().getRequiredFee(1000));
|
||||
ui->customFee->setSingleStep(model->wallet().getRequiredFee(1000));
|
||||
updateFeeSectionControls();
|
||||
updateMinFeeLabel();
|
||||
updateSmartFeeLabel();
|
||||
@ -193,7 +193,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()));
|
||||
}
|
||||
@ -629,7 +629,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()
|
||||
@ -661,7 +661,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")
|
||||
);
|
||||
}
|
||||
|
||||
@ -675,7 +675,7 @@ void SendCoinsDialog::updateCoinControlState(CCoinControl& ctrl)
|
||||
// Avoid using global defaults when sending money from the GUI
|
||||
// Either custom fee will be used or if not selected, the confirmation target from dropdown box
|
||||
ctrl.m_confirm_target = getConfTargetForIndex(ui->confTargetSelector->currentIndex());
|
||||
ctrl.signalRbf = ui->optInRBF->isChecked();
|
||||
ctrl.m_signal_bip125_rbf = ui->optInRBF->isChecked();
|
||||
}
|
||||
|
||||
void SendCoinsDialog::updateSmartFeeLabel()
|
||||
@ -687,7 +687,7 @@ void SendCoinsDialog::updateSmartFeeLabel()
|
||||
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, coin_control, &returned_target, &reason));
|
||||
CFeeRate feeRate = CFeeRate(model->wallet().getMinimumFee(1000, coin_control, &returned_target, &reason));
|
||||
|
||||
ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), feeRate.GetFeePerK()) + "/kB");
|
||||
|
||||
|
@ -486,7 +486,7 @@ bool WalletModel::saveReceiveRequest(const std::string &sAddress, const int64_t
|
||||
bool WalletModel::bumpFee(uint256 hash)
|
||||
{
|
||||
CCoinControl coin_control;
|
||||
coin_control.signalRbf = true;
|
||||
coin_control.m_signal_bip125_rbf = true;
|
||||
std::vector<std::string> errors;
|
||||
CAmount old_fee;
|
||||
CAmount new_fee;
|
||||
|
@ -26,12 +26,12 @@ 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 default confirmation target if set
|
||||
boost::optional<unsigned int> m_confirm_target;
|
||||
//! Signal BIP-125 replace by fee.
|
||||
bool signalRbf;
|
||||
//! Override the wallet's m_signal_rbf if set
|
||||
boost::optional<bool> m_signal_bip125_rbf;
|
||||
//! Fee estimation mode to control arguments to estimateSmartFee
|
||||
FeeEstimateMode m_fee_mode;
|
||||
|
||||
@ -50,7 +50,7 @@ public:
|
||||
m_feerate.reset();
|
||||
fOverrideFeeRate = false;
|
||||
m_confirm_target.reset();
|
||||
signalRbf = fWalletRbf;
|
||||
m_signal_bip125_rbf.reset();
|
||||
m_fee_mode = FeeEstimateMode::UNSET;
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,7 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin
|
||||
FormatMoney(minTotalFee), FormatMoney(nOldFeeRate.GetFee(maxNewTxSize)), FormatMoney(::incrementalRelayFee.GetFee(maxNewTxSize))));
|
||||
return Result::INVALID_PARAMETER;
|
||||
}
|
||||
CAmount requiredFee = GetRequiredFee(maxNewTxSize);
|
||||
CAmount requiredFee = GetRequiredFee(*wallet, maxNewTxSize);
|
||||
if (total_fee < requiredFee) {
|
||||
errors.push_back(strprintf("Insufficient totalFee (cannot be less than required fee %s)",
|
||||
FormatMoney(requiredFee)));
|
||||
@ -143,7 +143,7 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin
|
||||
new_fee = total_fee;
|
||||
nNewFeeRate = CFeeRate(total_fee, maxNewTxSize);
|
||||
} else {
|
||||
new_fee = GetMinimumFee(maxNewTxSize, coin_control, mempool, ::feeEstimator, nullptr /* FeeCalculation */);
|
||||
new_fee = GetMinimumFee(*wallet, maxNewTxSize, coin_control, mempool, ::feeEstimator, nullptr /* FeeCalculation */);
|
||||
nNewFeeRate = CFeeRate(new_fee, maxNewTxSize);
|
||||
|
||||
// New fee rate must be at least old rate + minimum incremental relay rate
|
||||
@ -194,14 +194,14 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin
|
||||
|
||||
// If the output would become dust, discard it (converting the dust to fee)
|
||||
poutput->nValue -= nDelta;
|
||||
if (poutput->nValue <= GetDustThreshold(*poutput, GetDiscardRate(::feeEstimator))) {
|
||||
if (poutput->nValue <= GetDustThreshold(*poutput, GetDiscardRate(*wallet, ::feeEstimator))) {
|
||||
LogPrint(BCLog::RPC, "Bumping fee and discarding dust output\n");
|
||||
new_fee += poutput->nValue;
|
||||
mtx.vout.erase(mtx.vout.begin() + nOutput);
|
||||
}
|
||||
|
||||
// Mark new tx not replaceable, if requested.
|
||||
if (!coin_control.signalRbf) {
|
||||
if (!coin_control.m_signal_bip125_rbf.get_value_or(wallet->m_signal_rbf)) {
|
||||
for (auto& input : mtx.vin) {
|
||||
if (input.nSequence < 0xfffffffe) input.nSequence = 0xfffffffe;
|
||||
}
|
||||
|
@ -13,15 +13,15 @@
|
||||
#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;
|
||||
@ -30,48 +30,48 @@ 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 iff we are signaling opt-in-RBF
|
||||
bool conservative_estimate = !coin_control.signalRbf;
|
||||
bool conservative_estimate = !coin_control.m_signal_bip125_rbf.get_value_or(wallet.m_signal_rbf);
|
||||
// Allow to override the default fee estimate mode over the CoinControl instance
|
||||
if (coin_control.m_fee_mode == FeeEstimateMode::CONSERVATIVE) conservative_estimate = true;
|
||||
else if (coin_control.m_fee_mode == FeeEstimateMode::ECONOMICAL) conservative_estimate = false;
|
||||
|
||||
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;
|
||||
|
||||
// directly return if fallback fee is disabled (feerate 0 == disabled)
|
||||
if (CWallet::fallbackFee == CFeeRate(0)) return feerate_needed;
|
||||
if (wallet.m_fallback_fee == CFeeRate(0)) return feerate_needed;
|
||||
}
|
||||
// Obey mempool min fee when using smart fee estimation
|
||||
CFeeRate min_mempool_feerate = pool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000);
|
||||
@ -81,8 +81,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;
|
||||
@ -90,12 +90,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
|
||||
|
@ -64,7 +64,7 @@ std::string WalletInit::GetHelpString(bool showDebug) const
|
||||
strUsage += HelpMessageOpt("-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)));
|
||||
strUsage += HelpMessageOpt("-paytxfee=<amt>", strprintf(_("Fee (in %s/kB) to add to transactions you send (default: %s)"),
|
||||
CURRENCY_UNIT, FormatMoney(payTxFee.GetFeePerK())));
|
||||
CURRENCY_UNIT, FormatMoney(CFeeRate{DEFAULT_PAY_TX_FEE}.GetFeePerK())));
|
||||
strUsage += HelpMessageOpt("-rescan", _("Rescan the block chain for missing wallet transactions on startup"));
|
||||
strUsage += HelpMessageOpt("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet on startup"));
|
||||
strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), DEFAULT_SPEND_ZEROCONF_CHANGE));
|
||||
@ -149,55 +149,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);
|
||||
}
|
||||
|
||||
g_wallet_allow_fallback_fee = Params().IsFallbackFeeEnabled();
|
||||
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);
|
||||
g_wallet_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))
|
||||
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;
|
||||
@ -212,9 +163,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);
|
||||
fWalletRbf = gArgs.GetBoolArg("-walletrbf", DEFAULT_WALLET_RBF);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -529,7 +529,7 @@ UniValue sendtoaddress(const JSONRPCRequest& request)
|
||||
|
||||
CCoinControl coin_control;
|
||||
if (!request.params[5].isNull()) {
|
||||
coin_control.signalRbf = request.params[5].get_bool();
|
||||
coin_control.m_signal_bip125_rbf = request.params[5].get_bool();
|
||||
}
|
||||
|
||||
if (!request.params[6].isNull()) {
|
||||
@ -1108,7 +1108,7 @@ UniValue sendmany(const JSONRPCRequest& request)
|
||||
|
||||
CCoinControl coin_control;
|
||||
if (!request.params[5].isNull()) {
|
||||
coin_control.signalRbf = request.params[5].get_bool();
|
||||
coin_control.m_signal_bip125_rbf = request.params[5].get_bool();
|
||||
}
|
||||
|
||||
if (!request.params[6].isNull()) {
|
||||
@ -2757,10 +2757,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"
|
||||
@ -2769,13 +2769,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;
|
||||
}
|
||||
|
||||
@ -2836,9 +2836,9 @@ UniValue getwalletinfo(const JSONRPCRequest& request)
|
||||
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 (!masterKeyID.IsNull())
|
||||
obj.pushKV("hdmasterkeyid", masterKeyID.GetHex());
|
||||
obj.pushKV("hdmasterkeyid", masterKeyID.GetHex());
|
||||
return obj;
|
||||
}
|
||||
|
||||
@ -3217,7 +3217,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
|
||||
subtractFeeFromOutputs = options["subtractFeeFromOutputs"].get_array();
|
||||
|
||||
if (options.exists("replaceable")) {
|
||||
coinControl.signalRbf = options["replaceable"].get_bool();
|
||||
coinControl.m_signal_bip125_rbf = options["replaceable"].get_bool();
|
||||
}
|
||||
if (options.exists("conf_target")) {
|
||||
if (options.exists("feeRate")) {
|
||||
@ -3406,7 +3406,7 @@ UniValue bumpfee(const JSONRPCRequest& request)
|
||||
// optional parameters
|
||||
CAmount totalFee = 0;
|
||||
CCoinControl coin_control;
|
||||
coin_control.signalRbf = true;
|
||||
coin_control.m_signal_bip125_rbf = true;
|
||||
if (!request.params[1].isNull()) {
|
||||
UniValue options = request.params[1];
|
||||
RPCTypeCheckObj(options,
|
||||
@ -3430,7 +3430,7 @@ UniValue bumpfee(const JSONRPCRequest& request)
|
||||
}
|
||||
|
||||
if (options.exists("replaceable")) {
|
||||
coin_control.signalRbf = options["replaceable"].get_bool();
|
||||
coin_control.m_signal_bip125_rbf = options["replaceable"].get_bool();
|
||||
}
|
||||
if (options.exists("estimate_mode")) {
|
||||
if (!FeeModeFromString(options["estimate_mode"].get_str(), coin_control.m_fee_mode)) {
|
||||
|
@ -72,29 +72,8 @@ 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;
|
||||
bool fWalletRbf = DEFAULT_WALLET_RBF;
|
||||
bool g_wallet_allow_fallback_fee = true; //<! will be defined via chainparams
|
||||
|
||||
const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;
|
||||
|
||||
/**
|
||||
* Fees smaller than this (in satoshi) 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);
|
||||
|
||||
const uint256 CMerkleTx::ABANDON_HASH(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
|
||||
|
||||
/** @defgroup mapWallet
|
||||
@ -2054,7 +2033,7 @@ bool CWalletTx::IsTrusted() const
|
||||
return true;
|
||||
if (nDepth < 0)
|
||||
return false;
|
||||
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.
|
||||
@ -2490,10 +2469,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)
|
||||
@ -2590,11 +2569,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) ||
|
||||
SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(1, 1, 0), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used) ||
|
||||
(bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, 2), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
|
||||
(bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, std::min((size_t)4, nMaxChainLength/3)), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
|
||||
(bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, nMaxChainLength/2), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
|
||||
(bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, nMaxChainLength), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
|
||||
(bSpendZeroConfChange && !fRejectLongChains && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, std::numeric_limits<uint64_t>::max()), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used));
|
||||
(m_spend_zero_conf_change && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, 2), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
|
||||
(m_spend_zero_conf_change && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, std::min((size_t)4, nMaxChainLength/3)), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
|
||||
(m_spend_zero_conf_change && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, nMaxChainLength/2), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
|
||||
(m_spend_zero_conf_change && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, nMaxChainLength), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
|
||||
(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));
|
||||
|
||||
// because SelectCoinsMinConf clears the setCoinsRet, we now add the possible inputs to the coinset
|
||||
setCoinsRet.insert(setPresetCoins.begin(), setPresetCoins.end());
|
||||
@ -2813,10 +2792,10 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
|
||||
CTxOut change_prototype_txout(0, scriptChange);
|
||||
coin_selection_params.change_output_size = GetSerializeSize(change_prototype_txout, SER_DISK, 0);
|
||||
|
||||
CFeeRate discard_rate = GetDiscardRate(::feeEstimator);
|
||||
CFeeRate discard_rate = GetDiscardRate(*this, ::feeEstimator);
|
||||
|
||||
// Get the fee rate to use effective values in coin selection
|
||||
CFeeRate nFeeRateNeeded = GetMinimumFeeRate(coin_control, ::mempool, ::feeEstimator, &feeCalc);
|
||||
CFeeRate nFeeRateNeeded = GetMinimumFeeRate(*this, coin_control, ::mempool, ::feeEstimator, &feeCalc);
|
||||
|
||||
nFeeRet = 0;
|
||||
bool pick_new_inputs = true;
|
||||
@ -2940,8 +2919,8 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
|
||||
return false;
|
||||
}
|
||||
|
||||
nFeeNeeded = GetMinimumFee(nBytes, coin_control, ::mempool, ::feeEstimator, &feeCalc);
|
||||
if (feeCalc.reason == FeeReason::FALLBACK && !g_wallet_allow_fallback_fee) {
|
||||
nFeeNeeded = GetMinimumFee(*this, nBytes, coin_control, ::mempool, ::feeEstimator, &feeCalc);
|
||||
if (feeCalc.reason == FeeReason::FALLBACK && !m_allow_fallback_fee) {
|
||||
// eventually allow a fallback fee
|
||||
strFailReason = _("Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.");
|
||||
return false;
|
||||
@ -2968,7 +2947,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
|
||||
// change output. Only try this once.
|
||||
if (nChangePosInOut == -1 && nSubtractFeeFromAmount == 0 && pick_new_inputs) {
|
||||
unsigned int tx_size_with_change = nBytes + coin_selection_params.change_output_size + 2; // Add 2 as a buffer in case increasing # of outputs changes compact size
|
||||
CAmount fee_needed_with_change = GetMinimumFee(tx_size_with_change, coin_control, ::mempool, ::feeEstimator, nullptr);
|
||||
CAmount fee_needed_with_change = GetMinimumFee(*this, tx_size_with_change, coin_control, ::mempool, ::feeEstimator, nullptr);
|
||||
CAmount minimum_value_for_change = GetDustThreshold(change_prototype_txout, discard_rate);
|
||||
if (nFeeRet >= fee_needed_with_change + minimum_value_for_change) {
|
||||
pick_new_inputs = false;
|
||||
@ -3035,7 +3014,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
|
||||
// to avoid conflicting with other possible uses of nSequence,
|
||||
// and in the spirit of "smallest possible change from prior
|
||||
// behavior."
|
||||
const uint32_t nSequence = coin_control.signalRbf ? MAX_BIP125_RBF_SEQUENCE : (CTxIn::SEQUENCE_FINAL - 1);
|
||||
const uint32_t nSequence = coin_control.m_signal_bip125_rbf.get_value_or(m_signal_rbf) ? MAX_BIP125_RBF_SEQUENCE : (CTxIn::SEQUENCE_FINAL - 1);
|
||||
for (const auto& coin : selected_coins) {
|
||||
txNew.vin.push_back(CTxIn(coin.outpoint, CScript(), nSequence));
|
||||
}
|
||||
@ -4080,6 +4059,66 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
walletInstance->m_signal_rbf = gArgs.GetBoolArg("-walletrbf", DEFAULT_WALLET_RBF);
|
||||
|
||||
LogPrintf(" wallet %15dms\n", GetTimeMillis() - nStart);
|
||||
|
||||
// Try to top up keypool. No-op if the wallet is locked.
|
||||
|
@ -38,22 +38,13 @@ bool HasWallets();
|
||||
std::vector<CWallet*> GetWallets();
|
||||
CWallet* GetWallet(const std::string& name);
|
||||
|
||||
/**
|
||||
* Settings
|
||||
*/
|
||||
extern CFeeRate payTxFee;
|
||||
extern unsigned int nTxConfirmTarget;
|
||||
extern bool bSpendZeroConfChange;
|
||||
extern bool fWalletRbf;
|
||||
extern bool g_wallet_allow_fallback_fee;
|
||||
|
||||
//! Default for -keypool
|
||||
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 = 20000;
|
||||
//! -m_discard_rate default
|
||||
//! -discardfee default
|
||||
static const CAmount DEFAULT_DISCARD_FEE = 10000;
|
||||
//! -mintxfee default
|
||||
static const CAmount DEFAULT_TRANSACTION_MINFEE = 1000;
|
||||
@ -968,9 +959,19 @@ 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_signal_rbf{DEFAULT_WALLET_RBF};
|
||||
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};
|
||||
OutputType m_default_address_type{DEFAULT_ADDRESS_TYPE};
|
||||
OutputType m_default_change_type{OutputType::NONE}; // Default to OutputType::NONE if not set by -changetype
|
||||
|
||||
|
@ -150,5 +150,12 @@ class MultiWalletTest(BitcoinTestFramework):
|
||||
assert_equal(batch[0]["result"]["chain"], "regtest")
|
||||
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)
|
||||
|
||||
if __name__ == '__main__':
|
||||
MultiWalletTest().main()
|
||||
|
Loading…
Reference in New Issue
Block a user