From 2844337c090f4fe77ce2fd9e6ee2a9b4ef059c69 Mon Sep 17 00:00:00 2001 From: woodser Date: Mon, 11 Aug 2025 09:17:48 -0400 Subject: [PATCH] fix upgrading cloned offers after protocol update (#1902) --- .../java/haveno/core/offer/OpenOffer.java | 8 +++---- .../haveno/core/offer/OpenOfferManager.java | 24 ++++++++++++------- .../core/xmr/wallet/XmrWalletService.java | 21 ++++++++++++++++ .../haveno/core/trade/TradableListTest.java | 2 +- 4 files changed, 41 insertions(+), 14 deletions(-) diff --git a/core/src/main/java/haveno/core/offer/OpenOffer.java b/core/src/main/java/haveno/core/offer/OpenOffer.java index 9c51dead66..f5a69f7528 100644 --- a/core/src/main/java/haveno/core/offer/OpenOffer.java +++ b/core/src/main/java/haveno/core/offer/OpenOffer.java @@ -122,16 +122,16 @@ public final class OpenOffer implements Tradable { this(offer, 0, false); } - public OpenOffer(Offer offer, long triggerPrice) { - this(offer, triggerPrice, false); + public OpenOffer(Offer offer, long triggerPrice, boolean reserveExactAmount) { + this(offer, triggerPrice, reserveExactAmount, null); } - public OpenOffer(Offer offer, long triggerPrice, boolean reserveExactAmount) { + public OpenOffer(Offer offer, long triggerPrice, boolean reserveExactAmount, String groupId) { this.offer = offer; this.triggerPrice = triggerPrice; this.reserveExactAmount = reserveExactAmount; this.challenge = offer.getChallenge(); - this.groupId = UUID.randomUUID().toString(); + this.groupId = groupId == null ? UUID.randomUUID().toString() : groupId; state = State.PENDING; } diff --git a/core/src/main/java/haveno/core/offer/OpenOfferManager.java b/core/src/main/java/haveno/core/offer/OpenOfferManager.java index 34ca91ddee..d196b2a35c 100644 --- a/core/src/main/java/haveno/core/offer/OpenOfferManager.java +++ b/core/src/main/java/haveno/core/offer/OpenOfferManager.java @@ -1260,7 +1260,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe } private List getSplitOutputFundingTxs(BigInteger reserveAmount, Integer preferredSubaddressIndex) { - List splitOutputTxs = xmrWalletService.getTxs(new MoneroTxQuery().setIsIncoming(true).setIsFailed(false)); + List splitOutputTxs = xmrWalletService.getTxs(new MoneroTxQuery().setIsFailed(false)); // TODO: not using setIsIncoming(true) because split output txs sent to self have false; fix in monero-java? Set removeTxs = new HashSet(); for (MoneroTxWallet tx : splitOutputTxs) { if (tx.getOutputs() != null) { // outputs not available until first confirmation @@ -1283,6 +1283,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe boolean hasExactTransfer = (tx.getTransfers(new MoneroTransferQuery() .setAccountIndex(0) .setSubaddressIndex(preferredSubaddressIndex) + .setIsIncoming(true) .setAmount(amount)).size() > 0); return hasExactTransfer; } @@ -1972,8 +1973,10 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe /////////////////////////////////////////////////////////////////////////////////////////// private void maybeUpdatePersistedOffers() { - List openOffersClone = getOpenOffers(); - openOffersClone.forEach(originalOpenOffer -> { + + // update open offers + List updatedOpenOffers = new ArrayList<>(); + getOpenOffers().forEach(originalOpenOffer -> { Offer originalOffer = originalOpenOffer.getOffer(); OfferPayload originalOfferPayload = originalOffer.getOfferPayload(); @@ -2068,16 +2071,19 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe // create new offer Offer updatedOffer = new Offer(updatedPayload); updatedOffer.setPriceFeedService(priceFeedService); - long normalizedTriggerPrice = originalOffer.isInverted() ? PriceUtil.invertLongPrice(originalOpenOffer.getTriggerPrice(), originalOffer.getCounterCurrencyCode()) : originalOpenOffer.getTriggerPrice(); - OpenOffer updatedOpenOffer = new OpenOffer(updatedOffer, normalizedTriggerPrice); + OpenOffer updatedOpenOffer = new OpenOffer(updatedOffer, normalizedTriggerPrice, originalOpenOffer.isReserveExactAmount(), originalOpenOffer.getGroupId()); updatedOpenOffer.setChallenge(originalOpenOffer.getChallenge()); - addOpenOffer(updatedOpenOffer); - requestPersistence(); - - log.info("Updating offer completed. id={}", originalOffer.getId()); + updatedOpenOffers.add(updatedOpenOffer); } }); + + // add updated open offers + updatedOpenOffers.forEach(updatedOpenOffer -> { + addOpenOffer(updatedOpenOffer); + requestPersistence(); + log.info("Updating offer completed. id={}", updatedOpenOffer.getId()); + }); } diff --git a/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java b/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java index 1849981731..56ab9c7c61 100644 --- a/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java +++ b/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java @@ -575,6 +575,7 @@ public class XmrWalletService extends XmrWalletBase { // freeze outputs for (String keyImage : unfrozenKeyImages) wallet.freezeOutput(keyImage); + cacheNonPoolTxs(); cacheWalletInfo(); requestSaveWallet(); } @@ -597,11 +598,31 @@ public class XmrWalletService extends XmrWalletBase { // thaw outputs for (String keyImage : frozenKeyImages) wallet.thawOutput(keyImage); + cacheNonPoolTxs(); cacheWalletInfo(); requestSaveWallet(); } } + private void cacheNonPoolTxs() { + + // get non-pool txs + List nonPoolTxs = wallet.getTxs(new MoneroTxQuery().setIncludeOutputs(true).setInTxPool(false)); + + // replace non-pool txs in cache + for (MoneroTxWallet nonPoolTx : nonPoolTxs) { + boolean replaced = false; + for (int i = 0; i < cachedTxs.size(); i++) { + if (cachedTxs.get(i).getHash().equals(nonPoolTx.getHash())) { + cachedTxs.set(i, nonPoolTx); + replaced = true; + break; + } + } + if (!replaced) cachedTxs.add(nonPoolTx); + } + } + private List getSubaddressesWithExactInput(BigInteger amount) { // fetch unspent, unfrozen, unlocked outputs diff --git a/core/src/test/java/haveno/core/trade/TradableListTest.java b/core/src/test/java/haveno/core/trade/TradableListTest.java index 7577d6365a..5fac7064a5 100644 --- a/core/src/test/java/haveno/core/trade/TradableListTest.java +++ b/core/src/test/java/haveno/core/trade/TradableListTest.java @@ -38,7 +38,7 @@ public class TradableListTest { // test adding an OpenOffer and convert toProto Offer offer = new Offer(offerPayload); - OpenOffer openOffer = new OpenOffer(offer, 0); + OpenOffer openOffer = new OpenOffer(offer, 0, false); openOfferTradableList.add(openOffer); message = (protobuf.PersistableEnvelope) openOfferTradableList.toProtoMessage(); assertEquals(message.getMessageCase(), TRADABLE_LIST);