Merge pull request 'OP_RETURN fees' (#429) from opretfees into dev

Reviewed-on: https://git.hush.is/hush/hush3/pulls/429
This commit is contained in:
duke
2024-09-28 13:34:19 +02:00
4 changed files with 36 additions and 16 deletions

View File

@@ -479,7 +479,6 @@ std::string HelpMessage(HelpMessageMode mode)
if (showDebug)
strUsage += HelpMessageOpt("-mintxfee=<amt>", strprintf("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)",
CURRENCY_UNIT, FormatMoney(CWallet::minTxFee.GetFeePerK())));
strUsage += HelpMessageOpt("-opretmintxfee=<amt>", strprintf(_("Minimum fee (in %s/kB) to allow for OP_RETURN transactions (default: %s)"), CURRENCY_UNIT, 400000 ));
strUsage += HelpMessageOpt("-paytxfee=<amt>", strprintf(_("Fee (in %s/kB) to add to transactions you send (default: %s)"), CURRENCY_UNIT, FormatMoney(payTxFee.GetFeePerK())));
// If this is used incorrectly (-rescanheight too large), then the local wallet may attempt to spend funds which it does not have witness data about
// which will cause a "missing inputs" error when added to the mempool. Rescanning from correct height will fix this.

View File

@@ -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(),

View File

@@ -475,14 +475,10 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
// fprintf(stderr,"%s: nTxSize = %u\n", __func__, nTxSize);
// Opret spam limits
if (mapArgs.count("-opretmintxfee"))
const bool opretminfee = true;
if (opretminfee)
{
CAmount n = 0;
CFeeRate opretMinFeeRate;
if (ParseMoney(mapArgs["-opretmintxfee"], n) && n > 0)
opretMinFeeRate = CFeeRate(n);
else
opretMinFeeRate = CFeeRate(400000); // default opretMinFeeRate (1 HUSH per 250 Kb = 0.004 per 1 Kb = 400000 puposhis per 1 Kb)
CFeeRate opretMinFeeRate = CFeeRate(10000000); // default opretMinFeeRate 0.1 HUSH
bool fSpamTx = false;
unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
@@ -501,9 +497,13 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
}
}
if ((nTxOpretSize > 256) && (feeRate < opretMinFeeRate)) fSpamTx = true;
// std::cerr << tx.GetHash().ToString() << " nTxSize." << nTxSize << " nTxOpretSize." << nTxOpretSize << " feeRate." << feeRate.ToString() << " opretMinFeeRate." << opretMinFeeRate.ToString() << " fSpamTx." << fSpamTx << std::endl;
if (fSpamTx) continue;
// opreturns of this size or smaller get amnesty and do not have to pay increased fees
int amnestySize = 128;
if ((nTxOpretSize > amnestySize) && (feeRate < opretMinFeeRate)) {
fSpamTx = true;
std::cerr << __func__ << ": " << tx.GetHash().ToString() << " nTxSize=" << nTxSize << " nTxOpretSize=" << nTxOpretSize << " feeRate=" << feeRate.ToString() << " opretMinFeeRate=" << opretMinFeeRate.ToString() << " fSpamTx=" << fSpamTx << std::endl;
continue;
}
// std::cerr << tx.GetHash().ToString() << " vecPriority.size() = " << vecPriority.size() << std::endl;
}

View File

@@ -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,15 +5347,21 @@ 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) {
// 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) {
// 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)));
}
}
}
}
// Use input parameters as the optional context info to be returned by z_getoperationstatus and z_getoperationresult.
UniValue o(UniValue::VOBJ);