diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -42,11 +43,11 @@ #include /** - * High fee for sendrawtransaction and testmempoolaccept. - * By default, transaction with a fee higher than this will be rejected by the - * RPCs. This can be overridden with the maxfeerate argument. + * High fee rate for sendrawtransaction and testmempoolaccept. + * By default, transaction with a fee rate higher than this will be rejected by + * the RPCs. This can be overridden with the maxfeerate argument. */ -constexpr static Amount DEFAULT_MAX_RAW_TX_FEE{COIN / 10}; +static const CFeeRate DEFAULT_MAX_RAW_TX_FEE_RATE{COIN / 10}; static void TxToJSON(const CTransaction &tx, const BlockHash &hashBlock, UniValue &entry) { @@ -897,7 +898,8 @@ {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex string of the raw transaction"}, {"maxfeerate", RPCArg::Type::AMOUNT, - /* default */ FormatMoney(DEFAULT_MAX_RAW_TX_FEE), + /* default */ + FormatMoney(DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK()), "Reject transactions whose fee rate is higher than the specified " "value, expressed in " + CURRENCY_UNIT + "/kB\n"}, @@ -932,18 +934,20 @@ CTransactionRef tx(MakeTransactionRef(std::move(mtx))); - Amount max_raw_tx_fee = DEFAULT_MAX_RAW_TX_FEE; - // TODO: temporary migration code for old clients. Remove in v0.22 + CFeeRate max_raw_tx_fee_rate = DEFAULT_MAX_RAW_TX_FEE_RATE; + // TODO: temporary migration code for old clients. Remove in v0.20 if (request.params[1].isBool()) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Second argument must be numeric (maxfeerate) and " "no longer supports a boolean. To allow a " "transaction with high fees, set maxfeerate to 0."); } else if (!request.params[1].isNull()) { - size_t sz = tx->GetTotalSize(); - CFeeRate fr(AmountFromValue(request.params[1])); - max_raw_tx_fee = fr.GetFee(sz); + max_raw_tx_fee_rate = CFeeRate(AmountFromValue(request.params[1])); } + + int64_t virtual_size = GetVirtualTransactionSize(*tx); + Amount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size); + std::string err_string; AssertLockNotHeld(cs_main); NodeContext &node = EnsureNodeContext(request.context); @@ -979,7 +983,8 @@ }, }, {"maxfeerate", RPCArg::Type::AMOUNT, - /* default */ FormatMoney(DEFAULT_MAX_RAW_TX_FEE), + /* default */ + FormatMoney(DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK()), "Reject transactions whose fee rate is higher than the specified " "value, expressed in " + CURRENCY_UNIT + "/kB\n"}, @@ -1030,7 +1035,7 @@ CTransactionRef tx(MakeTransactionRef(std::move(mtx))); const TxId &txid = tx->GetId(); - Amount max_raw_tx_fee = DEFAULT_MAX_RAW_TX_FEE; + CFeeRate max_raw_tx_fee_rate = DEFAULT_MAX_RAW_TX_FEE_RATE; // TODO: temporary migration code for old clients. Remove in v0.20 if (request.params[1].isBool()) { throw JSONRPCError(RPC_INVALID_PARAMETER, @@ -1038,11 +1043,12 @@ "no longer supports a boolean. To allow a " "transaction with high fees, set maxfeerate to 0."); } else if (!request.params[1].isNull()) { - size_t sz = tx->GetTotalSize(); - CFeeRate fr(AmountFromValue(request.params[1])); - max_raw_tx_fee = fr.GetFee(sz); + max_raw_tx_fee_rate = CFeeRate(AmountFromValue(request.params[1])); } + int64_t virtual_size = GetVirtualTransactionSize(*tx); + Amount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size); + CTxMemPool &mempool = EnsureMemPool(request.context); UniValue result(UniValue::VARR); diff --git a/test/functional/mempool_accept.py b/test/functional/mempool_accept.py --- a/test/functional/mempool_accept.py +++ b/test/functional/mempool_accept.py @@ -195,6 +195,7 @@ self.check_mempool_result( result_expected=[{'txid': tx.rehash(), 'allowed': True}], rawtxs=[ToHex(tx)], + maxfeerate=0, ) self.log.info('A transaction with no outputs') diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py --- a/test/functional/wallet_basic.py +++ b/test/functional/wallet_basic.py @@ -514,7 +514,7 @@ raw_tx = self.nodes[0].createrawtransaction([{"txid": singletxid, "vout": 0}], { chain_addrs[0]: node0_balance / 2 - Decimal('0.01'), chain_addrs[1]: node0_balance / 2 - Decimal('0.01')}) signedtx = self.nodes[0].signrawtransactionwithwallet(raw_tx) - singletxid = self.nodes[0].sendrawtransaction(signedtx["hex"]) + singletxid = self.nodes[0].sendrawtransaction(signedtx["hex"], 0) self.nodes[0].generate(1) # Make a long chain of unconfirmed payments without hitting mempool limit