mirror of
https://github.com/retoaccess1/haveno-reto.git
synced 2024-11-10 05:03:35 +01:00
thaw reserved inputs and re-freeze offer inputs on create tx errors
This commit is contained in:
parent
5d7991e4f7
commit
f1b8cd1e2e
@ -45,12 +45,15 @@ import java.security.PrivateKey;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import monero.common.MoneroRpcConnection;
|
||||
import monero.daemon.model.MoneroOutput;
|
||||
import monero.wallet.model.MoneroDestination;
|
||||
import monero.wallet.model.MoneroTxWallet;
|
||||
|
||||
@ -496,4 +499,10 @@ public class HavenoUtils {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<String> getInputKeyImages(MoneroTxWallet tx) {
|
||||
List<String> inputKeyImages = new ArrayList<String>();
|
||||
for (MoneroOutput input : tx.getInputs()) inputKeyImages.add(input.getKeyImage().getHex());
|
||||
return inputKeyImages;
|
||||
}
|
||||
}
|
||||
|
@ -31,13 +31,10 @@ import haveno.core.xmr.model.XmrAddressEntry;
|
||||
import haveno.core.xmr.wallet.XmrWalletService;
|
||||
import haveno.network.p2p.SendDirectMessageListener;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import monero.daemon.model.MoneroOutput;
|
||||
import monero.wallet.model.MoneroTxWallet;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
// TODO (woodser): separate classes for deposit tx creation and contract request, or combine into ProcessInitMultisigRequest
|
||||
@ -118,9 +115,15 @@ public class MaybeSendSignContractRequest extends TradeTask {
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
// re-freeze reserved outputs
|
||||
if (trade.getSelf().getReserveTxKeyImages() != null) {
|
||||
trade.getXmrWalletService().freezeOutputs(trade.getSelf().getReserveTxKeyImages());
|
||||
// thaw deposit inputs
|
||||
if (depositTx != null) {
|
||||
trade.getXmrWalletService().thawOutputs(HavenoUtils.getInputKeyImages(depositTx));
|
||||
trade.getSelf().setReserveTxKeyImages(null);
|
||||
}
|
||||
|
||||
// re-freeze maker offer inputs
|
||||
if (trade instanceof MakerTrade) {
|
||||
trade.getXmrWalletService().freezeOutputs(trade.getOffer().getOfferPayload().getReserveTxKeyImages());
|
||||
}
|
||||
|
||||
throw e;
|
||||
@ -129,17 +132,13 @@ public class MaybeSendSignContractRequest extends TradeTask {
|
||||
// reset protocol timeout
|
||||
trade.addInitProgressStep();
|
||||
|
||||
// collect reserved key images
|
||||
List<String> reservedKeyImages = new ArrayList<String>();
|
||||
for (MoneroOutput input : depositTx.getInputs()) reservedKeyImages.add(input.getKeyImage().getHex());
|
||||
|
||||
// update trade state
|
||||
BigInteger securityDeposit = trade instanceof BuyerTrade ? trade.getBuyerSecurityDepositBeforeMiningFee() : trade.getSellerSecurityDepositBeforeMiningFee();
|
||||
trade.getSelf().setSecurityDeposit(securityDeposit.subtract(depositTx.getFee()));
|
||||
trade.getSelf().setDepositTx(depositTx);
|
||||
trade.getSelf().setDepositTxHash(depositTx.getHash());
|
||||
trade.getSelf().setDepositTxFee(depositTx.getFee());
|
||||
trade.getSelf().setReserveTxKeyImages(reservedKeyImages);
|
||||
trade.getSelf().setReserveTxKeyImages(HavenoUtils.getInputKeyImages(depositTx));
|
||||
trade.getSelf().setPayoutAddressString(trade.getXmrWalletService().getOrCreateAddressEntry(trade.getOffer().getId(), XmrAddressEntry.Context.TRADE_PAYOUT).getAddressString()); // TODO (woodser): allow custom payout address?
|
||||
trade.getSelf().setPaymentAccountPayload(trade.getProcessModel().getPaymentAccountPayload(trade.getSelf().getPaymentAccountId()));
|
||||
}
|
||||
|
@ -20,17 +20,15 @@ package haveno.core.trade.protocol.tasks;
|
||||
import haveno.common.taskrunner.TaskRunner;
|
||||
import haveno.core.offer.OfferDirection;
|
||||
import haveno.core.trade.HavenoUtils;
|
||||
import haveno.core.trade.TakerTrade;
|
||||
import haveno.core.trade.Trade;
|
||||
import haveno.core.trade.protocol.TradeProtocol;
|
||||
import haveno.core.xmr.model.XmrAddressEntry;
|
||||
import haveno.core.xmr.wallet.XmrWalletService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import monero.daemon.model.MoneroOutput;
|
||||
import monero.wallet.model.MoneroTxWallet;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
public class TakerReserveTradeFunds extends TradeTask {
|
||||
@ -44,6 +42,11 @@ public class TakerReserveTradeFunds extends TradeTask {
|
||||
try {
|
||||
runInterceptHook();
|
||||
|
||||
// taker trade expected
|
||||
if (!(trade instanceof TakerTrade)) {
|
||||
throw new RuntimeException("Expected taker trade but was " + trade.getClass().getSimpleName() + " " + trade.getShortId() + ". That should never happen.");
|
||||
}
|
||||
|
||||
// create reserve tx
|
||||
MoneroTxWallet reserveTx = null;
|
||||
synchronized (XmrWalletService.WALLET_LOCK) {
|
||||
@ -60,31 +63,39 @@ public class TakerReserveTradeFunds extends TradeTask {
|
||||
String returnAddress = trade.getXmrWalletService().getOrCreateAddressEntry(trade.getOffer().getId(), XmrAddressEntry.Context.TRADE_PAYOUT).getAddressString();
|
||||
|
||||
// attempt creating reserve tx
|
||||
synchronized (HavenoUtils.getWalletFunctionLock()) {
|
||||
for (int i = 0; i < TradeProtocol.MAX_ATTEMPTS; i++) {
|
||||
try {
|
||||
reserveTx = model.getXmrWalletService().createReserveTx(penaltyFee, takerFee, sendAmount, securityDeposit, returnAddress, false, null);
|
||||
} catch (Exception e) {
|
||||
log.warn("Error creating reserve tx, attempt={}/{}, tradeId={}, error={}", i + 1, TradeProtocol.MAX_ATTEMPTS, trade.getShortId(), e.getMessage());
|
||||
if (i == TradeProtocol.MAX_ATTEMPTS - 1) throw e;
|
||||
HavenoUtils.waitFor(TradeProtocol.REPROCESS_DELAY_MS); // wait before retrying
|
||||
try {
|
||||
synchronized (HavenoUtils.getWalletFunctionLock()) {
|
||||
for (int i = 0; i < TradeProtocol.MAX_ATTEMPTS; i++) {
|
||||
try {
|
||||
reserveTx = model.getXmrWalletService().createReserveTx(penaltyFee, takerFee, sendAmount, securityDeposit, returnAddress, false, null);
|
||||
} catch (Exception e) {
|
||||
log.warn("Error creating reserve tx, attempt={}/{}, tradeId={}, error={}", i + 1, TradeProtocol.MAX_ATTEMPTS, trade.getShortId(), e.getMessage());
|
||||
if (i == TradeProtocol.MAX_ATTEMPTS - 1) throw e;
|
||||
HavenoUtils.waitFor(TradeProtocol.REPROCESS_DELAY_MS); // wait before retrying
|
||||
}
|
||||
|
||||
// check for timeout
|
||||
if (isTimedOut()) throw new RuntimeException("Trade protocol has timed out while creating reserve tx, tradeId=" + trade.getShortId());
|
||||
if (reserveTx != null) break;
|
||||
}
|
||||
|
||||
// check for timeout
|
||||
if (isTimedOut()) throw new RuntimeException("Trade protocol has timed out while creating reserve tx, tradeId=" + trade.getShortId());
|
||||
if (reserveTx != null) break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
// thaw reserved inputs
|
||||
if (reserveTx != null) {
|
||||
model.getXmrWalletService().thawOutputs(HavenoUtils.getInputKeyImages(reserveTx));
|
||||
trade.getSelf().setReserveTxKeyImages(null);
|
||||
}
|
||||
|
||||
throw e;
|
||||
}
|
||||
|
||||
|
||||
// reset protocol timeout
|
||||
trade.startProtocolTimeout();
|
||||
|
||||
// collect reserved key images
|
||||
List<String> reservedKeyImages = new ArrayList<String>();
|
||||
for (MoneroOutput input : reserveTx.getInputs()) reservedKeyImages.add(input.getKeyImage().getHex());
|
||||
|
||||
// update trade state
|
||||
trade.getTaker().setReserveTxKeyImages(reservedKeyImages);
|
||||
trade.getTaker().setReserveTxKeyImages(HavenoUtils.getInputKeyImages(reserveTx));
|
||||
}
|
||||
|
||||
// save process state
|
||||
|
Loading…
Reference in New Issue
Block a user