tolerate miner fees within 5x of each other

This commit is contained in:
woodser 2025-04-25 17:49:48 -04:00 committed by woodser
parent adcd5da431
commit 350aa10839
4 changed files with 19 additions and 12 deletions

View file

@ -487,10 +487,8 @@ public final class ArbitrationManager extends DisputeManager<ArbitrationDisputeL
log.warn("Could not recreate dispute payout tx to verify fee: {}\n", e.getMessage(), e); log.warn("Could not recreate dispute payout tx to verify fee: {}\n", e.getMessage(), e);
} }
if (feeEstimateTx != null) { if (feeEstimateTx != null) {
BigInteger feeEstimate = feeEstimateTx.getFee(); HavenoUtils.verifyMinerFee(feeEstimateTx.getFee(), arbitratorSignedPayoutTx.getFee());
double feeDiff = arbitratorSignedPayoutTx.getFee().subtract(feeEstimate).abs().doubleValue() / feeEstimate.doubleValue(); log.info("Dispute payout tx fee {} is within tolerance");
if (feeDiff > XmrWalletService.MINER_FEE_TOLERANCE) throw new RuntimeException("Miner fee is not within " + (XmrWalletService.MINER_FEE_TOLERANCE * 100) + "% of estimated fee, expected " + feeEstimate + " but was " + arbitratorSignedPayoutTx.getFee());
log.info("Payout tx fee {} is within tolerance, diff %={}", arbitratorSignedPayoutTx.getFee(), feeDiff);
} }
} else { } else {
disputeTxSet.setMultisigTxHex(trade.getPayoutTxHex()); disputeTxSet.setMultisigTxHex(trade.getPayoutTxHex());

View file

@ -96,6 +96,7 @@ public class HavenoUtils {
public static final double MAKER_FEE_PCT = 0.0015; // 0.15% public static final double MAKER_FEE_PCT = 0.0015; // 0.15%
public static final double TAKER_FEE_PCT = 0.0075; // 0.75% public static final double TAKER_FEE_PCT = 0.0075; // 0.75%
public static final double MAKER_FEE_FOR_TAKER_WITHOUT_DEPOSIT_PCT = MAKER_FEE_PCT + TAKER_FEE_PCT; // customize maker's fee when no deposit or fee from taker public static final double MAKER_FEE_FOR_TAKER_WITHOUT_DEPOSIT_PCT = MAKER_FEE_PCT + TAKER_FEE_PCT; // customize maker's fee when no deposit or fee from taker
public static final double MINER_FEE_TOLERANCE_FACTOR = 5.0; // miner fees must be within 5x of each other
// other configuration // other configuration
public static final long LOG_POLL_ERROR_PERIOD_MS = 1000 * 60 * 4; // log poll errors up to once every 4 minutes public static final long LOG_POLL_ERROR_PERIOD_MS = 1000 * 60 * 4; // log poll errors up to once every 4 minutes
@ -650,4 +651,16 @@ public class HavenoUtils {
} }
}).start(); }).start();
} }
public static void verifyMinerFee(BigInteger expected, BigInteger actual) {
BigInteger max = expected.max(actual);
BigInteger min = expected.min(actual);
if (min.compareTo(BigInteger.ZERO) <= 0) {
throw new IllegalArgumentException("Miner fees must be greater than zero");
}
double factor = divide(max, min);
if (factor > MINER_FEE_TOLERANCE_FACTOR) {
throw new IllegalArgumentException("Miner fees are not within " + MINER_FEE_TOLERANCE_FACTOR + "x of each other. Expected=" + expected + ", actual=" + actual + ", factor=" + factor);
}
}
} }

View file

