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 8c5552abcd..8a8f53e0fe 100644 --- a/bootstrap/src/main/java/io/bitsquare/app/bootstrap/BootstrapNode.java +++ b/bootstrap/src/main/java/io/bitsquare/app/bootstrap/BootstrapNode.java @@ -18,14 +18,16 @@ package io.bitsquare.app.bootstrap; import io.bitsquare.app.Logging; +import io.bitsquare.app.Version; import io.bitsquare.p2p.BootstrapNodes; import io.bitsquare.p2p.Node; -import java.util.Collection; +import java.util.List; import java.util.stream.Collectors; +import net.tomp2p.connection.ChannelClientConfiguration; +import net.tomp2p.connection.ChannelServerConfiguration; 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; @@ -37,13 +39,12 @@ 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 { private static final Logger log = LoggerFactory.getLogger(BootstrapNode.class); - private static final String VERSION = "0.1.3"; - private static Peer peer = null; private final Environment env; @@ -53,29 +54,31 @@ public class BootstrapNode { this.env = env; } - public void start() { - String name = env.getProperty(Node.NAME_KEY, BootstrapNodes.getLocalhostNode().getName()); - int p2pId = env.getProperty(Node.P2P_ID_KEY, Integer.class, BootstrapNodes.getLocalhostNode().getP2pId()); - int port = env.getProperty(Node.PORT_KEY, Integer.class, BootstrapNodes.getLocalhostNode().getPort()); + BootstrapNodes bootstrapNodes = new BootstrapNodes(); + int p2pId = env.getProperty(Node.P2P_ID_KEY, Integer.class, Node.REG_TEST_P2P_ID); // use regtest as default + bootstrapNodes.initWithNetworkId(p2pId); + String name = env.getProperty(Node.NAME_KEY, bootstrapNodes.getLocalhostNode().getName()); + int port = env.getProperty(Node.PORT_KEY, Integer.class, bootstrapNodes.getLocalhostNode().getPort()); + Logging.setup(name + "_" + port); try { Number160 peerId = Number160.createHash(name); -/* + 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) .p2pId(p2pId) - /* .channelClientConfiguration(clientConf) - .channelServerConfiguration(serverConf)*/ + .channelClientConfiguration(clientConf) + .channelServerConfiguration(serverConf) .start(); /*peer.objectDataReply((sender, request) -> { @@ -83,62 +86,49 @@ public class BootstrapNode { return "pong"; });*/ - PeerDHT peerDHT = new PeerBuilderDHT(peer).start(); + new PeerBuilderDHT(peer).start(); new PeerBuilderNAT(peer).start(); final int _port = port; - if (!name.equals(BootstrapNodes.getLocalhostNode().getName())) { - Collection bootstrapNodes = BootstrapNodes.getAllBootstrapNodes(p2pId).stream().filter(e -> !e.getName().equals(name)) + if (!name.equals(bootstrapNodes.getLocalhostNode().getName())) { + List bootstrapNodesExcludingMyself = bootstrapNodes.getBootstrapNodes().stream().filter(e -> !e.getName().equals + (name)).collect(Collectors.toList()); + log.info("Bootstrapping to bootstrapNodes " + bootstrapNodesExcludingMyself); + long ts = System.currentTimeMillis(); + List bootstrapAddressesExcludingMyself = bootstrapNodesExcludingMyself.stream() .map(e -> e.toPeerAddressWithPort(_port)).collect(Collectors.toList()); - - log.info("Bootstrapping to " + bootstrapNodes.size() + " bootstrapNode(s)"); - log.info("Bootstrapping bootstrapNodes " + bootstrapNodes); - peer.bootstrap().bootstrapTo(bootstrapNodes).start().awaitUninterruptibly(); + peer.bootstrap().bootstrapTo(bootstrapAddressesExcludingMyself).start().awaitUninterruptibly(); + log.info("Bootstrapping done after {} msec", System.currentTimeMillis() - ts); } else { - log.info("We are localhost, we do not bootstrap to other nodes"); + log.info("When using localhost we do not bootstrap to other nodes"); } peer.peerBean().peerMap().addPeerMapChangeListener(new PeerMapChangeListener() { @Override public void peerInserted(PeerAddress peerAddress, boolean verified) { - try { - log.info("Peer inserted: peerAddress=" + peerAddress + ", verified=" + verified); - } catch (Throwable t) { - log.error("Exception at peerInserted " + t.getMessage()); - } + log.info("Peer inserted: peerAddress=" + peerAddress + ", verified=" + verified); } @Override public void peerRemoved(PeerAddress peerAddress, PeerStatistic peerStatistics) { - try { - log.info("Peer removed: peerAddress=" + peerAddress + ", peerStatistics=" + peerStatistics); - } catch (Throwable t) { - log.error("Exception at peerRemoved " + t.getMessage()); - } + log.info("Peer removed: peerAddress=" + peerAddress + ", peerStatistics=" + peerStatistics); } @Override public void peerUpdated(PeerAddress peerAddress, PeerStatistic peerStatistics) { - try { - //log.info("Peer updated: peerAddress=" + peerAddress + ", peerStatistics=" + peerStatistics); - } catch (Throwable t) { - log.error("Exception at peerUpdated " + t.getMessage()); - } + //log.info("Peer updated: peerAddress=" + peerAddress + ", peerStatistics=" + peerStatistics); } }); - log.info("Bootstrap node started with name=" + name + " ,p2pId=" + p2pId + " ,port=" + port + " and version=" + VERSION); + log.info("Bootstrap node started with name=" + name + " ,p2pId=" + p2pId + " ,port=" + port + + " and network protocol version=" + Version.NETWORK_PROTOCOL_VERSION); new Thread(() -> { while (true) { if (peer.peerBean().peerMap().all().size() > 0) { noPeersInfoPrinted = false; - try { - log.info("Number of peers online = " + peer.peerBean().peerMap().all().size()); - for (PeerAddress peerAddress : peer.peerBean().peerMap().all()) { - log.info("Peer: " + peerAddress.toString()); - } - } catch (Throwable t) { - log.error("Exception at run loop " + t.getMessage()); + log.info("Number of peers online = " + peer.peerBean().peerMap().all().size()); + for (PeerAddress peerAddress : peer.peerBean().peerMap().all()) { + log.info("Peer: " + peerAddress.toString()); } } else if (noPeersInfoPrinted) { @@ -146,7 +136,7 @@ public class BootstrapNode { noPeersInfoPrinted = true; } try { - Thread.sleep(2000); + Thread.sleep(10000); } 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 438c4141a6..5f50cde526 100644 --- a/bootstrap/src/main/java/io/bitsquare/app/bootstrap/BootstrapNodeMain.java +++ b/bootstrap/src/main/java/io/bitsquare/app/bootstrap/BootstrapNodeMain.java @@ -32,14 +32,16 @@ public class BootstrapNodeMain extends BitsquareExecutable { } protected void customizeOptionParsing(OptionParser parser) { - parser.accepts(Node.NAME_KEY, description("Name of this node", BootstrapNodes.getLocalhostNode().getName())) + BootstrapNodes bootstrapNodes = new BootstrapNodes(); + bootstrapNodes.initWithNetworkId(Node.REG_TEST_P2P_ID); // use regtest as default + parser.accepts(Node.NAME_KEY, description("Name of this node", bootstrapNodes.getLocalhostNode().getName())) .withRequiredArg() .ofType(String.class); parser.accepts(Node.P2P_ID_KEY, description("P2P network ID", - BootstrapNodes.getLocalhostNode().getP2pId())) + bootstrapNodes.getLocalhostNode().getP2pId())) .withRequiredArg() .ofType(int.class); - parser.accepts(Node.PORT_KEY, description("Port to listen on", BootstrapNodes.getLocalhostNode().getPort())) + parser.accepts(Node.PORT_KEY, description("Port to listen on", bootstrapNodes.getLocalhostNode().getPort())) .withRequiredArg() .ofType(int.class); } diff --git a/core/src/main/java/io/bitsquare/app/BitsquareEnvironment.java b/core/src/main/java/io/bitsquare/app/BitsquareEnvironment.java index 9d6cc6ed59..4193d266ba 100644 --- a/core/src/main/java/io/bitsquare/app/BitsquareEnvironment.java +++ b/core/src/main/java/io/bitsquare/app/BitsquareEnvironment.java @@ -18,6 +18,7 @@ package io.bitsquare.app; import io.bitsquare.BitsquareException; +import io.bitsquare.btc.BitcoinNetwork; import io.bitsquare.btc.UserAgent; import io.bitsquare.btc.WalletService; import io.bitsquare.crypto.KeyStorage; @@ -26,10 +27,19 @@ import io.bitsquare.storage.Storage; import io.bitsquare.util.Utilities; import io.bitsquare.util.spring.JOptCommandLinePropertySource; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + import java.nio.file.Paths; import java.util.Properties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import joptsimple.OptionSet; import org.springframework.core.env.MutablePropertySources; import org.springframework.core.env.PropertiesPropertySource; @@ -43,7 +53,9 @@ import org.springframework.core.io.support.ResourcePropertySource; import static com.google.common.base.Preconditions.checkNotNull; public class BitsquareEnvironment extends StandardEnvironment { + private static final Logger log = LoggerFactory.getLogger(BitsquareEnvironment.class); + private static final String BITCOIN_NETWORK_PROP = "bitcoinNetwork.properties"; public static final String USER_DATA_DIR_KEY = "user.data.dir"; public static final String DEFAULT_USER_DATA_DIR = defaultUserDataDir(); @@ -52,7 +64,7 @@ public class BitsquareEnvironment extends StandardEnvironment { public static final String DEFAULT_APP_NAME = "Bitsquare"; public static final String APP_DATA_DIR_KEY = "app.data.dir"; - public static final String DEFAULT_APP_DATA_DIR = appDataDir(DEFAULT_USER_DATA_DIR, DEFAULT_APP_NAME); + public static final String DEFAULT_APP_DATA_DIR = appDataDir(DEFAULT_USER_DATA_DIR, DEFAULT_APP_NAME, BitcoinNetwork.DEFAULT, Version.VERSION); public static final String APP_DATA_DIR_CLEAN_KEY = "app.data.dir.clean"; public static final String DEFAULT_APP_DATA_DIR_CLEAN = "false"; @@ -60,12 +72,13 @@ public class BitsquareEnvironment extends StandardEnvironment { static final String BITSQUARE_COMMANDLINE_PROPERTY_SOURCE_NAME = "bitsquareCommandLineProperties"; static final String BITSQUARE_APP_DIR_PROPERTY_SOURCE_NAME = "bitsquareAppDirProperties"; static final String BITSQUARE_HOME_DIR_PROPERTY_SOURCE_NAME = "bitsquareHomeDirProperties"; - static final String BITSQUARE_CLASSPATH_PROPERTY_SOURCE_NAME = "bitsquareClasspathProperties"; + public static final String BITSQUARE_CLASSPATH_PROPERTY_SOURCE_NAME = "bitsquareClasspathProperties"; static final String BITSQUARE_DEFAULT_PROPERTY_SOURCE_NAME = "bitsquareDefaultProperties"; private final ResourceLoader resourceLoader = new DefaultResourceLoader(); protected final String appName; + protected final String userDataDir; protected final String appDataDir; protected final String bootstrapNodePort; @@ -73,20 +86,60 @@ public class BitsquareEnvironment extends StandardEnvironment { this(new JOptCommandLinePropertySource(BITSQUARE_COMMANDLINE_PROPERTY_SOURCE_NAME, checkNotNull(options))); } + public BitcoinNetwork getBtcNetworkProperty() { + String dirString = Paths.get(userDataDir, appName, Version.VERSION).toString(); + String fileString = Paths.get(dirString, BITCOIN_NETWORK_PROP).toString(); + File dir = new File(dirString); + File file = new File(fileString); + if (!dir.exists()) + dir.mkdirs(); + + if (!file.exists()) { + try { + file.createNewFile(); + } catch (Throwable e) { + log.error(e.getMessage()); + } + } + try (InputStream fileInputStream = new FileInputStream(file)) { + Properties properties = new Properties(); + properties.load(fileInputStream); + String bitcoinNetwork = properties.getProperty("bitcoinNetwork", BitcoinNetwork.DEFAULT.name()); + return BitcoinNetwork.valueOf(bitcoinNetwork); + } catch (Throwable e) { + e.printStackTrace(); + log.error(e.getMessage()); + return BitcoinNetwork.DEFAULT; + } + } + + public void setBitcoinNetwork(BitcoinNetwork bitcoinNetwork) { + String path = Paths.get(userDataDir, appName, Version.VERSION, BITCOIN_NETWORK_PROP).toString(); + File file = new File(path); + try (FileOutputStream fos = new FileOutputStream(file)) { + Properties properties = new Properties(); + properties.setProperty("bitcoinNetwork", bitcoinNetwork.name()); + properties.store(fos, null); + } catch (IOException e) { + e.printStackTrace(); + log.error(e.getMessage()); + } + } + protected BitsquareEnvironment(PropertySource commandLineProperties) { - String userDataDir = commandLineProperties.containsProperty(USER_DATA_DIR_KEY) ? + userDataDir = commandLineProperties.containsProperty(USER_DATA_DIR_KEY) ? (String) commandLineProperties.getProperty(USER_DATA_DIR_KEY) : DEFAULT_USER_DATA_DIR; - this.appName = commandLineProperties.containsProperty(APP_NAME_KEY) ? + appName = commandLineProperties.containsProperty(APP_NAME_KEY) ? (String) commandLineProperties.getProperty(APP_NAME_KEY) : DEFAULT_APP_NAME; - this.appDataDir = commandLineProperties.containsProperty(APP_DATA_DIR_KEY) ? + appDataDir = commandLineProperties.containsProperty(APP_DATA_DIR_KEY) ? (String) commandLineProperties.getProperty(APP_DATA_DIR_KEY) : - appDataDir(userDataDir, appName); + appDataDir(userDataDir, appName, getBtcNetworkProperty(), Version.VERSION); - this.bootstrapNodePort = commandLineProperties.containsProperty(TomP2PModule.BOOTSTRAP_NODE_PORT_KEY) ? + bootstrapNodePort = commandLineProperties.containsProperty(TomP2PModule.BOOTSTRAP_NODE_PORT_KEY) ? (String) commandLineProperties.getProperty(TomP2PModule.BOOTSTRAP_NODE_PORT_KEY) : "-1"; MutablePropertySources propertySources = this.getPropertySources(); @@ -129,7 +182,6 @@ public class BitsquareEnvironment extends StandardEnvironment { protected PropertySource defaultProperties() { return new PropertiesPropertySource(BITSQUARE_DEFAULT_PROPERTY_SOURCE_NAME, new Properties() { private static final long serialVersionUID = -8478089705207326165L; - { setProperty(APP_DATA_DIR_KEY, appDataDir); setProperty(APP_DATA_DIR_CLEAN_KEY, DEFAULT_APP_DATA_DIR_CLEAN); @@ -149,7 +201,6 @@ public class BitsquareEnvironment extends StandardEnvironment { }); } - private static String defaultUserDataDir() { if (Utilities.isWindows()) return System.getenv("APPDATA"); @@ -159,7 +210,7 @@ public class BitsquareEnvironment extends StandardEnvironment { return Paths.get(System.getProperty("user.home"), ".local", "share").toString(); } - private static String appDataDir(String userDataDir, String appName) { - return Paths.get(userDataDir, appName).toString(); + private static String appDataDir(String userDataDir, String appName, BitcoinNetwork bitcoinNetwork, String version) { + return Paths.get(userDataDir, appName, version, bitcoinNetwork.name().toLowerCase()).toString(); } } diff --git a/core/src/main/java/io/bitsquare/btc/WalletService.java b/core/src/main/java/io/bitsquare/btc/WalletService.java index 3eadb5de95..aae4261253 100644 --- a/core/src/main/java/io/bitsquare/btc/WalletService.java +++ b/core/src/main/java/io/bitsquare/btc/WalletService.java @@ -136,7 +136,7 @@ public class WalletService { this.addressEntryList = addressEntryList; this.params = preferences.getBitcoinNetwork().getParameters(); this.cryptoService = cryptoService; - this.walletDir = new File(walletDir, preferences.getBitcoinNetwork().toString().toLowerCase()); + this.walletDir = new File(walletDir, "bitcoin"); this.walletPrefix = walletPrefix; this.userAgent = userAgent; } @@ -176,6 +176,7 @@ 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()) { + log.debug("regTestHost " + regTestHost); if (regTestHost == RegTestHost.REG_TEST_SERVER) { try { walletAppKit.setPeerNodes(new PeerAddress(InetAddress.getByName(RegTestHost.SERVER_IP), params.getPort())); diff --git a/core/src/main/java/io/bitsquare/p2p/BootstrapNodes.java b/core/src/main/java/io/bitsquare/p2p/BootstrapNodes.java index de367dd812..3dabc209df 100644 --- a/core/src/main/java/io/bitsquare/p2p/BootstrapNodes.java +++ b/core/src/main/java/io/bitsquare/p2p/BootstrapNodes.java @@ -19,83 +19,121 @@ package io.bitsquare.p2p; import io.bitsquare.BitsquareException; +import com.google.inject.name.Named; + +import java.net.InetAddress; +import java.net.UnknownHostException; + import java.util.Arrays; import java.util.List; import java.util.Random; import java.util.stream.Collectors; +import javax.inject.Inject; + +import net.tomp2p.peers.Number160; +import net.tomp2p.peers.PeerAddress; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class BootstrapNodes { private static final Logger log = LoggerFactory.getLogger(BootstrapNodes.class); + public static final String BOOTSTRAP_NODE_KEY = "bootstrapNode"; - private static final List bootstrapNodes = Arrays.asList( - Node.at("digitalocean1.bitsquare.io", "188.226.179.109"), - Node.at("aws1.bitsquare.io", "52.24.144.42"), - Node.at("aws2.bitsquare.io", "52.11.125.194") + private final List rawBootstrapNodes = Arrays.asList( + Node.rawNodeAt("digitalocean1.bitsquare.io", "188.226.179.109"), + Node.rawNodeAt("aws1.bitsquare.io", "52.24.144.42"), + Node.rawNodeAt("aws2.bitsquare.io", "52.11.125.194") ); - private static Node selectedNode; + private Node rawLocalhostNode = Node.rawNodeAt("localhost", "127.0.0.1"); - public static List getAllBootstrapNodes(int p2pId) { - switch (p2pId) { - case Node.MAIN_NET_P2P_ID: - return bootstrapNodes.stream().map(e -> e.withP2pIdAndPort(Node.MAIN_NET_P2P_ID, Node.MAIN_NET_PORT)).collect(Collectors.toList()); - case Node.TEST_NET_P2P_ID: - return bootstrapNodes.stream().map(e -> e.withP2pIdAndPort(Node.TEST_NET_P2P_ID, Node.TEST_NET_PORT)).collect(Collectors.toList()); - case Node.REG_TEST_P2P_ID: - return bootstrapNodes.stream().map(e -> e.withP2pIdAndPort(Node.REG_TEST_P2P_ID, Node.REG_TEST_PORT)).collect(Collectors.toList()); - default: - throw new BitsquareException("Unsupported P2pId. p2pId=" + p2pId); + + private Node preferredBootstrapNode; + private List bootstrapNodes; + private Node localhostNode; + private int p2pId; + private boolean inited; + + @Inject + public BootstrapNodes(@Named(BOOTSTRAP_NODE_KEY) Node preferredBootstrapNode) { + // preferredBootstrapNode need to be fully defined to get accepted (name, IP, p2pId, port) + if (preferredBootstrapNode.getName() != null + && preferredBootstrapNode.getIp() != null + && preferredBootstrapNode.getP2pId() != -1 + && preferredBootstrapNode.getPort() != -1) { + this.preferredBootstrapNode = preferredBootstrapNode; + } + else if (preferredBootstrapNode.getName() != null + || preferredBootstrapNode.getIp() != null + || preferredBootstrapNode.getP2pId() != -1 + || preferredBootstrapNode.getPort() != -1) { + log.debug("preferredBootstrapNode not fully defined (name, IP, p2pId, port). preferredBootstrapNode=" + preferredBootstrapNode); } } - public static Node selectNode(int p2pId) { - if (selectedNode == null) - selectedNode = getAllBootstrapNodes(p2pId).get(new Random().nextInt(bootstrapNodes.size())); - else - throw new BitsquareException("selectNode must be called only once."); - - return selectedNode; + public BootstrapNodes() { } - public static Node getSelectedNode() { - if (selectedNode == null) - throw new BitsquareException("selectNode must be called first."); - - return selectedNode; - } - - public static Node getFallbackNode() { - if (bootstrapNodes.size() > 1) - return BootstrapNodes.getAllBootstrapNodes(selectedNode.getP2pId()).stream().filter(e -> !e.equals(selectedNode)).findAny().get(); - else - return null; - - } - - // Localhost default use regtest - private static Node localhostNode = selectLocalhostNode(Node.REG_TEST_P2P_ID); - - public static Node selectLocalhostNode(int p2pId) { - final Node localhostNode = Node.at("localhost", "127.0.0.1"); - switch (p2pId) { - case Node.MAIN_NET_P2P_ID: - BootstrapNodes.localhostNode = localhostNode.withP2pIdAndPort(Node.MAIN_NET_P2P_ID, Node.MAIN_NET_PORT); - break; - case Node.TEST_NET_P2P_ID: - BootstrapNodes.localhostNode = localhostNode.withP2pIdAndPort(Node.TEST_NET_P2P_ID, Node.TEST_NET_PORT); - break; - case Node.REG_TEST_P2P_ID: - BootstrapNodes.localhostNode = localhostNode.withP2pIdAndPort(Node.REG_TEST_P2P_ID, Node.REG_TEST_PORT); - break; - default: - throw new BitsquareException("Unsupported P2pId. p2pId=" + p2pId); + public void initWithNetworkId(int p2pId) { + if (!inited) { + inited = true; + this.p2pId = p2pId; + if (preferredBootstrapNode != null) { + bootstrapNodes = Arrays.asList(preferredBootstrapNode); + } + else { + switch (p2pId) { + case Node.MAIN_NET_P2P_ID: + bootstrapNodes = rawBootstrapNodes.stream() + .map(e -> e.withP2pIdAndPort(Node.MAIN_NET_P2P_ID, Node.MAIN_NET_PORT)).collect(Collectors.toList()); + localhostNode = rawLocalhostNode.withP2pIdAndPort(Node.MAIN_NET_P2P_ID, Node.MAIN_NET_PORT); + break; + case Node.TEST_NET_P2P_ID: + bootstrapNodes = rawBootstrapNodes.stream() + .map(e -> e.withP2pIdAndPort(Node.TEST_NET_P2P_ID, Node.TEST_NET_PORT)).collect(Collectors.toList()); + localhostNode = rawLocalhostNode.withP2pIdAndPort(Node.TEST_NET_P2P_ID, Node.TEST_NET_PORT); + break; + case Node.REG_TEST_P2P_ID: + bootstrapNodes = rawBootstrapNodes.stream() + .map(e -> e.withP2pIdAndPort(Node.REG_TEST_P2P_ID, Node.REG_TEST_PORT)).collect(Collectors.toList()); + localhostNode = rawLocalhostNode.withP2pIdAndPort(Node.REG_TEST_P2P_ID, Node.REG_TEST_PORT); + break; + default: + throw new BitsquareException("Unsupported P2pId. p2pId=" + p2pId); + } + } + } + else { + throw new BitsquareException("initWithNetworkId called twice"); } - return BootstrapNodes.localhostNode; } - public static Node getLocalhostNode() { + public Node getRandomDiscoverNode() { + return bootstrapNodes.get(new Random().nextInt(rawBootstrapNodes.size())); + } + + public List getBootstrapNodes() { + return bootstrapNodes; + } + + public List getBootstrapPeerAddresses() { + return bootstrapNodes.stream().map(e -> { + try { + return new PeerAddress(Number160.createHash(e.getName()), InetAddress.getByName(e.getIp()), e.getPort(), e.getPort()); + } catch (UnknownHostException e1) { + e1.printStackTrace(); + log.error(e1.getMessage()); + return null; + } + }).collect(Collectors.toList()); + } + + public Node getLocalhostNode() { return localhostNode; } + + public int getP2pId() { + return p2pId; + } } diff --git a/core/src/main/java/io/bitsquare/p2p/ClientNode.java b/core/src/main/java/io/bitsquare/p2p/ClientNode.java index 5f06f3cb0e..f4314b576d 100644 --- a/core/src/main/java/io/bitsquare/p2p/ClientNode.java +++ b/core/src/main/java/io/bitsquare/p2p/ClientNode.java @@ -32,9 +32,7 @@ public interface ClientNode { String getClientNodeInfo(); - Node getBootstrapNode(); - - Observable bootstrap(int networkId, KeyPair keyPair); + Observable bootstrap(KeyPair keyPair); ReadOnlyIntegerProperty numPeersProperty(); diff --git a/core/src/main/java/io/bitsquare/p2p/Node.java b/core/src/main/java/io/bitsquare/p2p/Node.java index 4881448194..83f2a9b09f 100644 --- a/core/src/main/java/io/bitsquare/p2p/Node.java +++ b/core/src/main/java/io/bitsquare/p2p/Node.java @@ -64,7 +64,7 @@ public final class Node { } // Not fully defined node - public static Node at(String name, String ip) { + public static Node rawNodeAt(String name, String ip) { return Node.at(name, ip, -1, -1); } @@ -76,10 +76,6 @@ public final class Node { return Node.at(this.name, this.ip, p2pId, port); } - /* public static Node at(String name, int p2pId, String ip) { - return Node.at(name, ip, p2pId, DEFAULT_PORT); - }*/ - public static final int CLIENT_PORT = findFreeSystemPort(); public static int findFreeSystemPort() { @@ -98,8 +94,20 @@ public final class Node { public PeerAddress toPeerAddressWithPort(int port) { try { - return new PeerAddress(Number160.createHash(getName()), - InetAddress.getByName(getIp()), + return new PeerAddress(Number160.createHash(name), + InetAddress.getByName(ip), + port, + port); + } catch (UnknownHostException e) { + log.error(e.getMessage()); + throw new RuntimeException(e); + } + } + + public PeerAddress toPeerAddress() { + try { + return new PeerAddress(Number160.createHash(name), + InetAddress.getByName(ip), port, port); } catch (UnknownHostException e) { 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 dde18f6084..1667c86ca1 100644 --- a/core/src/main/java/io/bitsquare/p2p/tomp2p/BootstrappedPeerBuilder.java +++ b/core/src/main/java/io/bitsquare/p2p/tomp2p/BootstrappedPeerBuilder.java @@ -27,9 +27,6 @@ import com.google.inject.name.Named; import java.io.IOException; -import java.net.InetAddress; -import java.net.UnknownHostException; - import java.security.KeyPair; import java.util.concurrent.Executor; @@ -55,7 +52,6 @@ import net.tomp2p.nat.PeerBuilderNAT; import net.tomp2p.nat.PeerNAT; import net.tomp2p.p2p.Peer; import net.tomp2p.p2p.PeerBuilder; -import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerMapChangeListener; import net.tomp2p.peers.PeerStatistic; @@ -75,7 +71,6 @@ import io.netty.util.concurrent.DefaultEventExecutorGroup; public class BootstrappedPeerBuilder { private static final Logger log = LoggerFactory.getLogger(BootstrappedPeerBuilder.class); - static final String BOOTSTRAP_NODE_KEY = "bootstrapNode"; static final String NETWORK_INTERFACE_KEY = "interface"; static final String NETWORK_INTERFACE_UNSPECIFIED = ""; static final String USE_MANUAL_PORT_FORWARDING_KEY = "node.useManualPortForwarding"; @@ -117,17 +112,16 @@ public class BootstrappedPeerBuilder { private final int port; private final boolean useManualPortForwarding; private final String networkInterface; + private BootstrapNodes bootstrapNodes; private final Preferences preferences; private final SettableFuture settableFuture = SettableFuture.create(); private final ObjectProperty state = new SimpleObjectProperty<>(State.UNDEFINED); private final ObjectProperty connectionType = new SimpleObjectProperty<>(ConnectionType.UNDEFINED); - private Node bootstrapNode; private KeyPair keyPair; private Peer peer; private PeerDHT peerDHT; - private boolean retriedOtherBootstrapNode; private Executor executor; @@ -138,13 +132,13 @@ public class BootstrappedPeerBuilder { @Inject public BootstrappedPeerBuilder(@Named(Node.PORT_KEY) int port, @Named(USE_MANUAL_PORT_FORWARDING_KEY) boolean useManualPortForwarding, - @Named(BOOTSTRAP_NODE_KEY) Node bootstrapNode, @Named(NETWORK_INTERFACE_KEY) String networkInterface, + BootstrapNodes bootstrapNodes, Preferences preferences) { this.port = port; this.useManualPortForwarding = useManualPortForwarding; - this.bootstrapNode = bootstrapNode; this.networkInterface = networkInterface; + this.bootstrapNodes = bootstrapNodes; this.preferences = preferences; } @@ -166,28 +160,8 @@ public class BootstrappedPeerBuilder { this.executor = executor; } - public SettableFuture start(int p2pId) { + public SettableFuture start() { try { - Node selectedNode = BootstrapNodes.selectNode(p2pId); - String bootstrapNodeName = bootstrapNode.getName(); - if (bootstrapNodeName == null) - bootstrapNodeName = selectedNode.getName(); - - String bootstrapNodeIp = bootstrapNode.getIp(); - if (bootstrapNodeIp == null) - bootstrapNodeIp = selectedNode.getIp(); - - int bootstrapNodeP2pId = bootstrapNode.getP2pId(); - if (bootstrapNodeP2pId == -1) - bootstrapNodeP2pId = selectedNode.getP2pId(); - - int bootstrapNodePort = bootstrapNode.getPort(); - if (bootstrapNodePort == -1) - bootstrapNodePort = selectedNode.getPort(); - - bootstrapNode = Node.at(bootstrapNodeName, bootstrapNodeIp, bootstrapNodeP2pId, bootstrapNodePort); - log.debug("Bootstrap to {}", bootstrapNode.toString()); - DefaultEventExecutorGroup eventExecutorGroup = new DefaultEventExecutorGroup(20); ChannelClientConfiguration clientConf = PeerBuilder.createDefaultChannelClientConfiguration(); clientConf.pipelineFilter(new PeerBuilder.EventExecutorGroupFilter(eventExecutorGroup)); @@ -202,7 +176,7 @@ public class BootstrappedPeerBuilder { if (useManualPortForwarding) { peer = new PeerBuilder(keyPair) - .p2pId(p2pId) + .p2pId(bootstrapNodes.getP2pId()) .channelClientConfiguration(clientConf) .channelServerConfiguration(serverConf) .ports(port) @@ -213,7 +187,7 @@ public class BootstrappedPeerBuilder { } else { peer = new PeerBuilder(keyPair) - .p2pId(p2pId) + .p2pId(bootstrapNodes.getP2pId()) .channelClientConfiguration(clientConf) .channelServerConfiguration(serverConf) .ports(port) @@ -270,13 +244,13 @@ public class BootstrappedPeerBuilder { // bootstrap node and use that peer as relay private void discoverExternalAddressUsingUPnP() { - FutureDiscover futureDiscover = peer.discover().peerAddress(getBootstrapAddress()).start(); + Node randomNode = bootstrapNodes.getRandomDiscoverNode(); + log.info("Random Node for discovering own address visible form outside: " + randomNode); + FutureDiscover futureDiscover = peer.discover().peerAddress(randomNode.toPeerAddress()).start(); setState(State.DISCOVERY_STARTED); PeerNAT peerNAT = new PeerBuilderNAT(peer).start(); - FutureNAT futureNAT = peerNAT.startSetupPortforwarding(futureDiscover); FutureRelayNAT futureRelayNAT = peerNAT.startRelay(new TCPRelayClientConfig(), futureDiscover, futureNAT); - futureRelayNAT.addListener(new BaseFutureListener() { @Override public void operationComplete(BaseFuture futureRelayNAT) throws Exception { @@ -309,17 +283,8 @@ public class BootstrappedPeerBuilder { bootstrap(); } else { - Node fallbackNode = BootstrapNodes.getFallbackNode(); - if (!retriedOtherBootstrapNode && fallbackNode != null) { - retriedOtherBootstrapNode = true; - bootstrapNode = fallbackNode; - log.warn("Bootstrap failed with bootstrapNode: " + bootstrapNode + ". We try again with another node."); - executor.execute(() -> discoverExternalAddress()); - } - else { - // All attempts failed. Give up... - handleError(State.RELAY_FAILED, "NAT traversal using relay mode failed " + futureRelayNAT.failedReason()); - } + // All attempts failed. Give up... + handleError(State.RELAY_FAILED, "NAT traversal using relay mode failed " + futureRelayNAT.failedReason()); } } } @@ -333,12 +298,12 @@ public class BootstrappedPeerBuilder { } private void discoverExternalAddress() { - FutureDiscover futureDiscover = peer.discover().peerAddress(getBootstrapAddress()).start(); + Node randomNode = bootstrapNodes.getRandomDiscoverNode(); + log.info("Random Node for discovering own address visible form outside: " + randomNode); + FutureDiscover futureDiscover = peer.discover().peerAddress(randomNode.toPeerAddress()).start(); setState(State.DISCOVERY_STARTED); PeerNAT peerNAT = new PeerBuilderNAT(peer).start(); - FutureRelayNAT futureRelayNAT = peerNAT.startRelay(new TCPRelayClientConfig(), futureDiscover); - futureRelayNAT.addListener(new BaseFutureListener() { @Override public void operationComplete(BaseFuture futureRelayNAT) throws Exception { @@ -363,17 +328,8 @@ public class BootstrappedPeerBuilder { bootstrap(); } else { - Node fallbackNode = BootstrapNodes.getFallbackNode(); - if (!retriedOtherBootstrapNode && fallbackNode != null) { - retriedOtherBootstrapNode = true; - bootstrapNode = fallbackNode; - log.warn("Bootstrap failed with bootstrapNode: " + bootstrapNode + ". We try again with another node."); - executor.execute(() -> discoverExternalAddress()); - } - else { - // All attempts failed. Give up... - handleError(State.RELAY_FAILED, "NAT traversal using relay mode failed " + futureRelayNAT.failedReason()); - } + // All attempts failed. Give up... + handleError(State.RELAY_FAILED, "NAT traversal using relay mode failed " + futureRelayNAT.failedReason()); } } } @@ -389,9 +345,7 @@ public class BootstrappedPeerBuilder { log.trace("start bootstrap"); // We don't wait until bootstrap is done for speeding up startup process - // settableFuture.set(peerDHT); - - FutureBootstrap futureBootstrap = peer.bootstrap().peerAddress(getBootstrapAddress()).start(); + FutureBootstrap futureBootstrap = peer.bootstrap().bootstrapTo(bootstrapNodes.getBootstrapPeerAddresses()).start(); futureBootstrap.addListener(new BaseFutureListener() { @Override public void operationComplete(BaseFuture future) throws Exception { @@ -413,22 +367,6 @@ public class BootstrappedPeerBuilder { }); } - private PeerAddress getBootstrapAddress() { - try { - return new PeerAddress(Number160.createHash(bootstrapNode.getName()), - InetAddress.getByName(bootstrapNode.getIp()), - bootstrapNode.getPort(), - bootstrapNode.getPort()); - } catch (UnknownHostException e) { - log.error("getBootstrapAddress failed: " + e.getMessage()); - return null; - } - } - - public Node getBootstrapNode() { - return bootstrapNode; - } - public ConnectionType getConnectionType() { return connectionType.get(); } 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 ef22157ea2..ea67a11207 100644 --- a/core/src/main/java/io/bitsquare/p2p/tomp2p/TomP2PModule.java +++ b/core/src/main/java/io/bitsquare/p2p/tomp2p/TomP2PModule.java @@ -18,6 +18,7 @@ package io.bitsquare.p2p.tomp2p; import io.bitsquare.p2p.AddressService; +import io.bitsquare.p2p.BootstrapNodes; import io.bitsquare.p2p.ClientNode; import io.bitsquare.p2p.MailboxService; import io.bitsquare.p2p.MessageService; @@ -33,11 +34,11 @@ import org.slf4j.LoggerFactory; import org.springframework.core.env.Environment; -import static io.bitsquare.p2p.tomp2p.BootstrappedPeerBuilder.*; +import static io.bitsquare.p2p.tomp2p.BootstrappedPeerBuilder.NETWORK_INTERFACE_UNSPECIFIED; public class TomP2PModule extends P2PModule { private static final Logger log = LoggerFactory.getLogger(TomP2PModule.class); - public static final String BOOTSTRAP_NODE_NAME_KEY = "bootstrap.node.name"; + public static final String BOOTSTRAP_NODE_NAME_KEY = "bootstrap.node.name"; public static final String BOOTSTRAP_NODE_IP_KEY = "bootstrap.node.ip"; public static final String BOOTSTRAP_NODE_P2P_ID_KEY = "bootstrap.node.p2pId"; public static final String BOOTSTRAP_NODE_PORT_KEY = "bootstrap.node.port"; @@ -51,6 +52,7 @@ public class TomP2PModule extends P2PModule { @Override protected void doConfigure() { // Used both ClientNode and TomP2PNode for injection + bind(BootstrapNodes.class).in(Singleton.class); bind(ClientNode.class).to(TomP2PNode.class).in(Singleton.class); bind(TomP2PNode.class).in(Singleton.class); @@ -64,7 +66,7 @@ public class TomP2PModule extends P2PModule { bind(boolean.class).annotatedWith(Names.named(USE_MANUAL_PORT_FORWARDING_KEY)).toInstance( env.getProperty(USE_MANUAL_PORT_FORWARDING_KEY, boolean.class, false)); - bind(Node.class).annotatedWith(Names.named(BOOTSTRAP_NODE_KEY)).toInstance( + bind(Node.class).annotatedWith(Names.named(BootstrapNodes.BOOTSTRAP_NODE_KEY)).toInstance( Node.at(env.getProperty(BOOTSTRAP_NODE_NAME_KEY, ""), env.getProperty(BOOTSTRAP_NODE_IP_KEY, ""), Integer.valueOf(env.getProperty(BOOTSTRAP_NODE_P2P_ID_KEY, "-1")), 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 81d6e647a8..c9a8e390ae 100644 --- a/core/src/main/java/io/bitsquare/p2p/tomp2p/TomP2PNode.java +++ b/core/src/main/java/io/bitsquare/p2p/tomp2p/TomP2PNode.java @@ -21,7 +21,6 @@ import io.bitsquare.BitsquareException; import io.bitsquare.common.handlers.ResultHandler; import io.bitsquare.p2p.BaseP2PService; import io.bitsquare.p2p.ClientNode; -import io.bitsquare.p2p.Node; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; @@ -91,7 +90,7 @@ public class TomP2PNode implements ClientNode { bootstrappedPeerBuilder.setExecutor(executor); } - public Observable bootstrap(int p2pId, KeyPair keyPair) { + public Observable bootstrap(KeyPair keyPair) { bootstrappedPeerBuilder.setKeyPair(keyPair); bootstrappedPeerBuilder.getState().addListener((ov, oldValue, newValue) -> { @@ -99,7 +98,7 @@ public class TomP2PNode implements ClientNode { bootstrapStateSubject.onNext(newValue); }); - SettableFuture bootstrapFuture = bootstrappedPeerBuilder.start(p2pId); + SettableFuture bootstrapFuture = bootstrappedPeerBuilder.start(); Futures.addCallback(bootstrapFuture, new FutureCallback() { @Override public void onSuccess(@Nullable PeerDHT peerDHT) { @@ -179,11 +178,6 @@ public class TomP2PNode implements ClientNode { "; port=" + peerAddress.peerSocketAddress().tcpPort(); } - @Override - public Node getBootstrapNode() { - return bootstrappedPeerBuilder.getBootstrapNode(); - } - public void addResultHandler(ResultHandler resultHandler) { resultHandlers.add(resultHandler); } diff --git a/core/src/main/java/io/bitsquare/trade/BuyerAsOffererTrade.java b/core/src/main/java/io/bitsquare/trade/BuyerAsOffererTrade.java index 4c4a99f77b..b75a3ad9b3 100644 --- a/core/src/main/java/io/bitsquare/trade/BuyerAsOffererTrade.java +++ b/core/src/main/java/io/bitsquare/trade/BuyerAsOffererTrade.java @@ -47,12 +47,10 @@ public class BuyerAsOffererTrade extends BuyerTrade implements OffererTrade, Ser public BuyerAsOffererTrade(Offer offer, Storage storage) { super(offer, storage); - log.trace("Created by constructor"); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); - log.trace("Created from serialized form."); initStateProperties(); initAmountProperty(); diff --git a/core/src/main/java/io/bitsquare/trade/BuyerAsTakerTrade.java b/core/src/main/java/io/bitsquare/trade/BuyerAsTakerTrade.java index c70505152a..9c3ad201af 100644 --- a/core/src/main/java/io/bitsquare/trade/BuyerAsTakerTrade.java +++ b/core/src/main/java/io/bitsquare/trade/BuyerAsTakerTrade.java @@ -46,12 +46,10 @@ public class BuyerAsTakerTrade extends BuyerTrade implements TakerTrade, Seriali public BuyerAsTakerTrade(Offer offer, Coin tradeAmount, Peer tradingPeer, Storage storage) { super(offer, tradeAmount, tradingPeer, storage); - log.trace("Created by constructor"); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); - log.trace("Created from serialized form."); initStateProperties(); initAmountProperty(); diff --git a/core/src/main/java/io/bitsquare/trade/BuyerTrade.java b/core/src/main/java/io/bitsquare/trade/BuyerTrade.java index d87b5aa466..a1266dc1a0 100644 --- a/core/src/main/java/io/bitsquare/trade/BuyerTrade.java +++ b/core/src/main/java/io/bitsquare/trade/BuyerTrade.java @@ -40,12 +40,10 @@ public abstract class BuyerTrade extends Trade implements Serializable { public BuyerTrade(Offer offer, Coin tradeAmount, Peer tradingPeer, Storage storage) { super(offer, tradeAmount, tradingPeer, storage); - log.trace("Created by constructor"); } public BuyerTrade(Offer offer, Storage storage) { super(offer, storage); - log.trace("Created by constructor"); } @Override diff --git a/core/src/main/java/io/bitsquare/trade/SellerAsOffererTrade.java b/core/src/main/java/io/bitsquare/trade/SellerAsOffererTrade.java index 44618d43bd..8af27c7e27 100644 --- a/core/src/main/java/io/bitsquare/trade/SellerAsOffererTrade.java +++ b/core/src/main/java/io/bitsquare/trade/SellerAsOffererTrade.java @@ -45,12 +45,10 @@ public class SellerAsOffererTrade extends SellerTrade implements OffererTrade, S public SellerAsOffererTrade(Offer offer, Storage storage) { super(offer, storage); - log.trace("Created by constructor"); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); - log.trace("Created from serialized form."); initStateProperties(); initAmountProperty(); diff --git a/core/src/main/java/io/bitsquare/trade/SellerAsTakerTrade.java b/core/src/main/java/io/bitsquare/trade/SellerAsTakerTrade.java index ebb3d8d6f3..6dc0f24d04 100644 --- a/core/src/main/java/io/bitsquare/trade/SellerAsTakerTrade.java +++ b/core/src/main/java/io/bitsquare/trade/SellerAsTakerTrade.java @@ -45,12 +45,10 @@ public class SellerAsTakerTrade extends SellerTrade implements TakerTrade, Seria public SellerAsTakerTrade(Offer offer, Coin tradeAmount, Peer tradingPeer, Storage storage) { super(offer, tradeAmount, tradingPeer, storage); - log.trace("Created by constructor"); } private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); - log.trace("Created from serialized form."); initStateProperties(); initAmountProperty(); diff --git a/core/src/main/java/io/bitsquare/trade/SellerTrade.java b/core/src/main/java/io/bitsquare/trade/SellerTrade.java index 48ca93fb1e..bc3f885dc1 100644 --- a/core/src/main/java/io/bitsquare/trade/SellerTrade.java +++ b/core/src/main/java/io/bitsquare/trade/SellerTrade.java @@ -40,12 +40,10 @@ public abstract class SellerTrade extends Trade implements Serializable { public SellerTrade(Offer offer, Coin tradeAmount, Peer tradingPeer, Storage storage) { super(offer, tradeAmount, tradingPeer, storage); - log.trace("Created by constructor"); } public SellerTrade(Offer offer, Storage storage) { super(offer, storage); - log.trace("Created by constructor"); } @Override diff --git a/core/src/main/java/io/bitsquare/trade/TradableList.java b/core/src/main/java/io/bitsquare/trade/TradableList.java index 8e1ff3fa7b..c2963a36f6 100644 --- a/core/src/main/java/io/bitsquare/trade/TradableList.java +++ b/core/src/main/java/io/bitsquare/trade/TradableList.java @@ -49,8 +49,6 @@ public class TradableList extends ArrayList implements Se /////////////////////////////////////////////////////////////////////////////////////////// public TradableList(Storage> storage, String fileName) { - log.trace("Created by constructor"); - this.storage = storage; TradableList persisted = storage.initAndGetPersisted(this, fileName); @@ -62,7 +60,6 @@ public class TradableList extends ArrayList implements Se private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); - log.trace("Created from serialized form."); } @Override diff --git a/core/src/main/java/io/bitsquare/trade/Trade.java b/core/src/main/java/io/bitsquare/trade/Trade.java index 03062ebc42..69484eeeee 100644 --- a/core/src/main/java/io/bitsquare/trade/Trade.java +++ b/core/src/main/java/io/bitsquare/trade/Trade.java @@ -128,7 +128,6 @@ abstract public class Trade implements Tradable, Model, Serializable { /////////////////////////////////////////////////////////////////////////////////////////// protected Trade(Offer offer, Storage storage) { - log.trace("Created by constructor"); this.offer = offer; this.storage = storage; @@ -156,7 +155,6 @@ abstract public class Trade implements Tradable, Model, Serializable { private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); - log.trace("Created from serialized form."); initStateProperties(); initAmountProperty(); diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/ProcessModel.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/ProcessModel.java index efaf147c8f..45ed63ac2f 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/ProcessModel.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/ProcessModel.java @@ -80,13 +80,11 @@ public class ProcessModel implements Model, Serializable { public ProcessModel() { - log.trace("Created by constructor"); tradingPeer = new TradingPeer(); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); - log.trace("Created from serialized form."); } public void onAllServicesInitialized(Offer offer, diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/TradingPeer.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/TradingPeer.java index 52d6cc6b0a..5bbeea17d1 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/TradingPeer.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/TradingPeer.java @@ -60,12 +60,10 @@ public class TradingPeer implements Serializable { /////////////////////////////////////////////////////////////////////////////////////////// public TradingPeer() { - log.trace("Created by constructor"); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); - log.trace("Created from serialized form."); } diff --git a/core/src/main/java/io/bitsquare/user/Preferences.java b/core/src/main/java/io/bitsquare/user/Preferences.java index 4b686eede5..e3e818fa94 100644 --- a/core/src/main/java/io/bitsquare/user/Preferences.java +++ b/core/src/main/java/io/bitsquare/user/Preferences.java @@ -17,6 +17,7 @@ package io.bitsquare.user; +import io.bitsquare.app.BitsquareEnvironment; import io.bitsquare.app.Version; import io.bitsquare.btc.BitcoinNetwork; import io.bitsquare.storage.Storage; @@ -38,8 +39,6 @@ import javafx.beans.property.StringProperty; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.core.env.Environment; - public class Preferences implements Serializable { // That object is saved to disc. We need to take care of changes to not break deserialization. private static final long serialVersionUID = Version.LOCAL_DB_VERSION; @@ -48,11 +47,13 @@ public class Preferences implements Serializable { // Deactivate mBit for now as most screens are not supporting it yet transient private static final List BTC_DENOMINATIONS = Arrays.asList(MonetaryFormat.CODE_BTC/*, MonetaryFormat.CODE_MBTC*/); + public static List getBtcDenominations() { return BTC_DENOMINATIONS; } transient private final Storage storage; + transient private BitsquareEnvironment bitsquareEnvironment; // Persisted fields private String btcDenomination = MonetaryFormat.CODE_BTC; @@ -61,7 +62,7 @@ public class Preferences implements Serializable { private boolean useEffects = true; private boolean displaySecurityDepositInfo = true; private boolean useUPnP = true; - private BitcoinNetwork bitcoinNetwork; + transient private BitcoinNetwork bitcoinNetwork; // Observable wrappers transient private final StringProperty btcDenominationProperty = new SimpleStringProperty(btcDenomination); @@ -74,8 +75,9 @@ public class Preferences implements Serializable { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - public Preferences(Storage storage, Environment environment) { + public Preferences(Storage storage, BitsquareEnvironment bitsquareEnvironment) { this.storage = storage; + this.bitsquareEnvironment = bitsquareEnvironment; Preferences persisted = storage.initAndGetPersisted(this); if (persisted != null) { @@ -83,12 +85,10 @@ public class Preferences implements Serializable { setUseAnimations(persisted.useAnimations); setUseEffects(persisted.useEffects); setUseUPnP(persisted.useUPnP); - setBitcoinNetwork(persisted.bitcoinNetwork); displaySecurityDepositInfo = persisted.getDisplaySecurityDepositInfo(); } - else { - setBitcoinNetwork(environment.getProperty(BitcoinNetwork.KEY, BitcoinNetwork.class, BitcoinNetwork.DEFAULT)); - } + + setBitcoinNetwork(bitsquareEnvironment.getBtcNetworkProperty()); // Use that to guarantee update of the serializable field and to make a storage update in case of a change btcDenominationProperty.addListener((ov) -> { @@ -133,8 +133,10 @@ public class Preferences implements Serializable { } public void setBitcoinNetwork(BitcoinNetwork bitcoinNetwork) { + if (this.bitcoinNetwork != bitcoinNetwork) + bitsquareEnvironment.setBitcoinNetwork(bitcoinNetwork); + this.bitcoinNetwork = bitcoinNetwork; - storage.queueUpForSave(); } diff --git a/core/src/test/java/io/bitsquare/p2p/NodeTests.java b/core/src/test/java/io/bitsquare/p2p/NodeTests.java index b3e74f5bd7..806d92e5ac 100644 --- a/core/src/test/java/io/bitsquare/p2p/NodeTests.java +++ b/core/src/test/java/io/bitsquare/p2p/NodeTests.java @@ -26,8 +26,8 @@ public class NodeTests { @Test public void testEqualsAndHashCode() { - Node node1a = Node.at("bitsquare1.example.com", "203.0.113.1"); - Node node1b = Node.at("bitsquare1.example.com", "203.0.113.1"); + Node node1a = Node.rawNodeAt("bitsquare1.example.com", "203.0.113.1"); + Node node1b = Node.rawNodeAt("bitsquare1.example.com", "203.0.113.1"); assertThat(node1a, equalTo(node1a)); @@ -37,10 +37,10 @@ public class NodeTests { assertThat(node1a, not((Object) equalTo(null))); assertThat(node1a, not((Object) equalTo("not a node"))); - assertThat(node1a, not(equalTo(Node.at("bitsquare2.example.com", node1a.getIp())))); - assertThat(node1a, not(equalTo(Node.at(node1a.getName(), "203.0.113.2")))); + assertThat(node1a, not(equalTo(Node.rawNodeAt("bitsquare2.example.com", node1a.getIp())))); + assertThat(node1a, not(equalTo(Node.rawNodeAt(node1a.getName(), "203.0.113.2")))); - Node node2 = Node.at("bitsquare2.example.com", "203.0.113.2"); + Node node2 = Node.rawNodeAt("bitsquare2.example.com", "203.0.113.2"); assertThat(node1a.hashCode(), equalTo(node1b.hashCode())); assertThat(node1a.hashCode(), not(equalTo(node2.hashCode()))); } diff --git a/core/src/test/java/io/bitsquare/p2p/TomP2PTests.java b/core/src/test/java/io/bitsquare/p2p/TomP2PTests.java index e9dde3dae9..e69f284a16 100644 --- a/core/src/test/java/io/bitsquare/p2p/TomP2PTests.java +++ b/core/src/test/java/io/bitsquare/p2p/TomP2PTests.java @@ -90,11 +90,14 @@ public class TomP2PTests { private static final PeerAddress BOOTSTRAP_NODE_ADDRESS; + private static final BootstrapNodes bootstrapNodes; + static { int p2pId = 1; + bootstrapNodes = new BootstrapNodes(); if (FORCED_CONNECTION_TYPE == BootstrappedPeerBuilder.ConnectionType.DIRECT) { - BootstrapNodes.selectLocalhostNode(p2pId); - BOOTSTRAP_NODE = BootstrapNodes.getLocalhostNode(); + bootstrapNodes.initWithNetworkId(p2pId); + BOOTSTRAP_NODE = bootstrapNodes.getLocalhostNode(); } else { BOOTSTRAP_NODE = Node.at("digitalocean1.dev.bitsquare.io", "188.226.179.109", p2pId, 7367); @@ -318,9 +321,7 @@ public class TomP2PTests { PeerDHT peer1 = new PeerBuilderDHT(new PeerBuilder(Number160.createHash("peer1")).ports(3006).start()).start(); PeerDHT peer2 = new PeerBuilderDHT(new PeerBuilder(Number160.createHash("peer2")).ports(3007).start()).start(); */ - PeerAddress masterPeerAddress = new PeerAddress(Number160.createHash(BootstrapNodes.getLocalhostNode().getName()), - BootstrapNodes.getLocalhostNode().getIp(), BootstrapNodes.getLocalhostNode().getPort(), - BootstrapNodes.getLocalhostNode().getPort()); + PeerAddress masterPeerAddress = bootstrapNodes.getLocalhostNode().toPeerAddress(); // start both at the same time BaseFuture fb1 = peer1.peer().bootstrap().peerAddress(masterPeerAddress).start(); diff --git a/gui/src/main/java/io/bitsquare/app/BitsquareAppMain.java b/gui/src/main/java/io/bitsquare/app/BitsquareAppMain.java index 1675ecb63c..94d7464b2a 100644 --- a/gui/src/main/java/io/bitsquare/app/BitsquareAppMain.java +++ b/gui/src/main/java/io/bitsquare/app/BitsquareAppMain.java @@ -123,7 +123,7 @@ public class BitsquareAppMain extends BitsquareExecutable { parser.accepts(USE_MANUAL_PORT_FORWARDING_KEY, description("Use manual port forwarding", false)) .withRequiredArg() .ofType(boolean.class); - parser.accepts(BitcoinNetwork.KEY, description("", BitcoinNetwork.DEFAULT)) + parser.accepts(BitcoinNetwork.KEY, description("Bitcoin network", BitcoinNetwork.DEFAULT)) .withRequiredArg() .ofType(BitcoinNetwork.class) .withValuesConvertedBy(new EnumValueConverter(BitcoinNetwork.class)); @@ -133,15 +133,16 @@ public class BitsquareAppMain extends BitsquareExecutable { .ofType(RegTestHost.class) .withValuesConvertedBy(new EnumValueConverter(RegTestHost.class)); - - parser.accepts(BOOTSTRAP_NODE_NAME_KEY, description("Bootstrap node name", BootstrapNodes.getLocalhostNode().getName())) + BootstrapNodes bootstrapNodes = new BootstrapNodes(); + bootstrapNodes.initWithNetworkId(Node.REG_TEST_P2P_ID); // use regtest as default + parser.accepts(BOOTSTRAP_NODE_NAME_KEY, description("Bootstrap node name", bootstrapNodes.getLocalhostNode().getName())) .withRequiredArg(); - parser.accepts(BOOTSTRAP_NODE_IP_KEY, description("Bootstrap node IP", BootstrapNodes.getLocalhostNode().getIp())) + parser.accepts(BOOTSTRAP_NODE_IP_KEY, description("Bootstrap node IP", bootstrapNodes.getLocalhostNode().getIp())) .withRequiredArg(); - parser.accepts(BOOTSTRAP_NODE_P2P_ID_KEY, description("Bootstrap node p2p network ID", BootstrapNodes.getLocalhostNode().getPort())) + parser.accepts(BOOTSTRAP_NODE_P2P_ID_KEY, description("Bootstrap node p2p network ID", bootstrapNodes.getLocalhostNode().getPort())) .withRequiredArg() .ofType(int.class); - parser.accepts(BOOTSTRAP_NODE_PORT_KEY, description("Bootstrap node port", BootstrapNodes.getLocalhostNode().getPort())) + parser.accepts(BOOTSTRAP_NODE_PORT_KEY, description("Bootstrap node port", bootstrapNodes.getLocalhostNode().getPort())) .withRequiredArg() .ofType(int.class); parser.accepts(NETWORK_INTERFACE_KEY, description("Network interface", null)) diff --git a/gui/src/main/java/io/bitsquare/app/BitsquareAppModule.java b/gui/src/main/java/io/bitsquare/app/BitsquareAppModule.java index f9d588b457..6150d024d9 100644 --- a/gui/src/main/java/io/bitsquare/app/BitsquareAppModule.java +++ b/gui/src/main/java/io/bitsquare/app/BitsquareAppModule.java @@ -73,7 +73,7 @@ class BitsquareAppModule extends BitsquareModule { File keyStorageDir = new File(env.getRequiredProperty(KeyStorage.DIR_KEY)); bind(File.class).annotatedWith(named(KeyStorage.DIR_KEY)).toInstance(keyStorageDir); - bind(Environment.class).toInstance(env); + bind(BitsquareEnvironment.class).toInstance((BitsquareEnvironment) env); bind(UpdateProcess.class).in(Singleton.class); // ordering is used for shut down sequence diff --git a/gui/src/main/java/io/bitsquare/app/UpdateProcess.java b/gui/src/main/java/io/bitsquare/app/UpdateProcess.java index 03e04532b0..43a5497cd5 100644 --- a/gui/src/main/java/io/bitsquare/app/UpdateProcess.java +++ b/gui/src/main/java/io/bitsquare/app/UpdateProcess.java @@ -68,7 +68,7 @@ public class UpdateProcess { protected Timer timeoutTimer; @Inject - public UpdateProcess(Environment environment) { + public UpdateProcess(BitsquareEnvironment environment) { this.environment = environment; } 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 55e252e81b..8f1f771286 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java @@ -27,6 +27,7 @@ import io.bitsquare.gui.common.model.ViewModel; import io.bitsquare.gui.util.BSFormatter; import io.bitsquare.locale.CountryUtil; import io.bitsquare.p2p.BaseP2PService; +import io.bitsquare.p2p.BootstrapNodes; import io.bitsquare.p2p.ClientNode; import io.bitsquare.p2p.tomp2p.BootstrappedPeerBuilder; import io.bitsquare.trade.Trade; @@ -77,7 +78,6 @@ class MainViewModel implements ViewModel { private final OpenOfferManager openOfferManager; private final UpdateProcess updateProcess; private final BSFormatter formatter; - private final int p2pId; // BTC network final StringProperty blockchainSyncInfo = new SimpleStringProperty("Initializing"); @@ -120,7 +120,7 @@ class MainViewModel implements ViewModel { @Inject public MainViewModel(User user, KeyRing keyRing, WalletService walletService, ArbitrationRepository arbitrationRepository, ClientNode clientNode, TradeManager tradeManager, OpenOfferManager openOfferManager, Preferences preferences, UpdateProcess updateProcess, - BSFormatter formatter) { + BootstrapNodes bootstrapNodes, BSFormatter formatter) { this.user = user; this.keyRing = keyRing; this.walletService = walletService; @@ -132,7 +132,7 @@ class MainViewModel implements ViewModel { this.formatter = formatter; bitcoinNetworkAsString = formatter.formatBitcoinNetwork(preferences.getBitcoinNetwork()); - p2pId = preferences.getBitcoinNetwork().ordinal() + 10; // p2pId: Mainnet 10, testnet 11, regtest 12 + bootstrapNodes.initWithNetworkId(preferences.getBitcoinNetwork().ordinal() + 10); updateProcess.state.addListener((observableValue, oldValue, newValue) -> applyUpdateState(newValue)); applyUpdateState(updateProcess.state.get()); @@ -206,7 +206,7 @@ class MainViewModel implements ViewModel { }); clientNode.setExecutor(Platform::runLater); - Observable bootstrapStateAsObservable = clientNode.bootstrap(p2pId, keyRing.getDhtSignatureKeyPair()); + Observable bootstrapStateAsObservable = clientNode.bootstrap(keyRing.getDhtSignatureKeyPair()); bootstrapStateAsObservable.publish(); bootstrapStateAsObservable.subscribe( state -> Platform.runLater(() -> setBootstrapState(state)), 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 ce66564213..57df3c7aa0 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 @@ -85,8 +85,8 @@ -