diff --git a/common/src/main/java/io/bisq/common/crypto/PubKeyRing.java b/common/src/main/java/io/bisq/common/crypto/PubKeyRing.java index 9f2e3bef75..b96e542462 100644 --- a/common/src/main/java/io/bisq/common/crypto/PubKeyRing.java +++ b/common/src/main/java/io/bisq/common/crypto/PubKeyRing.java @@ -17,6 +17,7 @@ package io.bisq.common.crypto; +import com.google.common.annotations.VisibleForTesting; import com.google.protobuf.ByteString; import io.bisq.common.proto.network.NetworkPayload; import io.bisq.common.util.Utilities; @@ -43,10 +44,10 @@ public final class PubKeyRing implements NetworkPayload, RestrictedByContractJso @Nullable private final String pgpPubKeyAsPem; - private PublicKey signaturePubKey; - private PublicKey encryptionPubKey; + private transient PublicKey signaturePubKey; + private transient PublicKey encryptionPubKey; @Nullable - private PGPPublicKey pgpPubKey; + private transient PGPPublicKey pgpPubKey; public PubKeyRing(PublicKey signaturePubKey, PublicKey encryptionPubKey, @Nullable PGPPublicKey pgpPubKey) { this.signaturePubKeyBytes = Sig.getPublicKeyBytes(signaturePubKey); @@ -63,6 +64,7 @@ public final class PubKeyRing implements NetworkPayload, RestrictedByContractJso // PROTO BUFFER /////////////////////////////////////////////////////////////////////////////////////////// + @VisibleForTesting public PubKeyRing(byte[] signaturePubKeyBytes, byte[] encryptionPubKeyBytes, @Nullable String pgpPubKeyAsPem) { this.signaturePubKeyBytes = signaturePubKeyBytes; this.encryptionPubKeyBytes = encryptionPubKeyBytes; diff --git a/core/src/main/java/io/bisq/core/btc/BitcoinNodes.java b/core/src/main/java/io/bisq/core/btc/BitcoinNodes.java index 7558c54a29..076dea9ef4 100644 --- a/core/src/main/java/io/bisq/core/btc/BitcoinNodes.java +++ b/core/src/main/java/io/bisq/core/btc/BitcoinNodes.java @@ -28,7 +28,6 @@ import java.util.Arrays; import java.util.List; import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; // Managed here: https://github.com/bisq-network/roles/issues/39 @Slf4j @@ -44,23 +43,33 @@ public class BitcoinNodes { public List getProvidedBtcNodes() { return useProvidedBtcNodes() ? Arrays.asList( - BtcNode.fromHostNameAddressAndPort("kirsche.emzy.de", "78.47.61.83", BtcNode.DEFAULT_PORT, "https://github.com/emzy"), - BtcNode.fromAddressAndPort("62.75.210.81", BtcNode.DEFAULT_PORT, "https://github.com/emzy"), // used also for r3dsojfhwcm7x7p6, not used: c6ac4jdfyeiakex2 - BtcNode.fromAddressAndPort("163.172.171.119", BtcNode.DEFAULT_PORT, "https://github.com/emzy"), // not used: sjyzmwwu6diiit3r + // ManfredKarrer + new BtcNode("btc1.0-2-1.net", "r3dsojfhwcm7x7p6.onion", "159.89.16.222", BtcNode.DEFAULT_PORT, "https://github.com/ManfredKarrer"), + new BtcNode("btc2.0-2-1.net", "vlf5i3grro3wux24.onion", "165.227.34.56", BtcNode.DEFAULT_PORT, "https://github.com/ManfredKarrer"), + new BtcNode("btc3.0-2-1.net", "i3a5xtzfm4xwtybd.onion", "165.227.44.202", BtcNode.DEFAULT_PORT, "https://github.com/ManfredKarrer"), - BtcNode.fromHostNameAddressAndPort("bitcoin.christophatteneder.com", "174.138.35.229", BtcNode.DEFAULT_PORT, "https://github.com/ripcurlx"), - BtcNode.fromHostNameAddressAndPort("btc.vante.me", "138.68.117.247", BtcNode.DEFAULT_PORT, "https://github.com/mrosseel"), + // emzy + new BtcNode("kirsche.emzy.de", null, "78.47.61.83", BtcNode.DEFAULT_PORT, "https://github.com/emzy"), + new BtcNode("node2.emzy.de", "c6ac4jdfyeiakex2.onion", "62.75.210.81", BtcNode.DEFAULT_PORT, "https://github.com/emzy"), + new BtcNode("node1.emzy.de", "sjyzmwwu6diiit3r.onion", "163.172.171.119", BtcNode.DEFAULT_PORT, "https://github.com/emzy"), + new BtcNode(null, "poyvpdt762gllauu.onion", null, BtcNode.DEFAULT_PORT, "https://github.com/emzy"), - BtcNode.fromHostNameAddressAndPort("bitcoin4-fullnode.csg.uzh.ch", "192.41.136.217", BtcNode.DEFAULT_PORT, "https://github.com/tbocek"), - BtcNode.fromHostNameAddressAndPort("bcwat.ch", "5.189.166.193", BtcNode.DEFAULT_PORT, "https://github.com/sgeisler"), - BtcNode.fromHostNameAddressAndPort("btc.jochen-hoenicke.de", "37.221.198.57", BtcNode.DEFAULT_PORT, "https://github.com/jhoenicke"), + // ripcurlx + new BtcNode("bitcoin.christophatteneder.com", "lgkvbvro67jomosw.onion", "174.138.35.229", BtcNode.DEFAULT_PORT, "https://github.com/ripcurlx"), - BtcNode.fromHostName("poyvpdt762gllauu.onion", BtcNode.DEFAULT_PORT, "https://github.com/emzy"), // onion only - BtcNode.fromHostName("r3dsojfhwcm7x7p6.onion", BtcNode.DEFAULT_PORT, "https://github.com/emzy"), // 62.75.210.81 - BtcNode.fromHostName("vlf5i3grro3wux24.onion", BtcNode.DEFAULT_PORT, "https://github.com/alexej996"), // onion only - BtcNode.fromHostName("3r44ddzjitznyahw.onion", BtcNode.DEFAULT_PORT, "https://github.com/sqrrm"), // not used: 185.25.48.184 - BtcNode.fromHostName("i3a5xtzfm4xwtybd.onion", BtcNode.DEFAULT_PORT, "https://github.com/sqrrm"), // not used: 80.233.134.60 - BtcNode.fromHostName("mxdtrjhe2yfsx3pg.onion", BtcNode.DEFAULT_PORT, "https://github.com/mrosseel") // onion only*/ + // mrosseel + new BtcNode("btc.vante.me", null, "138.68.117.247", BtcNode.DEFAULT_PORT, "https://github.com/mrosseel"), + new BtcNode(null, "mxdtrjhe2yfsx3pg.onion", null, BtcNode.DEFAULT_PORT, "https://github.com/mrosseel"), + + // sqrrm + new BtcNode("btc4.0-2-1.net", "3r44ddzjitznyahw.onion", "185.25.48.184", BtcNode.DEFAULT_PORT, "https://github.com/sqrrm"), //TODO change dns + + // sgeisler + new BtcNode("bcwat.ch", "z33nukt7ngik3cpe.onion", "5.189.166.193", BtcNode.DEFAULT_PORT, "https://github.com/sgeisler"), + + // others + new BtcNode("btc.jochen-hoenicke.de", null, "37.221.198.57", BtcNode.DEFAULT_PORT, "https://github.com/jhoenicke"), + new BtcNode("bitcoin4-fullnode.csg.uzh.ch", null, "192.41.136.217", BtcNode.DEFAULT_PORT, "https://github.com/tbocek") ) : new ArrayList<>(); } @@ -74,6 +83,8 @@ public class BitcoinNodes { public static class BtcNode { private static final int DEFAULT_PORT = BisqEnvironment.getParameters().getPort(); //8333 + @Nullable + private final String onionAddress; @Nullable private final String hostName; @Nullable @@ -83,69 +94,30 @@ public class BitcoinNodes { private int port = DEFAULT_PORT; /** - * @param fullAddress [hostName:port | IPv4 address:port] + * @param fullAddress [IPv4 address:port or onion:port] * @return BtcNode instance */ public static BtcNode fromFullAddress(String fullAddress) { String[] parts = fullAddress.split(":"); checkArgument(parts.length > 0); - if (parts.length == 1) { - return BtcNode.fromHostName(parts[0], DEFAULT_PORT, null); - } else { - checkArgument(parts.length == 2); - return BtcNode.fromHostNameAndPort(parts[0], Integer.valueOf(parts[1]), null); - } + final String host = parts[0]; + int port = DEFAULT_PORT; + if (parts.length == 2) + port = Integer.valueOf(parts[1]); + + return host.contains(".onion") ? new BtcNode(null, host, null, port, null) : new BtcNode(null, null, host, port, null); } - public static BtcNode fromHostName(String hostName, int port, @Nullable String operator) { - return new BtcNode(hostName, null, port, operator); - } - - public static BtcNode fromAddress(String address, @Nullable String operator) { - return new BtcNode(null, address, operator); - } - - public static BtcNode fromHostNameAndPort(String hostName, int port, @Nullable String operator) { - return new BtcNode(hostName, null, port, operator); - } - - public static BtcNode fromHostNameAndAddress(String hostName, String address, @Nullable String operator) { - return new BtcNode(hostName, address, operator); - } - - public static BtcNode fromHostNameAddressAndPort(String hostName, String address, int port, @Nullable String operator) { - return new BtcNode(hostName, address, port, operator); - } - - public static BtcNode fromAddressAndPort(String address, int port, @Nullable String operator) { - return new BtcNode(null, address, port, operator); - } - - private BtcNode(@Nullable String hostName, @Nullable String address, int port, @Nullable String operator) { + public BtcNode(@Nullable String hostName, @Nullable String onionAddress, @Nullable String address, int port, @Nullable String operator) { this.hostName = hostName; + this.onionAddress = onionAddress; this.address = address; this.port = port; this.operator = operator; - - if (address == null) - checkNotNull(hostName, "hostName must not be null if address is null"); - else if (hostName == null) - checkNotNull(address, "address must not be null if hostName is null"); } - private BtcNode(@Nullable String hostName, @Nullable String address, @Nullable String operator) { - this.hostName = hostName; - this.address = address; - this.operator = operator; - - if (address == null) - checkNotNull(hostName, "hostName must not be null if address is null"); - else if (hostName == null) - checkNotNull(address, "address must not be null if hostName is null"); - } - - public boolean isHiddenService() { - return hostName != null && hostName.endsWith("onion"); + public boolean hasOnionAddress() { + return onionAddress != null; } public String getHostNameOrAddress() { @@ -155,9 +127,8 @@ public class BitcoinNodes { return address; } - public String getHostNameOrAddressWithPort() { - log.error(getHostNameOrAddress() + ":" + port); - return getHostNameOrAddress() + ":" + port; + public boolean hasClearNetAddress() { + return hostName != null || address != null; } } } diff --git a/core/src/main/java/io/bisq/core/btc/wallet/WalletsSetup.java b/core/src/main/java/io/bisq/core/btc/wallet/WalletsSetup.java index eb93fd426a..a1c02add99 100644 --- a/core/src/main/java/io/bisq/core/btc/wallet/WalletsSetup.java +++ b/core/src/main/java/io/bisq/core/btc/wallet/WalletsSetup.java @@ -32,10 +32,10 @@ import io.bisq.common.storage.FileUtil; import io.bisq.core.app.BisqEnvironment; import io.bisq.core.btc.*; import io.bisq.core.user.Preferences; -import io.bisq.network.DnsLookupTor; import io.bisq.network.Socks5MultiDiscovery; import io.bisq.network.Socks5ProxyProvider; import javafx.beans.property.*; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.bitcoinj.core.*; import org.bitcoinj.core.listeners.DownloadProgressTracker; @@ -46,8 +46,6 @@ import org.bitcoinj.utils.Threading; import org.bitcoinj.wallet.DeterministicSeed; import org.bitcoinj.wallet.Wallet; import org.jetbrains.annotations.NotNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import javax.annotation.Nullable; import javax.inject.Named; @@ -70,9 +68,8 @@ import static com.google.common.base.Preconditions.checkNotNull; // Setup wallets and use WalletConfig for BitcoinJ wiring. // Other like WalletConfig we are here always on the user thread. That is one reason why we do not // merge WalletsSetup with WalletConfig to one class. +@Slf4j public class WalletsSetup { - private static final Logger log = LoggerFactory.getLogger(WalletsSetup.class); - private static final long STARTUP_TIMEOUT_SEC = 120; private final String btcWalletFileName; private static final String BSQ_WALLET_FILE_NAME = "bisq_BSQ.wallet"; @@ -301,55 +298,41 @@ public class WalletsSetup { final boolean useTorForBitcoinJ = socks5Proxy != null; List peerAddressList = new ArrayList<>(); - btcNodeList.forEach(btcNode -> { - if (useTorForBitcoinJ) { - if (btcNode.isHiddenService()) { - // no DNS lookup for onion addresses - log.info("We add a onion node with btcNode={}", btcNode); - final String hostName = btcNode.getHostName(); - if (hostName != null) { - try { - // OnionCat.onionHostToInetAddress converts onion to ipv6 representation - final InetAddress inetAddress = OnionCat.onionHostToInetAddress(hostName); - final PeerAddress peerAddress = new PeerAddress(hostName, btcNode.getPort()); - // inetAddress is not used but required for wallet persistence. Throws nullpointer if not set. - peerAddress.setAddr(inetAddress); - peerAddressList.add(peerAddress); - } catch (UnknownHostException e) { - log.error("OnionCat.onionHostToInetAddress() failed with btcNode={}, error={}", btcNode.toString(), e.toString()); - e.printStackTrace(); - } - } else { - log.error("hostName is null for btcNode={}", btcNode.toString()); - } - } else { - try { - // We use DnsLookupTor to not leak with DNS lookup - // Blocking call. takes about 600 ms ;-( - InetSocketAddress address = new InetSocketAddress(DnsLookupTor.lookup(socks5Proxy, btcNode.getHostNameOrAddress()), btcNode.getPort()); - log.info("We add a clear net node (tor is used) with InetAddress={}, btcNode={}", address.getAddress(), btcNode); - peerAddressList.add(new PeerAddress(address.getAddress(), address.getPort())); - } catch (Exception e) { - log.warn("Dns lookup failed for btcNode: {}", btcNode); - } - } - } else { - // We don't use Tor for BitcoinJ - // onion addresses are not supported + + // We connect to onion nodes only in case we use Tor for BitcoinJ (default) to avoid privacy leaks at + // exit nodes with bloom filters. + if (useTorForBitcoinJ) { + btcNodeList.stream() + .filter(BitcoinNodes.BtcNode::hasOnionAddress) + .forEach(btcNode -> { + // no DNS lookup for onion addresses + log.info("We add a onion node. btcNode={}", btcNode); + final String onionAddress = btcNode.getOnionAddress(); try { - if (!btcNode.isHiddenService()) { - InetSocketAddress address = new InetSocketAddress(btcNode.getHostNameOrAddress(), btcNode.getPort()); - log.info("We add a clear net node (no tor is used) with host={}, btcNode.getPort()={}", btcNode.getHostNameOrAddress(), btcNode.getPort()); - peerAddressList.add(new PeerAddress(address.getAddress(), address.getPort())); - } else { - log.warn("Onion addresses are only supported when using Tor with BitcoinJ. Ignore btcNode {}", btcNode); - } + // OnionCat.onionHostToInetAddress converts onion to ipv6 representation + // inetAddress is not used but required for wallet persistence. Throws nullPointer if not set. + final InetAddress inetAddress = OnionCat.onionHostToInetAddress(onionAddress); + final PeerAddress peerAddress = new PeerAddress(onionAddress, btcNode.getPort()); + peerAddress.setAddr(inetAddress); + peerAddressList.add(peerAddress); + } catch (UnknownHostException e) { + log.error("OnionCat.onionHostToInetAddress() failed with btcNode={}, error={}", btcNode.toString(), e.toString()); + e.printStackTrace(); + } + }); + } else { + btcNodeList.stream() + .filter(BitcoinNodes.BtcNode::hasClearNetAddress) + .forEach(btcNode -> { + try { + InetSocketAddress address = new InetSocketAddress(btcNode.getHostNameOrAddress(), btcNode.getPort()); + log.info("We add a clear net node (no tor is used) with host={}, btcNode.getPort()={}", btcNode.getHostNameOrAddress(), btcNode.getPort()); + peerAddressList.add(new PeerAddress(address.getAddress(), address.getPort())); } catch (Throwable t) { log.warn("Failed to create InetSocketAddress from btcNode {}", btcNode); } - } - } - ); + }); + } if (!peerAddressList.isEmpty()) { final PeerAddress[] peerAddresses = peerAddressList.toArray(new PeerAddress[peerAddressList.size()]); diff --git a/core/src/main/java/io/bisq/core/network/CoreSeedNodesRepository.java b/core/src/main/java/io/bisq/core/network/CoreSeedNodesRepository.java index cc87bc1f99..78a02c668d 100644 --- a/core/src/main/java/io/bisq/core/network/CoreSeedNodesRepository.java +++ b/core/src/main/java/io/bisq/core/network/CoreSeedNodesRepository.java @@ -13,7 +13,6 @@ import org.apache.commons.lang3.StringUtils; import javax.annotation.Nullable; import javax.inject.Inject; import java.util.Arrays; -import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -24,8 +23,6 @@ public class CoreSeedNodesRepository implements SeedNodesRepository { @Getter private final Set seedNodeAddresses; - @Getter - private final Set seedNodeAddressesOldVersions; @Inject public CoreSeedNodesRepository(BisqEnvironment bisqEnvironment, @@ -35,27 +32,17 @@ public class CoreSeedNodesRepository implements SeedNodesRepository { @Nullable @Named(NetworkOptionKeys.SEED_NODES_KEY) String seedNodes) { List bannedNodes = bisqEnvironment.getBannedSeedNodes(); Set nodeAddresses; - Set nodeAddressesOldVersions; if (seedNodes != null && !seedNodes.isEmpty()) { nodeAddresses = Arrays.asList(StringUtils.deleteWhitespace(seedNodes).split(",")) .stream() .map(NodeAddress::new) .collect(Collectors.toSet()); - nodeAddressesOldVersions = new HashSet<>(); } else { nodeAddresses = useLocalhostForP2P ? localhostSeedNodeAddresses : torSeedNodeAddresses; nodeAddresses = nodeAddresses.stream() .filter(e -> String.valueOf(e.getPort()).endsWith("0" + String.valueOf(networkId))) .collect(Collectors.toSet()); - - if (!useLocalhostForP2P) { - nodeAddressesOldVersions = torSeedNodeAddressesOldVersions.stream() - .filter(e -> String.valueOf(e.getPort()).endsWith("0" + String.valueOf(networkId))) - .collect(Collectors.toSet()); - } else { - nodeAddressesOldVersions = new HashSet<>(); - } } seedNodeAddresses = nodeAddresses.stream() @@ -67,11 +54,6 @@ public class CoreSeedNodesRepository implements SeedNodesRepository { log.info("seedNodeAddresses={}", seedNodeAddresses); else log.warn("We received banned seed nodes={}, seedNodeAddresses={}", bannedNodes, seedNodeAddresses); - - seedNodeAddressesOldVersions = nodeAddressesOldVersions.stream() - .filter(e -> myAddress == null || myAddress.isEmpty() || !e.getFullAddress().equals(myAddress)) - .filter(e -> bannedNodes == null || !bannedNodes.contains(e.getHostName())) - .collect(Collectors.toSet()); } public String getOperator(NodeAddress nodeAddress) { @@ -83,7 +65,7 @@ public class CoreSeedNodesRepository implements SeedNodesRepository { case "s67qglwhkgkyvr74.onion:8000": return "@emzy"; case "jhgcy2won7xnslrb.onion:8000": - return "@sqrrm"; + return "@ManfredKarrer"; case "3f3cu2yw7u457ztq.onion:8000": return "@ManfredKarrer"; case "723ljisnynbtdohi.onion:8000": @@ -106,7 +88,7 @@ public class CoreSeedNodesRepository implements SeedNodesRepository { case "s67qglwhkgkyvr74.onion:8000": return "@emzy"; case "jhgcy2won7xnslrb.onion:8000": - return "@sqrrm"; + return "@ManfredKarrer"; case "3f3cu2yw7u457ztq.onion:8000": return "@manfredkarrer"; case "723ljisnynbtdohi.onion:8000": @@ -120,15 +102,6 @@ public class CoreSeedNodesRepository implements SeedNodesRepository { } } - /* old nodes pre 0.6.0 (still running for 0.5.* versions */ - private Set torSeedNodeAddressesOldVersions = - Sets.newHashSet( - new NodeAddress("3f3cu2yw7u457ztq.onion:8000"), // @ManfredKarrer - new NodeAddress("723ljisnynbtdohi.onion:8000"), // @ManfredKarrer - new NodeAddress("rm7b56wbrcczpjvl.onion:8000"), // @ManfredKarrer - new NodeAddress("fl3mmribyxgrv63c.onion:8000") // @ManfredKarrer - ); - // Addresses are used if their port match the network id: // - mainnet uses port 8000 // - testnet uses port 8001 @@ -137,9 +110,13 @@ public class CoreSeedNodesRepository implements SeedNodesRepository { private Set torSeedNodeAddresses = Sets.newHashSet( // BTC mainnet new NodeAddress("5quyxpxheyvzmb2d.onion:8000"), // @mrosseel - new NodeAddress("ef5qnzx6znifo3df.onion:8000"), // @ManfredKarrer new NodeAddress("s67qglwhkgkyvr74.onion:8000"), // @emzy - new NodeAddress("jhgcy2won7xnslrb.onion:8000"), // @sqrrm + new NodeAddress("ef5qnzx6znifo3df.onion:8000"), // @ManfredKarrer + new NodeAddress("jhgcy2won7xnslrb.onion:8000"), // @ManfredKarrer + new NodeAddress("3f3cu2yw7u457ztq.onion:8000"), // @ManfredKarrer + new NodeAddress("723ljisnynbtdohi.onion:8000"), // @ManfredKarrer + new NodeAddress("rm7b56wbrcczpjvl.onion:8000"), // @ManfredKarrer + new NodeAddress("fl3mmribyxgrv63c.onion:8000"), // @ManfredKarrer //TODO dev // local dev diff --git a/core/src/main/java/io/bisq/core/provider/ProvidersRepository.java b/core/src/main/java/io/bisq/core/provider/ProvidersRepository.java index 01975a287a..6d59286ccf 100644 --- a/core/src/main/java/io/bisq/core/provider/ProvidersRepository.java +++ b/core/src/main/java/io/bisq/core/provider/ProvidersRepository.java @@ -35,10 +35,10 @@ import java.util.stream.Collectors; public class ProvidersRepository { private static final String NODES = "http://xc3nh4juf2hshy7e.onion/, " + // @emzy "http://ceaanhbvluug4we6.onion/, " +// @mrosseel + "http://44mgyoe2b6oqiytt.onion/, " +// @ManfredKarrer + "http://5bmpx76qllutpcyp.onion/, " +// @ManfredKarrer "http://rb2l2qale2pqzjyo.onion/"; // @sqrrm - // Old nodes before v 0.6.0: "http://44mgyoe2b6oqiytt.onion/, http://5bmpx76qllutpcyp.onion/"; @ManfredKarrer - private final String providersFromProgramArgs; private final boolean useLocalhostForP2P; diff --git a/network/src/main/java/io/bisq/network/p2p/seed/SeedNodesRepository.java b/network/src/main/java/io/bisq/network/p2p/seed/SeedNodesRepository.java index 77be32de26..3a52129ecc 100644 --- a/network/src/main/java/io/bisq/network/p2p/seed/SeedNodesRepository.java +++ b/network/src/main/java/io/bisq/network/p2p/seed/SeedNodesRepository.java @@ -30,8 +30,6 @@ public interface SeedNodesRepository { Set getSeedNodeAddresses(); - Set getSeedNodeAddressesOldVersions(); - String getOperator(NodeAddress nodeAddress); String getSlackUser(NodeAddress nodeAddress); diff --git a/seednode_monitor/src/main/java/io/bisq/seednode_monitor/MetricsByNodeAddressMap.java b/seednode_monitor/src/main/java/io/bisq/seednode_monitor/MetricsByNodeAddressMap.java index a387e5df6b..ae15b6bdcd 100644 --- a/seednode_monitor/src/main/java/io/bisq/seednode_monitor/MetricsByNodeAddressMap.java +++ b/seednode_monitor/src/main/java/io/bisq/seednode_monitor/MetricsByNodeAddressMap.java @@ -102,12 +102,15 @@ public class MetricsByNodeAddressMap extends HashMap { "Num requests" + "Num errors" + "Last error message" + - "Duration average" + + "RRT average" + "Last data" + "Data deviation last request" + ""); StringBuilder sb = new StringBuilder(); + sb.append("Seed nodes in error:" + totalErrors); + sb.append("\nLast check started at: " + time); + entryList.stream().forEach(e -> { final List allDurations = e.getValue().getRequestDurations(); final String allDurationsString = allDurations.stream().map(Object::toString).collect(Collectors.joining("
")); @@ -120,7 +123,16 @@ public class MetricsByNodeAddressMap extends HashMap { final List errorMessages = e.getValue().getErrorMessages(); final int numErrors = (int) errorMessages.stream().filter(s -> !s.isEmpty()).count(); int numRequests = allDurations.size(); - final String lastErrorMsg = numErrors > 0 ? errorMessages.get(errorMessages.size() - 1) : ""; + String lastErrorMsg = ""; + int lastIndexOfError = -1; + for (int i = 0; i < errorMessages.size(); i++) { + final String msg = errorMessages.get(i); + if (!msg.isEmpty()) { + lastIndexOfError = i; + lastErrorMsg = "Error at request " + lastIndexOfError + ":" + msg; + } + } + // String lastErrorMsg = numErrors > 0 ? errorMessages.get(errorMessages.size() - 1) : ""; final List> allReceivedData = e.getValue().getReceivedObjectsList(); Map lastReceivedData = !allReceivedData.isEmpty() ? allReceivedData.get(allReceivedData.size() - 1) : new HashMap<>(); final String lastReceivedDataString = lastReceivedData.entrySet().stream().map(Object::toString).collect(Collectors.joining("
")); @@ -131,10 +143,10 @@ public class MetricsByNodeAddressMap extends HashMap { .append("\nNum requests: ").append(numRequests) .append("\nNum errors: ").append(numErrors) .append("\nLast error message: ").append(lastErrorMsg) - .append("\nDuration average: ").append(durationAverage) + .append("\nRRT average: ").append(durationAverage) .append("\nLast data: ").append(lastReceivedDataString); - String colorNumErrors = lastErrorMsg.isEmpty() ? "black" : "red"; + String colorNumErrors = lastIndexOfError == numErrors ? "black" : "red"; String colorDurationAverage = durationAverage < 30 ? "black" : "red"; html.append("") .append("").append("" + operator + " ").append("") @@ -167,7 +179,7 @@ public class MetricsByNodeAddressMap extends HashMap { if (slackApi != null) slackApi.call(new SlackMessage("Warning: " + nodeAddress.getFullAddress(), "<" + seedNodesRepository.getSlackUser(nodeAddress) + ">" + " Your seed node delivers diverging results for " + dataItem + ". " + - "Please check the monitoring status page at http://178.62.249.232:8080/")); + "Please check the monitoring status page at http://seedmonitor.0-2-1.net:8080/")); } }); sb.append("\nDuration all requests: ").append(allDurationsString) diff --git a/seednode_monitor/src/main/java/io/bisq/seednode_monitor/request/MonitorRequestManager.java b/seednode_monitor/src/main/java/io/bisq/seednode_monitor/request/MonitorRequestManager.java index 5df564265d..ca54fd63df 100644 --- a/seednode_monitor/src/main/java/io/bisq/seednode_monitor/request/MonitorRequestManager.java +++ b/seednode_monitor/src/main/java/io/bisq/seednode_monitor/request/MonitorRequestManager.java @@ -71,7 +71,6 @@ public class MonitorRequestManager implements ConnectionListener { this.networkNode.addConnectionListener(this); seedNodeAddresses = new HashSet<>(seedNodesRepository.getSeedNodeAddresses()); - seedNodeAddresses.addAll(seedNodesRepository.getSeedNodeAddressesOldVersions()); seedNodeAddresses.stream().forEach(nodeAddress -> metricsByNodeAddressMap.put(nodeAddress, new Metrics())); }