recover from deleted wallet cache

This commit is contained in:
woodser 2024-05-03 17:46:46 -04:00
parent b50238a805
commit ceff34672d
3 changed files with 52 additions and 12 deletions

View File

@ -895,6 +895,9 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
// if not found, create tx to split exact output // if not found, create tx to split exact output
if (splitOutputTx == null) { if (splitOutputTx == null) {
if (openOffer.getSplitOutputTxHash() != null) {
log.warn("Split output tx not found for offer {}", openOffer.getId());
}
splitOrSchedule(openOffers, openOffer, amountNeeded); splitOrSchedule(openOffers, openOffer, amountNeeded);
} else if (!splitOutputTx.isLocked()) { } else if (!splitOutputTx.isLocked()) {
@ -1026,7 +1029,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
// handle sufficient available balance to split output // handle sufficient available balance to split output
boolean sufficientAvailableBalance = xmrWalletService.getAvailableBalance().compareTo(offerReserveAmount) >= 0; boolean sufficientAvailableBalance = xmrWalletService.getAvailableBalance().compareTo(offerReserveAmount) >= 0;
if (sufficientAvailableBalance) { if (sufficientAvailableBalance && openOffer.getSplitOutputTxHash() == null) {
log.info("Splitting and scheduling outputs for offer {}", openOffer.getShortId()); log.info("Splitting and scheduling outputs for offer {}", openOffer.getShortId());
splitAndSchedule(openOffer); splitAndSchedule(openOffer);
} else if (openOffer.getScheduledTxHashes() == null) { } else if (openOffer.getScheduledTxHashes() == null) {
@ -1053,7 +1056,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
break; break;
} catch (Exception e) { } catch (Exception e) {
log.warn("Error creating split output tx to fund offer {} at subaddress {}, attempt={}/{}, error={}", openOffer.getShortId(), entry.getSubaddressIndex(), i + 1, TradeProtocol.MAX_ATTEMPTS, e.getMessage()); log.warn("Error creating split output tx to fund offer {} at subaddress {}, attempt={}/{}, error={}", openOffer.getShortId(), entry.getSubaddressIndex(), i + 1, TradeProtocol.MAX_ATTEMPTS, e.getMessage());
if (i == TradeProtocol.MAX_ATTEMPTS - 1) throw e; if (stopped || i == TradeProtocol.MAX_ATTEMPTS - 1) throw e;
HavenoUtils.waitFor(TradeProtocol.REPROCESS_DELAY_MS); // wait before retrying HavenoUtils.waitFor(TradeProtocol.REPROCESS_DELAY_MS); // wait before retrying
} }
} }

View File

@ -482,8 +482,8 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
maybeRemoveTradeOnError(trade); maybeRemoveTradeOnError(trade);
} }
// thaw unreserved outputs // freeze or thaw outputs
xmrWalletService.thawUnreservedOutputs(); xmrWalletService.fixReservedOutputs();
// reset any available funded address entries // reset any available funded address entries
if (isShutDownStarted) return; if (isShutDownStarted) return;

View File

