Merge branch 'master_upstream' into reenable-chat-on-dispute-reopen

This commit is contained in:
chimp1984 2020-08-28 14:11:59 -05:00
commit a148850685
No known key found for this signature in database
GPG Key ID: 9801B4EC591F90E3
8 changed files with 108 additions and 55 deletions

View File

@ -497,6 +497,14 @@ configure(project(':pricenode')) {
test {
useJUnitPlatform()
// Disabled by default, since spot provider tests include connections to external API endpoints
// Can be enabled by adding -Dtest.pricenode.includeSpotProviderTests=true to the gradle command:
// ./gradlew test -Dtest.pricenode.includeSpotProviderTests=true
if (System.properties['test.pricenode.includeSpotProviderTests'] != 'true') {
project.logger.lifecycle('Pricenode: Skipping spot provider tests')
exclude 'bisq/price/spot/providers/**'
}
}
task stage {

View File

@ -67,7 +67,7 @@ public abstract class BisqExecutable implements GracefulShutDownHandler, BisqSet
protected Injector injector;
protected AppModule module;
protected Config config;
private boolean isShutdown = false;
private boolean isShutdownInProgress;
public BisqExecutable(String fullName, String scriptName, String appName, String version) {
this.fullName = fullName;
@ -204,47 +204,56 @@ public abstract class BisqExecutable implements GracefulShutDownHandler, BisqSet
// This might need to be overwritten in case the application is not using all modules
@Override
public void gracefulShutDown(ResultHandler resultHandler) {
if (isShutdown) // prevent double cleanup
log.info("Start graceful shutDown");
if (isShutdownInProgress) {
return;
}
isShutdownInProgress = true;
if (injector == null) {
log.warn("Shut down called before injector was created");
resultHandler.handleResult();
System.exit(0);
}
isShutdown = true;
try {
if (injector != null) {
injector.getInstance(ArbitratorManager.class).shutDown();
injector.getInstance(TradeManager.class).shutDown();
injector.getInstance(DaoSetup.class).shutDown();
injector.getInstance(OpenOfferManager.class).shutDown(() -> {
log.info("OpenOfferManager shutdown completed");
injector.getInstance(ArbitratorManager.class).shutDown();
injector.getInstance(TradeManager.class).shutDown();
injector.getInstance(DaoSetup.class).shutDown();
injector.getInstance(AvoidStandbyModeService.class).shutDown();
injector.getInstance(OpenOfferManager.class).shutDown(() -> {
log.info("OpenOfferManager shutdown completed");
injector.getInstance(BtcWalletService.class).shutDown();
injector.getInstance(BsqWalletService.class).shutDown();
// We need to shutdown BitcoinJ before the P2PService as it uses Tor.
WalletsSetup walletsSetup = injector.getInstance(WalletsSetup.class);
walletsSetup.shutDownComplete.addListener((ov, o, n) -> {
log.info("WalletsSetup shutdown completed");
injector.getInstance(P2PService.class).shutDown(() -> {
log.info("P2PService shutdown completed");
injector.getInstance(WalletsSetup.class).shutDownComplete.addListener((ov, o, n) -> {
log.info("WalletsSetup shutdown completed");
module.close(injector);
resultHandler.handleResult();
log.info("Graceful shutdown completed. Exiting now.");
System.exit(0);
});
injector.getInstance(WalletsSetup.class).shutDown();
injector.getInstance(BtcWalletService.class).shutDown();
injector.getInstance(BsqWalletService.class).shutDown();
module.close(injector);
resultHandler.handleResult();
log.info("Graceful shutdown completed. Exiting now.");
System.exit(0);
});
});
injector.getInstance(AvoidStandbyModeService.class).shutDown();
// we wait max 20 sec.
UserThread.runAfter(() -> {
log.warn("Timeout triggered resultHandler");
resultHandler.handleResult();
System.exit(0);
}, 20);
} else {
log.warn("injector == null triggered resultHandler");
UserThread.runAfter(() -> {
resultHandler.handleResult();
System.exit(0);
}, 1);
}
walletsSetup.shutDown();
});
// Wait max 20 sec.
UserThread.runAfter(() -> {
log.warn("Timeout triggered resultHandler");
resultHandler.handleResult();
System.exit(0);
}, 20);
} catch (Throwable t) {
log.error("App shutdown failed with exception");
log.error("App shutdown failed with exception {}", t.toString());
t.printStackTrace();
System.exit(1);
}

View File

@ -492,8 +492,11 @@ public class WalletConfig extends AbstractIdleService {
}
}
private Wallet createOrLoadWallet(File walletFile, boolean shouldReplayWallet,
BisqKeyChainGroup keyChainGroup, boolean isBsqWallet, DeterministicSeed restoreFromSeed)
private Wallet createOrLoadWallet(File walletFile,
boolean shouldReplayWallet,
BisqKeyChainGroup keyChainGroup,
boolean isBsqWallet,
DeterministicSeed restoreFromSeed)
throws Exception {
if (restoreFromSeed != null)
@ -530,7 +533,9 @@ public class WalletConfig extends AbstractIdleService {
}
}
private Wallet loadWallet(File walletFile, boolean shouldReplayWallet, boolean useBitcoinDeterministicKeyChain) throws Exception {
private Wallet loadWallet(File walletFile,
boolean shouldReplayWallet,
boolean useBitcoinDeterministicKeyChain) throws Exception {
Wallet wallet;
try (FileInputStream walletStream = new FileInputStream(walletFile)) {
List<WalletExtension> extensions = provideWalletExtensions();
@ -570,21 +575,30 @@ public class WalletConfig extends AbstractIdleService {
// Runs in a separate thread.
try {
Context.propagate(context);
vPeerGroup.stop();
vBtcWallet.saveToFile(vBtcWalletFile);
if (vBsqWallet != null && vBsqWalletFile != null)
//noinspection ConstantConditions,ConstantConditions
vBsqWallet.saveToFile(vBsqWalletFile);
vStore.close();
vPeerGroup = null;
vBtcWallet.saveToFile(vBtcWalletFile);
vBtcWallet = null;
vBsqWallet = null;
log.info("BtcWallet saved to file");
if (vBsqWallet != null && vBsqWalletFile != null) {
vBsqWallet.saveToFile(vBsqWalletFile);
vBsqWallet = null;
log.info("BsqWallet saved to file");
}
vStore.close();
vStore = null;
log.info("SPV file closed");
vChain = null;
// vPeerGroup.stop has no timeout and can take very long (10 sec. in my test). So we call it at the end.
// We might get likely interrupted by the parent call timeout.
vPeerGroup.stop();
vPeerGroup = null;
log.info("PeerGroup stopped");
} catch (BlockStoreException e) {
throw new IOException(e);
} catch (Throwable ignore) {
}
}

View File

@ -18,7 +18,6 @@
package bisq.core.btc.setup;
import bisq.core.btc.exceptions.InvalidHostException;
import bisq.core.btc.nodes.LocalBitcoinNode;
import bisq.core.btc.exceptions.RejectedTxException;
import bisq.core.btc.model.AddressEntry;
import bisq.core.btc.model.AddressEntryList;
@ -27,6 +26,7 @@ import bisq.core.btc.nodes.BtcNodes;
import bisq.core.btc.nodes.BtcNodes.BtcNode;
import bisq.core.btc.nodes.BtcNodesRepository;
import bisq.core.btc.nodes.BtcNodesSetupPreferences;
import bisq.core.btc.nodes.LocalBitcoinNode;
import bisq.core.user.Preferences;
import bisq.network.Socks5MultiDiscovery;
@ -314,14 +314,16 @@ public class WalletsSetup {
public void shutDown() {
if (walletConfig != null) {
try {
log.info("walletConfig shutDown started");
walletConfig.stopAsync();
walletConfig.awaitTerminated(5, TimeUnit.SECONDS);
walletConfig.awaitTerminated(1, TimeUnit.SECONDS);
log.info("walletConfig shutDown completed");
} catch (Throwable ignore) {
log.info("walletConfig shutDown interrupted by timeout");
}
shutDownComplete.set(true);
} else {
shutDownComplete.set(true);
}
shutDownComplete.set(true);
}
public void reSyncSPVChain() throws IOException {

View File

@ -82,6 +82,8 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
new BlockChainExplorer("mempool.space Tor V3", "http://mempoolhqx4isw62xs7abwphsq7ldayuidyx2v2oethdhhj6mlo2r6ad.onion/tx/", "http://mempoolhqx4isw62xs7abwphsq7ldayuidyx2v2oethdhhj6mlo2r6ad.onion/address/"),
new BlockChainExplorer("mempool.emzy.de (@emzy)", "https://mempool.emzy.de/tx/", "https://mempool.emzy.de/address/"),
new BlockChainExplorer("mempool.emzy.de Tor V3", "http://mempool4t6mypeemozyterviq3i5de4kpoua65r3qkn5i3kknu5l2cad.onion/tx/", "http://mempool4t6mypeemozyterviq3i5de4kpoua65r3qkn5i3kknu5l2cad.onion/address/"),
new BlockChainExplorer("mempool.bisq.services (@devinbileck)", "https://mempool.bisq.services/tx/", "https://mempool.bisq.services/address/"),
new BlockChainExplorer("mempool.bisq.services Tor V3", "http://mempoolusb2f67qi7mz2it7n5e77a6komdzx6wftobcduxszkdfun2yd.onion/tx/", "http://mempoolusb2f67qi7mz2it7n5e77a6komdzx6wftobcduxszkdfun2yd.onion/address/"),
new BlockChainExplorer("Blockstream.info", "https://blockstream.info/tx/", "https://blockstream.info/address/"),
new BlockChainExplorer("Blockstream.info Tor V3", "http://explorerzydxu5ecjrkwceayqybizmpjjznk5izmitf2modhcusuqlid.onion/tx/", "http://explorerzydxu5ecjrkwceayqybizmpjjznk5izmitf2modhcusuqlid.onion/address/"),
new BlockChainExplorer("OXT", "https://oxt.me/transaction/", "https://oxt.me/address/"),

View File

@ -123,6 +123,7 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis
private final IntegerProperty numConnectedPeers = new SimpleIntegerProperty(0);
private volatile boolean shutDownInProgress;
@Getter
private boolean shutDownComplete;
private final Subscription networkReadySubscription;
private boolean isBootstrapped;
@ -446,7 +447,9 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis
}
@Override
public void onRemoved(Collection<ProtectedStorageEntry> protectedStorageEntries) { }
public void onRemoved(Collection<ProtectedStorageEntry> protectedStorageEntries) {
// not handled
}
///////////////////////////////////////////////////////////////////////////////////////////
// DirectMessages
@ -463,7 +466,9 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis
}
}
private void doSendEncryptedDirectMessage(@NotNull NodeAddress peersNodeAddress, PubKeyRing pubKeyRing, NetworkEnvelope message,
private void doSendEncryptedDirectMessage(@NotNull NodeAddress peersNodeAddress,
PubKeyRing pubKeyRing,
NetworkEnvelope message,
SendDirectMessageListener sendDirectMessageListener) {
log.debug("Send encrypted direct message {} to peer {}",
message.getClass().getSimpleName(), peersNodeAddress);
@ -691,7 +696,9 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis
}
@Override
public void onBroadcastCompleted(BroadcastMessage message, int numOfCompletedBroadcasts, int numOfFailedBroadcasts) {
public void onBroadcastCompleted(BroadcastMessage message,
int numOfCompletedBroadcasts,
int numOfFailedBroadcasts) {
log.info("Broadcast completed: Sent to {} peers (failed: {}). Message = {}",
numOfCompletedBroadcasts, numOfFailedBroadcasts, Utilities.toTruncatedString(message));
if (numOfCompletedBroadcasts == 0)

View File

@ -332,7 +332,17 @@ public abstract class NetworkNode implements MessageListener {
Set<Connection> allConnections = getAllConnections();
int numConnections = allConnections.size();
if (numConnections == 0) {
log.info("Shutdown immediately because no connections are open.");
if (shutDownCompleteHandler != null) {
shutDownCompleteHandler.run();
}
return;
}
log.info("Shutdown {} connections", numConnections);
AtomicInteger shutdownCompleted = new AtomicInteger();
Timer timeoutHandler = UserThread.runAfter(() -> {
if (shutDownCompleteHandler != null) {
@ -340,6 +350,7 @@ public abstract class NetworkNode implements MessageListener {
shutDownCompleteHandler.run();
}
}, 3);
allConnections.forEach(c -> c.shutDown(CloseConnectionReason.APP_SHUT_DOWN,
() -> {
shutdownCompleted.getAndIncrement();

View File

@ -5,5 +5,5 @@ spring.jackson.serialization.indent_output=true
bisq.price.mining.providers.mempoolHostname.1=mempool.space
bisq.price.mining.providers.mempoolHostname.2=mempool.emzy.de
bisq.price.mining.providers.mempoolHostname.3=mempool.ninja
# bisq.price.mining.providers.mempoolHostname.4=someHostOrIP
bisq.price.mining.providers.mempoolHostname.4=mempool.bisq.services
# bisq.price.mining.providers.mempoolHostname.5=someHostOrIP