@ -57,6 +57,8 @@ CFeeRate CWallet::minTxFee = CFeeRate(DEFAULT_TRANSACTION_MINFEE);
@@ -57,6 +57,8 @@ CFeeRate CWallet::minTxFee = CFeeRate(DEFAULT_TRANSACTION_MINFEE);
*/
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
@ -2501,6 +2503,17 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC
@@ -2501,6 +2503,17 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC
return true ;
}
static CFeeRate GetDiscardRate ( 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 must be at least dustRelayFee
discard_rate = std : : max ( discard_rate , : : dustRelayFee ) ;
return discard_rate ;
}
bool CWallet : : CreateTransaction ( const std : : vector < CRecipient > & vecSend , CWalletTx & wtxNew , CReserveKey & reservekey , CAmount & nFeeRet ,
int & nChangePosInOut , std : : string & strFailReason , const CCoinControl & coin_control , bool sign )
{
@ -2600,6 +2613,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
@@ -2600,6 +2613,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
CTxOut change_prototype_txout ( 0 , scriptChange ) ;
size_t change_prototype_size = GetSerializeSize ( change_prototype_txout , SER_DISK , 0 ) ;
CFeeRate discard_rate = GetDiscardRate ( : : feeEstimator ) ;
nFeeRet = 0 ;
bool pick_new_inputs = true ;
CAmount nValueIn = 0 ;
@ -2667,7 +2681,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
@@ -2667,7 +2681,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
// Never create dust outputs; if we would, just
// add the dust to the fee.
if ( IsDust ( newTxOut , : : dustRelayFe e) )
if ( IsDust ( newTxOut , discard_rat e) )
{
nChangePosInOut = - 1 ;
nFeeRet + = nChange ;
@ -2747,7 +2761,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
@@ -2747,7 +2761,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
// (because of reduced tx size) and so we should add a
// change output. Only try this once.
CAmount fee_needed_for_change = GetMinimumFee ( change_prototype_size , coin_control , : : mempool , : : feeEstimator , nullptr ) ;
CAmount minimum_value_for_change = GetDustThreshold ( change_prototype_txout , : : dustRelayFe e) ;
CAmount minimum_value_for_change = GetDustThreshold ( change_prototype_txout , discard_rat e) ;
CAmount max_excess_fee = fee_needed_for_change + minimum_value_for_change ;
if ( nFeeRet > nFeeNeeded + max_excess_fee & & nChangePosInOut = = - 1 & & nSubtractFeeFromAmount = = 0 & & pick_new_inputs ) {
pick_new_inputs = false ;
@ -3788,6 +3802,9 @@ std::string CWallet::GetWalletHelpString(bool showDebug)
@@ -3788,6 +3802,9 @@ std::string CWallet::GetWalletHelpString(bool showDebug)
strUsage + = HelpMessageOpt ( " -keypool=<n> " , strprintf ( _ ( " Set key pool size to <n> (default: %u) " ) , DEFAULT_KEYPOOL_SIZE ) ) ;
strUsage + = HelpMessageOpt ( " -fallbackfee=<amt> " , strprintf ( _ ( " A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s) " ) ,
CURRENCY_UNIT , FormatMoney ( DEFAULT_FALLBACK_FEE ) ) ) ;
strUsage + = HelpMessageOpt ( " -discardfee=<amt> " , strprintf ( _ ( " The fee rate (in %s/kB) used to discard change (to fee) if it would be dust at this fee rate (default: %s) "
" Note: We will always discard up to the dust relay fee and a discard fee above that is limited by the longest target fee estimate " ) ,
CURRENCY_UNIT , FormatMoney ( DEFAULT_DISCARD_FEE ) ) ) ;
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) " ) ,
@ -4113,6 +4130,16 @@ bool CWallet::ParameterInteraction()
@@ -4113,6 +4130,16 @@ bool CWallet::ParameterInteraction()
_ ( " This is the transaction fee you may pay when fee estimates are not available. " ) ) ;
CWallet : : fallbackFee = CFeeRate ( nFeePerK ) ;
}
if ( IsArgSet ( " -discardfee " ) )
{
CAmount nFeePerK = 0 ;
if ( ! ParseMoney ( GetArg ( " -discardfee " , " " ) , nFeePerK ) )
return InitError ( strprintf ( _ ( " Invalid amount for -discardfee=<amount>: '%s' " ) , 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 ( IsArgSet ( " -paytxfee " ) )
{
CAmount nFeePerK = 0 ;