diff --git a/build.gradle b/build.gradle index ec504a8839..38e3689412 100644 --- a/build.gradle +++ b/build.gradle @@ -360,6 +360,7 @@ configure(project(':p2p')) { testImplementation "ch.qos.logback:logback-core:$logbackVersion" testImplementation "org.apache.commons:commons-lang3:$langVersion" testImplementation("org.mockito:mockito-core:$mockitoVersion") + testImplementation("org.mockito:mockito-junit-jupiter:$mockitoVersion") implementation "org.openjfx:javafx-base:$javafxVersion:$os" implementation "org.openjfx:javafx-graphics:$javafxVersion:$os" diff --git a/core/src/main/java/haveno/core/account/sign/SignedWitnessService.java b/core/src/main/java/haveno/core/account/sign/SignedWitnessService.java index 1d7c7607f4..b4ba7b58a8 100644 --- a/core/src/main/java/haveno/core/account/sign/SignedWitnessService.java +++ b/core/src/main/java/haveno/core/account/sign/SignedWitnessService.java @@ -132,7 +132,7 @@ public class SignedWitnessService { } else { p2PService.addP2PServiceListener(new BootstrapListener() { @Override - public void onUpdatedDataReceived() { + public void onDataReceived() { onBootstrapComplete(); } }); diff --git a/core/src/main/java/haveno/core/account/witness/AccountAgeWitnessService.java b/core/src/main/java/haveno/core/account/witness/AccountAgeWitnessService.java index ea50e4bea4..deab92eb50 100644 --- a/core/src/main/java/haveno/core/account/witness/AccountAgeWitnessService.java +++ b/core/src/main/java/haveno/core/account/witness/AccountAgeWitnessService.java @@ -200,7 +200,7 @@ public class AccountAgeWitnessService { } else { p2PService.addP2PServiceListener(new BootstrapListener() { @Override - public void onUpdatedDataReceived() { + public void onDataReceived() { onBootStrapped(); } }); diff --git a/core/src/main/java/haveno/core/app/AppStartupState.java b/core/src/main/java/haveno/core/app/AppStartupState.java index 7e74d81b9d..85da2af9d4 100644 --- a/core/src/main/java/haveno/core/app/AppStartupState.java +++ b/core/src/main/java/haveno/core/app/AppStartupState.java @@ -58,7 +58,7 @@ public class AppStartupState { p2PService.addP2PServiceListener(new BootstrapListener() { @Override - public void onUpdatedDataReceived() { + public void onDataReceived() { updatedDataReceived.set(true); } }); diff --git a/core/src/main/java/haveno/core/offer/OfferBookService.java b/core/src/main/java/haveno/core/offer/OfferBookService.java index 0bb08a4618..4e7adbb52e 100644 --- a/core/src/main/java/haveno/core/offer/OfferBookService.java +++ b/core/src/main/java/haveno/core/offer/OfferBookService.java @@ -151,7 +151,7 @@ public class OfferBookService { if (dumpStatistics) { p2PService.addP2PServiceListener(new BootstrapListener() { @Override - public void onUpdatedDataReceived() { + public void onDataReceived() { addOfferBookChangedListener(new OfferBookChangedListener() { @Override public void onAdded(Offer offer) { diff --git a/core/src/main/java/haveno/core/offer/OpenOfferManager.java b/core/src/main/java/haveno/core/offer/OpenOfferManager.java index cefb735678..e9565728c6 100644 --- a/core/src/main/java/haveno/core/offer/OpenOfferManager.java +++ b/core/src/main/java/haveno/core/offer/OpenOfferManager.java @@ -295,7 +295,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe } else { p2PService.addP2PServiceListener(new BootstrapListener() { @Override - public void onUpdatedDataReceived() { + public void onDataReceived() { onBootstrapComplete(); } }); diff --git a/core/src/main/java/haveno/core/offer/TriggerPriceService.java b/core/src/main/java/haveno/core/offer/TriggerPriceService.java index 7cefac2148..59705de064 100644 --- a/core/src/main/java/haveno/core/offer/TriggerPriceService.java +++ b/core/src/main/java/haveno/core/offer/TriggerPriceService.java @@ -62,7 +62,7 @@ public class TriggerPriceService { } else { p2PService.addP2PServiceListener(new BootstrapListener() { @Override - public void onUpdatedDataReceived() { + public void onDataReceived() { onBootstrapComplete(); } }); diff --git a/core/src/main/java/haveno/core/support/dispute/DisputeManager.java b/core/src/main/java/haveno/core/support/dispute/DisputeManager.java index 72cdb9194f..e1ae29802e 100644 --- a/core/src/main/java/haveno/core/support/dispute/DisputeManager.java +++ b/core/src/main/java/haveno/core/support/dispute/DisputeManager.java @@ -264,7 +264,7 @@ public abstract class DisputeManager> extends Sup p2PService.addP2PServiceListener(new BootstrapListener() { @Override - public void onUpdatedDataReceived() { + public void onDataReceived() { tryApplyMessages(); } }); diff --git a/core/src/main/java/haveno/core/support/dispute/agent/DisputeAgentManager.java b/core/src/main/java/haveno/core/support/dispute/agent/DisputeAgentManager.java index f9bf8476a8..4b4fc1011e 100644 --- a/core/src/main/java/haveno/core/support/dispute/agent/DisputeAgentManager.java +++ b/core/src/main/java/haveno/core/support/dispute/agent/DisputeAgentManager.java @@ -151,7 +151,7 @@ public abstract class DisputeAgentManager { else p2PService.addP2PServiceListener(new BootstrapListener() { @Override - public void onUpdatedDataReceived() { + public void onDataReceived() { startRepublishDisputeAgent(); } }); diff --git a/core/src/main/java/haveno/core/trade/CleanupMailboxMessages.java b/core/src/main/java/haveno/core/trade/CleanupMailboxMessages.java index 9b9df16d04..ee10d599ee 100644 --- a/core/src/main/java/haveno/core/trade/CleanupMailboxMessages.java +++ b/core/src/main/java/haveno/core/trade/CleanupMailboxMessages.java @@ -63,7 +63,7 @@ public class CleanupMailboxMessages { } else { p2PService.addP2PServiceListener(new BootstrapListener() { @Override - public void onUpdatedDataReceived() { + public void onDataReceived() { cleanupMailboxMessages(trades); } }); diff --git a/core/src/main/java/haveno/core/trade/CleanupMailboxMessagesService.java b/core/src/main/java/haveno/core/trade/CleanupMailboxMessagesService.java index a2b5cde8d7..3b4f244e3f 100644 --- a/core/src/main/java/haveno/core/trade/CleanupMailboxMessagesService.java +++ b/core/src/main/java/haveno/core/trade/CleanupMailboxMessagesService.java @@ -62,7 +62,7 @@ public class CleanupMailboxMessagesService { } else { p2PService.addP2PServiceListener(new BootstrapListener() { @Override - public void onUpdatedDataReceived() { + public void onDataReceived() { cleanupMailboxMessages(trades); } }); diff --git a/core/src/main/java/haveno/core/trade/TradeManager.java b/core/src/main/java/haveno/core/trade/TradeManager.java index 81dce3d353..7430ccaa67 100644 --- a/core/src/main/java/haveno/core/trade/TradeManager.java +++ b/core/src/main/java/haveno/core/trade/TradeManager.java @@ -310,7 +310,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi } else { p2PService.addP2PServiceListener(new BootstrapListener() { @Override - public void onUpdatedDataReceived() { + public void onDataReceived() { initPersistedTrades(); } }); diff --git a/desktop/src/main/java/haveno/desktop/main/MainViewModel.java b/desktop/src/main/java/haveno/desktop/main/MainViewModel.java index 811d2cf14c..bd37e66b14 100644 --- a/desktop/src/main/java/haveno/desktop/main/MainViewModel.java +++ b/desktop/src/main/java/haveno/desktop/main/MainViewModel.java @@ -449,7 +449,7 @@ public class MainViewModel implements ViewModel, HavenoSetup.HavenoSetupListener } else { p2PService.addP2PServiceListener(new BootstrapListener() { @Override - public void onUpdatedDataReceived() { + public void onDataReceived() { setupInvalidOpenOffersHandler(); } }); @@ -527,7 +527,7 @@ public class MainViewModel implements ViewModel, HavenoSetup.HavenoSetupListener } else { p2PService.addP2PServiceListener(new BootstrapListener() { @Override - public void onUpdatedDataReceived() { + public void onDataReceived() { accountAgeWitnessService.publishMyAccountAgeWitness(aliPayAccount.getPaymentAccountPayload()); } }); diff --git a/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java b/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java index 32ac5895ab..5a83d591c1 100644 --- a/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java +++ b/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java @@ -208,7 +208,7 @@ public abstract class TradeStepView extends AnchorPane { } else { bootstrapListener = new BootstrapListener() { @Override - public void onUpdatedDataReceived() { + public void onDataReceived() { registerSubscriptions(); } }; diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index b525385197..4d4aff803a 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1994,6 +1994,11 @@ + + + + + @@ -2007,6 +2012,11 @@ + + + + + @@ -2020,6 +2030,11 @@ + + + + + @@ -2033,6 +2048,11 @@ + + + + + @@ -2054,6 +2074,11 @@ + + + + + @@ -2450,6 +2475,11 @@ + + + + + @@ -2568,6 +2598,11 @@ + + + + + diff --git a/p2p/src/main/java/haveno/network/Socks5DnsDiscovery.java b/p2p/src/main/java/haveno/network/Socks5DnsDiscovery.java index ac6c514f05..9b8894bd25 100644 --- a/p2p/src/main/java/haveno/network/Socks5DnsDiscovery.java +++ b/p2p/src/main/java/haveno/network/Socks5DnsDiscovery.java @@ -18,6 +18,7 @@ package haveno.network; import com.runjva.sourceforge.jsocks.protocol.Socks5Proxy; +import haveno.common.util.SingleThreadExecutorUtils; import haveno.common.util.Utilities; import lombok.extern.slf4j.Slf4j; import org.bitcoinj.core.NetworkParameters; @@ -32,7 +33,6 @@ import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** @@ -83,9 +83,9 @@ public class Socks5DnsDiscovery extends MultiplexingDiscovery { // Attempted workaround for reported bugs on Linux in which gethostbyname does not appear to be properly // thread safe and can cause segfaults on some libc versions. if (Utilities.isLinux()) - return Executors.newSingleThreadExecutor(new ContextPropagatingThreadFactory("DNS seed lookups")); + return SingleThreadExecutorUtils.getSingleThreadExecutor(new ContextPropagatingThreadFactory("DNS seed lookups")); else - return Executors.newFixedThreadPool(seeds.size(), new DaemonThreadFactory("DNS seed lookups")); + return Utilities.getFixedThreadPoolExecutor(seeds.size(), new DaemonThreadFactory("DNS seed lookups")); } /** diff --git a/p2p/src/main/java/haveno/network/p2p/BootstrapListener.java b/p2p/src/main/java/haveno/network/p2p/BootstrapListener.java index e7a571739b..932ced6136 100644 --- a/p2p/src/main/java/haveno/network/p2p/BootstrapListener.java +++ b/p2p/src/main/java/haveno/network/p2p/BootstrapListener.java @@ -40,11 +40,11 @@ public abstract class BootstrapListener implements P2PServiceListener { } @Override - public void onDataReceived() { + public void onUpdatedDataReceived() { } @Override - public abstract void onUpdatedDataReceived(); + public abstract void onDataReceived(); @Override public void onRequestCustomBridges() { diff --git a/p2p/src/main/java/haveno/network/p2p/P2PService.java b/p2p/src/main/java/haveno/network/p2p/P2PService.java index be7b61df86..8bdae835b8 100644 --- a/p2p/src/main/java/haveno/network/p2p/P2PService.java +++ b/p2p/src/main/java/haveno/network/p2p/P2PService.java @@ -189,6 +189,7 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis } private void doShutDown() { + log.info("P2PService doShutDown started"); if (p2PDataStorage != null) { p2PDataStorage.shutDown(); @@ -298,7 +299,7 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis @Override public void onUpdatedDataReceived() { - applyIsBootstrapped(P2PServiceListener::onUpdatedDataReceived); + p2pServiceListeners.forEach(P2PServiceListener::onUpdatedDataReceived); } @Override @@ -313,7 +314,8 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis @Override public void onDataReceived() { - p2pServiceListeners.forEach(P2PServiceListener::onDataReceived); + applyIsBootstrapped(P2PServiceListener::onDataReceived); + } private void applyIsBootstrapped(Consumer listenerHandler) { diff --git a/p2p/src/main/java/haveno/network/p2p/network/CloseConnectionReason.java b/p2p/src/main/java/haveno/network/p2p/network/CloseConnectionReason.java index 55a2bef7ef..4e7afa967d 100644 --- a/p2p/src/main/java/haveno/network/p2p/network/CloseConnectionReason.java +++ b/p2p/src/main/java/haveno/network/p2p/network/CloseConnectionReason.java @@ -44,7 +44,7 @@ public enum CloseConnectionReason { // illegal requests RULE_VIOLATION(true, false), - PEER_BANNED(true, false), + PEER_BANNED(false, false), INVALID_CLASS_RECEIVED(false, false), MANDATORY_CAPABILITIES_NOT_SUPPORTED(false, false); diff --git a/p2p/src/main/java/haveno/network/p2p/network/ConnectionState.java b/p2p/src/main/java/haveno/network/p2p/network/ConnectionState.java index 0dd48893ac..1e3add859c 100644 --- a/p2p/src/main/java/haveno/network/p2p/network/ConnectionState.java +++ b/p2p/src/main/java/haveno/network/p2p/network/ConnectionState.java @@ -47,6 +47,16 @@ public class ConnectionState implements MessageListener { @Setter private static int expectedRequests = 6; + // We have 2 GetDataResponses and 3 GetHashResponses. If node is a lite node it also has a GetBlocksResponse if + // blocks are missing. + private static final int MIN_EXPECTED_RESPONSES = 5; + private static int expectedInitialDataResponses = MIN_EXPECTED_RESPONSES; + + // If app runs in LiteNode mode there is one more expected request for the getBlocks request, so we increment standard value. + public static void incrementExpectedInitialDataResponses() { + expectedInitialDataResponses += 1; + } + private final Connection connection; @Getter @@ -121,7 +131,7 @@ public class ConnectionState implements MessageListener { } private void maybeResetInitialDataExchangeType() { - if (numInitialDataResponses >= expectedRequests) { + if (numInitialDataResponses >= expectedInitialDataResponses) { // We have received the expected messages from initial data requests. We delay a bit the reset // to give time for processing the response and more tolerance to edge cases where we expect more responses. // Reset to PEER does not mean disconnection as well, but just that this connection has lower priority and @@ -165,7 +175,7 @@ public class ConnectionState implements MessageListener { ",\n numInitialDataResponses=" + numInitialDataResponses + ",\n lastInitialDataMsgTimeStamp=" + lastInitialDataMsgTimeStamp + ",\n isSeedNode=" + isSeedNode + - ",\n expectedRequests=" + expectedRequests + + ",\n expectedInitialDataResponses=" + expectedInitialDataResponses + "\n}"; } } diff --git a/p2p/src/main/java/haveno/network/p2p/network/NetworkNode.java b/p2p/src/main/java/haveno/network/p2p/network/NetworkNode.java index d910fc2c28..d74ef1fd2e 100644 --- a/p2p/src/main/java/haveno/network/p2p/network/NetworkNode.java +++ b/p2p/src/main/java/haveno/network/p2p/network/NetworkNode.java @@ -361,6 +361,7 @@ public abstract class NetworkNode implements MessageListener { } public void shutDown(Runnable shutDownCompleteHandler) { + log.info("NetworkNode shutdown started"); if (!shutDownInProgress) { shutDownInProgress = true; if (server != null) { diff --git a/p2p/src/main/java/haveno/network/p2p/network/RunningTor.java b/p2p/src/main/java/haveno/network/p2p/network/RunningTor.java index eb2011d16a..801ebcc9e4 100644 --- a/p2p/src/main/java/haveno/network/p2p/network/RunningTor.java +++ b/p2p/src/main/java/haveno/network/p2p/network/RunningTor.java @@ -18,12 +18,16 @@ package haveno.network.p2p.network; import java.io.File; + import java.util.Date; import lombok.extern.slf4j.Slf4j; import org.berndpruenster.netlayer.tor.ExternalTor; import org.berndpruenster.netlayer.tor.Tor; import org.berndpruenster.netlayer.tor.TorCtlException; +import java.net.ConnectException; +import java.net.UnknownHostException; + /** * This class creates a brand new instance of the Tor onion router. * @@ -61,24 +65,47 @@ public class RunningTor extends TorMode { @Override public Tor getTor() throws TorCtlException { long ts1 = new Date().getTime(); + boolean retry = true; + long twoMinutesInMilli = 1000 * 60 * 2; - log.info("Connecting to running tor"); + while (retry && ((new Date().getTime() - ts1) <= twoMinutesInMilli)) { + retry = false; + try { + log.info("Connecting to running tor"); - Tor result; - if (!password.isEmpty()) - result = new ExternalTor(controlHost, controlPort, password); - else if (cookieFile != null && cookieFile.exists()) - result = new ExternalTor(controlHost, controlPort, cookieFile, useSafeCookieAuthentication); - else - result = new ExternalTor(controlHost, controlPort); + Tor result; + if (!password.isEmpty()) + result = new ExternalTor(controlHost, controlPort, password); + else if (cookieFile != null && cookieFile.exists()) + result = new ExternalTor(controlHost, controlPort, cookieFile, useSafeCookieAuthentication); + else + result = new ExternalTor(controlHost, controlPort); - log.info( - "\n################################################################\n" - + "Connecting to Tor successful after {} ms. Start publishing hidden service.\n" - + "################################################################", - (new Date().getTime() - ts1)); // takes usually a few seconds + boolean isTorBootstrapped = result.control.waitUntilBootstrapped(); + if (!isTorBootstrapped) { + log.error("Couldn't bootstrap Tor."); + } - return result; + log.info( + "\n################################################################\n" + + "Connecting to Tor successful after {} ms. Start publishing hidden service.\n" + + "################################################################", + (new Date().getTime() - ts1)); // takes usually a few seconds + + return result; + } catch (Exception e) { + // netlayer throws UnknownHostException when tor docker container is not ready yet. + // netlayer throws ConnectException before tor container bind to control port. + if (e instanceof UnknownHostException || e instanceof ConnectException) { + log.warn("Couldn't connect to Tor control port. Retrying...", e); + retry = true; + } + + log.error("Couldn't connect to Tor.", e); + } + } + + return null; } @Override diff --git a/p2p/src/main/java/haveno/network/p2p/network/Statistic.java b/p2p/src/main/java/haveno/network/p2p/network/Statistic.java index bb3b8d10a1..0c21c9f872 100644 --- a/p2p/src/main/java/haveno/network/p2p/network/Statistic.java +++ b/p2p/src/main/java/haveno/network/p2p/network/Statistic.java @@ -70,7 +70,7 @@ public class Statistic { totalReceivedBytesPerSec.set(((double) totalReceivedBytes.get()) / passed); }, 1); - // We log statistics every 5 minutes + // We log statistics every 60 minutes UserThread.runPeriodically(() -> { String ls = System.lineSeparator(); log.info("Accumulated network statistics:" + ls + @@ -79,14 +79,14 @@ public class Statistic { "Number of sent messages per sec: {};" + ls + "Bytes received: {}" + ls + "Number of received messages/Received messages: {} / {};" + ls + - "Number of received messages per sec: {};" + ls, + "Number of received messages per sec: {}" + ls, Utilities.readableFileSize(totalSentBytes.get()), numTotalSentMessages.get(), totalSentMessages, numTotalSentMessagesPerSec.get(), Utilities.readableFileSize(totalReceivedBytes.get()), numTotalReceivedMessages.get(), totalReceivedMessages, numTotalReceivedMessagesPerSec.get()); - }, TimeUnit.MINUTES.toSeconds(5)); + }, TimeUnit.MINUTES.toSeconds(60)); } public static LongProperty totalSentBytesProperty() { @@ -236,6 +236,30 @@ public class Statistic { return roundTripTime; } + public static long getTotalSentBytes() { + return totalSentBytes.get(); + } + + public static double getTotalSentBytesPerSec() { + return totalSentBytesPerSec.get(); + } + + public static long getTotalReceivedBytes() { + return totalReceivedBytes.get(); + } + + public static double getTotalReceivedBytesPerSec() { + return totalReceivedBytesPerSec.get(); + } + + public static double numTotalReceivedMessagesPerSec() { + return numTotalReceivedMessagesPerSec.get(); + } + + public static double getNumTotalSentMessagesPerSec() { + return numTotalSentMessagesPerSec.get(); + } + @Override public String toString() { return "Statistic{" + diff --git a/p2p/src/main/java/haveno/network/p2p/peers/BroadcastHandler.java b/p2p/src/main/java/haveno/network/p2p/peers/BroadcastHandler.java index 68531d2ba0..238a509b56 100644 --- a/p2p/src/main/java/haveno/network/p2p/peers/BroadcastHandler.java +++ b/p2p/src/main/java/haveno/network/p2p/peers/BroadcastHandler.java @@ -74,6 +74,7 @@ public class BroadcastHandler implements PeerManager.Listener { private final NetworkNode networkNode; private final PeerManager peerManager; + @Nullable private final ResultHandler resultHandler; private final String uid; @@ -276,6 +277,9 @@ public class BroadcastHandler implements PeerManager.Listener { @Override public void onFailure(@NotNull Throwable throwable) { + log.warn("Broadcast to " + connection.getPeersNodeAddressOptional() + " failed. ", throwable); + numOfFailedBroadcasts.incrementAndGet(); + if (stopped.get()) { return; } diff --git a/p2p/src/main/java/haveno/network/p2p/peers/Broadcaster.java b/p2p/src/main/java/haveno/network/p2p/peers/Broadcaster.java index 2aa255b81a..647182feeb 100644 --- a/p2p/src/main/java/haveno/network/p2p/peers/Broadcaster.java +++ b/p2p/src/main/java/haveno/network/p2p/peers/Broadcaster.java @@ -34,6 +34,7 @@ import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; + import lombok.Value; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.Nullable; @@ -51,6 +52,7 @@ public class Broadcaster implements BroadcastHandler.ResultHandler { private Runnable shutDownResultHandler; private final ListeningExecutorService executor; + /////////////////////////////////////////////////////////////////////////////////////////// // Constructor /////////////////////////////////////////////////////////////////////////////////////////// @@ -90,6 +92,7 @@ public class Broadcaster implements BroadcastHandler.ResultHandler { } private void doShutDown() { + log.info("Broadcaster doShutDown started"); broadcastHandlers.forEach(BroadcastHandler::cancel); if (timer != null) { timer.stop(); diff --git a/p2p/src/main/java/haveno/network/p2p/peers/PeerManager.java b/p2p/src/main/java/haveno/network/p2p/peers/PeerManager.java index 2e361b75a4..b5bf10df7b 100644 --- a/p2p/src/main/java/haveno/network/p2p/peers/PeerManager.java +++ b/p2p/src/main/java/haveno/network/p2p/peers/PeerManager.java @@ -77,6 +77,7 @@ public final class PeerManager implements ConnectionListener, PersistedDataHost private static final boolean PRINT_REPORTED_PEERS_DETAILS = true; private Timer printStatisticsTimer; private boolean shutDownRequested; + private int numOnConnections; /////////////////////////////////////////////////////////////////////////////////////////// @@ -167,7 +168,7 @@ public final class PeerManager implements ConnectionListener, PersistedDataHost }; clockWatcher.addListener(clockWatcherListener); - printStatisticsTimer = UserThread.runPeriodically(this::printStatistics, TimeUnit.MINUTES.toSeconds(5)); + printStatisticsTimer = UserThread.runPeriodically(this::printStatistics, TimeUnit.MINUTES.toSeconds(60)); } public void shutDown() { @@ -209,6 +210,8 @@ public final class PeerManager implements ConnectionListener, PersistedDataHost doHouseKeeping(); + numOnConnections++; + if (lostAllConnections) { lostAllConnections = false; stopped = false; @@ -224,14 +227,15 @@ public final class PeerManager implements ConnectionListener, PersistedDataHost @Override public void onDisconnect(CloseConnectionReason closeConnectionReason, Connection connection) { - log.info("onDisconnect called: nodeAddress={}, closeConnectionReason={}", + log.debug("onDisconnect called: nodeAddress={}, closeConnectionReason={}", connection.getPeersNodeAddressOptional(), closeConnectionReason); handleConnectionFault(connection); boolean previousLostAllConnections = lostAllConnections; lostAllConnections = networkNode.getAllConnections().isEmpty(); - if (lostAllConnections) { + // At start-up we ignore if we would lose a connection and would fall back to no connections + if (lostAllConnections && numOnConnections > 2) { stopped = true; if (!shutDownRequested) { @@ -553,7 +557,7 @@ public final class PeerManager implements ConnectionListener, PersistedDataHost if (!candidates.isEmpty()) { Connection connection = candidates.remove(0); - log.info("checkMaxConnections: Num candidates for shut down={}. We close oldest connection to peer {}", + log.info("checkMaxConnections: Num candidates (inbound/peer) for shut down={}. We close oldest connection to peer {}", candidates.size(), connection.getPeersNodeAddressOptional()); if (!connection.isStopped()) { connection.shutDown(CloseConnectionReason.TOO_MANY_CONNECTIONS_OPEN, diff --git a/p2p/src/main/java/haveno/network/p2p/peers/getdata/GetDataRequestHandler.java b/p2p/src/main/java/haveno/network/p2p/peers/getdata/GetDataRequestHandler.java index 350539a39f..9023815d80 100644 --- a/p2p/src/main/java/haveno/network/p2p/peers/getdata/GetDataRequestHandler.java +++ b/p2p/src/main/java/haveno/network/p2p/peers/getdata/GetDataRequestHandler.java @@ -37,16 +37,16 @@ import java.util.concurrent.atomic.AtomicBoolean; @Slf4j public class GetDataRequestHandler { - private static final long TIMEOUT = 180; + private static final long TIMEOUT = 240; - private static final int MAX_ENTRIES = 10000; + private static final int MAX_ENTRIES = 5000; /////////////////////////////////////////////////////////////////////////////////////////// // Listener /////////////////////////////////////////////////////////////////////////////////////////// public interface Listener { - void onComplete(); + void onComplete(int serializedSize); void onFault(String errorMessage, Connection connection); } @@ -94,15 +94,11 @@ public class GetDataRequestHandler { connection.getCapabilities()); if (wasPersistableNetworkPayloadsTruncated.get()) { - log.warn("The getData request from peer with {} caused too much PersistableNetworkPayload " + - "entries to get delivered. We limited the entries for the response to {} entries", - connectionInfo, MAX_ENTRIES); + log.info("The getDataResponse for peer {} got truncated.", connectionInfo); } if (wasProtectedStorageEntriesTruncated.get()) { - log.warn("The getData request from peer with {} caused too much ProtectedStorageEntry " + - "entries to get delivered. We limited the entries for the response to {} entries", - connectionInfo, MAX_ENTRIES); + log.info("The getDataResponse for peer {} got truncated.", connectionInfo); } log.info("The getDataResponse to peer with {} contains {} ProtectedStorageEntries and {} PersistableNetworkPayloads", @@ -126,8 +122,8 @@ public class GetDataRequestHandler { if (!stopped) { log.trace("Send DataResponse to {} succeeded. getDataResponse={}", connection.getPeersNodeAddressOptional(), getDataResponse); + listener.onComplete(getDataResponse.toProtoNetworkEnvelope().getSerializedSize()); cleanup(); - listener.onComplete(); } else { log.trace("We have stopped already. We ignore that networkNode.sendMessage.onSuccess call."); } @@ -136,7 +132,7 @@ public class GetDataRequestHandler { @Override public void onFailure(@NotNull Throwable throwable) { if (!stopped) { - String errorMessage = "Sending getDataRequest to " + connection + + String errorMessage = "Sending getDataResponse to " + connection + " failed. That is expected if the peer is offline. getDataResponse=" + getDataResponse + "." + "Exception: " + throwable.getMessage(); handleFault(errorMessage, CloseConnectionReason.SEND_MSG_FAILURE, connection); diff --git a/p2p/src/main/java/haveno/network/p2p/peers/getdata/RequestDataHandler.java b/p2p/src/main/java/haveno/network/p2p/peers/getdata/RequestDataHandler.java index bb9e240e14..85a1cc89ca 100644 --- a/p2p/src/main/java/haveno/network/p2p/peers/getdata/RequestDataHandler.java +++ b/p2p/src/main/java/haveno/network/p2p/peers/getdata/RequestDataHandler.java @@ -50,7 +50,7 @@ import java.util.concurrent.atomic.AtomicInteger; @Slf4j class RequestDataHandler implements MessageListener { - private static final long TIMEOUT = 180; + private static final long TIMEOUT = 240; private NodeAddress peersNodeAddress; private String getDataRequestType; @@ -69,7 +69,7 @@ class RequestDataHandler implements MessageListener { /////////////////////////////////////////////////////////////////////////////////////////// public interface Listener { - void onComplete(); + void onComplete(boolean wasTruncated); @SuppressWarnings("UnusedParameters") void onFault(String errorMessage, @SuppressWarnings("SameParameterValue") @Nullable Connection connection); @@ -138,7 +138,7 @@ class RequestDataHandler implements MessageListener { } getDataRequestType = getDataRequest.getClass().getSimpleName(); - log.info("We send a {} to peer {}. ", getDataRequestType, nodeAddress); + log.info("\n\n>> We send a {} to peer {}\n", getDataRequestType, nodeAddress); networkNode.addMessageListener(this); SettableFuture future = networkNode.sendMessage(nodeAddress, getDataRequest); //noinspection UnstableApiUsage @@ -197,8 +197,7 @@ class RequestDataHandler implements MessageListener { connection.getPeersNodeAddressOptional().get()); cleanup(); - listener.onComplete(); - // firstRequest = false; + listener.onComplete(getDataResponse.isWasTruncated()); } else { log.warn("Nonce not matching. That can happen rarely if we get a response after a canceled " + "handshake (timeout causes connection close but peer might have sent a msg before " + @@ -239,7 +238,7 @@ class RequestDataHandler implements MessageListener { StringBuilder sb = new StringBuilder(); String sep = System.lineSeparator(); sb.append(sep).append("#################################################################").append(sep); - sb.append("Connected to node: ").append(peersNodeAddress.getFullAddress()).append(sep); + sb.append("Data provided by node: ").append(peersNodeAddress.getFullAddress()).append(sep); int items = dataSet.size() + persistableNetworkPayloadSet.size(); sb.append("Received ").append(items).append(" instances from a ") .append(getDataRequestType).append(sep); @@ -249,7 +248,7 @@ class RequestDataHandler implements MessageListener { .append(" / ") .append(Utilities.readableFileSize(value.second.get())) .append(sep)); - sb.append("#################################################################"); + sb.append("#################################################################\n"); log.info(sb.toString()); } diff --git a/p2p/src/main/java/haveno/network/p2p/peers/getdata/RequestDataManager.java b/p2p/src/main/java/haveno/network/p2p/peers/getdata/RequestDataManager.java index 98cffc7c1d..39277f6d58 100644 --- a/p2p/src/main/java/haveno/network/p2p/peers/getdata/RequestDataManager.java +++ b/p2p/src/main/java/haveno/network/p2p/peers/getdata/RequestDataManager.java @@ -42,6 +42,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; @@ -55,8 +56,10 @@ public class RequestDataManager implements MessageListener, ConnectionListener, private static int NUM_SEEDS_FOR_PRELIMINARY_REQUEST = 2; // how many seeds additional to the first responding PreliminaryGetDataRequest seed we request the GetUpdatedDataRequest from private static int NUM_ADDITIONAL_SEEDS_FOR_UPDATE_REQUEST = 1; + private static int MAX_REPEATED_REQUESTS = 30; private boolean isPreliminaryDataRequest = true; + /////////////////////////////////////////////////////////////////////////////////////////// // Listener /////////////////////////////////////////////////////////////////////////////////////////// @@ -75,6 +78,12 @@ public class RequestDataManager implements MessageListener, ConnectionListener, } } + public interface ResponseListener { + void onSuccess(int serializedSize); + + void onFault(); + } + /////////////////////////////////////////////////////////////////////////////////////////// // Class fields @@ -84,6 +93,7 @@ public class RequestDataManager implements MessageListener, ConnectionListener, private final P2PDataStorage dataStorage; private final PeerManager peerManager; private final List seedNodeAddresses; + private final List responseListeners = new CopyOnWriteArrayList<>(); // As we use Guice injection we cannot set the listener in our constructor but the P2PService calls the setListener // in it's constructor so we can guarantee it is not null. @@ -94,8 +104,9 @@ public class RequestDataManager implements MessageListener, ConnectionListener, private Optional nodeAddressOfPreliminaryDataRequest = Optional.empty(); private Timer retryTimer; private boolean dataUpdateRequested; + private boolean allDataReceived; private boolean stopped; - + private int numRepeatedRequests = 0; /////////////////////////////////////////////////////////////////////////////////////////// // Constructor @@ -124,6 +135,7 @@ public class RequestDataManager implements MessageListener, ConnectionListener, if (seedNodeRepository.isSeedNode(myAddress)) { NUM_SEEDS_FOR_PRELIMINARY_REQUEST = 3; NUM_ADDITIONAL_SEEDS_FOR_UPDATE_REQUEST = 2; + MAX_REPEATED_REQUESTS = 100; } } }); @@ -199,6 +211,10 @@ public class RequestDataManager implements MessageListener, ConnectionListener, return nodeAddressOfPreliminaryDataRequest; } + public void addResponseListener(ResponseListener responseListener) { + responseListeners.add(responseListener); + } + /////////////////////////////////////////////////////////////////////////////////////////// // ConnectionListener implementation @@ -266,9 +282,11 @@ public class RequestDataManager implements MessageListener, ConnectionListener, GetDataRequestHandler getDataRequestHandler = new GetDataRequestHandler(networkNode, dataStorage, new GetDataRequestHandler.Listener() { @Override - public void onComplete() { + public void onComplete(int serializedSize) { getDataRequestHandlers.remove(uid); log.trace("requestDataHandshake completed.\n\tConnection={}", connection); + + responseListeners.forEach(listener -> listener.onSuccess(serializedSize)); } @Override @@ -278,6 +296,8 @@ public class RequestDataManager implements MessageListener, ConnectionListener, log.trace("GetDataRequestHandler failed.\n\tConnection={}\n\t" + "ErrorMessage={}", connection, errorMessage); peerManager.handleConnectionFault(connection); + + responseListeners.forEach(ResponseListener::onFault); } else { log.warn("We have stopped already. We ignore that getDataRequestHandler.handle.onFault call."); } @@ -313,7 +333,7 @@ public class RequestDataManager implements MessageListener, ConnectionListener, RequestDataHandler requestDataHandler = new RequestDataHandler(networkNode, dataStorage, peerManager, new RequestDataHandler.Listener() { @Override - public void onComplete() { + public void onComplete(boolean wasTruncated) { log.trace("RequestDataHandshake of outbound connection complete. nodeAddress={}", nodeAddress); stopRetryTimer(); @@ -336,7 +356,27 @@ public class RequestDataManager implements MessageListener, ConnectionListener, checkNotNull(listener).onUpdatedDataReceived(); } - checkNotNull(listener).onDataReceived(); + if (wasTruncated) { + if (numRepeatedRequests < MAX_REPEATED_REQUESTS) { + // If we had allDataReceived already set to true but get a response with truncated flag, + // we still repeat the request to that node for higher redundancy. Otherwise, one seed node + // providing incomplete data would stop others to fill the gaps. + log.info("DataResponse did not contain all data, so we repeat request until we got all data"); + UserThread.runAfter(() -> requestData(nodeAddress, remainingNodeAddresses), 2); + } else if (!allDataReceived) { + allDataReceived = true; + log.warn("\n#################################################################\n" + + "Loading initial data from {} did not complete after 20 repeated requests. \n" + + "#################################################################\n", nodeAddress); + checkNotNull(listener).onDataReceived(); + } + } else if (!allDataReceived) { + allDataReceived = true; + log.info("\n\n#################################################################\n" + + "Loading initial data from {} completed\n" + + "#################################################################\n", nodeAddress); + checkNotNull(listener).onDataReceived(); + } } @Override @@ -377,6 +417,7 @@ public class RequestDataManager implements MessageListener, ConnectionListener, } }); handlerMap.put(nodeAddress, requestDataHandler); + numRepeatedRequests++; requestDataHandler.requestData(nodeAddress, isPreliminaryDataRequest); } else { log.warn("We have started already a requestDataHandshake to peer. nodeAddress=" + nodeAddress + "\n" + diff --git a/p2p/src/main/java/haveno/network/p2p/peers/peerexchange/PeerExchangeManager.java b/p2p/src/main/java/haveno/network/p2p/peers/peerexchange/PeerExchangeManager.java index ccc52e6930..a6a637fbff 100644 --- a/p2p/src/main/java/haveno/network/p2p/peers/peerexchange/PeerExchangeManager.java +++ b/p2p/src/main/java/haveno/network/p2p/peers/peerexchange/PeerExchangeManager.java @@ -130,7 +130,7 @@ public class PeerExchangeManager implements MessageListener, ConnectionListener, @Override public void onDisconnect(CloseConnectionReason closeConnectionReason, Connection connection) { - log.info("onDisconnect closeConnectionReason={}, nodeAddressOpt={}", closeConnectionReason, connection.getPeersNodeAddressOptional()); + log.debug("onDisconnect closeConnectionReason={}, nodeAddressOpt={}", closeConnectionReason, connection.getPeersNodeAddressOptional()); closeHandler(connection); if (retryTimer == null) { diff --git a/p2p/src/main/java/haveno/network/p2p/storage/payload/ProtectedStorageEntry.java b/p2p/src/main/java/haveno/network/p2p/storage/payload/ProtectedStorageEntry.java index a30c4e5f12..02c7775bb9 100644 --- a/p2p/src/main/java/haveno/network/p2p/storage/payload/ProtectedStorageEntry.java +++ b/p2p/src/main/java/haveno/network/p2p/storage/payload/ProtectedStorageEntry.java @@ -22,6 +22,7 @@ import com.google.protobuf.ByteString; import com.google.protobuf.Message; import haveno.common.crypto.CryptoException; import haveno.common.crypto.Sig; +import haveno.common.proto.network.GetDataResponsePriority; import haveno.common.proto.network.NetworkPayload; import haveno.common.proto.network.NetworkProtoResolver; import haveno.common.proto.persistable.PersistablePayload; @@ -141,6 +142,10 @@ public class ProtectedStorageEntry implements NetworkPayload, PersistablePayload (clock.millis() - creationTimeStamp) > ((ExpirablePayload) protectedStoragePayload).getTTL(); } + public GetDataResponsePriority getGetDataResponsePriority() { + return protectedStoragePayload.getGetDataResponsePriority(); + } + /* * Returns true if the Entry is valid for an add operation. For non-mailbox Entrys, the entry owner must * match the payload owner. diff --git a/p2p/src/main/java/haveno/network/p2p/storage/persistence/AppendOnlyDataStoreService.java b/p2p/src/main/java/haveno/network/p2p/storage/persistence/AppendOnlyDataStoreService.java index ee44123bdd..6431aa9502 100644 --- a/p2p/src/main/java/haveno/network/p2p/storage/persistence/AppendOnlyDataStoreService.java +++ b/p2p/src/main/java/haveno/network/p2p/storage/persistence/AppendOnlyDataStoreService.java @@ -27,8 +27,10 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.atomic.AtomicInteger; + import lombok.Getter; import lombok.extern.slf4j.Slf4j; + import org.jetbrains.annotations.NotNull; /** diff --git a/p2p/src/main/java/haveno/network/p2p/storage/persistence/HistoricalDataStoreService.java b/p2p/src/main/java/haveno/network/p2p/storage/persistence/HistoricalDataStoreService.java index 6e7cbe4bdc..c74790c50e 100644 --- a/p2p/src/main/java/haveno/network/p2p/storage/persistence/HistoricalDataStoreService.java +++ b/p2p/src/main/java/haveno/network/p2p/storage/persistence/HistoricalDataStoreService.java @@ -79,7 +79,7 @@ public abstract class HistoricalDataStoreService { - log.info("We have created the {} store for the live data and filled it with {} entries from the persisted data.", + log.debug("We have created the {} store for the live data and filled it with {} entries from the persisted data.", getFileName(), getMapOfLiveData().size()); // Now we add our historical data stores. @@ -181,7 +181,7 @@ public abstract class HistoricalDataStoreService { storesByVersion.put(version, persisted); allHistoricalPayloads.putAll(persisted.getMap()); - log.info("We have read from {} {} historical items.", fileName, persisted.getMap().size()); + log.debug("We have read from {} {} historical items.", fileName, persisted.getMap().size()); pruneStore(persisted, version); completeHandler.run(); }, @@ -195,11 +195,11 @@ public abstract class HistoricalDataStoreService postLive) { - log.info("We pruned data from our live data store which are already contained in the historical data store with version {}. " + + log.debug("We pruned data from our live data store which are already contained in the historical data store with version {}. " + "The live map had {} entries before pruning and has {} entries afterwards.", version, preLive, postLive); } else { - log.info("No pruning from historical data store with version {} was applied", version); + log.debug("No pruning from historical data store with version {} was applied", version); } requestPersistence(); } diff --git a/p2p/src/main/java/haveno/network/p2p/storage/persistence/StoreService.java b/p2p/src/main/java/haveno/network/p2p/storage/persistence/StoreService.java index d844cdbafb..6d9f3df16a 100644 --- a/p2p/src/main/java/haveno/network/p2p/storage/persistence/StoreService.java +++ b/p2p/src/main/java/haveno/network/p2p/storage/persistence/StoreService.java @@ -109,18 +109,18 @@ public abstract class StoreService { File destinationFile = new File(Paths.get(absolutePathOfStorageDir, fileName).toString()); if (!destinationFile.exists()) { try { - log.info("We copy resource to file: resourceFileName={}, destinationFile={}", resourceFileName, destinationFile); + log.debug("We copy resource to file: resourceFileName={}, destinationFile={}", resourceFileName, destinationFile); FileUtil.resourceToFile(resourceFileName, destinationFile); return true; } catch (ResourceNotFoundException e) { - log.info("Could not find resourceFile " + resourceFileName + ". That is expected if none is provided yet."); + log.debug("Could not find resourceFile " + resourceFileName + ". That is expected if none is provided yet."); } catch (Throwable e) { log.error("Could not copy resourceFile " + resourceFileName + " to " + destinationFile.getAbsolutePath() + ".\n" + e.getMessage()); e.printStackTrace(); } } else { - log.info("No resource file was copied. {} exists already.", fileName); + log.debug("No resource file was copied. {} exists already.", fileName); } return false; } diff --git a/p2p/src/test/java/haveno/network/p2p/storage/P2PDataStorageBuildGetDataResponseTest.java b/p2p/src/test/java/haveno/network/p2p/storage/P2PDataStorageBuildGetDataResponseTest.java index 7cb077b31f..1af5685506 100644 --- a/p2p/src/test/java/haveno/network/p2p/storage/P2PDataStorageBuildGetDataResponseTest.java +++ b/p2p/src/test/java/haveno/network/p2p/storage/P2PDataStorageBuildGetDataResponseTest.java @@ -33,10 +33,10 @@ import haveno.network.p2p.storage.payload.CapabilityRequiringPayload; import haveno.network.p2p.storage.payload.PersistableNetworkPayload; import haveno.network.p2p.storage.payload.ProtectedStorageEntry; import haveno.network.p2p.storage.payload.ProtectedStoragePayload; +import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import java.security.KeyPair; import java.security.NoSuchAlgorithmException; @@ -45,6 +45,10 @@ import java.util.HashSet; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -54,6 +58,8 @@ import static org.mockito.Mockito.when; import static org.mockito.Mockito.withSettings; public class P2PDataStorageBuildGetDataResponseTest { + @ExtendWith(MockitoExtension.class) + @MockitoSettings(strictness = Strictness.LENIENT) // there are unused stubs in TestState & elsewhere abstract static class P2PDataStorageBuildGetDataResponseTestBase { // GIVEN null & non-null supportedCapabilities private TestState testState; @@ -67,7 +73,6 @@ public class P2PDataStorageBuildGetDataResponseTest { @BeforeEach public void setUp() { - MockitoAnnotations.initMocks(this); this.testState = new TestState(); this.localNodeAddress = new NodeAddress("localhost", 8080); diff --git a/p2p/src/test/java/haveno/network/p2p/storage/P2PDataStoragePersistableNetworkPayloadTest.java b/p2p/src/test/java/haveno/network/p2p/storage/P2PDataStoragePersistableNetworkPayloadTest.java index ad1d6616a4..9322ef136f 100644 --- a/p2p/src/test/java/haveno/network/p2p/storage/P2PDataStoragePersistableNetworkPayloadTest.java +++ b/p2p/src/test/java/haveno/network/p2p/storage/P2PDataStoragePersistableNetworkPayloadTest.java @@ -30,7 +30,6 @@ import java.util.Optional; import java.util.stream.Stream; import static haveno.network.p2p.storage.TestState.SavedTestState; -import static haveno.network.p2p.storage.TestState.getTestNodeAddress; import static java.util.stream.Stream.of; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.mock; @@ -67,8 +66,9 @@ public class P2PDataStoragePersistableNetworkPayloadTest { @BeforeEach public void setup() { - persistableNetworkPayload = createInstance(); - testState = new TestState(); + this.persistableNetworkPayload = this.createInstance(); + + this.testState = new TestState(); } void assertAndDoAdd(PersistableNetworkPayload persistableNetworkPayload, @@ -82,14 +82,15 @@ public class P2PDataStoragePersistableNetworkPayloadTest { if (testCase == TestCase.PUBLIC_API) { assertEquals(expectedReturnValue, - testState.mockedStorage.addPersistableNetworkPayload(persistableNetworkPayload, getTestNodeAddress(), reBroadcast)); + this.testState.mockedStorage.addPersistableNetworkPayload(persistableNetworkPayload, TestState.getTestNodeAddress(), reBroadcast)); } else { // onMessage - Connection mockedConnection = mock(); - when(mockedConnection.getPeersNodeAddressOptional()).thenReturn(Optional.of(getTestNodeAddress())); + Connection mockedConnection = mock(Connection.class); + when(mockedConnection.getPeersNodeAddressOptional()).thenReturn(Optional.of(TestState.getTestNodeAddress())); testState.mockedStorage.onMessage(new AddPersistableNetworkPayloadMessage(persistableNetworkPayload), mockedConnection); } - testState.verifyPersistableAdd(beforeState, persistableNetworkPayload, expectedHashMapAndDataStoreUpdated, expectedListenersSignaled, expectedBroadcast); + + this.testState.verifyPersistableAdd(beforeState, persistableNetworkPayload, expectedHashMapAndDataStoreUpdated, expectedListenersSignaled, expectedBroadcast); } static Stream data() { @@ -103,16 +104,17 @@ public class P2PDataStoragePersistableNetworkPayloadTest { @MethodSource("data") @ParameterizedTest(name = "{index}: Test with TestCase={0} allowBroadcast={1} reBroadcast={2} checkDate={3}") public void addPersistableNetworkPayload(TestCase testCase, boolean reBroadcast) { - assertAndDoAdd(persistableNetworkPayload, testCase, reBroadcast, true, true, true, true); + // First add should succeed regardless of parameters + assertAndDoAdd(this.persistableNetworkPayload, testCase, reBroadcast, true, true, true, true); } @MethodSource("data") @ParameterizedTest(name = "{index}: Test with TestCase={0} allowBroadcast={1} reBroadcast={2} checkDate={3}") public void addPersistableNetworkPayloadDuplicate(TestCase testCase, boolean reBroadcast) { - assertAndDoAdd(persistableNetworkPayload, testCase, reBroadcast, true, true, true, true); + assertAndDoAdd(this.persistableNetworkPayload, testCase, reBroadcast, true, true, true, true); // We return true and broadcast if reBroadcast is set - // assertAndDoAdd(persistableNetworkPayload, testCase, reBroadcast, reBroadcast, false, false, reBroadcast); + // assertAndDoAdd(this.persistableNetworkPayload, testCase, reBroadcast, reBroadcast, false, false, reBroadcast); } } diff --git a/p2p/src/test/java/haveno/network/p2p/storage/P2PDataStorageProcessGetDataResponse.java b/p2p/src/test/java/haveno/network/p2p/storage/P2PDataStorageProcessGetDataResponse.java index f379eca341..1ec2c53d04 100644 --- a/p2p/src/test/java/haveno/network/p2p/storage/P2PDataStorageProcessGetDataResponse.java +++ b/p2p/src/test/java/haveno/network/p2p/storage/P2PDataStorageProcessGetDataResponse.java @@ -28,7 +28,6 @@ import haveno.network.p2p.storage.payload.ProtectedStorageEntry; import haveno.network.p2p.storage.payload.ProtectedStoragePayload; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.MockitoAnnotations; import java.security.KeyPair; import java.security.NoSuchAlgorithmException; @@ -47,7 +46,6 @@ public class P2PDataStorageProcessGetDataResponse { @BeforeEach public void setUp() { - MockitoAnnotations.initMocks(this); this.testState = new TestState(); this.peerNodeAddress = new NodeAddress("peer", 8080); @@ -108,7 +106,7 @@ public class P2PDataStorageProcessGetDataResponse { // XXXBUGXXX: We signal listeners w/ non ProcessOncePersistableNetworkPayloads @Test public void processGetDataResponse_newPNPUpdatesState() { - PersistableNetworkPayload persistableNetworkPayload = new PersistableNetworkPayloadStub(new byte[] { 1 }); + PersistableNetworkPayload persistableNetworkPayload = new PersistableNetworkPayloadStub(new byte[]{1}); GetDataResponse getDataResponse = buildGetDataResponse(persistableNetworkPayload); @@ -134,7 +132,7 @@ public class P2PDataStorageProcessGetDataResponse { // TESTCASE: GetDataResponse w/ existing PNP changes no state @Test public void processGetDataResponse_duplicatePNPDoesNothing() { - PersistableNetworkPayload persistableNetworkPayload = new PersistableNetworkPayloadStub(new byte[] { 1 }); + PersistableNetworkPayload persistableNetworkPayload = new PersistableNetworkPayloadStub(new byte[]{1}); this.testState.mockedStorage.addPersistableNetworkPayload(persistableNetworkPayload, this.peerNodeAddress, false); @@ -149,7 +147,7 @@ public class P2PDataStorageProcessGetDataResponse { // TESTCASE: GetDataResponse w/ missing PNP is added with no broadcast or listener signal (ProcessOncePersistableNetworkPayload) @Test public void processGetDataResponse_newPNPUpdatesState_LazyProcessed() { - PersistableNetworkPayload persistableNetworkPayload = new LazyPersistableNetworkPayloadStub(new byte[] { 1 }); + PersistableNetworkPayload persistableNetworkPayload = new LazyPersistableNetworkPayloadStub(new byte[]{1}); GetDataResponse getDataResponse = buildGetDataResponse(persistableNetworkPayload); @@ -162,7 +160,7 @@ public class P2PDataStorageProcessGetDataResponse { // TESTCASE: GetDataResponse w/ existing PNP changes no state (ProcessOncePersistableNetworkPayload) @Test public void processGetDataResponse_duplicatePNPDoesNothing_LazyProcessed() { - PersistableNetworkPayload persistableNetworkPayload = new LazyPersistableNetworkPayloadStub(new byte[] { 1 }); + PersistableNetworkPayload persistableNetworkPayload = new LazyPersistableNetworkPayloadStub(new byte[]{1}); this.testState.mockedStorage.addPersistableNetworkPayload(persistableNetworkPayload, this.peerNodeAddress, false); @@ -177,7 +175,7 @@ public class P2PDataStorageProcessGetDataResponse { // TESTCASE: Second call to processGetDataResponse adds PNP for non-ProcessOncePersistableNetworkPayloads @Test public void processGetDataResponse_secondProcessNewPNPUpdatesState() { - PersistableNetworkPayload addFromFirstProcess = new PersistableNetworkPayloadStub(new byte[] { 1 }); + PersistableNetworkPayload addFromFirstProcess = new PersistableNetworkPayloadStub(new byte[]{1}); GetDataResponse getDataResponse = buildGetDataResponse(addFromFirstProcess); TestState.SavedTestState beforeState = this.testState.saveTestState(addFromFirstProcess); @@ -185,7 +183,7 @@ public class P2PDataStorageProcessGetDataResponse { this.testState.verifyPersistableAdd( beforeState, addFromFirstProcess, true, true, false); - PersistableNetworkPayload addFromSecondProcess = new PersistableNetworkPayloadStub(new byte[] { 2 }); + PersistableNetworkPayload addFromSecondProcess = new PersistableNetworkPayloadStub(new byte[]{2}); getDataResponse = buildGetDataResponse(addFromSecondProcess); beforeState = this.testState.saveTestState(addFromSecondProcess); this.testState.mockedStorage.processGetDataResponse(getDataResponse, this.peerNodeAddress); @@ -196,7 +194,7 @@ public class P2PDataStorageProcessGetDataResponse { // TESTCASE: Second call to processGetDataResponse does not add any PNP (LazyProcessed) @Test public void processGetDataResponse_secondProcessNoPNPUpdates_LazyProcessed() { - PersistableNetworkPayload addFromFirstProcess = new LazyPersistableNetworkPayloadStub(new byte[] { 1 }); + PersistableNetworkPayload addFromFirstProcess = new LazyPersistableNetworkPayloadStub(new byte[]{1}); GetDataResponse getDataResponse = buildGetDataResponse(addFromFirstProcess); TestState.SavedTestState beforeState = this.testState.saveTestState(addFromFirstProcess); @@ -204,7 +202,7 @@ public class P2PDataStorageProcessGetDataResponse { this.testState.verifyPersistableAdd( beforeState, addFromFirstProcess, true, false, false); - PersistableNetworkPayload addFromSecondProcess = new LazyPersistableNetworkPayloadStub(new byte[] { 2 }); + PersistableNetworkPayload addFromSecondProcess = new LazyPersistableNetworkPayloadStub(new byte[]{2}); getDataResponse = buildGetDataResponse(addFromSecondProcess); beforeState = this.testState.saveTestState(addFromSecondProcess); this.testState.mockedStorage.processGetDataResponse(getDataResponse, this.peerNodeAddress); diff --git a/p2p/src/test/java/haveno/network/p2p/storage/P2PDataStorageRequestDataTest.java b/p2p/src/test/java/haveno/network/p2p/storage/P2PDataStorageRequestDataTest.java index d3194a591a..e6496d3343 100644 --- a/p2p/src/test/java/haveno/network/p2p/storage/P2PDataStorageRequestDataTest.java +++ b/p2p/src/test/java/haveno/network/p2p/storage/P2PDataStorageRequestDataTest.java @@ -30,7 +30,6 @@ import haveno.network.p2p.storage.payload.ProtectedStorageEntry; import haveno.network.p2p.storage.payload.ProtectedStoragePayload; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.MockitoAnnotations; import java.security.KeyPair; import java.security.NoSuchAlgorithmException; @@ -49,7 +48,6 @@ public class P2PDataStorageRequestDataTest { @BeforeEach public void setUp() { - MockitoAnnotations.initMocks(this); this.testState = new TestState(); this.localNodeAddress = new NodeAddress("localhost", 8080); @@ -115,8 +113,8 @@ public class P2PDataStorageRequestDataTest { // correct GetDataRequestMessage with both sets of keys. @Test public void buildPreliminaryGetDataRequest_FilledP2PDataStore() throws NoSuchAlgorithmException { - PersistableNetworkPayload toAdd1 = new PersistableNetworkPayloadStub(new byte[] { 1 }); - PersistableNetworkPayload toAdd2 = new PersistableNetworkPayloadStub(new byte[] { 2 }); + PersistableNetworkPayload toAdd1 = new PersistableNetworkPayloadStub(new byte[]{1}); + PersistableNetworkPayload toAdd2 = new PersistableNetworkPayloadStub(new byte[]{2}); ProtectedStorageEntry toAdd3 = getProtectedStorageEntryForAdd(); ProtectedStorageEntry toAdd4 = getProtectedStorageEntryForAdd(); @@ -143,8 +141,8 @@ public class P2PDataStorageRequestDataTest { // correct GetDataRequestMessage with both sets of keys. @Test public void requestData_FilledP2PDataStore_GetUpdatedDataRequest() throws NoSuchAlgorithmException { - PersistableNetworkPayload toAdd1 = new PersistableNetworkPayloadStub(new byte[] { 1 }); - PersistableNetworkPayload toAdd2 = new PersistableNetworkPayloadStub(new byte[] { 2 }); + PersistableNetworkPayload toAdd1 = new PersistableNetworkPayloadStub(new byte[]{1}); + PersistableNetworkPayload toAdd2 = new PersistableNetworkPayloadStub(new byte[]{2}); ProtectedStorageEntry toAdd3 = getProtectedStorageEntryForAdd(); ProtectedStorageEntry toAdd4 = getProtectedStorageEntryForAdd(); diff --git a/statsnode/src/main/java/haveno/statistics/Statistics.java b/statsnode/src/main/java/haveno/statistics/Statistics.java index 4ba2469acc..d2d3b65c33 100644 --- a/statsnode/src/main/java/haveno/statistics/Statistics.java +++ b/statsnode/src/main/java/haveno/statistics/Statistics.java @@ -52,7 +52,7 @@ public class Statistics { priceFeedService.setCurrencyCode("USD"); p2pService.addP2PServiceListener(new BootstrapListener() { @Override - public void onUpdatedDataReceived() { + public void onDataReceived() { // we need to have tor ready log.info("onBootstrapComplete: we start requestPriceFeed"); priceFeedService.startRequestingPrices(price -> log.info("requestPriceFeed. price=" + price),