Use separate dirs for version and btc network, bootstrap to all bootstrap nodes, change config of bootstrap node

This commit is contained in:
Manfred Karrer 2015-05-18 17:05:53 +02:00
parent 7a9de65e86
commit fc3634af7b
29 changed files with 285 additions and 272 deletions

View File

@ -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<PeerAddress> bootstrapNodes = BootstrapNodes.getAllBootstrapNodes(p2pId).stream().filter(e -> !e.getName().equals(name))
if (!name.equals(bootstrapNodes.getLocalhostNode().getName())) {
List<Node> bootstrapNodesExcludingMyself = bootstrapNodes.getBootstrapNodes().stream().filter(e -> !e.getName().equals
(name)).collect(Collectors.toList());
log.info("Bootstrapping to bootstrapNodes " + bootstrapNodesExcludingMyself);
long ts = System.currentTimeMillis();
List<PeerAddress> 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;

View File

@ -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);
}

View File

@ -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();
}
}

View File

@ -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()));

View File

@ -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<Node> 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<Node> 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<Node> 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<Node> 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<Node> getBootstrapNodes() {
return bootstrapNodes;
}
public List<PeerAddress> 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;
}
}

View File

@ -32,9 +32,7 @@ public interface ClientNode {
String getClientNodeInfo();
Node getBootstrapNode();
Observable<BootstrappedPeerBuilder.State> bootstrap(int networkId, KeyPair keyPair);
Observable<BootstrappedPeerBuilder.State> bootstrap(KeyPair keyPair);
ReadOnlyIntegerProperty numPeersProperty();

View File

@ -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) {

View File

@ -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 = "<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<PeerDHT> settableFuture = SettableFuture.create();
private final ObjectProperty<State> state = new SimpleObjectProperty<>(State.UNDEFINED);
private final ObjectProperty<ConnectionType> 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<PeerDHT> start(int p2pId) {
public SettableFuture<PeerDHT> 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<BaseFuture>() {
@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<BaseFuture>() {
@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<BaseFuture>() {
@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();
}

View File

@ -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")),

View File

@ -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<BootstrappedPeerBuilder.State> bootstrap(int p2pId, KeyPair keyPair) {
public Observable<BootstrappedPeerBuilder.State> 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<PeerDHT> bootstrapFuture = bootstrappedPeerBuilder.start(p2pId);
SettableFuture<PeerDHT> bootstrapFuture = bootstrappedPeerBuilder.start();
Futures.addCallback(bootstrapFuture, new FutureCallback<PeerDHT>() {
@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);
}

View File

@ -47,12 +47,10 @@ public class BuyerAsOffererTrade extends BuyerTrade implements OffererTrade, Ser
public BuyerAsOffererTrade(Offer offer, Storage<? extends TradableList> 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();

View File

@ -46,12 +46,10 @@ public class BuyerAsTakerTrade extends BuyerTrade implements TakerTrade, Seriali
public BuyerAsTakerTrade(Offer offer, Coin tradeAmount, Peer tradingPeer, Storage<? extends TradableList> 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();

View File

@ -40,12 +40,10 @@ public abstract class BuyerTrade extends Trade implements Serializable {
public BuyerTrade(Offer offer, Coin tradeAmount, Peer tradingPeer, Storage<? extends TradableList> storage) {
super(offer, tradeAmount, tradingPeer, storage);
log.trace("Created by constructor");
}
public BuyerTrade(Offer offer, Storage<? extends TradableList> storage) {
super(offer, storage);
log.trace("Created by constructor");
}
@Override

View File

@ -45,12 +45,10 @@ public class SellerAsOffererTrade extends SellerTrade implements OffererTrade, S
public SellerAsOffererTrade(Offer offer, Storage<? extends TradableList> 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();

View File

@ -45,12 +45,10 @@ public class SellerAsTakerTrade extends SellerTrade implements TakerTrade, Seria
public SellerAsTakerTrade(Offer offer, Coin tradeAmount, Peer tradingPeer, Storage<? extends TradableList> 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();

View File

@ -40,12 +40,10 @@ public abstract class SellerTrade extends Trade implements Serializable {
public SellerTrade(Offer offer, Coin tradeAmount, Peer tradingPeer, Storage<? extends TradableList> storage) {
super(offer, tradeAmount, tradingPeer, storage);
log.trace("Created by constructor");
}
public SellerTrade(Offer offer, Storage<? extends TradableList> storage) {
super(offer, storage);
log.trace("Created by constructor");
}
@Override

View File

@ -49,8 +49,6 @@ public class TradableList<T extends Tradable> extends ArrayList<T> implements Se
///////////////////////////////////////////////////////////////////////////////////////////
public TradableList(Storage<TradableList<T>> storage, String fileName) {
log.trace("Created by constructor");
this.storage = storage;
TradableList persisted = storage.initAndGetPersisted(this, fileName);
@ -62,7 +60,6 @@ public class TradableList<T extends Tradable> extends ArrayList<T> implements Se
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
log.trace("Created from serialized form.");
}
@Override

View File

@ -128,7 +128,6 @@ abstract public class Trade implements Tradable, Model, Serializable {
///////////////////////////////////////////////////////////////////////////////////////////
protected Trade(Offer offer, Storage<? extends TradableList> 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();

View File

@ -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,

View File

@ -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.");
}

View File

@ -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<String> BTC_DENOMINATIONS = Arrays.asList(MonetaryFormat.CODE_BTC/*, MonetaryFormat.CODE_MBTC*/);
public static List<String> getBtcDenominations() {
return BTC_DENOMINATIONS;
}
transient private final Storage<Preferences> 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<Preferences> storage, Environment environment) {
public Preferences(Storage<Preferences> 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();
}

View File

@ -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())));
}

View File

@ -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();

View File

@ -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))

View File

@ -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

View File

@ -68,7 +68,7 @@ public class UpdateProcess {
protected Timer timeoutTimer;
@Inject
public UpdateProcess(Environment environment) {
public UpdateProcess(BitsquareEnvironment environment) {
this.environment = environment;
}

View File

@ -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<BootstrappedPeerBuilder.State> bootstrapStateAsObservable = clientNode.bootstrap(p2pId, keyRing.getDhtSignatureKeyPair());
Observable<BootstrappedPeerBuilder.State> bootstrapStateAsObservable = clientNode.bootstrap(keyRing.getDhtSignatureKeyPair());
bootstrapStateAsObservable.publish();
bootstrapStateAsObservable.subscribe(
state -> Platform.runLater(() -> setBootstrapState(state)),

View File

@ -85,8 +85,8 @@
<TextField fx:id="nodeAddress" GridPane.rowIndex="6" GridPane.columnIndex="1"
mouseTransparent="true" focusTraversable="false"/>
<Label text="P2P bootstrap node address:" GridPane.rowIndex="7"/>
<TextField fx:id="bootstrapNodeAddress" GridPane.rowIndex="7" GridPane.columnIndex="1"
<Label text="P2P bootstrap node addresses:" GridPane.rowIndex="7" GridPane.valignment="TOP"/>
<TextArea fx:id="bootstrapNodeAddress" GridPane.rowIndex="7" GridPane.columnIndex="1"
mouseTransparent="true" focusTraversable="false"/>
<columnConstraints>

View File

@ -25,11 +25,13 @@ import io.bitsquare.gui.common.view.InitializableView;
import io.bitsquare.gui.components.Popups;
import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.locale.BSResources;
import io.bitsquare.p2p.BootstrapNodes;
import io.bitsquare.p2p.ClientNode;
import io.bitsquare.user.Preferences;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import javax.inject.Inject;
@ -48,17 +50,20 @@ public class NetworkSettingsView extends InitializableView {
private final String bitcoinNetworkString;
private final WalletService walletService;
private BootstrapNodes bootstrapNodes;
private final Preferences preferences;
private final ClientNode clientNode;
@FXML TextField bitcoinNetwork, connectionType, nodeAddress, bootstrapNodeAddress, connectedPeersBTC, connectedPeersP2P;
@FXML TextField bitcoinNetwork, connectionType, nodeAddress, connectedPeersBTC, connectedPeersP2P;
@FXML CheckBox useUPnP;
@FXML ComboBox<BitcoinNetwork> netWorkComboBox;
@FXML TextArea bootstrapNodeAddress;
@Inject
public NetworkSettingsView(WalletService walletService, ClientNode clientNode, Preferences preferences, BSFormatter
public NetworkSettingsView(WalletService walletService, ClientNode clientNode, BootstrapNodes bootstrapNodes, Preferences preferences, BSFormatter
formatter) {
this.walletService = walletService;
this.bootstrapNodes = bootstrapNodes;
this.preferences = preferences;
this.bitcoinNetworkString = formatter.formatBitcoinNetwork(preferences.getBitcoinNetwork());
this.clientNode = clientNode;
@ -72,7 +77,10 @@ public class NetworkSettingsView extends InitializableView {
connectionType.setText(clientNode.getConnectionType().toString());
connectedPeersP2P.textProperty().bind(createStringBinding(() -> String.valueOf(clientNode.numPeersProperty().get()), clientNode.numPeersProperty()));
nodeAddress.setText(clientNode.getClientNodeInfo());
bootstrapNodeAddress.setText(clientNode.getBootstrapNode().toString());
String bootstrapNodesText = bootstrapNodes.getBootstrapNodes().stream().map(e -> e.toString() + "\n").collect(Collectors.toList()).toString()
.replace(", ", "").replace("[", "").replace("\n]", "");
bootstrapNodeAddress.setPrefRowCount(bootstrapNodes.getBootstrapNodes().size());
bootstrapNodeAddress.setText(bootstrapNodesText);
useUPnP.setSelected(preferences.getUseUPnP());