From 54eee73c0466d072a37876ec5d27552d7b6f926f Mon Sep 17 00:00:00 2001 From: woodser Date: Sun, 14 Aug 2022 22:18:25 -0400 Subject: [PATCH] add mining fee padding to maker and taker reserve txs --- .../bisq/core/btc/wallet/XmrWalletService.java | 16 +++++++++++----- .../tasks/MakerReservesOfferFunds.java | 9 +++++++-- .../trade/protocol/TakerReservesTradeFunds.java | 11 ++++++++--- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/bisq/core/btc/wallet/XmrWalletService.java b/core/src/main/java/bisq/core/btc/wallet/XmrWalletService.java index a286c56519..c108f051b0 100644 --- a/core/src/main/java/bisq/core/btc/wallet/XmrWalletService.java +++ b/core/src/main/java/bisq/core/btc/wallet/XmrWalletService.java @@ -233,7 +233,6 @@ public class XmrWalletService { throw e; } } - /** * Create the reserve tx and freeze its inputs. The deposit amount is returned @@ -244,7 +243,7 @@ public class XmrWalletService { * @param depositAmount the amount needed for the trade minus the trade fee * @return a transaction to reserve a trade */ - public MoneroTxWallet createReserveTx(BigInteger tradeFee, String returnAddress, BigInteger depositAmount) { + public MoneroTxWallet createReserveTx(BigInteger tradeFee, String returnAddress, BigInteger depositAmount, boolean freezeInputs) { MoneroWallet wallet = getWallet(); synchronized (wallet) { @@ -262,8 +261,10 @@ public class XmrWalletService { .addDestination(returnAddress, depositAmount.add(miningFee.multiply(BigInteger.valueOf(3l))))); // add thrice the mining fee // TODO (woodser): really require more funds on top of security deposit? // freeze inputs - for (MoneroOutput input : reserveTx.getInputs()) { - wallet.freezeOutput(input.getKeyImage().getHex()); + if (freezeInputs) { + for (MoneroOutput input : reserveTx.getInputs()) { + wallet.freezeOutput(input.getKeyImage().getHex()); + } } return reserveTx; @@ -343,7 +344,7 @@ public class XmrWalletService { if (!check.getReceivedAmount().equals(tradeFee)) throw new RuntimeException("Trade fee is incorrect amount, expected " + tradeFee + " but was " + check.getReceivedAmount()); // verify mining fee - BigInteger feeEstimate = daemon.getFeeEstimate().multiply(BigInteger.valueOf(txHex.length())); // TODO (woodser): fee estimates are too high, use more accurate estimate + BigInteger feeEstimate = getFeeEstimate(txHex); BigInteger feeThreshold = feeEstimate.multiply(BigInteger.valueOf(1l)).divide(BigInteger.valueOf(2l)); // must be at least 50% of estimated fee tx = daemon.getTx(txHash); if (tx.getFee().compareTo(feeThreshold) < 0) { @@ -366,6 +367,11 @@ public class XmrWalletService { } } + // TODO (woodser): fee estimates are too high, use more accurate estimate + public BigInteger getFeeEstimate(String txHex) { + return getDaemon().getFeeEstimate().multiply(BigInteger.valueOf(txHex.length())); + } + public void shutDown() { closeAllWallets(); } diff --git a/core/src/main/java/bisq/core/offer/placeoffer/tasks/MakerReservesOfferFunds.java b/core/src/main/java/bisq/core/offer/placeoffer/tasks/MakerReservesOfferFunds.java index 80542c4550..e084bf6043 100644 --- a/core/src/main/java/bisq/core/offer/placeoffer/tasks/MakerReservesOfferFunds.java +++ b/core/src/main/java/bisq/core/offer/placeoffer/tasks/MakerReservesOfferFunds.java @@ -43,11 +43,16 @@ public class MakerReservesOfferFunds extends Task { try { runInterceptHook(); - // freeze offer funds and get reserve tx + // create tx to estimate fee String returnAddress = model.getXmrWalletService().getOrCreateAddressEntry(offer.getId(), XmrAddressEntry.Context.TRADE_PAYOUT).getAddressString(); BigInteger makerFee = ParsingUtils.coinToAtomicUnits(offer.getMakerFee()); BigInteger depositAmount = ParsingUtils.coinToAtomicUnits(model.getReservedFundsForOffer()); - MoneroTxWallet reserveTx = model.getXmrWalletService().createReserveTx(makerFee, returnAddress, depositAmount); + MoneroTxWallet feeEstimateTx = model.getXmrWalletService().createReserveTx(makerFee, returnAddress, depositAmount, false); + + // create reserve tx and freeze inputs + BigInteger feeEstimate = model.getXmrWalletService().getFeeEstimate(feeEstimateTx.getFullHex()); + depositAmount = depositAmount.add(feeEstimate.multiply(BigInteger.valueOf(3))); + MoneroTxWallet reserveTx = model.getXmrWalletService().createReserveTx(makerFee, returnAddress, depositAmount, true); // collect reserved key images // TODO (woodser): switch to proof of reserve? List reservedKeyImages = new ArrayList(); diff --git a/core/src/main/java/bisq/core/trade/protocol/TakerReservesTradeFunds.java b/core/src/main/java/bisq/core/trade/protocol/TakerReservesTradeFunds.java index 175003a8b9..d5c9c28a9a 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TakerReservesTradeFunds.java +++ b/core/src/main/java/bisq/core/trade/protocol/TakerReservesTradeFunds.java @@ -39,12 +39,17 @@ public class TakerReservesTradeFunds extends TradeTask { try { runInterceptHook(); - // freeze trade funds and get reserve tx + // create tx to estimate fee String returnAddress = model.getXmrWalletService().getOrCreateAddressEntry(trade.getOffer().getId(), XmrAddressEntry.Context.TRADE_PAYOUT).getAddressString(); BigInteger takerFee = ParsingUtils.coinToAtomicUnits(trade.getTakerFee()); BigInteger depositAmount = ParsingUtils.centinerosToAtomicUnits(processModel.getFundsNeededForTradeAsLong()); - MoneroTxWallet reserveTx = model.getXmrWalletService().createReserveTx(takerFee, returnAddress, depositAmount); - + MoneroTxWallet feeEstimateTx = model.getXmrWalletService().createReserveTx(takerFee, returnAddress, depositAmount, false); + + // create reserve tx and freeze inputs + BigInteger feeEstimate = model.getXmrWalletService().getFeeEstimate(feeEstimateTx.getFullHex()); + depositAmount = depositAmount.add(feeEstimate.multiply(BigInteger.valueOf(3))); + MoneroTxWallet reserveTx = model.getXmrWalletService().createReserveTx(takerFee, returnAddress, depositAmount, true); + // collect reserved key images // TODO (woodser): switch to proof of reserve? List reservedKeyImages = new ArrayList(); for (MoneroOutput input : reserveTx.getInputs()) reservedKeyImages.add(input.getKeyImage().getHex());