diff --git a/src/config.h b/src/config.h --- a/src/config.h +++ b/src/config.h @@ -33,6 +33,14 @@ virtual void SetMinFeePerKB(CFeeRate amt) = 0; virtual CFeeRate GetMinFeePerKB() const = 0; + /** + * Absolute maximum transaction fee per kb (in satoshis) used by wallet and + * mempool + * (rejects high fee in sendrawtransaction) + */ + virtual bool SetMaxFee(Amount amt) = 0; + virtual Amount GetMaxFee() const = 0; + virtual void SetRPCUserAndPassword(std::string userAndPassword) = 0; virtual std::string GetRPCUserAndPassword() const = 0; virtual void SetRPCCORSDomain(std::string corsDomain) = 0; @@ -56,6 +64,9 @@ void SetMinFeePerKB(CFeeRate amt) override; CFeeRate GetMinFeePerKB() const override; + bool SetMaxFee(Amount amt) override; + Amount GetMaxFee() const override; + void SetRPCUserAndPassword(std::string userAndPassword) override; std::string GetRPCUserAndPassword() const override; void SetRPCCORSDomain(std::string corsDomain) override; @@ -64,7 +75,8 @@ private: bool useCashAddr; Amount excessUTXOCharge; - CFeeRate feePerKB; + CFeeRate minFeePerKB; + Amount maxFee; }; // Dummy for subclassing in unittests @@ -93,6 +105,9 @@ return CFeeRate(Amount::zero()); } + bool SetMaxFee(Amount amt) override { return false; }; + Amount GetMaxFee() const override { return MAX_MONEY; } + void SetRPCUserAndPassword(std::string userAndPassword) override{}; std::string GetRPCUserAndPassword() const override { return ""; }; void SetRPCCORSDomain(std::string corsDomain) override{}; diff --git a/src/config.cpp b/src/config.cpp --- a/src/config.cpp +++ b/src/config.cpp @@ -73,11 +73,23 @@ } void GlobalConfig::SetMinFeePerKB(CFeeRate fee) { - feePerKB = fee; + minFeePerKB = fee; } CFeeRate GlobalConfig::GetMinFeePerKB() const { - return feePerKB; + return minFeePerKB; +} + +bool GlobalConfig::SetMaxFee(Amount fee) { + if (minFeePerKB.GetFeePerK() > fee) { + return false; + } + maxFee = fee; + return true; +} + +Amount GlobalConfig::GetMaxFee() const { + return maxFee; } void GlobalConfig::SetRPCUserAndPassword(std::string userAndPassword) { diff --git a/src/init.cpp b/src/init.cpp --- a/src/init.cpp +++ b/src/init.cpp @@ -1652,7 +1652,7 @@ nBytesPerSigOp = gArgs.GetArg("-bytespersigop", nBytesPerSigOp); #ifdef ENABLE_WALLET - if (!WalletParameterInteraction()) { + if (!WalletParameterInteraction(config)) { return false; } #endif diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -1133,7 +1133,7 @@ const uint256 &txid = tx->GetId(); bool fLimitFree = false; - Amount nMaxRawTxFee = maxTxFee; + Amount nMaxRawTxFee = config.GetMaxFee(); if (request.params.size() > 1 && request.params[1].get_bool()) { nMaxRawTxFee = Amount::zero(); } diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp --- a/src/test/txvalidationcache_tests.cpp +++ b/src/test/txvalidationcache_tests.cpp @@ -28,8 +28,7 @@ CValidationState state; return AcceptToMemoryPool(GetConfig(), mempool, state, - MakeTransactionRef(tx), false, nullptr, true, - Amount::zero()); + MakeTransactionRef(tx), false, nullptr, true); } BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup) { diff --git a/src/validation.h b/src/validation.h --- a/src/validation.h +++ b/src/validation.h @@ -211,11 +211,6 @@ extern bool fCheckpointsEnabled; extern size_t nCoinCacheUsage; -/** - * Absolute maximum transaction fee (in satoshis) used by wallet and mempool - * (rejects high fee in sendrawtransaction) - */ -extern Amount maxTxFee; /** * If the tip is older than this (in seconds), the node is considered to be in * initial block download. diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -84,8 +84,6 @@ uint256 hashAssumeValid; arith_uint256 nMinimumChainWork; -Amount maxTxFee = DEFAULT_TRANSACTION_MAXFEE; - CTxMemPool mempool; static void CheckBlockIndex(const Consensus::Params &consensusParams); diff --git a/src/wallet/fees.cpp b/src/wallet/fees.cpp --- a/src/wallet/fees.cpp +++ b/src/wallet/fees.cpp @@ -33,8 +33,9 @@ std::max(nFeeNeeded, GetConfig().GetMinFeePerKB().GetFee(nTxBytes)); // But always obey the maximum. - if (nFeeNeeded > maxTxFee) { - nFeeNeeded = maxTxFee; + Amount maxFee = GetConfig().GetMaxFee(); + if (nFeeNeeded > maxFee) { + nFeeNeeded = maxFee; } return nFeeNeeded; diff --git a/src/wallet/init.h b/src/wallet/init.h --- a/src/wallet/init.h +++ b/src/wallet/init.h @@ -19,7 +19,7 @@ /** * Wallets parameter interaction */ -bool WalletParameterInteraction(); +bool WalletParameterInteraction(Config &config); /** * Responsible for reading and validating the -wallet arguments and verifying diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -100,8 +100,8 @@ return strUsage; } -bool WalletParameterInteraction() { - CFeeRate minRelayTxFee = GetConfig().GetMinFeePerKB(); +bool WalletParameterInteraction(Config &config) { + CFeeRate minRelayTxFee = config.GetMinFeePerKB(); gArgs.SoftSetArg("-wallet", DEFAULT_WALLET_DAT); const bool is_multiwallet = gArgs.GetArgs("-wallet").size() > 1; @@ -219,6 +219,7 @@ } } + config.SetMaxFee(DEFAULT_TRANSACTION_MAXFEE); if (gArgs.IsArgSet("-maxtxfee")) { Amount nMaxFee = Amount::zero(); if (!ParseMoney(gArgs.GetArg("-maxtxfee", ""), nMaxFee)) { @@ -231,8 +232,7 @@ "be paid on a single transaction.")); } - maxTxFee = nMaxFee; - if (CFeeRate(maxTxFee, 1000) < minRelayTxFee) { + if (!config.SetMaxFee(nMaxFee)) { return InitError(strprintf( _("Invalid amount for -maxtxfee=: '%s' (must " "be at least the minrelay fee of %s to prevent " diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -257,7 +257,7 @@ * Pass this transaction to the mempool. Fails if absolute fee exceeds * absurd fee. */ - bool AcceptToMemoryPool(const Amount nAbsurdFee, CValidationState &state); + bool AcceptToMemoryPool(CValidationState &state); bool hashUnset() const { return (hashBlock.IsNull() || hashBlock == ABANDON_HASH); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1763,7 +1763,7 @@ LOCK(mempool.cs); CValidationState state; - wtx.AcceptToMemoryPool(maxTxFee, state); + wtx.AcceptToMemoryPool(state); } } @@ -1775,7 +1775,7 @@ CValidationState state; // GetDepthInMainChain already catches known conflicts. - if (InMempool() || AcceptToMemoryPool(maxTxFee, state)) { + if (InMempool() || AcceptToMemoryPool(state)) { LogPrintf("Relaying wtx %s\n", GetId().ToString()); if (connman) { CInv inv(MSG_TX, GetId()); @@ -3096,7 +3096,7 @@ if (fBroadcastTransactions) { // Broadcast - if (!wtxNew.AcceptToMemoryPool(maxTxFee, state)) { + if (!wtxNew.AcceptToMemoryPool(state)) { LogPrintf("CommitTransaction(): Transaction cannot be " "broadcast immediately, %s\n", state.GetRejectReason()); @@ -4254,8 +4254,8 @@ return std::max(0, (COINBASE_MATURITY + 1) - GetDepthInMainChain()); } -bool CMerkleTx::AcceptToMemoryPool(const Amount nAbsurdFee, - CValidationState &state) { - return ::AcceptToMemoryPool(GetConfig(), mempool, state, tx, true, nullptr, - false, nAbsurdFee); +bool CMerkleTx::AcceptToMemoryPool(CValidationState &state) { + const Config &config = GetConfig(); + return ::AcceptToMemoryPool(config, mempool, state, tx, true, nullptr, + false, config.GetMaxFee()); }