start main wallet when daemon synced with improved UserThread
This commit is contained in:
parent
5466689857
commit
5d88936600
@ -45,7 +45,7 @@ public class UserThread {
|
||||
@Getter
|
||||
@Setter
|
||||
private static Executor executor;
|
||||
private static final String USER_THREAD_NAME = "UserThread";
|
||||
private static Thread USER_THREAD;
|
||||
|
||||
public static void setTimerClass(Class<? extends Timer> timerClass) {
|
||||
UserThread.timerClass = timerClass;
|
||||
@ -59,8 +59,10 @@ public class UserThread {
|
||||
|
||||
public static void execute(Runnable command) {
|
||||
executor.execute(() -> {
|
||||
Thread.currentThread().setName(USER_THREAD_NAME);
|
||||
command.run();
|
||||
synchronized (executor) {
|
||||
USER_THREAD = Thread.currentThread();
|
||||
command.run();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -79,9 +81,9 @@ public class UserThread {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: better way to determine if on UserThread, since this is not reliable
|
||||
private static boolean isUserThread(Thread thread) {
|
||||
return USER_THREAD_NAME.equals(thread.getName());
|
||||
public static boolean isUserThread(Thread thread) {
|
||||
return thread == USER_THREAD;
|
||||
|
||||
}
|
||||
|
||||
// Prefer FxTimer if a delay is needed in a JavaFx class (gui module)
|
||||
@ -99,7 +101,7 @@ public class UserThread {
|
||||
}
|
||||
|
||||
public static Timer runAfter(Runnable runnable, long delay, TimeUnit timeUnit) {
|
||||
return getTimer().runLater(Duration.ofMillis(timeUnit.toMillis(delay)), runnable);
|
||||
return getTimer().runLater(Duration.ofMillis(timeUnit.toMillis(delay)), () -> execute(runnable));
|
||||
}
|
||||
|
||||
public static Timer runPeriodically(Runnable runnable, long intervalInSec) {
|
||||
@ -107,7 +109,7 @@ public class UserThread {
|
||||
}
|
||||
|
||||
public static Timer runPeriodically(Runnable runnable, long interval, TimeUnit timeUnit) {
|
||||
return getTimer().runPeriodically(Duration.ofMillis(timeUnit.toMillis(interval)), runnable);
|
||||
return getTimer().runPeriodically(Duration.ofMillis(timeUnit.toMillis(interval)), () -> execute(runnable));
|
||||
}
|
||||
|
||||
private static Timer getTimer() {
|
||||
|
@ -87,7 +87,6 @@ import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
import lombok.Getter;
|
||||
import monero.daemon.model.MoneroTx;
|
||||
import monero.wallet.model.MoneroOutputQuery;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import org.fxmisc.easybind.EasyBind;
|
||||
@ -353,35 +352,6 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||
}
|
||||
}
|
||||
|
||||
private void thawUnreservedOutputs() {
|
||||
if (xmrWalletService.getWallet() == null) return;
|
||||
|
||||
// collect reserved outputs
|
||||
Set<String> reservedKeyImages = new HashSet<String>();
|
||||
for (Trade trade : getObservableList()) {
|
||||
if (trade.getSelf().getReserveTxKeyImages() == null) continue;
|
||||
reservedKeyImages.addAll(trade.getSelf().getReserveTxKeyImages());
|
||||
}
|
||||
for (OpenOffer openOffer : openOfferManager.getObservableList()) {
|
||||
if (openOffer.getOffer().getOfferPayload().getReserveTxKeyImages() == null) continue;
|
||||
reservedKeyImages.addAll(openOffer.getOffer().getOfferPayload().getReserveTxKeyImages());
|
||||
}
|
||||
|
||||
// thaw unreserved outputs
|
||||
Set<String> unreservedFrozenKeyImages = xmrWalletService.getWallet().getOutputs(new MoneroOutputQuery()
|
||||
.setIsFrozen(true)
|
||||
.setIsSpent(false))
|
||||
.stream()
|
||||
.map(output -> output.getKeyImage().getHex())
|
||||
.collect(Collectors.toSet());
|
||||
unreservedFrozenKeyImages.removeAll(reservedKeyImages);
|
||||
if (!unreservedFrozenKeyImages.isEmpty()) {
|
||||
log.warn("Thawing outputs which are not reserved for offer or trade: " + unreservedFrozenKeyImages);
|
||||
xmrWalletService.thawOutputs(unreservedFrozenKeyImages);
|
||||
xmrWalletService.saveMainWallet();
|
||||
}
|
||||
}
|
||||
|
||||
public TradeProtocol getTradeProtocol(Trade trade) {
|
||||
synchronized (tradeProtocolByTradeId) {
|
||||
return tradeProtocolByTradeId.get(trade.getUid());
|
||||
@ -464,9 +434,10 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||
}
|
||||
|
||||
// thaw unreserved outputs
|
||||
thawUnreservedOutputs();
|
||||
xmrWalletService.thawUnreservedOutputs();
|
||||
|
||||
// reset any available funded address entries
|
||||
if (isShutDownStarted) return;
|
||||
xmrWalletService.getAddressEntriesForAvailableBalanceStream()
|
||||
.filter(addressEntry -> addressEntry.getOfferId() != null)
|
||||
.forEach(addressEntry -> {
|
||||
@ -476,6 +447,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||
}
|
||||
|
||||
// notify that persisted trades initialized
|
||||
if (isShutDownStarted) return;
|
||||
persistedTradesInitialized.set(true);
|
||||
getObservableList().addListener((ListChangeListener<Trade>) change -> onTradesChanged());
|
||||
onTradesChanged();
|
||||
|
@ -12,6 +12,7 @@ import haveno.common.util.Utilities;
|
||||
import haveno.core.api.AccountServiceListener;
|
||||
import haveno.core.api.CoreAccountService;
|
||||
import haveno.core.api.XmrConnectionService;
|
||||
import haveno.core.offer.OpenOffer;
|
||||
import haveno.core.trade.BuyerTrade;
|
||||
import haveno.core.trade.HavenoUtils;
|
||||
import haveno.core.trade.MakerTrade;
|
||||
@ -80,6 +81,7 @@ import java.util.stream.Stream;
|
||||
import javafx.beans.property.LongProperty;
|
||||
import javafx.beans.property.ReadOnlyDoubleProperty;
|
||||
import javafx.beans.property.SimpleLongProperty;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
@ -120,6 +122,7 @@ public class XmrWalletService {
|
||||
protected final CopyOnWriteArraySet<XmrBalanceListener> balanceListeners = new CopyOnWriteArraySet<>();
|
||||
protected final CopyOnWriteArraySet<MoneroWalletListenerI> walletListeners = new CopyOnWriteArraySet<>();
|
||||
|
||||
private ChangeListener<? super Number> walletInitListener;
|
||||
private TradeManager tradeManager;
|
||||
private MoneroWalletRpc wallet;
|
||||
private Object walletLock = new Object();
|
||||
@ -364,6 +367,45 @@ public class XmrWalletService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thaw all outputs not reserved for a trade.
|
||||
*/
|
||||
public void thawUnreservedOutputs() {
|
||||
synchronized (walletLock) {
|
||||
|
||||
// collect reserved outputs
|
||||
Set<String> reservedKeyImages = new HashSet<String>();
|
||||
for (Trade trade : tradeManager.getObservableList()) {
|
||||
if (trade.getSelf().getReserveTxKeyImages() == null) continue;
|
||||
reservedKeyImages.addAll(trade.getSelf().getReserveTxKeyImages());
|
||||
}
|
||||
for (OpenOffer openOffer : tradeManager.getOpenOfferManager().getObservableList()) {
|
||||
if (openOffer.getOffer().getOfferPayload().getReserveTxKeyImages() == null) continue;
|
||||
reservedKeyImages.addAll(openOffer.getOffer().getOfferPayload().getReserveTxKeyImages());
|
||||
}
|
||||
|
||||
// ensure wallet is open
|
||||
if (wallet == null) {
|
||||
log.warn("Cannot thaw unreserved outputs because wallet not open");
|
||||
return;
|
||||
}
|
||||
|
||||
// thaw unreserved outputs
|
||||
Set<String> unreservedFrozenKeyImages = wallet.getOutputs(new MoneroOutputQuery()
|
||||
.setIsFrozen(true)
|
||||
.setIsSpent(false))
|
||||
.stream()
|
||||
.map(output -> output.getKeyImage().getHex())
|
||||
.collect(Collectors.toSet());
|
||||
unreservedFrozenKeyImages.removeAll(reservedKeyImages);
|
||||
if (!unreservedFrozenKeyImages.isEmpty()) {
|
||||
log.warn("Thawing outputs which are not reserved for offer or trade: " + unreservedFrozenKeyImages);
|
||||
thawOutputs(unreservedFrozenKeyImages);
|
||||
saveMainWallet();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thaw the given outputs with a lock on the wallet.
|
||||
*
|
||||
@ -695,17 +737,21 @@ public class XmrWalletService {
|
||||
HavenoUtils.submitToThread(() -> onConnectionChanged(connection), THREAD_ID);
|
||||
});
|
||||
|
||||
// wait for monerod to sync
|
||||
if (xmrConnectionService.downloadPercentageProperty().get() != 1) {
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
xmrConnectionService.downloadPercentageProperty().addListener((obs, oldVal, newVal) -> {
|
||||
if (xmrConnectionService.downloadPercentageProperty().get() == 1) latch.countDown();
|
||||
});
|
||||
HavenoUtils.awaitLatch(latch);
|
||||
}
|
||||
// initialize main wallet when daemon synced
|
||||
walletInitListener = (obs, oldVal, newVal) -> initMainWalletIfConnected();
|
||||
xmrConnectionService.downloadPercentageProperty().addListener(walletInitListener);
|
||||
initMainWalletIfConnected();
|
||||
}
|
||||
|
||||
// initialize main wallet
|
||||
maybeInitMainWallet(true);
|
||||
private void initMainWalletIfConnected() {
|
||||
HavenoUtils.submitToThread(() -> {
|
||||
synchronized (walletLock) {
|
||||
if (xmrConnectionService.downloadPercentageProperty().get() == 1 && wallet == null && !isShutDownStarted) {
|
||||
maybeInitMainWallet(true);
|
||||
if (walletInitListener != null) xmrConnectionService.downloadPercentageProperty().removeListener(walletInitListener);
|
||||
}
|
||||
}
|
||||
}, THREAD_ID);
|
||||
}
|
||||
|
||||
private void maybeInitMainWallet(boolean sync) {
|
||||
|
Loading…
Reference in New Issue
Block a user