@ -1457,10 +1457,8 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
log.info("Creating fee estimate tx for {} {}", getClass().getSimpleName(), getId()); log.info("Creating fee estimate tx for {} {}", getClass().getSimpleName(), getId());
saveWallet(); // save wallet before creating fee estimate tx saveWallet(); // save wallet before creating fee estimate tx
MoneroTxWallet feeEstimateTx = createPayoutTx(); MoneroTxWallet feeEstimateTx = createPayoutTx();
BigInteger feeEstimate = feeEstimateTx.getFee(); HavenoUtils.verifyMinerFee(feeEstimateTx.getFee(), payoutTx.getFee());
double feeDiff = payoutTx.getFee().subtract(feeEstimate).abs().doubleValue() / feeEstimate.doubleValue(); // TODO: use BigDecimal? log.info("Payout tx fee {} is within tolerance");
if (feeDiff > XmrWalletService.MINER_FEE_TOLERANCE) throw new IllegalArgumentException("Miner fee is not within " + (XmrWalletService.MINER_FEE_TOLERANCE * 100) + "% of estimated fee, expected " + feeEstimate + " but was " + payoutTx.getFee());
log.info("Payout tx fee {} is within tolerance, diff %={}", payoutTx.getFee(), feeDiff);
} }
// set signed payout tx hex // set signed payout tx hex

View file

@ -110,7 +110,6 @@ public class XmrWalletService extends XmrWalletBase {
public static final String MONERO_BINS_DIR = Config.appDataDir().getAbsolutePath(); public static final String MONERO_BINS_DIR = Config.appDataDir().getAbsolutePath();
public static final String MONERO_WALLET_RPC_NAME = Utilities.isWindows() ? "monero-wallet-rpc.exe" : "monero-wallet-rpc"; public static final String MONERO_WALLET_RPC_NAME = Utilities.isWindows() ? "monero-wallet-rpc.exe" : "monero-wallet-rpc";
public static final String MONERO_WALLET_RPC_PATH = MONERO_BINS_DIR + File.separator + MONERO_WALLET_RPC_NAME; public static final String MONERO_WALLET_RPC_PATH = MONERO_BINS_DIR + File.separator + MONERO_WALLET_RPC_NAME;
public static final double MINER_FEE_TOLERANCE = 0.25; // miner fee must be within percent of estimated fee
public static final MoneroTxPriority PROTOCOL_FEE_PRIORITY = MoneroTxPriority.DEFAULT; public static final MoneroTxPriority PROTOCOL_FEE_PRIORITY = MoneroTxPriority.DEFAULT;
public static final int MONERO_LOG_LEVEL = -1; // monero library log level, -1 to disable public static final int MONERO_LOG_LEVEL = -1; // monero library log level, -1 to disable
private static final MoneroNetworkType MONERO_NETWORK_TYPE = getMoneroNetworkType(); private static final MoneroNetworkType MONERO_NETWORK_TYPE = getMoneroNetworkType();
@ -767,9 +766,8 @@ public class XmrWalletService extends XmrWalletBase {
// verify miner fee // verify miner fee
BigInteger minerFeeEstimate = getFeeEstimate(tx.getWeight()); BigInteger minerFeeEstimate = getFeeEstimate(tx.getWeight());
double minerFeeDiff = tx.getFee().subtract(minerFeeEstimate).abs().doubleValue() / minerFeeEstimate.doubleValue(); HavenoUtils.verifyMinerFee(minerFeeEstimate, tx.getFee());
if (minerFeeDiff > MINER_FEE_TOLERANCE) throw new RuntimeException("Miner fee is not within " + (MINER_FEE_TOLERANCE * 100) + "% of estimated fee, expected " + minerFeeEstimate + " but was " + tx.getFee() + ", diff%=" + minerFeeDiff); log.info("Trade miner fee {} is within tolerance");
log.info("Trade miner fee {} is within tolerance, diff%={}", tx.getFee(), minerFeeDiff);
// verify proof to fee address // verify proof to fee address
BigInteger actualTradeFee = BigInteger.ZERO; BigInteger actualTradeFee = BigInteger.ZERO;