diff --git a/src/interfaces/node.h b/src/interfaces/node.h index 81844c6185..6718b2b77c 100644 --- a/src/interfaces/node.h +++ b/src/interfaces/node.h @@ -20,6 +20,7 @@ #include #include #include +#include #include class BanMan; @@ -214,7 +215,7 @@ public: virtual std::optional getUnspentOutput(const COutPoint& output) = 0; //! Broadcast transaction. - virtual node::TransactionError broadcastTransaction(CTransactionRef tx, CAmount max_tx_fee, std::string& err_string) = 0; + virtual node::TransactionError broadcastTransaction(CTransactionRef tx, const std::variant& max_tx_fee, std::string& err_string) = 0; //! Get wallet loader. virtual WalletLoader& walletLoader() = 0; diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index 54b986c926..9cdc64b77c 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -355,7 +355,7 @@ public: if (chainman().ActiveChainstate().CoinsTip().GetCoin(output, coin)) return coin; return {}; } - TransactionError broadcastTransaction(CTransactionRef tx, CAmount max_tx_fee, std::string& err_string) override + TransactionError broadcastTransaction(CTransactionRef tx, const std::variant& max_tx_fee, std::string& err_string) override { return BroadcastTransaction(*m_context, std::move(tx), err_string, max_tx_fee, /*relay=*/ true, /*wait_callback=*/ false); } diff --git a/src/node/transaction.cpp b/src/node/transaction.cpp index 0f45da45db..5014ec61e1 100644 --- a/src/node/transaction.cpp +++ b/src/node/transaction.cpp @@ -31,7 +31,7 @@ static TransactionError HandleATMPError(const TxValidationState& state, std::str } } -TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback) +TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef tx, std::string& err_string, const std::variant& max_tx_fee, bool relay, bool wait_callback) { // BroadcastTransaction can be called by RPC or by the wallet. // chainman, mempool and peerman are initialized before the RPC server and wallet are started @@ -69,14 +69,23 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t wtxid = mempool_tx->GetWitnessHash(); } else { // Transaction is not already in the mempool. - if (max_tx_fee > 0) { + const bool max_tx_fee_set{(std::holds_alternative(max_tx_fee) ? std::get(max_tx_fee) : std::get(max_tx_fee).GetFeePerK()) > 0}; + if (max_tx_fee_set) { // First, call ATMP with test_accept and check the fee. If ATMP // fails here, return error immediately. const MempoolAcceptResult result = node.chainman->ProcessTransaction(tx, /*test_accept=*/ true); if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) { return HandleATMPError(result.m_state, err_string); - } else if (result.m_base_fees.value() > max_tx_fee) { - return TransactionError::MAX_FEE_EXCEEDED; + } else { + CAmount max_tx_fee_abs; + if (std::holds_alternative(max_tx_fee)) { + max_tx_fee_abs = std::get(max_tx_fee).GetFee(*Assert(result.m_vsize)); + } else { + max_tx_fee_abs = std::get(max_tx_fee); + } + if (result.m_base_fees.value() > max_tx_fee_abs) { + return TransactionError::MAX_FEE_EXCEEDED; + } } } // Try to submit the transaction to the mempool. diff --git a/src/node/transaction.h b/src/node/transaction.h index 5f524f4e28..8b03c3ba3d 100644 --- a/src/node/transaction.h +++ b/src/node/transaction.h @@ -9,6 +9,8 @@ #include #include +#include + class CBlockIndex; class CTxMemPool; namespace Consensus { @@ -49,7 +51,7 @@ static const CAmount DEFAULT_MAX_BURN_AMOUNT{0}; * @param[in] wait_callback wait until callbacks have been processed to avoid stale result due to a sequentially RPC. * return error */ -[[nodiscard]] TransactionError BroadcastTransaction(NodeContext& node, CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback); +[[nodiscard]] TransactionError BroadcastTransaction(NodeContext& node, CTransactionRef tx, std::string& err_string, const std::variant& max_tx_fee, bool relay, bool wait_callback); /** * Return transaction with a given hash.