Skip to content

Commit

Permalink
switch to next best monerod if missing trade deposits
Browse files Browse the repository at this point in the history
  • Loading branch information
woodser committed Jul 5, 2024
1 parent ec9f91e commit a8573a2
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 15 deletions.
32 changes: 29 additions & 3 deletions core/src/main/java/haveno/core/api/XmrConnectionService.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@
import haveno.network.p2p.P2PService;
import haveno.network.p2p.P2PServiceListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.LongProperty;
Expand Down Expand Up @@ -201,12 +204,24 @@ public List<MoneroRpcConnection> getConnections() {
return connectionManager.getConnections();
}

public void switchToBestConnection() {
if (isFixedConnection() || !connectionManager.getAutoSwitch()) return;
private void switchToBestConnection() {
if (isFixedConnection() || !connectionManager.getAutoSwitch()) {
log.info("Skipping switch to best Monero connection because connection is fixed or auto switch is disabled");
return;
}
MoneroRpcConnection bestConnection = getBestAvailableConnection();
if (bestConnection != null) setConnection(bestConnection);
}

public void switchToNextBestConnection() {
if (isFixedConnection() || !connectionManager.getAutoSwitch()) {
log.info("Skipping switch to next best Monero connection because connection is fixed or auto switch is disabled");
return;
}
MoneroRpcConnection bestConnection = getBestAvailableConnection(List.of(getConnection()));
if (bestConnection != null) setConnection(bestConnection);
}

public void setConnection(String connectionUri) {
accountService.checkAccountOpen();
connectionManager.setConnection(connectionUri); // listener will update connection list
Expand Down Expand Up @@ -244,10 +259,21 @@ public void stopCheckingConnection() {
public MoneroRpcConnection getBestAvailableConnection() {
accountService.checkAccountOpen();
List<MoneroRpcConnection> ignoredConnections = new ArrayList<MoneroRpcConnection>();
if (xmrLocalNode.shouldBeIgnored() && connectionManager.hasConnection(xmrLocalNode.getUri())) ignoredConnections.add(connectionManager.getConnectionByUri(xmrLocalNode.getUri()));
addLocalNodeIfIgnored(ignoredConnections);
return connectionManager.getBestAvailableConnection(ignoredConnections.toArray(new MoneroRpcConnection[0]));
}

private MoneroRpcConnection getBestAvailableConnection(Collection<MoneroRpcConnection> ignoredConnections) {
accountService.checkAccountOpen();
Set<MoneroRpcConnection> ignoredConnectionsSet = new HashSet<>(ignoredConnections);
addLocalNodeIfIgnored(ignoredConnectionsSet);
return connectionManager.getBestAvailableConnection(ignoredConnectionsSet.toArray(new MoneroRpcConnection[0]));
}

private void addLocalNodeIfIgnored(Collection<MoneroRpcConnection> ignoredConnections) {
if (xmrLocalNode.shouldBeIgnored() && connectionManager.hasConnection(xmrLocalNode.getUri())) ignoredConnections.add(connectionManager.getConnectionByUri(xmrLocalNode.getUri()));
}

public void setAutoSwitch(boolean autoSwitch) {
accountService.checkAccountOpen();
connectionManager.setAutoSwitch(autoSwitch);
Expand Down
28 changes: 17 additions & 11 deletions core/src/main/java/haveno/core/trade/Trade.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -627,9 +628,7 @@ public void initialize(ProcessModelServiceProvider serviceProvider) {

// handle connection change on dedicated thread
xmrConnectionService.addConnectionListener(connection -> {
ThreadUtils.submitToPool(() -> { // TODO: remove this?
ThreadUtils.execute(() -> onConnectionChanged(connection), getConnectionChangedThreadId());
});
ThreadUtils.execute(() -> onConnectionChanged(connection), getConnectionChangedThreadId());
});

// reset buyer's payment sent state if no ack receive
Expand Down Expand Up @@ -1133,10 +1132,10 @@ private MoneroTxWallet doCreatePayoutTx() {
// check if multisig import needed
if (wallet.isMultisigImportNeeded()) throw new RuntimeException("Cannot create payout tx because multisig import is needed");

// TODO: wallet sometimes returns empty data, after disconnect?
List<MoneroTxWallet> txs = wallet.getTxs(); // TODO: this fetches from pool
if (txs.isEmpty()) {
log.warn("Restarting wallet for {} {} because deposit txs are missing to create payout tx", getClass().getSimpleName(), getId());
// TODO: wallet sometimes returns empty data, due to unreliable connection with specific daemons?
if (getMakerDepositTx() == null || getTakerDepositTx() == null) {
log.warn("Switching Monero connection and restarting trade wallet because deposit txs are missing to create payout tx for {} {}", getClass().getSimpleName(), getShortId());
switchToNextBestConnection();
forceRestartTradeWallet();
}

Expand Down Expand Up @@ -2236,10 +2235,6 @@ private void doPublishTradeStatistics() {
// Private
///////////////////////////////////////////////////////////////////////////////////////////

private String getConnectionChangedThreadId() {
return getId() + ".onConnectionChanged";
}

// lazy initialization
private ObjectProperty<BigInteger> getAmountProperty() {
if (tradeAmountProperty == null)
Expand All @@ -2255,6 +2250,17 @@ private ObjectProperty<Volume> getVolumeProperty() {
return tradeVolumeProperty;
}

private String getConnectionChangedThreadId() {
return getId() + ".onConnectionChanged";
}

private void switchToNextBestConnection() {
xmrConnectionService.switchToNextBestConnection();
CountDownLatch latch = new CountDownLatch(1);
ThreadUtils.execute(() -> latch.countDown(), getConnectionChangedThreadId()); // wait for connection change to complete
HavenoUtils.awaitLatch(latch);
}

private void onConnectionChanged(MoneroRpcConnection connection) {
synchronized (walletLock) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1817,7 +1817,7 @@ private void doPollWallet(boolean updateTxs) {
// switch to best connection if wallet is too far behind
if (wasWalletSynced && walletHeight.get() < xmrConnectionService.getTargetHeight() - NUM_BLOCKS_BEHIND_TOLERANCE && !Config.baseCurrencyNetwork().isTestnet()) {
log.warn("Updating connection because main wallet is {} blocks behind monerod, wallet height={}, monerod height={}", xmrConnectionService.getTargetHeight() - walletHeight.get(), walletHeight.get(), lastInfo.getHeight());
xmrConnectionService.switchToBestConnection();
xmrConnectionService.switchToNextBestConnection();
}

// sync wallet if behind daemon
Expand Down

0 comments on commit a8573a2

Please sign in to comment.