From c1e0524090597bd5213f0fc62a197b7fa1641d68 Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Sun, 10 May 2015 09:17:09 +0200 Subject: [PATCH] Add new bootstrap node servers --- .../app/bootstrap/BootstrapNode.java | 44 ++++++++++++------- .../app/bootstrap/BootstrapNodeMain.java | 7 ++- .../java/io/bitsquare/BitsquareModule.java | 2 - .../bitsquare/app/BitsquareEnvironment.java | 21 +-------- .../java/io/bitsquare/btc/BitcoinNetwork.java | 2 +- .../java/io/bitsquare/btc/RegTestHost.java | 8 ++-- .../java/io/bitsquare/btc/WalletService.java | 6 +-- .../java/io/bitsquare/p2p/BootstrapNodes.java | 38 +++++++++------- .../java/io/bitsquare/p2p/ClientNode.java | 6 ++- core/src/main/java/io/bitsquare/p2p/Node.java | 17 +++++++ .../p2p/tomp2p/BootstrappedPeerBuilder.java | 33 +++++++++++--- .../io/bitsquare/p2p/tomp2p/TomP2PModule.java | 6 +-- .../io/bitsquare/p2p/tomp2p/TomP2PNode.java | 44 +++++++++++++++---- .../io/bitsquare/app/BitsquareAppMain.java | 6 +-- .../java/io/bitsquare/gui/main/MainView.java | 31 ++++++++----- .../io/bitsquare/gui/main/MainViewModel.java | 41 +++++++++++------ .../settings/network/NetworkSettingsView.fxml | 21 ++++++--- .../settings/network/NetworkSettingsView.java | 13 +++++- 18 files changed, 231 insertions(+), 115 deletions(-) diff --git a/bootstrap/src/main/java/io/bitsquare/app/bootstrap/BootstrapNode.java b/bootstrap/src/main/java/io/bitsquare/app/bootstrap/BootstrapNode.java index a1c87b19c7..617b490c33 100644 --- a/bootstrap/src/main/java/io/bitsquare/app/bootstrap/BootstrapNode.java +++ b/bootstrap/src/main/java/io/bitsquare/app/bootstrap/BootstrapNode.java @@ -21,9 +21,12 @@ import io.bitsquare.app.Logging; import io.bitsquare.p2p.BootstrapNodes; import io.bitsquare.p2p.Node; -import net.tomp2p.connection.ChannelClientConfiguration; -import net.tomp2p.connection.ChannelServerConfiguration; +import java.util.Collection; +import java.util.Random; +import java.util.stream.Collectors; + import net.tomp2p.dht.PeerBuilderDHT; +import net.tomp2p.dht.PeerDHT; import net.tomp2p.nat.PeerBuilderNAT; import net.tomp2p.p2p.Peer; import net.tomp2p.p2p.PeerBuilder; @@ -35,7 +38,6 @@ import net.tomp2p.peers.PeerStatistic; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.netty.util.concurrent.DefaultEventExecutorGroup; import org.springframework.core.env.Environment; public class BootstrapNode { @@ -52,26 +54,27 @@ public class BootstrapNode { this.env = env; } + public void start() { - int port = env.getProperty(Node.PORT_KEY, Integer.class, BootstrapNodes.DEFAULT_PORT); - String name = env.getRequiredProperty(Node.NAME_KEY); + int port = env.getProperty(Node.PORT_KEY, Integer.class, BootstrapNodes.PORT); + String name = env.getProperty(Node.NAME_KEY, BootstrapNodes.DEFAULT_NODE_NAME); Logging.setup(name + "_" + port); try { - Number160 peerId = Number160.createHash(name); - + Number160 peerId = Number160.createHash(new Random().nextInt()); +/* DefaultEventExecutorGroup eventExecutorGroup = new DefaultEventExecutorGroup(50); ChannelClientConfiguration clientConf = PeerBuilder.createDefaultChannelClientConfiguration(); clientConf.pipelineFilter(new PeerBuilder.EventExecutorGroupFilter(eventExecutorGroup)); ChannelServerConfiguration serverConf = PeerBuilder.createDefaultChannelServerConfiguration(); serverConf.pipelineFilter(new PeerBuilder.EventExecutorGroupFilter(eventExecutorGroup)); - serverConf.connectionTimeoutTCPMillis(5000); + serverConf.connectionTimeoutTCPMillis(5000);*/ peer = new PeerBuilder(peerId) .ports(port) - .channelClientConfiguration(clientConf) - .channelServerConfiguration(serverConf) + /* .channelClientConfiguration(clientConf) + .channelServerConfiguration(serverConf)*/ .start(); /*peer.objectDataReply((sender, request) -> { @@ -79,14 +82,25 @@ public class BootstrapNode { return "pong"; });*/ - new PeerBuilderDHT(peer).start(); + PeerDHT peerDHT = new PeerBuilderDHT(peer).start(); new PeerBuilderNAT(peer).start(); + if (!name.equals(BootstrapNodes.LOCALHOST.getName())) { + Collection bootstrapNodes = BootstrapNodes.getAllBootstrapNodes().stream().filter(e -> !e.getName().equals(name)) + .map(e -> e.toPeerAddress()).collect(Collectors.toList()); + + log.info("Bootstrapping to " + bootstrapNodes.size() + " bootstrapNode(s)"); + log.info("Bootstrapping bootstrapNodes " + bootstrapNodes); + peer.bootstrap().bootstrapTo(bootstrapNodes).start().awaitUninterruptibly(); + } + else { + log.info("Localhost, no bootstrap"); + } peer.peerBean().peerMap().addPeerMapChangeListener(new PeerMapChangeListener() { @Override public void peerInserted(PeerAddress peerAddress, boolean verified) { try { - log.debug("Peer inserted: peerAddress=" + peerAddress + ", verified=" + verified); + log.info("Peer inserted: peerAddress=" + peerAddress + ", verified=" + verified); } catch (Throwable t) { log.error("Exception at peerInserted " + t.getMessage()); } @@ -95,7 +109,7 @@ public class BootstrapNode { @Override public void peerRemoved(PeerAddress peerAddress, PeerStatistic peerStatistics) { try { - log.debug("Peer removed: peerAddress=" + peerAddress + ", peerStatistics=" + peerStatistics); + log.info("Peer removed: peerAddress=" + peerAddress + ", peerStatistics=" + peerStatistics); } catch (Throwable t) { log.error("Exception at peerRemoved " + t.getMessage()); } @@ -104,7 +118,7 @@ public class BootstrapNode { @Override public void peerUpdated(PeerAddress peerAddress, PeerStatistic peerStatistics) { try { - //log.debug("Peer updated: peerAddress=" + peerAddress + ", peerStatistics=" + peerStatistics); + log.info("Peer updated: peerAddress=" + peerAddress + ", peerStatistics=" + peerStatistics); } catch (Throwable t) { log.error("Exception at peerUpdated " + t.getMessage()); } @@ -130,7 +144,7 @@ public class BootstrapNode { noPeersInfoPrinted = true; } try { - Thread.sleep(10000); + Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); return; diff --git a/bootstrap/src/main/java/io/bitsquare/app/bootstrap/BootstrapNodeMain.java b/bootstrap/src/main/java/io/bitsquare/app/bootstrap/BootstrapNodeMain.java index aef600326c..0d0c416447 100644 --- a/bootstrap/src/main/java/io/bitsquare/app/bootstrap/BootstrapNodeMain.java +++ b/bootstrap/src/main/java/io/bitsquare/app/bootstrap/BootstrapNodeMain.java @@ -32,10 +32,9 @@ public class BootstrapNodeMain extends BitsquareExecutable { } protected void customizeOptionParsing(OptionParser parser) { - parser.accepts(Node.NAME_KEY, description("Name of this node", null)) - .withRequiredArg() - .isRequired(); - parser.accepts(Node.PORT_KEY, description("Port to listen on", BootstrapNodes.DEFAULT_PORT)) + parser.accepts(Node.NAME_KEY, description("Name of this node", BootstrapNodes.DEFAULT_NODE_NAME)) + .withRequiredArg(); + parser.accepts(Node.PORT_KEY, description("Port to listen on", BootstrapNodes.PORT)) .withRequiredArg() .ofType(int.class); } diff --git a/core/src/main/java/io/bitsquare/BitsquareModule.java b/core/src/main/java/io/bitsquare/BitsquareModule.java index 139cd9f01a..9048c51879 100644 --- a/core/src/main/java/io/bitsquare/BitsquareModule.java +++ b/core/src/main/java/io/bitsquare/BitsquareModule.java @@ -43,7 +43,6 @@ public abstract class BitsquareModule extends AbstractModule { protected void install(BitsquareModule module) { super.install(module); - log.trace("install " + module.getClass().getSimpleName()); modules.add(module); } @@ -68,6 +67,5 @@ public abstract class BitsquareModule extends AbstractModule { * @param injector the Injector originally initialized with this module */ protected void doClose(Injector injector) { - log.trace("doClose " + getClass().getSimpleName()); } } diff --git a/core/src/main/java/io/bitsquare/app/BitsquareEnvironment.java b/core/src/main/java/io/bitsquare/app/BitsquareEnvironment.java index fcb263838e..3c0994893d 100644 --- a/core/src/main/java/io/bitsquare/app/BitsquareEnvironment.java +++ b/core/src/main/java/io/bitsquare/app/BitsquareEnvironment.java @@ -19,7 +19,6 @@ package io.bitsquare.app; import io.bitsquare.BitsquareException; import io.bitsquare.btc.BitcoinNetwork; -import io.bitsquare.btc.RegTestHost; import io.bitsquare.btc.UserAgent; import io.bitsquare.btc.WalletService; import io.bitsquare.crypto.KeyStorage; @@ -93,13 +92,8 @@ public class BitsquareEnvironment extends StandardEnvironment { (String) commandLineProperties.getProperty(BitcoinNetwork.KEY) : BitcoinNetwork.DEFAULT.toString(); - String regTestHost = commandLineProperties.containsProperty(RegTestHost.KEY) ? - (String) commandLineProperties.getProperty(RegTestHost.KEY) : - RegTestHost.DEFAULT.toString(); - this.bootstrapNodePort = commandLineProperties.containsProperty(TomP2PModule.BOOTSTRAP_NODE_PORT_KEY) ? - (String) commandLineProperties.getProperty(TomP2PModule.BOOTSTRAP_NODE_PORT_KEY) : - getBootstrapNodePort(BitcoinNetwork.valueOf(bitcoinNetwork), RegTestHost.valueOf(regTestHost)); + (String) commandLineProperties.getProperty(TomP2PModule.BOOTSTRAP_NODE_PORT_KEY) : String.valueOf(BootstrapNodes.PORT); MutablePropertySources propertySources = this.getPropertySources(); propertySources.addFirst(commandLineProperties); @@ -113,19 +107,6 @@ public class BitsquareEnvironment extends StandardEnvironment { } } - private String getBootstrapNodePort(BitcoinNetwork bitcoinNetwork, RegTestHost regTestHost) { - // We use default port 7366 for mainnet, 7367 for testnet and 7368 for regtest - if (bitcoinNetwork == BitcoinNetwork.REGTEST && regTestHost == RegTestHost.DIGITAL_OCEAN_1) { - return String.valueOf(BootstrapNodes.DEFAULT_PORT + 2); - } - else if (bitcoinNetwork == BitcoinNetwork.TESTNET) { - return String.valueOf(BootstrapNodes.DEFAULT_PORT + 1); - } - else { - return String.valueOf(BootstrapNodes.DEFAULT_PORT); - } - } - PropertySource appDirProperties() throws Exception { String location = String.format("file:%s/bitsquare.properties", appDataDir); Resource resource = resourceLoader.getResource(location); diff --git a/core/src/main/java/io/bitsquare/btc/BitcoinNetwork.java b/core/src/main/java/io/bitsquare/btc/BitcoinNetwork.java index b3f6d7261b..152d01db6e 100644 --- a/core/src/main/java/io/bitsquare/btc/BitcoinNetwork.java +++ b/core/src/main/java/io/bitsquare/btc/BitcoinNetwork.java @@ -29,7 +29,7 @@ public enum BitcoinNetwork { REGTEST(RegTestParams.get()); public static final String KEY = "bitcoin.network"; - public static final BitcoinNetwork DEFAULT = REGTEST; + public static final BitcoinNetwork DEFAULT = TESTNET; private final NetworkParameters parameters; diff --git a/core/src/main/java/io/bitsquare/btc/RegTestHost.java b/core/src/main/java/io/bitsquare/btc/RegTestHost.java index 46b217c794..3367c3daf2 100644 --- a/core/src/main/java/io/bitsquare/btc/RegTestHost.java +++ b/core/src/main/java/io/bitsquare/btc/RegTestHost.java @@ -19,9 +19,11 @@ package io.bitsquare.btc; public enum RegTestHost { - LOCALHOST(), - DIGITAL_OCEAN_1(); // 188.226.179.109 + LOCALHOST, + REG_TEST_SERVER; // 188.226.179.109 public static final String KEY = "bitcoin.regtest.host"; - public static final RegTestHost DEFAULT = DIGITAL_OCEAN_1; + public static final RegTestHost DEFAULT = LOCALHOST; + public static final String SERVER_IP = "188.226.179.109"; + } diff --git a/core/src/main/java/io/bitsquare/btc/WalletService.java b/core/src/main/java/io/bitsquare/btc/WalletService.java index ceb533b528..f72bc3fe53 100644 --- a/core/src/main/java/io/bitsquare/btc/WalletService.java +++ b/core/src/main/java/io/bitsquare/btc/WalletService.java @@ -106,7 +106,7 @@ public class WalletService { private final DownloadListener downloadListener = new DownloadListener(); private final WalletEventListener walletEventListener = new BitsquareWalletEventListener(); - private RegTestHost regTestHost; + private final RegTestHost regTestHost; private final TradeWalletService tradeWalletService; private final AddressEntryList addressEntryList; private final NetworkParameters params; @@ -175,9 +175,9 @@ public class WalletService { // Now configure and start the appkit. This will take a second or two - we could show a temporary splash screen // or progress widget to keep the user engaged whilst we initialise, but we don't. if (params == RegTestParams.get()) { - if (regTestHost == RegTestHost.DIGITAL_OCEAN_1) { + if (regTestHost == RegTestHost.REG_TEST_SERVER) { try { - walletAppKit.setPeerNodes(new PeerAddress(InetAddress.getByName("188.226.179.109"), params.getPort())); + walletAppKit.setPeerNodes(new PeerAddress(InetAddress.getByName(RegTestHost.SERVER_IP), params.getPort())); } catch (UnknownHostException e) { throw new RuntimeException(e); } diff --git a/core/src/main/java/io/bitsquare/p2p/BootstrapNodes.java b/core/src/main/java/io/bitsquare/p2p/BootstrapNodes.java index a09f87df83..8effd1634c 100644 --- a/core/src/main/java/io/bitsquare/p2p/BootstrapNodes.java +++ b/core/src/main/java/io/bitsquare/p2p/BootstrapNodes.java @@ -19,30 +19,36 @@ package io.bitsquare.p2p; import java.util.Arrays; import java.util.List; +import java.util.Random; -public interface BootstrapNodes { +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; - int DEFAULT_PORT = 7366; +public class BootstrapNodes { + private static final Logger log = LoggerFactory.getLogger(BootstrapNodes.class); - Node DIGITAL_OCEAN_1 = Node.at("digitalocean1.bitsquare.io", "188.226.179.109", DEFAULT_PORT); + public static final int PORT = 7366; + public static final String DEFAULT_NODE_NAME = "default"; - /** - * Alias to the default bootstrap node. - */ - Node DEFAULT = DIGITAL_OCEAN_1; + private static List bootstrapNodes = Arrays.asList( + Node.at(DEFAULT_NODE_NAME, "188.226.179.109", PORT), + Node.at(DEFAULT_NODE_NAME, "52.24.144.42", PORT), + Node.at(DEFAULT_NODE_NAME, "52.11.125.194", PORT) + ); /** * A locally-running BootstrapNode instance. - * Typically used only for testing. Not included in results from {@link #all()}. + * Typically used only for testing. Not included in results from {@link #getAllBootstrapNodes()}. */ - Node LOCALHOST = Node.at("localhost", "127.0.0.1", DEFAULT_PORT); + public static Node LOCALHOST = Node.at("localhost", "127.0.0.1", PORT); - /** - * All known public bootstrap nodes. - */ - static List all() { - return Arrays.asList( - DIGITAL_OCEAN_1 - ); + private static Node selectedNode = bootstrapNodes.get(new Random().nextInt(bootstrapNodes.size())); + + public static List getAllBootstrapNodes() { + return bootstrapNodes; + } + + public static Node getSelectedNode() { + return selectedNode; } } diff --git a/core/src/main/java/io/bitsquare/p2p/ClientNode.java b/core/src/main/java/io/bitsquare/p2p/ClientNode.java index 2b13a3b829..b4e0e3b045 100644 --- a/core/src/main/java/io/bitsquare/p2p/ClientNode.java +++ b/core/src/main/java/io/bitsquare/p2p/ClientNode.java @@ -21,6 +21,8 @@ import io.bitsquare.p2p.tomp2p.BootstrappedPeerBuilder; import java.security.KeyPair; +import java.util.concurrent.Executor; + import javafx.beans.property.ReadOnlyIntegerProperty; import rx.Observable; @@ -32,7 +34,9 @@ public interface ClientNode { Node getBootstrapNodeAddress(); - Observable bootstrap(KeyPair keyPair); + Observable bootstrap(int networkId, KeyPair keyPair); ReadOnlyIntegerProperty numPeersProperty(); + + void setExecutor(Executor executor); } diff --git a/core/src/main/java/io/bitsquare/p2p/Node.java b/core/src/main/java/io/bitsquare/p2p/Node.java index 29b145500d..84998410b5 100644 --- a/core/src/main/java/io/bitsquare/p2p/Node.java +++ b/core/src/main/java/io/bitsquare/p2p/Node.java @@ -21,7 +21,12 @@ import com.google.common.base.Objects; import java.io.IOException; +import java.net.InetAddress; import java.net.ServerSocket; +import java.net.UnknownHostException; + +import net.tomp2p.peers.Number160; +import net.tomp2p.peers.PeerAddress; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -89,6 +94,18 @@ public final class Node { return port; } + public PeerAddress toPeerAddress() { + try { + return new PeerAddress(Number160.createHash(getName()), + InetAddress.getByName(getIp()), + getPort(), + getPort()); + } catch (UnknownHostException e) { + log.error("toPeerAddress failed: " + e.getMessage()); + return null; + } + } + @Override public boolean equals(Object object) { if (this == object) diff --git a/core/src/main/java/io/bitsquare/p2p/tomp2p/BootstrappedPeerBuilder.java b/core/src/main/java/io/bitsquare/p2p/tomp2p/BootstrappedPeerBuilder.java index f43c216dd3..66aedcc639 100644 --- a/core/src/main/java/io/bitsquare/p2p/tomp2p/BootstrappedPeerBuilder.java +++ b/core/src/main/java/io/bitsquare/p2p/tomp2p/BootstrappedPeerBuilder.java @@ -17,6 +17,7 @@ package io.bitsquare.p2p.tomp2p; +import io.bitsquare.p2p.BootstrapNodes; import io.bitsquare.p2p.Node; import com.google.common.util.concurrent.SettableFuture; @@ -30,6 +31,9 @@ import java.net.UnknownHostException; import java.security.KeyPair; +import java.util.Optional; +import java.util.concurrent.Executor; + import javax.inject.Inject; import javafx.beans.property.ObjectProperty; @@ -113,7 +117,7 @@ public class BootstrappedPeerBuilder { private KeyPair keyPair; private final int port; private final boolean useManualPortForwarding; - private final Node bootstrapNode; + private Node bootstrapNode; private final String networkInterface; private final SettableFuture settableFuture = SettableFuture.create(); @@ -123,6 +127,8 @@ public class BootstrappedPeerBuilder { private Peer peer; private PeerDHT peerDHT; + private boolean retriedOtherBootstrapNode; + private Executor executor; /////////////////////////////////////////////////////////////////////////////////////////// @@ -156,7 +162,11 @@ public class BootstrappedPeerBuilder { // Public methods /////////////////////////////////////////////////////////////////////////////////////////// - public SettableFuture start() { + public void setExecutor(Executor executor) { + this.executor = executor; + } + + public SettableFuture start(int networkId) { try { DefaultEventExecutorGroup eventExecutorGroup = new DefaultEventExecutorGroup(20); ChannelClientConfiguration clientConf = PeerBuilder.createDefaultChannelClientConfiguration(); @@ -172,6 +182,7 @@ public class BootstrappedPeerBuilder { if (useManualPortForwarding) { peer = new PeerBuilder(keyPair) + .p2pId(networkId) .channelClientConfiguration(clientConf) .channelServerConfiguration(serverConf) .ports(port) @@ -182,6 +193,7 @@ public class BootstrappedPeerBuilder { } else { peer = new PeerBuilder(keyPair) + .p2pId(networkId) .channelClientConfiguration(clientConf) .channelServerConfiguration(serverConf) .ports(port) @@ -274,9 +286,20 @@ public class BootstrappedPeerBuilder { bootstrap(); } else { - // All attempts failed. Give up... - handleError(State.RELAY_FAILED, "NAT traversal using relay mode failed " + - futureRelayNAT.failedReason()); + if (!retriedOtherBootstrapNode && BootstrapNodes.getAllBootstrapNodes().size() > 1) { + log.warn("Bootstrap failed with bootstrapNode: " + bootstrapNode + ". We try again with another node."); + retriedOtherBootstrapNode = true; + Optional optional = BootstrapNodes.getAllBootstrapNodes().stream().filter(e -> !e.equals(bootstrapNode)).findAny(); + if (optional.isPresent()) { + bootstrapNode = optional.get(); + executor.execute(() -> discoverExternalAddress()); + } + } + else { + // All attempts failed. Give up... + handleError(State.RELAY_FAILED, "NAT traversal using relay mode failed " + + futureRelayNAT.failedReason()); + } } } } diff --git a/core/src/main/java/io/bitsquare/p2p/tomp2p/TomP2PModule.java b/core/src/main/java/io/bitsquare/p2p/tomp2p/TomP2PModule.java index 6d0fbfd219..10004de9a6 100644 --- a/core/src/main/java/io/bitsquare/p2p/tomp2p/TomP2PModule.java +++ b/core/src/main/java/io/bitsquare/p2p/tomp2p/TomP2PModule.java @@ -65,9 +65,9 @@ public class TomP2PModule extends P2PModule { env.getProperty(USE_MANUAL_PORT_FORWARDING_KEY, boolean.class, false)); bind(Node.class).annotatedWith(Names.named(BOOTSTRAP_NODE_KEY)).toInstance( - Node.at(env.getProperty(BOOTSTRAP_NODE_NAME_KEY, BootstrapNodes.DEFAULT.getName()), - env.getProperty(BOOTSTRAP_NODE_IP_KEY, BootstrapNodes.DEFAULT.getIp()), - env.getProperty(BOOTSTRAP_NODE_PORT_KEY, int.class, BootstrapNodes.DEFAULT.getPort()) + Node.at(env.getProperty(BOOTSTRAP_NODE_NAME_KEY, BootstrapNodes.getSelectedNode().getName()), + env.getProperty(BOOTSTRAP_NODE_IP_KEY, BootstrapNodes.getSelectedNode().getIp()), + env.getProperty(BOOTSTRAP_NODE_PORT_KEY, int.class, BootstrapNodes.getSelectedNode().getPort()) ) ); bindConstant().annotatedWith(Names.named(NETWORK_INTERFACE_KEY)).to(env.getProperty(NETWORK_INTERFACE_KEY, NETWORK_INTERFACE_UNSPECIFIED)); diff --git a/core/src/main/java/io/bitsquare/p2p/tomp2p/TomP2PNode.java b/core/src/main/java/io/bitsquare/p2p/tomp2p/TomP2PNode.java index e7750b3717..4bf2b57d94 100644 --- a/core/src/main/java/io/bitsquare/p2p/tomp2p/TomP2PNode.java +++ b/core/src/main/java/io/bitsquare/p2p/tomp2p/TomP2PNode.java @@ -31,6 +31,7 @@ import java.security.KeyPair; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.Executor; import javax.annotation.Nullable; @@ -40,12 +41,10 @@ import javafx.beans.property.IntegerProperty; import javafx.beans.property.ReadOnlyIntegerProperty; import javafx.beans.property.SimpleIntegerProperty; -import net.tomp2p.connection.PeerConnection; -import net.tomp2p.connection.PeerException; import net.tomp2p.dht.PeerDHT; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerStatusListener; -import net.tomp2p.peers.RTT; +import net.tomp2p.peers.PeerMapChangeListener; +import net.tomp2p.peers.PeerStatistic; import org.jetbrains.annotations.NotNull; @@ -88,7 +87,11 @@ public class TomP2PNode implements ClientNode { // Public methods /////////////////////////////////////////////////////////////////////////////////////////// - public Observable bootstrap(KeyPair keyPair) { + public void setExecutor(Executor executor) { + bootstrappedPeerBuilder.setExecutor(executor); + } + + public Observable bootstrap(int networkId, KeyPair keyPair) { bootstrappedPeerBuilder.setKeyPair(keyPair); bootstrappedPeerBuilder.getState().addListener((ov, oldValue, newValue) -> { @@ -96,14 +99,39 @@ public class TomP2PNode implements ClientNode { bootstrapStateSubject.onNext(newValue); }); - SettableFuture bootstrapFuture = bootstrappedPeerBuilder.start(); + SettableFuture bootstrapFuture = bootstrappedPeerBuilder.start(networkId); Futures.addCallback(bootstrapFuture, new FutureCallback() { @Override public void onSuccess(@Nullable PeerDHT peerDHT) { if (peerDHT != null) { TomP2PNode.this.peerDHT = peerDHT; - peerDHT.peerBean().addPeerStatusListener(new PeerStatusListener() { + BaseP2PService.getUserThread().execute(() -> numPeers.set(peerDHT.peerBean().peerMap().all().size())); + log.debug("Number of peers = " + peerDHT.peerBean().peerMap().all().size()); + + peerDHT.peerBean().peerMap().addPeerMapChangeListener(new PeerMapChangeListener() { + @Override + public void peerInserted(PeerAddress peerAddress, boolean b) { + BaseP2PService.getUserThread().execute(() -> numPeers.set(peerDHT.peerBean().peerMap().all().size())); + log.debug("peerInserted " + peerAddress); + log.debug("Number of peers = " + peerDHT.peerBean().peerMap().all().size()); + } + + @Override + public void peerRemoved(PeerAddress peerAddress, PeerStatistic peerStatistic) { + BaseP2PService.getUserThread().execute(() -> numPeers.set(peerDHT.peerBean().peerMap().all().size())); + log.debug("peerRemoved " + peerAddress); + log.debug("Number of peers = " + peerDHT.peerBean().peerMap().all().size()); + } + + @Override + public void peerUpdated(PeerAddress peerAddress, PeerStatistic peerStatistic) { + BaseP2PService.getUserThread().execute(() -> numPeers.set(peerDHT.peerBean().peerMap().all().size())); + log.debug("peerUpdated " + peerAddress); + log.debug("Number of peers = " + peerDHT.peerBean().peerMap().all().size()); + } + }); + /* peerDHT.peerBean().addPeerStatusListener(new PeerStatusListener() { @Override public boolean peerFailed(PeerAddress peerAddress, PeerException e) { return false; @@ -114,7 +142,7 @@ public class TomP2PNode implements ClientNode { BaseP2PService.getUserThread().execute(() -> numPeers.set(peerDHT.peerBean().peerMap().size())); return false; } - }); + });*/ resultHandlers.stream().forEach(ResultHandler::handleResult); bootstrapStateSubject.onCompleted(); diff --git a/gui/src/main/java/io/bitsquare/app/BitsquareAppMain.java b/gui/src/main/java/io/bitsquare/app/BitsquareAppMain.java index 829d988554..1e1e8298b1 100644 --- a/gui/src/main/java/io/bitsquare/app/BitsquareAppMain.java +++ b/gui/src/main/java/io/bitsquare/app/BitsquareAppMain.java @@ -134,11 +134,11 @@ public class BitsquareAppMain extends BitsquareExecutable { .withValuesConvertedBy(new EnumValueConverter(RegTestHost.class)); - parser.accepts(BOOTSTRAP_NODE_NAME_KEY, description("", BootstrapNodes.DEFAULT.getName())) + parser.accepts(BOOTSTRAP_NODE_NAME_KEY, description("", BootstrapNodes.getSelectedNode().getName())) .withRequiredArg(); - parser.accepts(BOOTSTRAP_NODE_IP_KEY, description("", BootstrapNodes.DEFAULT.getIp())) + parser.accepts(BOOTSTRAP_NODE_IP_KEY, description("", BootstrapNodes.getSelectedNode().getIp())) .withRequiredArg(); - parser.accepts(BOOTSTRAP_NODE_PORT_KEY, description("", BootstrapNodes.DEFAULT.getPort())) + parser.accepts(BOOTSTRAP_NODE_PORT_KEY, description("", BootstrapNodes.getSelectedNode().getPort())) .withRequiredArg() .ofType(int.class); parser.accepts(NETWORK_INTERFACE_KEY, description("Network interface", null)) diff --git a/gui/src/main/java/io/bitsquare/gui/main/MainView.java b/gui/src/main/java/io/bitsquare/gui/main/MainView.java index f701023661..070b964ba5 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/MainView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/MainView.java @@ -360,10 +360,15 @@ public class MainView extends InitializableView { bitcoinNetworkLabel.setText(model.bitcoinNetworkAsString); model.walletServiceErrorMsg.addListener((ov, oldValue, newValue) -> { - bitcoinNetworkLabel.setId("splash-error-state-msg"); - bitcoinNetworkLabel.textProperty().unbind(); - bitcoinNetworkLabel.setText("Not connected"); - openBTCConnectionErrorPopup(newValue); + if (newValue != null) { + bitcoinNetworkLabel.setId("splash-error-state-msg"); + bitcoinNetworkLabel.setText("Not connected"); + openBTCConnectionErrorPopup(newValue); + } + else { + bitcoinNetworkLabel.setId("footer-bitcoin-network-label"); + bitcoinNetworkLabel.setText(model.bitcoinNetworkAsString); + } }); model.blockchainSyncProgress.addListener((ov, oldValue, newValue) -> { @@ -412,11 +417,17 @@ public class MainView extends InitializableView { setBottomAnchor(numPeersLabel, 7d); numPeersLabel.textProperty().bind(model.numDHTPeers); model.bootstrapErrorMsg.addListener((ov, oldValue, newValue) -> { - bootstrapLabel.setId("splash-error-state-msg"); - bootstrapLabel.textProperty().unbind(); - bootstrapLabel.setText("Not connected"); - Popups.openErrorPopup("Error", "Connecting to the P2P network failed. \n" + newValue - + "\nPlease check our internet connection."); + if (newValue != null) { + bootstrapLabel.setId("splash-error-state-msg"); + bootstrapLabel.textProperty().unbind(); + bootstrapLabel.setText("Not connected"); + Popups.openErrorPopup("Error", "Connecting to the P2P network failed. \n" + newValue + + "\nPlease check your internet connection."); + } + else { + bootstrapLabel.setId("footer-pane"); + bootstrapLabel.textProperty().bind(model.bootstrapInfoFooter); + } }); AnchorPane footerContainer = new AnchorPane(separator, blockchainSyncBox, versionLabel, bootstrapLabel, bootstrapIcon, numPeersLabel) {{ @@ -549,6 +560,6 @@ public class MainView extends InitializableView { private void openBTCConnectionErrorPopup(String errorMsg) { Popups.openErrorPopup("Error", "Connecting to the bitcoin network failed. \n" + errorMsg - + "\nPlease check our internet connection."); + + "\nPlease check your internet connection."); } } \ No newline at end of file diff --git a/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java b/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java index 1b629ba77b..cfa5227f28 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java @@ -36,6 +36,8 @@ import io.bitsquare.trade.offer.OpenOfferManager; import io.bitsquare.user.User; import io.bitsquare.util.Utilities; +import org.bitcoinj.store.BlockStoreException; + import com.google.inject.Inject; import java.util.Timer; @@ -65,6 +67,17 @@ class MainViewModel implements ViewModel { private static final long BLOCKCHAIN_SYNC_TIMEOUT = 30000; private static final long LOST_CONNECTION_TIMEOUT = 10000; + private final User user; + private final KeyRing keyRing; + private final WalletService walletService; + private final ArbitrationRepository arbitrationRepository; + private final ClientNode clientNode; + private final TradeManager tradeManager; + private final OpenOfferManager openOfferManager; + private final UpdateProcess updateProcess; + private final BSFormatter formatter; + private final int networkId; + // BTC network final StringProperty blockchainSyncInfo = new SimpleStringProperty("Initializing"); final StringProperty blockchainSyncInfoFooter = new SimpleStringProperty("Initializing"); @@ -98,15 +111,6 @@ class MainViewModel implements ViewModel { final String bitcoinNetworkAsString; - private final User user; - private KeyRing keyRing; - private final WalletService walletService; - private final ArbitrationRepository arbitrationRepository; - private final ClientNode clientNode; - private final TradeManager tradeManager; - private OpenOfferManager openOfferManager; - private final UpdateProcess updateProcess; - private final BSFormatter formatter; private Timer blockchainSyncTimeoutTimer; private Timer lostConnectionTimeoutTimer; @@ -126,6 +130,7 @@ class MainViewModel implements ViewModel { this.formatter = formatter; bitcoinNetworkAsString = formatter.formatBitcoinNetwork(bitcoinNetwork); + networkId = bitcoinNetwork.ordinal(); updateProcess.state.addListener((observableValue, oldValue, newValue) -> applyUpdateState(newValue)); applyUpdateState(updateProcess.state.get()); @@ -146,7 +151,8 @@ class MainViewModel implements ViewModel { public void initBackend() { Platform.runLater(updateProcess::init); - startBlockchainSyncTimeout(); + if (walletService.downloadPercentageProperty().get() > -1) + startBlockchainSyncTimeout(); walletService.downloadPercentageProperty().addListener((ov, oldValue, newValue) -> { setBitcoinNetworkSyncProgress((double) newValue); @@ -155,9 +161,10 @@ class MainViewModel implements ViewModel { walletService.numPeersProperty().addListener((observable, oldValue, newValue) -> { numBTCPeers.set(String.valueOf(newValue) + " peers"); - if ((int) newValue < 1) { + if ((int) newValue < 1) walletServiceErrorMsg.set("We lost connection to the last peer."); - } + else + walletServiceErrorMsg.set(null); }); // Set executor for all P2PServices @@ -178,10 +185,12 @@ class MainViewModel implements ViewModel { lostConnectionTimeoutTimer.cancel(); lostConnectionTimeoutTimer = null; } + bootstrapErrorMsg.set(null); } }); - Observable bootstrapStateAsObservable = clientNode.bootstrap(keyRing.getDhtSignatureKeyPair()); + clientNode.setExecutor(Platform::runLater); + Observable bootstrapStateAsObservable = clientNode.bootstrap(networkId, keyRing.getDhtSignatureKeyPair()); bootstrapStateAsObservable.publish(); bootstrapStateAsObservable.subscribe( state -> Platform.runLater(() -> setBootstrapState(state)), @@ -229,6 +238,7 @@ class MainViewModel implements ViewModel { private void onAllServicesInitialized() { log.trace("backend completed"); + setBitcoinNetworkSyncProgress(walletService.downloadPercentageProperty().get()); tradeManager.getPendingTrades().addListener((ListChangeListener) change -> updateNumPendingTrades()); updateNumPendingTrades(); showAppScreen.set(true); @@ -321,6 +331,9 @@ class MainViewModel implements ViewModel { "You must allow outgoing TCP connections to port 18333 for the bitcoin testnet.\n\n" + "See https://github.com/bitsquare/bitsquare/wiki for instructions."); } + else if (error.getCause() instanceof BlockStoreException) { + walletServiceErrorMsg.set("You cannot run 2 instances of the program."); + } else if (error.getMessage() != null) { walletServiceErrorMsg.set(error.getMessage()); } @@ -365,6 +378,8 @@ class MainViewModel implements ViewModel { private void setBitcoinNetworkSyncProgress(double value) { blockchainSyncProgress.set(value); if (value >= 1) { + stopBlockchainSyncTimeout(); + blockchainSyncInfo.set("Blockchain synchronization complete."); blockchainSyncIconId.set("image-connection-synced"); } diff --git a/gui/src/main/java/io/bitsquare/gui/main/settings/network/NetworkSettingsView.fxml b/gui/src/main/java/io/bitsquare/gui/main/settings/network/NetworkSettingsView.fxml index e3b39b7527..20c1c836d0 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/settings/network/NetworkSettingsView.fxml +++ b/gui/src/main/java/io/bitsquare/gui/main/settings/network/NetworkSettingsView.fxml @@ -45,20 +45,29 @@ -