Introduce a fee estimate mode.
GetMinimumFee now passes the conservative argument into estimateSmartFee. Call CalculateEstimateType(mode) before calling GetMinimumFee or estimateSmartFee to determine the value of this argument. CCoinControl can now be used to control this mode.
This commit is contained in:
parent
cfaef69ace
commit
d507c301bc
8 changed files with 42 additions and 8 deletions
|
@ -90,6 +90,13 @@ enum class FeeReason {
|
||||||
|
|
||||||
std::string StringForFeeReason(FeeReason reason);
|
std::string StringForFeeReason(FeeReason reason);
|
||||||
|
|
||||||
|
/* Used to determine type of fee estimation requested */
|
||||||
|
enum class FeeEstimateMode {
|
||||||
|
UNSET, //! Use default settings based on other criteria
|
||||||
|
ECONOMICAL, //! Force estimateSmartFee to use non-conservative estimates
|
||||||
|
CONSERVATIVE, //! Force estimateSmartFee to use conservative estimates
|
||||||
|
};
|
||||||
|
|
||||||
/* Used to return detailed information about a feerate bucket */
|
/* Used to return detailed information about a feerate bucket */
|
||||||
struct EstimatorBucket
|
struct EstimatorBucket
|
||||||
{
|
{
|
||||||
|
|
|
@ -490,6 +490,8 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
|
||||||
else nBytesInputs += 148;
|
else nBytesInputs += 148;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool conservative_estimate = CalculateEstimateType(FeeEstimateMode::UNSET);
|
||||||
|
|
||||||
// calculation
|
// calculation
|
||||||
if (nQuantity > 0)
|
if (nQuantity > 0)
|
||||||
{
|
{
|
||||||
|
@ -510,7 +512,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
|
||||||
nBytes -= 34;
|
nBytes -= 34;
|
||||||
|
|
||||||
// Fee
|
// Fee
|
||||||
nPayFee = CWallet::GetMinimumFee(nBytes, coinControl->nConfirmTarget, ::mempool, ::feeEstimator, nullptr /* FeeCalculation */, false /* ignoreGlobalPayTxFee */);
|
nPayFee = CWallet::GetMinimumFee(nBytes, coinControl->nConfirmTarget, ::mempool, ::feeEstimator, nullptr /* FeeCalculation */, false /* ignoreGlobalPayTxFee */, conservative_estimate);
|
||||||
|
|
||||||
if (nPayAmount > 0)
|
if (nPayAmount > 0)
|
||||||
{
|
{
|
||||||
|
@ -585,7 +587,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
|
||||||
if (payTxFee.GetFeePerK() > 0)
|
if (payTxFee.GetFeePerK() > 0)
|
||||||
dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), payTxFee.GetFeePerK()) / 1000;
|
dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), payTxFee.GetFeePerK()) / 1000;
|
||||||
else {
|
else {
|
||||||
dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), ::feeEstimator.estimateSmartFee(coinControl->nConfirmTarget, NULL, ::mempool).GetFeePerK()) / 1000;
|
dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), ::feeEstimator.estimateSmartFee(coinControl->nConfirmTarget, NULL, ::mempool, conservative_estimate).GetFeePerK()) / 1000;
|
||||||
}
|
}
|
||||||
QString toolTip4 = tr("Can vary +/- %1 satoshi(s) per input.").arg(dFeeVary);
|
QString toolTip4 = tr("Can vary +/- %1 satoshi(s) per input.").arg(dFeeVary);
|
||||||
|
|
||||||
|
|
|
@ -652,7 +652,8 @@ void SendCoinsDialog::updateSmartFeeLabel()
|
||||||
|
|
||||||
int nBlocksToConfirm = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2;
|
int nBlocksToConfirm = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2;
|
||||||
FeeCalculation feeCalc;
|
FeeCalculation feeCalc;
|
||||||
CFeeRate feeRate = ::feeEstimator.estimateSmartFee(nBlocksToConfirm, &feeCalc, ::mempool);
|
bool conservative_estimate = CalculateEstimateType(FeeEstimateMode::UNSET);
|
||||||
|
CFeeRate feeRate = ::feeEstimator.estimateSmartFee(nBlocksToConfirm, &feeCalc, ::mempool, conservative_estimate);
|
||||||
if (feeRate <= CFeeRate(0)) // not enough data => minfee
|
if (feeRate <= CFeeRate(0)) // not enough data => minfee
|
||||||
{
|
{
|
||||||
ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(),
|
ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(),
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "keystore.h"
|
#include "keystore.h"
|
||||||
#include "validation.h"
|
#include "validation.h"
|
||||||
#include "net.h" // for g_connman
|
#include "net.h" // for g_connman
|
||||||
|
#include "policy/fees.h"
|
||||||
#include "policy/rbf.h"
|
#include "policy/rbf.h"
|
||||||
#include "sync.h"
|
#include "sync.h"
|
||||||
#include "ui_interface.h"
|
#include "ui_interface.h"
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#define BITCOIN_WALLET_COINCONTROL_H
|
#define BITCOIN_WALLET_COINCONTROL_H
|
||||||
|
|
||||||
#include "policy/feerate.h"
|
#include "policy/feerate.h"
|
||||||
|
#include "policy/fees.h"
|
||||||
#include "primitives/transaction.h"
|
#include "primitives/transaction.h"
|
||||||
#include "wallet/wallet.h"
|
#include "wallet/wallet.h"
|
||||||
|
|
||||||
|
@ -26,6 +27,8 @@ public:
|
||||||
int nConfirmTarget;
|
int nConfirmTarget;
|
||||||
//! Signal BIP-125 replace by fee.
|
//! Signal BIP-125 replace by fee.
|
||||||
bool signalRbf;
|
bool signalRbf;
|
||||||
|
//! Fee estimation mode to control arguments to estimateSmartFee
|
||||||
|
FeeEstimateMode m_fee_mode;
|
||||||
|
|
||||||
CCoinControl()
|
CCoinControl()
|
||||||
{
|
{
|
||||||
|
@ -42,6 +45,7 @@ public:
|
||||||
fOverrideFeeRate = false;
|
fOverrideFeeRate = false;
|
||||||
nConfirmTarget = 0;
|
nConfirmTarget = 0;
|
||||||
signalRbf = fWalletRbf;
|
signalRbf = fWalletRbf;
|
||||||
|
m_fee_mode = FeeEstimateMode::UNSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasSelected() const
|
bool HasSelected() const
|
||||||
|
|
|
@ -165,7 +165,8 @@ CFeeBumper::CFeeBumper(const CWallet *pWallet, const uint256 txidIn, int newConf
|
||||||
nNewFee = totalFee;
|
nNewFee = totalFee;
|
||||||
nNewFeeRate = CFeeRate(totalFee, maxNewTxSize);
|
nNewFeeRate = CFeeRate(totalFee, maxNewTxSize);
|
||||||
} else {
|
} else {
|
||||||
nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool, ::feeEstimator, nullptr, ignoreGlobalPayTxFee);
|
bool conservative_estimate = CalculateEstimateType(FeeEstimateMode::UNSET);
|
||||||
|
nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool, ::feeEstimator, nullptr /* FeeCalculation */, ignoreGlobalPayTxFee, conservative_estimate);
|
||||||
nNewFeeRate = CFeeRate(nNewFee, maxNewTxSize);
|
nNewFeeRate = CFeeRate(nNewFee, maxNewTxSize);
|
||||||
|
|
||||||
// New fee rate must be at least old rate + minimum incremental relay rate
|
// New fee rate must be at least old rate + minimum incremental relay rate
|
||||||
|
|
|
@ -2724,7 +2724,10 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
|
||||||
if (coinControl && coinControl->nConfirmTarget > 0)
|
if (coinControl && coinControl->nConfirmTarget > 0)
|
||||||
currentConfirmationTarget = coinControl->nConfirmTarget;
|
currentConfirmationTarget = coinControl->nConfirmTarget;
|
||||||
|
|
||||||
CAmount nFeeNeeded = GetMinimumFee(nBytes, currentConfirmationTarget, ::mempool, ::feeEstimator, &feeCalc, false /* ignoreGlobalPayTxFee */);
|
// Allow to override the default fee estimate mode over the CoinControl instance
|
||||||
|
bool conservative_estimate = CalculateEstimateType(coinControl ? coinControl->m_fee_mode : FeeEstimateMode::UNSET);
|
||||||
|
|
||||||
|
CAmount nFeeNeeded = GetMinimumFee(nBytes, currentConfirmationTarget, ::mempool, ::feeEstimator, &feeCalc, false /* ignoreGlobalPayTxFee */, conservative_estimate);
|
||||||
if (coinControl && coinControl->fOverrideFeeRate)
|
if (coinControl && coinControl->fOverrideFeeRate)
|
||||||
nFeeNeeded = coinControl->nFeeRate.GetFee(nBytes);
|
nFeeNeeded = coinControl->nFeeRate.GetFee(nBytes);
|
||||||
|
|
||||||
|
@ -2905,13 +2908,13 @@ CAmount CWallet::GetRequiredFee(unsigned int nTxBytes)
|
||||||
return std::max(minTxFee.GetFee(nTxBytes), ::minRelayTxFee.GetFee(nTxBytes));
|
return std::max(minTxFee.GetFee(nTxBytes), ::minRelayTxFee.GetFee(nTxBytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation *feeCalc, bool ignoreGlobalPayTxFee)
|
CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation *feeCalc, bool ignoreGlobalPayTxFee, bool conservative_estimate)
|
||||||
{
|
{
|
||||||
// payTxFee is the user-set global for desired feerate
|
// payTxFee is the user-set global for desired feerate
|
||||||
CAmount nFeeNeeded = payTxFee.GetFee(nTxBytes);
|
CAmount nFeeNeeded = payTxFee.GetFee(nTxBytes);
|
||||||
// User didn't set: use -txconfirmtarget to estimate...
|
// User didn't set: use -txconfirmtarget to estimate...
|
||||||
if (nFeeNeeded == 0 || ignoreGlobalPayTxFee) {
|
if (nFeeNeeded == 0 || ignoreGlobalPayTxFee) {
|
||||||
nFeeNeeded = estimator.estimateSmartFee(nConfirmTarget, feeCalc, pool, true).GetFee(nTxBytes);
|
nFeeNeeded = estimator.estimateSmartFee(nConfirmTarget, feeCalc, pool, conservative_estimate).GetFee(nTxBytes);
|
||||||
// ... unless we don't have enough mempool data for estimatefee, then use fallbackFee
|
// ... unless we don't have enough mempool data for estimatefee, then use fallbackFee
|
||||||
if (nFeeNeeded == 0) {
|
if (nFeeNeeded == 0) {
|
||||||
nFeeNeeded = fallbackFee.GetFee(nTxBytes);
|
nFeeNeeded = fallbackFee.GetFee(nTxBytes);
|
||||||
|
@ -4154,3 +4157,14 @@ bool CMerkleTx::AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState&
|
||||||
{
|
{
|
||||||
return ::AcceptToMemoryPool(mempool, state, tx, true, NULL, NULL, false, nAbsurdFee);
|
return ::AcceptToMemoryPool(mempool, state, tx, true, NULL, NULL, false, nAbsurdFee);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CalculateEstimateType(FeeEstimateMode mode) {
|
||||||
|
switch (mode) {
|
||||||
|
case FeeEstimateMode::UNSET:
|
||||||
|
case FeeEstimateMode::CONSERVATIVE:
|
||||||
|
return true;
|
||||||
|
case FeeEstimateMode::ECONOMICAL:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -80,6 +80,7 @@ class CTxMemPool;
|
||||||
class CBlockPolicyEstimator;
|
class CBlockPolicyEstimator;
|
||||||
class CWalletTx;
|
class CWalletTx;
|
||||||
struct FeeCalculation;
|
struct FeeCalculation;
|
||||||
|
enum class FeeEstimateMode;
|
||||||
|
|
||||||
/** (client) version numbers for particular wallet features */
|
/** (client) version numbers for particular wallet features */
|
||||||
enum WalletFeature
|
enum WalletFeature
|
||||||
|
@ -963,7 +964,7 @@ public:
|
||||||
* Estimate the minimum fee considering user set parameters
|
* Estimate the minimum fee considering user set parameters
|
||||||
* and the required fee
|
* and the required fee
|
||||||
*/
|
*/
|
||||||
static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation *feeCalc, bool ignoreGlobalPayTxFee);
|
static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation *feeCalc, bool ignoreGlobalPayTxFee, bool conservative_estimate);
|
||||||
/**
|
/**
|
||||||
* Return the minimum required fee taking into account the
|
* Return the minimum required fee taking into account the
|
||||||
* floating relay fee and user set minimum transaction fee
|
* floating relay fee and user set minimum transaction fee
|
||||||
|
@ -1211,4 +1212,7 @@ bool CWallet::DummySignTx(CMutableTransaction &txNew, const ContainerType &coins
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CalculateEstimateType(FeeEstimateMode mode);
|
||||||
|
|
||||||
#endif // BITCOIN_WALLET_WALLET_H
|
#endif // BITCOIN_WALLET_WALLET_H
|
||||||
|
|
Loading…
Reference in a new issue