@ -459,35 +459,72 @@ public class XmrWalletService {
public MoneroTxWallet createTx(MoneroTxConfig txConfig) { public MoneroTxWallet createTx(MoneroTxConfig txConfig) {
synchronized (WALLET_LOCK) { synchronized (WALLET_LOCK) {
synchronized (HavenoUtils.getWalletFunctionLock()) { synchronized (HavenoUtils.getWalletFunctionLock()) {
return wallet.createTx(txConfig); MoneroTxWallet tx = wallet.createTx(txConfig);
if (Boolean.TRUE.equals(txConfig.getRelay())) {
cachedTxs.addFirst(tx);
cacheWalletInfo();
requestSaveMainWallet();
}
return tx;
} }
} }
} }
public MoneroTxWallet createTx(List<MoneroDestination> destinations) { public MoneroTxWallet createTx(List<MoneroDestination> destinations) {
MoneroTxWallet tx = createTx(new MoneroTxConfig().setAccountIndex(0).setDestinations(destinations).setRelay(false).setCanSplit(false));; MoneroTxWallet tx = createTx(new MoneroTxConfig().setAccountIndex(0).setDestinations(destinations).setRelay(false).setCanSplit(false));
//printTxs("XmrWalletService.createTx", tx); //printTxs("XmrWalletService.createTx", tx);
requestSaveMainWallet();
return tx; return tx;
} }
/** /**
* Thaw all outputs not reserved for a trade. * Freeze reserved outputs and thaw unreserved outputs.
*/ */
public void thawUnreservedOutputs() { public void fixReservedOutputs() {
synchronized (WALLET_LOCK) { synchronized (WALLET_LOCK) {
// collect reserved outputs // collect reserved outputs
Set<String> reservedKeyImages = new HashSet<String>(); Set<String> reservedKeyImages = new HashSet<String>();
for (Trade trade : tradeManager.getObservableList()) { for (Trade trade : tradeManager.getOpenTrades()) {
if (trade.getSelf().getReserveTxKeyImages() == null) continue; if (trade.getSelf().getReserveTxKeyImages() == null) continue;
reservedKeyImages.addAll(trade.getSelf().getReserveTxKeyImages()); reservedKeyImages.addAll(trade.getSelf().getReserveTxKeyImages());
} }
for (OpenOffer openOffer : tradeManager.getOpenOfferManager().getObservableList()) { for (OpenOffer openOffer : tradeManager.getOpenOfferManager().getOpenOffers()) {
if (openOffer.getOffer().getOfferPayload().getReserveTxKeyImages() == null) continue; if (openOffer.getOffer().getOfferPayload().getReserveTxKeyImages() == null) continue;
reservedKeyImages.addAll(openOffer.getOffer().getOfferPayload().getReserveTxKeyImages()); reservedKeyImages.addAll(openOffer.getOffer().getOfferPayload().getReserveTxKeyImages());
} }
freezeReservedOutputs(reservedKeyImages);
thawUnreservedOutputs(reservedKeyImages);
}
}
private void freezeReservedOutputs(Set<String> reservedKeyImages) {
synchronized (WALLET_LOCK) {
// ensure wallet is open
if (wallet == null) {
log.warn("Cannot freeze reserved outputs because wallet not open");
return;
}
// freeze reserved outputs
Set<String> reservedUnfrozenKeyImages = getOutputs(new MoneroOutputQuery()
.setIsFrozen(false)
.setIsSpent(false))
.stream()
.map(output -> output.getKeyImage().getHex())
.collect(Collectors.toSet());
reservedUnfrozenKeyImages.retainAll(reservedKeyImages);
if (!reservedUnfrozenKeyImages.isEmpty()) {
log.warn("Freezing unfrozen outputs which are reserved for offer or trade: " + reservedUnfrozenKeyImages);
freezeOutputs(reservedUnfrozenKeyImages);
}
}
}
private void thawUnreservedOutputs(Set<String> reservedKeyImages) {
synchronized (WALLET_LOCK) {
// ensure wallet is open // ensure wallet is open
if (wallet == null) { if (wallet == null) {
log.warn("Cannot thaw unreserved outputs because wallet not open"); log.warn("Cannot thaw unreserved outputs because wallet not open");
@ -503,7 +540,7 @@ public class XmrWalletService {
.collect(Collectors.toSet()); .collect(Collectors.toSet());
unreservedFrozenKeyImages.removeAll(reservedKeyImages); unreservedFrozenKeyImages.removeAll(reservedKeyImages);
if (!unreservedFrozenKeyImages.isEmpty()) { if (!unreservedFrozenKeyImages.isEmpty()) {
log.warn("Thawing outputs which are not reserved for offer or trade: " + unreservedFrozenKeyImages); log.warn("Thawing frozen outputs which are not reserved for offer or trade: " + unreservedFrozenKeyImages);
thawOutputs(unreservedFrozenKeyImages); thawOutputs(unreservedFrozenKeyImages);
} }
} }