diff --git a/core/src/main/java/bisq/core/CoreModule.java b/core/src/main/java/bisq/core/CoreModule.java index e22d44406ab..65e88eb18dd 100644 --- a/core/src/main/java/bisq/core/CoreModule.java +++ b/core/src/main/java/bisq/core/CoreModule.java @@ -30,6 +30,7 @@ import bisq.core.dao.DaoModule; import bisq.core.filter.FilterModule; import bisq.core.network.p2p.seed.DefaultSeedNodeRepository; +import bisq.core.network.p2p.seed.SeedNodeAddressLookup; import bisq.core.notifications.MobileMessageEncryption; import bisq.core.notifications.MobileModel; import bisq.core.notifications.MobileNotificationService; @@ -98,6 +99,7 @@ protected void configure() { bind(CorruptedDatabaseFilesHandler.class).in(Singleton.class); bind(AvoidStandbyModeService.class).in(Singleton.class); + bind(SeedNodeAddressLookup.class).in(Singleton.class); bind(SeedNodeRepository.class).to(DefaultSeedNodeRepository.class).in(Singleton.class); File storageDir = new File(environment.getRequiredProperty(Storage.STORAGE_DIR)); diff --git a/core/src/main/java/bisq/core/app/BisqEnvironment.java b/core/src/main/java/bisq/core/app/BisqEnvironment.java index 6f9b1a5f871..9a3ca198c4f 100644 --- a/core/src/main/java/bisq/core/app/BisqEnvironment.java +++ b/core/src/main/java/bisq/core/app/BisqEnvironment.java @@ -57,7 +57,6 @@ import java.io.FileOutputStream; import java.io.IOException; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Properties; @@ -346,7 +345,7 @@ public BisqEnvironment(PropertySource commandLineProperties) { bannedPriceRelayNodes = !bannedPriceRelayNodesAsString.isEmpty() ? Arrays.asList(StringUtils.deleteWhitespace(bannedPriceRelayNodesAsString).split(",")) : null; final String bannedSeedNodesAsString = getProperty(FilterManager.BANNED_SEED_NODES, ""); - bannedSeedNodes = !bannedSeedNodesAsString.isEmpty() ? Arrays.asList(StringUtils.deleteWhitespace(bannedSeedNodesAsString).split(",")) : new ArrayList<>(); + bannedSeedNodes = !bannedSeedNodesAsString.isEmpty() ? Arrays.asList(StringUtils.deleteWhitespace(bannedSeedNodesAsString).split(",")) : null; final String bannedBtcNodesAsString = getProperty(FilterManager.BANNED_BTC_NODES, ""); bannedBtcNodes = !bannedBtcNodesAsString.isEmpty() ? Arrays.asList(StringUtils.deleteWhitespace(bannedBtcNodesAsString).split(",")) : null; diff --git a/core/src/main/java/bisq/core/app/misc/ModuleForAppWithP2p.java b/core/src/main/java/bisq/core/app/misc/ModuleForAppWithP2p.java index 35413918c2d..16d1c87ea70 100644 --- a/core/src/main/java/bisq/core/app/misc/ModuleForAppWithP2p.java +++ b/core/src/main/java/bisq/core/app/misc/ModuleForAppWithP2p.java @@ -26,6 +26,7 @@ import bisq.core.dao.DaoModule; import bisq.core.filter.FilterModule; import bisq.core.network.p2p.seed.DefaultSeedNodeRepository; +import bisq.core.network.p2p.seed.SeedNodeAddressLookup; import bisq.core.offer.OfferModule; import bisq.core.proto.network.CoreNetworkProtoResolver; import bisq.core.proto.persistable.CorePersistenceProtoResolver; @@ -76,6 +77,7 @@ protected void configure() { bind(BridgeAddressProvider.class).to(Preferences.class).in(Singleton.class); bind(TorSetup.class).in(Singleton.class); + bind(SeedNodeAddressLookup.class).in(Singleton.class); bind(SeedNodeRepository.class).to(DefaultSeedNodeRepository.class).in(Singleton.class); File storageDir = new File(environment.getRequiredProperty(Storage.STORAGE_DIR)); diff --git a/core/src/main/java/bisq/core/network/p2p/seed/DefaultSeedNodeAddresses.java b/core/src/main/java/bisq/core/network/p2p/seed/DefaultSeedNodeAddresses.java new file mode 100644 index 00000000000..d6ef2f5b5d7 --- /dev/null +++ b/core/src/main/java/bisq/core/network/p2p/seed/DefaultSeedNodeAddresses.java @@ -0,0 +1,97 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.core.network.p2p.seed; + +import bisq.network.p2p.NodeAddress; + +import com.google.common.collect.ImmutableSet; + +import java.util.Set; + +class DefaultSeedNodeAddresses { + // Addresses are used if the last digit of their port match the network id: + // - mainnet use port ends in 0 + // - testnet use port ends in 1 + // - regtest use port ends in 2 + public static final Set DEFAULT_LOCALHOST_SEED_NODE_ADDRESSES = ImmutableSet.of( + // BTC + // mainnet + new NodeAddress("localhost:2000"), + new NodeAddress("localhost:3000"), + new NodeAddress("localhost:4000"), + + // testnet + new NodeAddress("localhost:2001"), + new NodeAddress("localhost:3001"), + new NodeAddress("localhost:4001"), + + // regtest + new NodeAddress("localhost:2002"), + new NodeAddress("localhost:3002") + /* new NodeAddress("localhost:4002"),*/ + ); + + // Addresses are used if their port match the network id: + // - mainnet uses port 8000 + // - testnet uses port 8001 + // - regtest uses port 8002 + public static final Set DEFAULT_TOR_SEED_NODE_ADDRESSES = ImmutableSet.of( + // BTC mainnet + new NodeAddress("5quyxpxheyvzmb2d.onion:8000"), // @miker + new NodeAddress("s67qglwhkgkyvr74.onion:8000"), // @emzy + 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 + + // local dev + // new NodeAddress("joehwtpe7ijnz4df.onion:8000"), + // new NodeAddress("uqxi3zrpobhtoes6.onion:8000"), + + // BTC testnet + // new NodeAddress("vjkh4ykq7x5skdlt.onion:8001"), // local dev test + //new NodeAddress("fjr5w4eckjghqtnu.onion:8001"), // testnet seed 1 + /* new NodeAddress("74w2sttlo4qk6go3.onion:8001"), // testnet seed 2 + new NodeAddress("jmc5ajqvtnzqaggm.onion:8001"), // testnet seed 3 + new NodeAddress("3d56s6acbi3vk52v.onion:8001"), // testnet seed 4*/ + + // BTC regtest + // For development you need to change that to your local onion addresses + // 1. Run a seed node with prog args: --bitcoinNetwork=regtest --nodePort=8002 --myAddress=rxdkppp3vicnbgqt:8002 --appName=bisq_seed_node_rxdkppp3vicnbgqt.onion_8002 + // 2. Find your local onion address in bisq_seed_node_rxdkppp3vicnbgqt.onion_8002/regtest/tor/hiddenservice/hostname + // 3. Shut down the seed node + // 4. Rename the directory with your local onion address + // 5. Edit here your found onion address (new NodeAddress("YOUR_ONION.onion:8002") + new NodeAddress("rxdkppp3vicnbgqt.onion:8002"), + new NodeAddress("4ie52dse64kaarxw.onion:8002"), + + // DAO TESTNET (server side regtest dedicated for DAO testing) + new NodeAddress("fjr5w4eckjghqtnu.onion:8003"), // testnet seed 1 + new NodeAddress("74w2sttlo4qk6go3.onion:8003"), // testnet seed 2 + new NodeAddress("jmc5ajqvtnzqaggm.onion:8003"), // testnet seed 3 + new NodeAddress("3d56s6acbi3vk52v.onion:8003") // testnet seed 4 + + // explorer + // new NodeAddress("gtif46mfxirv533z.onion:8003") + ); + + private DefaultSeedNodeAddresses() { + } +} diff --git a/core/src/main/java/bisq/core/network/p2p/seed/DefaultSeedNodeRepository.java b/core/src/main/java/bisq/core/network/p2p/seed/DefaultSeedNodeRepository.java index ad24cb7e30c..6c9e160bebf 100644 --- a/core/src/main/java/bisq/core/network/p2p/seed/DefaultSeedNodeRepository.java +++ b/core/src/main/java/bisq/core/network/p2p/seed/DefaultSeedNodeRepository.java @@ -17,87 +17,59 @@ package bisq.core.network.p2p.seed; -import bisq.core.app.BisqEnvironment; - -import bisq.network.NetworkOptionKeys; import bisq.network.p2p.NodeAddress; import bisq.network.p2p.seed.SeedNodeRepository; import javax.inject.Inject; -import javax.inject.Named; - -import java.net.URL; - -import java.io.BufferedReader; -import java.io.FileNotFoundException; -import java.io.FileReader; - -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import javax.annotation.Nullable; +import java.util.Set; +import java.util.stream.Stream; public class DefaultSeedNodeRepository implements SeedNodeRepository { - private static final Pattern pattern = Pattern.compile("^([a-z0-9]+\\.onion:\\d+)"); - private static final String ENDING = ".seednodes"; - private static final Collection cache = new HashSet<>(); - private final BisqEnvironment bisqEnvironment; - private final String seedNodes; + + private final Set seedNodeAddresses; + private final Set torSeedNodeAddresses; + private final Set localhostSeedNodeAddresses; @Inject - public DefaultSeedNodeRepository(BisqEnvironment environment, - @Nullable @Named(NetworkOptionKeys.SEED_NODES_KEY) String seedNodes) { - bisqEnvironment = environment; - this.seedNodes = seedNodes; + public DefaultSeedNodeRepository(SeedNodeAddressLookup lookup) { + this.seedNodeAddresses = lookup.resolveNodeAddresses(); + this.torSeedNodeAddresses = DefaultSeedNodeAddresses.DEFAULT_TOR_SEED_NODE_ADDRESSES; + this.localhostSeedNodeAddresses = DefaultSeedNodeAddresses.DEFAULT_LOCALHOST_SEED_NODE_ADDRESSES; } - private void reload() { - - // see if there are any seed nodes configured manually - if(seedNodes != null && !seedNodes.isEmpty()) { - cache.clear(); - Arrays.stream(seedNodes.split(",")).forEach(s -> cache.add(new NodeAddress(s))); - - return; - } - - // else, we fetch the seed nodes from our resources - try { - // read appropriate file - final URL file = DefaultSeedNodeRepository.class.getClassLoader().getResource(BisqEnvironment.getBaseCurrencyNetwork().name().toLowerCase() + ENDING); - final BufferedReader seedNodeFile = new BufferedReader(new FileReader(file.getFile())); - - // only clear if we have a fresh data source (otherwise, an exception would prevent us from getting here) - cache.clear(); - - // refill the cache - seedNodeFile.lines().forEach(s -> { - final Matcher matcher = pattern.matcher(s); - if(matcher.find()) - cache.add(new NodeAddress(matcher.group(1))); - }); - - // filter - cache.removeAll(bisqEnvironment.getBannedSeedNodes().stream().map(s -> new NodeAddress(s)).collect(Collectors.toSet())); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } + @Override + public Set getSeedNodeAddresses() { + return seedNodeAddresses; } - public Collection getSeedNodeAddresses() { - if(cache.isEmpty()) - reload(); - - return cache; + @Override + public String getOperator(NodeAddress nodeAddress) { + switch (nodeAddress.getFullAddress()) { + case "5quyxpxheyvzmb2d.onion:8000": + return "@miker"; + case "ef5qnzx6znifo3df.onion:8000": + return "@manfredkarrer"; + case "s67qglwhkgkyvr74.onion:8000": + return "@emzy"; + case "jhgcy2won7xnslrb.onion:8000": + return "@manfredkarrer"; + case "3f3cu2yw7u457ztq.onion:8000": + return "@manfredkarrer"; + case "723ljisnynbtdohi.onion:8000": + return "@manfredkarrer"; + case "rm7b56wbrcczpjvl.onion:8000": + return "@manfredkarrer"; + case "fl3mmribyxgrv63c.onion:8000": + return "@manfredkarrer"; + default: + return "Undefined"; + } } + @Override public boolean isSeedNode(NodeAddress nodeAddress) { - if(cache.isEmpty()) - reload(); - return cache.contains(nodeAddress); + return Stream.concat(localhostSeedNodeAddresses.stream(), torSeedNodeAddresses.stream()) + .anyMatch(e -> e.equals(nodeAddress)); } } diff --git a/core/src/main/java/bisq/core/network/p2p/seed/ImmutableSetDecorator.java b/core/src/main/java/bisq/core/network/p2p/seed/ImmutableSetDecorator.java new file mode 100644 index 00000000000..31fbb644b5f --- /dev/null +++ b/core/src/main/java/bisq/core/network/p2p/seed/ImmutableSetDecorator.java @@ -0,0 +1,45 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.core.network.p2p.seed; + +import com.google.common.collect.ImmutableSet; + +import java.util.AbstractSet; +import java.util.Iterator; +import java.util.Set; + +import org.jetbrains.annotations.NotNull; + +class ImmutableSetDecorator extends AbstractSet { + private final Set delegate; + + public ImmutableSetDecorator(Set delegate) { + this.delegate = ImmutableSet.copyOf(delegate); + } + + @NotNull + @Override + public Iterator iterator() { + return delegate.iterator(); + } + + @Override + public int size() { + return delegate.size(); + } +} diff --git a/core/src/main/java/bisq/core/network/p2p/seed/SeedNodeAddressLookup.java b/core/src/main/java/bisq/core/network/p2p/seed/SeedNodeAddressLookup.java new file mode 100644 index 00000000000..dc28119d615 --- /dev/null +++ b/core/src/main/java/bisq/core/network/p2p/seed/SeedNodeAddressLookup.java @@ -0,0 +1,106 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.core.network.p2p.seed; + +import bisq.core.app.BisqEnvironment; + +import bisq.network.NetworkOptionKeys; +import bisq.network.p2p.NodeAddress; + +import com.google.inject.name.Named; + +import javax.inject.Inject; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nullable; + +public class SeedNodeAddressLookup { + private static final Logger log = LoggerFactory.getLogger(SeedNodeAddressLookup.class); + + private final BisqEnvironment environment; + private final boolean isLocalHostUsed; + private final int networkId; + @Nullable + private final String myAddress; + @Nullable + private final String seedNodes; + + @Inject + public SeedNodeAddressLookup(BisqEnvironment environment, + @Named(NetworkOptionKeys.USE_LOCALHOST_FOR_P2P) boolean useLocalhostForP2P, + @Named(NetworkOptionKeys.NETWORK_ID) int networkId, + @Nullable @Named(NetworkOptionKeys.MY_ADDRESS) String myAddress, + @Nullable @Named(NetworkOptionKeys.SEED_NODES_KEY) String seedNodes) { + this.environment = environment; + this.isLocalHostUsed = useLocalhostForP2P; + this.networkId = networkId; + this.myAddress = myAddress; + this.seedNodes = seedNodes; + } + + public Set resolveNodeAddresses() { + SeedNodeAddresses allSeedNodeAddresses = getAllAddresses(); + + Set bannedHosts = getBannedHosts(); + allSeedNodeAddresses = allSeedNodeAddresses.excludeByHost(bannedHosts); + + if (myAddress != null) { + allSeedNodeAddresses = allSeedNodeAddresses.excludeByFullAddress(myAddress); + } + + log.debug("We received banned seed nodes={}, seedNodeAddresses={}", bannedHosts, allSeedNodeAddresses); + return allSeedNodeAddresses; + } + + private Set getBannedHosts() { + return Optional.ofNullable(environment.getBannedSeedNodes()) + .map(HashSet::new) + .map(hosts -> (Set) hosts) + .orElse(Collections.emptySet()); + } + + private SeedNodeAddresses getAllAddresses() { + SeedNodeAddresses seedNodeAddresses = Optional.ofNullable(seedNodes) + .map(nodes -> SeedNodeAddresses.fromString(seedNodes)) + .orElse(new SeedNodeAddresses(Collections.emptySet())); + + if (seedNodeAddresses.isEmpty()) { + Set delegate = isLocalHostUsed + ? DefaultSeedNodeAddresses.DEFAULT_LOCALHOST_SEED_NODE_ADDRESSES + : DefaultSeedNodeAddresses.DEFAULT_TOR_SEED_NODE_ADDRESSES; + seedNodeAddresses = delegate.stream() + .filter(address -> isAddressFromNetwork(address, networkId)) + .collect(SeedNodeAddresses.collector()); + } + return seedNodeAddresses; + } + + private static boolean isAddressFromNetwork(NodeAddress address, int networkId) { + String suffix = "0" + networkId; + int port = address.getPort(); + String portAsString = String.valueOf(port); + return portAsString.endsWith(suffix); + } +} diff --git a/core/src/main/java/bisq/core/network/p2p/seed/SeedNodeAddresses.java b/core/src/main/java/bisq/core/network/p2p/seed/SeedNodeAddresses.java new file mode 100644 index 00000000000..ad451e21722 --- /dev/null +++ b/core/src/main/java/bisq/core/network/p2p/seed/SeedNodeAddresses.java @@ -0,0 +1,67 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.core.network.p2p.seed; + +import bisq.network.p2p.NodeAddress; + +import org.apache.commons.lang3.StringUtils; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collector; +import java.util.stream.Collectors; + +class SeedNodeAddresses extends ImmutableSetDecorator { + + public SeedNodeAddresses(Set delegate) { + super(delegate); + } + + public SeedNodeAddresses excludeByHost(Set hosts) { + Set copy = new HashSet<>(this); + copy.removeIf(address -> { + String hostName = address.getHostName(); + return hosts.contains(hostName); + }); + return new SeedNodeAddresses(copy); + } + + public SeedNodeAddresses excludeByFullAddress(String fullAddress) { + Set copy = new HashSet<>(this); + copy.removeIf(address -> fullAddress.equals(address.getFullAddress())); + return new SeedNodeAddresses(copy); + } + + public static Collector collector() { + return Collectors.collectingAndThen(Collectors.toSet(), SeedNodeAddresses::new); + } + + public static SeedNodeAddresses fromString(String seedNodes) { + if (seedNodes.isEmpty()) { + return new SeedNodeAddresses(Collections.emptySet()); + } + + String trimmed = StringUtils.deleteWhitespace(seedNodes); + String[] nodes = trimmed.split(","); + return Arrays.stream(nodes) + .map(NodeAddress::new) + .collect(collector()); + } +} diff --git a/core/src/main/resources/btc_dao_testnet.seednodes b/core/src/main/resources/btc_dao_testnet.seednodes deleted file mode 100644 index fa63d9f5aed..00000000000 --- a/core/src/main/resources/btc_dao_testnet.seednodes +++ /dev/null @@ -1,5 +0,0 @@ -# nodeaddress.onion:port [(@owner)] -fjr5w4eckjghqtnu.onion:8003 -3d56s6acbi3vk52v.onion:8003 -74w2sttlo4qk6go3.onion:8003 -jmc5ajqvtnzqaggm.onion:8003 diff --git a/core/src/main/resources/btc_mainnet.seednodes b/core/src/main/resources/btc_mainnet.seednodes deleted file mode 100644 index 27a6f28feb9..00000000000 --- a/core/src/main/resources/btc_mainnet.seednodes +++ /dev/null @@ -1,9 +0,0 @@ -# nodeaddress.onion:port [(@owner)] -5quyxpxheyvzmb2d.onion:8000 (@miker) -s67qglwhkgkyvr74.onion:8000 (@emzy) -ef5qnzx6znifo3df.onion:8000 (@freimair) -jhgcy2won7xnslrb.onion:8000 (@freimair) -3f3cu2yw7u457ztq.onion:8000 (@manfredkarrer) -723ljisnynbtdohi.onion:8000 (@manfredkarrer) -rm7b56wbrcczpjvl.onion:8000 (@manfredkarrer) -fl3mmribyxgrv63c.onion:8000 (@manfredkarrer) diff --git a/core/src/main/resources/btc_regtest.seednodes b/core/src/main/resources/btc_regtest.seednodes deleted file mode 100644 index fb71abcae3e..00000000000 --- a/core/src/main/resources/btc_regtest.seednodes +++ /dev/null @@ -1,10 +0,0 @@ -# For development you need to change that to your local onion addresses -# 1. Run a seed node with prog args: --bitcoinNetwork=regtest --nodePort=8002 --myAddress=rxdkppp3vicnbgqt:8002 --appName=bisq_seed_node_rxdkppp3vicnbgqt.onion_8002 -# 2. Find your local onion address in bisq_seed_node_rxdkppp3vicnbgqt.onion_8002/regtest/tor/hiddenservice/hostname -# 3. Shut down the seed node -# 4. Rename the directory with your local onion address -# 5. Edit here your found onion address (new NodeAddress("YOUR_ONION.onion:8002") - -# nodeaddress.onion:port [(@owner)] -rxdkppp3vicnbgqt.onion:8002 -4ie52dse64kaarxw.onion:8002 diff --git a/core/src/main/resources/btc_testnet.seednodes b/core/src/main/resources/btc_testnet.seednodes deleted file mode 100644 index afc7c92300a..00000000000 --- a/core/src/main/resources/btc_testnet.seednodes +++ /dev/null @@ -1,2 +0,0 @@ -# nodeaddress.onion:port [(@owner)] -# Bisq on BTC TESTNET has been discontinued diff --git a/core/src/test/java/bisq/core/network/p2p/seed/DefaultSeedNodeRepositoryTest.java b/core/src/test/java/bisq/core/network/p2p/seed/DefaultSeedNodeRepositoryTest.java deleted file mode 100644 index 85b00a44fc6..00000000000 --- a/core/src/test/java/bisq/core/network/p2p/seed/DefaultSeedNodeRepositoryTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bisq. If not, see . - */ - -package bisq.core.network.p2p.seed; - -import bisq.core.app.BisqEnvironment; - -import bisq.network.p2p.NodeAddress; - -import org.springframework.core.env.PropertySource; - -import org.junit.Assert; -import org.junit.Test; - -public class DefaultSeedNodeRepositoryTest { - - @Test - public void getSeedNodes() { - DefaultSeedNodeRepository DUT = new DefaultSeedNodeRepository(new BisqEnvironment(new PropertySource.StubPropertySource("name")), null); - Assert.assertFalse(DUT.getSeedNodeAddresses().isEmpty()); - } - - @Test - public void manualSeedNodes() { - String seed1 = "asdf:8001"; - String seed2 = "fdsa:6001"; - String seedNodes = seed1 + "," + seed2; - DefaultSeedNodeRepository DUT = new DefaultSeedNodeRepository(new BisqEnvironment(new PropertySource.StubPropertySource("name")), seedNodes); - Assert.assertFalse(DUT.getSeedNodeAddresses().isEmpty()); - Assert.assertEquals(2, DUT.getSeedNodeAddresses().size()); - Assert.assertTrue(DUT.getSeedNodeAddresses().contains(new NodeAddress(seed1))); - Assert.assertTrue(DUT.getSeedNodeAddresses().contains(new NodeAddress(seed2))); - } -} diff --git a/core/src/test/java/bisq/core/network/p2p/seed/ImmutableSetDecoratorTest.java b/core/src/test/java/bisq/core/network/p2p/seed/ImmutableSetDecoratorTest.java new file mode 100644 index 00000000000..b1cab1649d6 --- /dev/null +++ b/core/src/test/java/bisq/core/network/p2p/seed/ImmutableSetDecoratorTest.java @@ -0,0 +1,65 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.core.network.p2p.seed; + +import com.google.common.collect.Sets; + +import java.util.Set; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +public class ImmutableSetDecoratorTest { + @Test(expected = UnsupportedOperationException.class) + public void testAdd() { + Set original = Sets.newHashSet(1, 2, 3); + Set decorator = new ImmutableSetDecorator<>(original); + decorator.add(4); + } + + @Test(expected = UnsupportedOperationException.class) + public void testRemove() { + Set original = Sets.newHashSet(1, 2, 3); + Set decorator = new ImmutableSetDecorator<>(original); + decorator.remove(3); + } + + @Test(expected = UnsupportedOperationException.class) + public void testClear() { + Set original = Sets.newHashSet(1, 2, 3); + Set decorator = new ImmutableSetDecorator<>(original); + decorator.clear(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testRemoveWithIterator() { + Set original = Sets.newHashSet(1, 2, 3); + Set decorator = new ImmutableSetDecorator<>(original); + decorator.iterator().remove(); + } + + @Test + public void testBackingCollection() { + Set original = Sets.newHashSet(1, 2, 3); + Set decorator = new ImmutableSetDecorator<>(original); + + original.remove(2); + assertTrue(decorator.contains(2)); + } +} diff --git a/core/src/test/java/bisq/core/network/p2p/seed/SeedNodeAddressLookupTest.java b/core/src/test/java/bisq/core/network/p2p/seed/SeedNodeAddressLookupTest.java new file mode 100644 index 00000000000..0ee76ef9686 --- /dev/null +++ b/core/src/test/java/bisq/core/network/p2p/seed/SeedNodeAddressLookupTest.java @@ -0,0 +1,55 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.core.network.p2p.seed; + +import bisq.core.app.BisqEnvironment; + +import bisq.network.p2p.NodeAddress; + +import java.util.Collections; +import java.util.Set; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.mockito.Mockito.mock; + +public class SeedNodeAddressLookupTest { + + + @Test + public void testResolveNodeAddressesWhenLocalAddressSpecified() { + SeedNodeAddressLookup lookup = new SeedNodeAddressLookup( + mock(BisqEnvironment.class), false, 0, "192.168.0.1:1234", + "192.168.0.1:1234, 192.168.0.2:9897"); + + Set actual = lookup.resolveNodeAddresses(); + Set expected = Collections.singleton(new NodeAddress("192.168.0.2:9897")); + assertEquals(expected, actual); + } + + @Test + public void testResolveNodeAddressesWhenSeedNodesAreNull() { + SeedNodeAddressLookup lookup = new SeedNodeAddressLookup( + mock(BisqEnvironment.class), false, 0, "192.168.0.1:1234", null); + + Set actual = lookup.resolveNodeAddresses(); + assertFalse(actual.isEmpty()); + } +} diff --git a/core/src/test/java/bisq/core/network/p2p/seed/SeedNodeAddressesTest.java b/core/src/test/java/bisq/core/network/p2p/seed/SeedNodeAddressesTest.java new file mode 100644 index 00000000000..b036f98faff --- /dev/null +++ b/core/src/test/java/bisq/core/network/p2p/seed/SeedNodeAddressesTest.java @@ -0,0 +1,102 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.core.network.p2p.seed; + +import bisq.network.p2p.NodeAddress; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +import java.security.Security; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class SeedNodeAddressesTest { + + + @Test + public void testCollector() { + List addresses = Lists.newArrayList( + new NodeAddress("192.168.0.1:1111"), + new NodeAddress("192.168.0.1:1111"), + new NodeAddress("192.168.0.2:2222")); + Set expected = new HashSet<>(addresses); + + SeedNodeAddresses actual = addresses.stream() + .collect(SeedNodeAddresses.collector()); + + assertEquals(expected, actual); + } + + @Test + public void testExcludeByFullAddress() { + Set delegate = Sets.newHashSet( + new NodeAddress("192.168.0.1:1111"), + new NodeAddress("192.168.0.2:2222")); + SeedNodeAddresses addresses = new SeedNodeAddresses(delegate); + SeedNodeAddresses actual = addresses.excludeByFullAddress("192.168.0.1:1111"); + + assertEquals(1, actual.size()); + } + + @Test + public void testExcludeByHost() { + Set delegate = Sets.newHashSet( + new NodeAddress("aaa:1111"), + new NodeAddress("aaa:2222"), + new NodeAddress("bbb:1111"), + new NodeAddress("bbb:2222"), + new NodeAddress("ccc:1111"), + new NodeAddress("ccc:2222")); + SeedNodeAddresses addresses = new SeedNodeAddresses(delegate); + + Set hosts = Sets.newHashSet("aaa", "bbb"); + SeedNodeAddresses actual = addresses.excludeByHost(hosts); + + Set expected = Sets.newHashSet( + new NodeAddress("ccc:1111"), + new NodeAddress("ccc:2222")); + + assertEquals(expected, actual); + } + + @Test + public void testFromString() { + Set expected = Sets.newHashSet( + new NodeAddress("192.168.0.1:1111"), + new NodeAddress("192.168.0.2:2222")); + SeedNodeAddresses actual = SeedNodeAddresses.fromString("192.168.0.1:1111, 192.168.0.2:2222"); + assertEquals(expected, actual); + } + + @Test + public void testFromEmptyString() { + SeedNodeAddresses nodeAddresses = SeedNodeAddresses.fromString(""); + assertTrue(nodeAddresses.isEmpty()); + } +} diff --git a/core/src/test/resources/mainnet.seednodes b/core/src/test/resources/mainnet.seednodes deleted file mode 100644 index fede53e55e5..00000000000 --- a/core/src/test/resources/mainnet.seednodes +++ /dev/null @@ -1,9 +0,0 @@ -# nodeaddress.onion:port [(@owner)] -5quyxpxheyvzmb2d.onion:8000 (@miker) -s67qglwhkgkyvr74.onion:8000 (@emzy) -ef5qnzx6znifo3df.onion:8000 (@manfredkarrer) -jhgcy2won7xnslrb.onion:8000 (@manfredkarrer) -3f3cu2yw7u457ztq.onion:8000 (@manfredkarrer) -723ljisnynbtdohi.onion:8000 (@manfredkarrer) -rm7b56wbrcczpjvl.onion:8000 (@manfredkarrer) -fl3mmribyxgrv63c.onion:8000 (@manfredkarrer) diff --git a/core/src/test/resources/regtest.seednodes b/core/src/test/resources/regtest.seednodes deleted file mode 100644 index fb71abcae3e..00000000000 --- a/core/src/test/resources/regtest.seednodes +++ /dev/null @@ -1,10 +0,0 @@ -# For development you need to change that to your local onion addresses -# 1. Run a seed node with prog args: --bitcoinNetwork=regtest --nodePort=8002 --myAddress=rxdkppp3vicnbgqt:8002 --appName=bisq_seed_node_rxdkppp3vicnbgqt.onion_8002 -# 2. Find your local onion address in bisq_seed_node_rxdkppp3vicnbgqt.onion_8002/regtest/tor/hiddenservice/hostname -# 3. Shut down the seed node -# 4. Rename the directory with your local onion address -# 5. Edit here your found onion address (new NodeAddress("YOUR_ONION.onion:8002") - -# nodeaddress.onion:port [(@owner)] -rxdkppp3vicnbgqt.onion:8002 -4ie52dse64kaarxw.onion:8002 diff --git a/core/src/test/resources/testnet.seednodes b/core/src/test/resources/testnet.seednodes deleted file mode 100644 index 77b6af07e63..00000000000 --- a/core/src/test/resources/testnet.seednodes +++ /dev/null @@ -1,7 +0,0 @@ -# nodeaddress.onion:port [(@owner)] -snenz4mea65wigen.onion:8001 -fjr5w4eckjghqtnu.onion:8001 -3d56s6acbi3vk52v.onion:8001 -74w2sttlo4qk6go3.onion:8001 -gtif46mfxirv533z.onion:8001 -jmc5ajqvtnzqaggm.onion:8001 diff --git a/monitor/src/main/java/bisq/monitor/metric/P2PNetworkLoad.java b/monitor/src/main/java/bisq/monitor/metric/P2PNetworkLoad.java index dcc03f1128a..1a5d0ea3078 100644 --- a/monitor/src/main/java/bisq/monitor/metric/P2PNetworkLoad.java +++ b/monitor/src/main/java/bisq/monitor/metric/P2PNetworkLoad.java @@ -32,12 +32,14 @@ import bisq.common.Clock; import bisq.common.app.Capabilities; +import bisq.common.app.Version; import bisq.common.proto.network.NetworkEnvelope; import bisq.common.proto.network.NetworkProtoResolver; import bisq.core.app.BisqEnvironment; import bisq.core.btc.BaseCurrencyNetwork; import bisq.core.btc.BtcOptionKeys; import bisq.core.network.p2p.seed.DefaultSeedNodeRepository; +import bisq.core.network.p2p.seed.SeedNodeAddressLookup; import bisq.core.proto.network.CoreNetworkProtoResolver; import bisq.core.proto.persistable.CorePersistenceProtoResolver; import bisq.monitor.AvailableTor; @@ -160,6 +162,7 @@ protected void execute() { // boot up P2P node File storageDir = torHiddenServiceDir; + String seedNodes = ""; try { BisqEnvironment environment = new BisqEnvironment(new PropertySource("name") { @@ -174,7 +177,8 @@ public String getProperty(String name) { NetworkProtoResolver networkProtoResolver = new CoreNetworkProtoResolver(); CorePersistenceProtoResolver persistenceProtoResolver = new CorePersistenceProtoResolver(null, networkProtoResolver, storageDir); - DefaultSeedNodeRepository seedNodeRepository = new DefaultSeedNodeRepository(environment, null); + DefaultSeedNodeRepository seedNodeRepository = new DefaultSeedNodeRepository( + new SeedNodeAddressLookup(environment, false, Version.getBaseCurrencyNetwork(), null, seedNodes)); PeerManager peerManager = new PeerManager(networkNode, seedNodeRepository, new Clock(), persistenceProtoResolver, maxConnections, storageDir); diff --git a/p2p/src/main/java/bisq/network/p2p/seed/SeedNodeRepository.java b/p2p/src/main/java/bisq/network/p2p/seed/SeedNodeRepository.java index a59807ddb04..c5805af277d 100644 --- a/p2p/src/main/java/bisq/network/p2p/seed/SeedNodeRepository.java +++ b/p2p/src/main/java/bisq/network/p2p/seed/SeedNodeRepository.java @@ -19,11 +19,13 @@ import bisq.network.p2p.NodeAddress; -import java.util.Collection; +import java.util.Set; public interface SeedNodeRepository { boolean isSeedNode(NodeAddress nodeAddress); - Collection getSeedNodeAddresses(); + Set getSeedNodeAddresses(); + + String getOperator(NodeAddress nodeAddress); }