diff --git a/src/main.cpp b/src/main.cpp index 3ddf5bb54..f2f3bf831 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1960,7 +1960,17 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa dFreeCount += nSize; } - if (!tx.IsCoinImport() && fRejectAbsurdFee && nFees > ::minRelayTxFee.GetFee(nSize) * 10000 && nFees > nValueOut/19) + // Disable checks for absurd fees when adding to the mempool. Instead, this check is done + // when a user attempts to make a transaction with an absurd fee and only rejects absurd + // fees when OP_RETURN data is NOT being used. This means users making normal financial + // transactions (z2z) are protected from absurd fees, it is only users who are storing + // arbitrary data via a z2t transaction are allowed to (or potentially required) to pay high fees + // It would be nice to detect the use of OP_RETURN right here but it seems to only be known + // inside of IsStandard() inside of IsStandardTx() and we want to avoid doing expensive checks + // multiple times. + fRejectAbsurdFee = false; + + if (fRejectAbsurdFee && !tx.IsCoinImport() && nFees > ::minRelayTxFee.GetFee(nSize) * 10000 && nFees > nValueOut/19) { string errmsg = strprintf("absurdly high fees %s, %d > %d", hash.ToString(), @@ -1968,7 +1978,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa LogPrint("mempool", errmsg.c_str()); return state.Error("AcceptToMemoryPool: " + errmsg); } -//fprintf(stderr,"addmempool 6\n"); + //fprintf(stderr,"addmempool 6\n"); // Check against previous transactions // This is done last to help prevent CPU exhaustion denial-of-service attacks. diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 46a059892..1b6110ec5 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -5155,6 +5155,8 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk) CAmount nTotalOut = 0; // Optional OP_RETURN data CScript opret; + // TODO: enforce that only a single opreturn exists + UniValue opretValue; bool containsSaplingOutput = false; @@ -5189,7 +5191,10 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk) // throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+address); setAddress.insert(address); - UniValue opretValue = find_value(o, "opreturn"); + UniValue this_opret = find_value(o, "opreturn"); + if (!this_opret.isNull()) { + opretValue = this_opret; + } // Create the CScript representation of the OP_RETURN if (!opretValue.isNull()) { @@ -5342,12 +5347,18 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk) // or anything less than nDefaultFee instead of being forced to use a custom fee and leak metadata if (nTotalOut < nDefaultFee) { if (nFee > nDefaultFee) { - throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Small transaction amount %s has fee %s that is greater than the default fee %s", FormatMoney(nTotalOut), FormatMoney(nFee), FormatMoney(nDefaultFee))); + // Allow large fees if OP_RETURN is being used + if( opretValue.isNull() ) { + throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Small transaction amount %s has fee %s that is greater than the default fee %s", FormatMoney(nTotalOut), FormatMoney(nFee), FormatMoney(nDefaultFee))); + } } } else { // Check that the user specified fee is not absurd. if (nFee > nTotalOut) { - throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the sum of outputs %s and also greater than the default fee", FormatMoney(nFee), FormatMoney(nTotalOut))); + // Allow large fees if OP_RETURN is being used + if( opretValue.isNull() ) { + throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the sum of outputs %s and also greater than the default fee", FormatMoney(nFee), FormatMoney(nTotalOut))); + } } } }