mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-04-19 07:15:54 -04:00
Use separate dirs for version and btc network, bootstrap to all bootstrap nodes, change config of bootstrap node
This commit is contained in:
parent
7a9de65e86
commit
fc3634af7b
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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()));
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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")),
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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.");
|
||||
}
|
||||
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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())));
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -68,7 +68,7 @@ public class UpdateProcess {
|
||||
protected Timer timeoutTimer;
|
||||
|
||||
@Inject
|
||||
public UpdateProcess(Environment environment) {
|
||||
public UpdateProcess(BitsquareEnvironment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
|
@ -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)),
|
||||
|
@ -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>
|
||||
|
@ -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());
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user