Add Network id

This commit is contained in:
Manfred Karrer 2015-11-10 15:30:47 +01:00
parent 09321c89b3
commit 5618f23654
28 changed files with 264 additions and 178 deletions

View file

@ -14,6 +14,7 @@ public class ProgramArguments {
public static final String NAME_KEY = "node.name"; public static final String NAME_KEY = "node.name";
public static final String PORT_KEY = "node.port"; public static final String PORT_KEY = "node.port";
public static final String NETWORK_ID = "network.id";
private static final Logger log = LoggerFactory.getLogger(ProgramArguments.class); private static final Logger log = LoggerFactory.getLogger(ProgramArguments.class);
} }

View file

@ -192,11 +192,13 @@ public class BitsquareEnvironment extends StandardEnvironment {
setProperty(Storage.DIR_KEY, Paths.get(btcNetworkDir, "db").toString()); setProperty(Storage.DIR_KEY, Paths.get(btcNetworkDir, "db").toString());
setProperty(KeyStorage.DIR_KEY, Paths.get(btcNetworkDir, "keys").toString()); setProperty(KeyStorage.DIR_KEY, Paths.get(btcNetworkDir, "keys").toString());
setProperty(ProgramArguments.TOR_DIR, Paths.get(btcNetworkDir, "tor").toString()); setProperty(ProgramArguments.TOR_DIR, Paths.get(btcNetworkDir, "tor").toString());
setProperty(ProgramArguments.NETWORK_ID, String.valueOf(bitcoinNetwork.ordinal()));
} }
}); });
} }
private static String defaultUserDataDir() { public static String defaultUserDataDir() {
if (Utilities.isWindows()) if (Utilities.isWindows())
return System.getenv("APPDATA"); return System.getenv("APPDATA");
else if (Utilities.isOSX()) else if (Utilities.isOSX())

View file

@ -21,8 +21,10 @@ import io.bitsquare.app.Version;
import io.bitsquare.p2p.messaging.MailboxMessage; import io.bitsquare.p2p.messaging.MailboxMessage;
public abstract class DisputeMessage implements MailboxMessage { public abstract class DisputeMessage implements MailboxMessage {
private final int networkId = Version.NETWORK_ID;
@Override @Override
public int networkId() { public int networkId() {
return Version.NETWORK_ID; return networkId;
} }
} }

View file

@ -27,6 +27,7 @@ public abstract class OfferMessage implements MailMessage {
// That object is sent over the wire, so we need to take care of version compatibility. // That object is sent over the wire, so we need to take care of version compatibility.
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION; private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
private final int networkId = Version.NETWORK_ID;
public final String offerId; public final String offerId;
protected OfferMessage(String offerId) { protected OfferMessage(String offerId) {
@ -35,6 +36,6 @@ public abstract class OfferMessage implements MailMessage {
@Override @Override
public int networkId() { public int networkId() {
return Version.NETWORK_ID; return networkId;
} }
} }

View file

@ -27,6 +27,7 @@ public abstract class TradeMessage implements MailMessage {
// That object is sent over the wire, so we need to take care of version compatibility. // That object is sent over the wire, so we need to take care of version compatibility.
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION; private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
private final int networkId = Version.NETWORK_ID;
public final String tradeId; public final String tradeId;
@Override @Override
@ -51,6 +52,6 @@ public abstract class TradeMessage implements MailMessage {
@Override @Override
public int networkId() { public int networkId() {
return Version.NETWORK_ID; return networkId;
} }
} }

View file

@ -29,7 +29,6 @@ import io.bitsquare.btc.AddressEntry;
import io.bitsquare.btc.TradeWalletService; import io.bitsquare.btc.TradeWalletService;
import io.bitsquare.btc.WalletService; import io.bitsquare.btc.WalletService;
import io.bitsquare.btc.listeners.BalanceListener; import io.bitsquare.btc.listeners.BalanceListener;
import io.bitsquare.common.crypto.KeyRing;
import io.bitsquare.gui.common.model.ViewModel; import io.bitsquare.gui.common.model.ViewModel;
import io.bitsquare.gui.components.BalanceTextField; import io.bitsquare.gui.components.BalanceTextField;
import io.bitsquare.gui.components.BalanceWithConfirmationTextField; import io.bitsquare.gui.components.BalanceWithConfirmationTextField;
@ -126,9 +125,8 @@ class MainViewModel implements ViewModel {
public MainViewModel(WalletService walletService, TradeWalletService tradeWalletService, public MainViewModel(WalletService walletService, TradeWalletService tradeWalletService,
ArbitratorManager arbitratorManager, P2PService p2PService, TradeManager tradeManager, ArbitratorManager arbitratorManager, P2PService p2PService, TradeManager tradeManager,
OpenOfferManager openOfferManager, DisputeManager disputeManager, Preferences preferences, OpenOfferManager openOfferManager, DisputeManager disputeManager, Preferences preferences,
KeyRing keyRing, User user, User user, AlertManager alertManager, WalletPasswordPopup walletPasswordPopup,
AlertManager alertManager, BSFormatter formatter) {
WalletPasswordPopup walletPasswordPopup, BSFormatter formatter) {
this.user = user; this.user = user;
log.debug("in"); log.debug("in");
this.walletService = walletService; this.walletService = walletService;

View file

@ -29,7 +29,7 @@ import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.p2p.Address; import io.bitsquare.p2p.Address;
import io.bitsquare.p2p.P2PService; import io.bitsquare.p2p.P2PService;
import io.bitsquare.p2p.P2PServiceListener; import io.bitsquare.p2p.P2PServiceListener;
import io.bitsquare.p2p.network.TorNetworkNode; import io.bitsquare.p2p.network.LocalhostNetworkNode;
import io.bitsquare.p2p.seed.SeedNodesRepository; import io.bitsquare.p2p.seed.SeedNodesRepository;
import io.bitsquare.user.Preferences; import io.bitsquare.user.Preferences;
import javafx.beans.value.ChangeListener; import javafx.beans.value.ChangeListener;
@ -68,13 +68,12 @@ public class NetworkSettingsView extends ActivatableViewAndModel<GridPane, Activ
formatter) { formatter) {
this.walletService = walletService; this.walletService = walletService;
this.preferences = preferences; this.preferences = preferences;
this.bitcoinNetworkString = formatter.formatBitcoinNetwork(preferences.getBitcoinNetwork()); BitcoinNetwork bitcoinNetwork = preferences.getBitcoinNetwork();
this.bitcoinNetworkString = formatter.formatBitcoinNetwork(bitcoinNetwork);
this.p2PService = p2PService; this.p2PService = p2PService;
if (p2PService.getNetworkNode() instanceof TorNetworkNode) boolean useLocalhost = p2PService.getNetworkNode() instanceof LocalhostNetworkNode;
this.seedNodeAddresses = seedNodesRepository.getTorSeedNodeAddresses(); this.seedNodeAddresses = seedNodesRepository.geSeedNodeAddresses(useLocalhost, bitcoinNetwork.ordinal());
else
this.seedNodeAddresses = seedNodesRepository.getLocalhostSeedNodeAddresses();
} }
public void initialize() { public void initialize() {

View file

@ -9,6 +9,7 @@ public final class SealedAndSignedMessage implements MailboxMessage {
// That object is sent over the wire, so we need to take care of version compatibility. // That object is sent over the wire, so we need to take care of version compatibility.
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION; private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
private final int networkId = Version.NETWORK_ID;
public final SealedAndSigned sealedAndSigned; public final SealedAndSigned sealedAndSigned;
public SealedAndSignedMessage(SealedAndSigned sealedAndSigned) { public SealedAndSignedMessage(SealedAndSigned sealedAndSigned) {
@ -22,6 +23,6 @@ public final class SealedAndSignedMessage implements MailboxMessage {
@Override @Override
public int networkId() { public int networkId() {
return Version.NETWORK_ID; return networkId;
} }
} }

View file

@ -52,5 +52,8 @@ public class P2PModule extends AppModule {
// use a fixed port as arbitrator use that for his ID // use a fixed port as arbitrator use that for his ID
Integer port = env.getProperty(ProgramArguments.PORT_KEY, int.class, 9999); Integer port = env.getProperty(ProgramArguments.PORT_KEY, int.class, 9999);
bind(int.class).annotatedWith(Names.named(ProgramArguments.PORT_KEY)).toInstance(port); bind(int.class).annotatedWith(Names.named(ProgramArguments.PORT_KEY)).toInstance(port);
Integer networkId = env.getProperty(ProgramArguments.NETWORK_ID, int.class, 1);
bind(int.class).annotatedWith(Names.named(ProgramArguments.NETWORK_ID)).toInstance(networkId);
} }
} }

View file

@ -42,7 +42,6 @@ import java.io.File;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.PublicKey; import java.security.PublicKey;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.CopyOnWriteArraySet;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
@ -69,7 +68,7 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis
private final CopyOnWriteArraySet<DecryptedMailListener> decryptedMailListeners = new CopyOnWriteArraySet<>(); private final CopyOnWriteArraySet<DecryptedMailListener> decryptedMailListeners = new CopyOnWriteArraySet<>();
private final CopyOnWriteArraySet<DecryptedMailboxListener> decryptedMailboxListeners = new CopyOnWriteArraySet<>(); private final CopyOnWriteArraySet<DecryptedMailboxListener> decryptedMailboxListeners = new CopyOnWriteArraySet<>();
private final CopyOnWriteArraySet<P2PServiceListener> p2pServiceListeners = new CopyOnWriteArraySet<>(); private final CopyOnWriteArraySet<P2PServiceListener> p2pServiceListeners = new CopyOnWriteArraySet<>();
private final Map<DecryptedMsgWithPubKey, ProtectedMailboxData> mailboxMap = new ConcurrentHashMap<>(); private final Map<DecryptedMsgWithPubKey, ProtectedMailboxData> mailboxMap = new HashMap<>();
private volatile boolean shutDownInProgress; private volatile boolean shutDownInProgress;
private Address connectedSeedNode; private Address connectedSeedNode;
private final Set<Address> authenticatedPeerAddresses = new HashSet<>(); private final Set<Address> authenticatedPeerAddresses = new HashSet<>();
@ -91,6 +90,7 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis
@Named(ProgramArguments.PORT_KEY) int port, @Named(ProgramArguments.PORT_KEY) int port,
@Named(ProgramArguments.TOR_DIR) File torDir, @Named(ProgramArguments.TOR_DIR) File torDir,
@Named(ProgramArguments.USE_LOCALHOST) boolean useLocalhost, @Named(ProgramArguments.USE_LOCALHOST) boolean useLocalhost,
@Named(ProgramArguments.NETWORK_ID) int networkId,
@Nullable EncryptionService encryptionService, @Nullable EncryptionService encryptionService,
KeyRing keyRing, KeyRing keyRing,
@Named("storage.dir") File storageDir) { @Named("storage.dir") File storageDir) {
@ -103,20 +103,14 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis
this.keyRing = keyRing; this.keyRing = keyRing;
this.storageDir = storageDir; this.storageDir = storageDir;
init(); init(networkId);
} }
private void init() { private void init(int networkId) {
Log.traceCall(); Log.traceCall();
// network // network
Set<Address> seedNodeAddresses; networkNode = useLocalhost ? new LocalhostNetworkNode(port) : new TorNetworkNode(port, torDir);
if (useLocalhost) { Set<Address> seedNodeAddresses = seedNodesRepository.geSeedNodeAddresses(useLocalhost, networkId);
networkNode = new LocalhostNetworkNode(port);
seedNodeAddresses = seedNodesRepository.getLocalhostSeedNodeAddresses();
} else {
networkNode = new TorNetworkNode(port, torDir);
seedNodeAddresses = seedNodesRepository.getTorSeedNodeAddresses();
}
// peer group // peer group
peerGroup = new PeerGroup(networkNode, seedNodeAddresses); peerGroup = new PeerGroup(networkNode, seedNodeAddresses);
@ -564,13 +558,19 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis
Log.traceCall(); Log.traceCall();
checkAuthentication(); checkAuthentication();
ProtectedMailboxData mailboxData = mailboxMap.get(decryptedMsgWithPubKey); if (mailboxMap.containsKey(decryptedMsgWithPubKey)) {
if (mailboxData != null && mailboxData.expirablePayload instanceof ExpirableMailboxPayload) { ProtectedMailboxData mailboxData = mailboxMap.get(decryptedMsgWithPubKey);
checkArgument(mailboxData.receiversPubKey.equals(keyRing.getSignatureKeyPair().getPublic()), if (mailboxData != null && mailboxData.expirablePayload instanceof ExpirableMailboxPayload) {
"mailboxData.receiversPubKey is not matching with our key. That must not happen."); checkArgument(mailboxData.receiversPubKey.equals(keyRing.getSignatureKeyPair().getPublic()),
removeMailboxData((ExpirableMailboxPayload) mailboxData.expirablePayload, mailboxData.receiversPubKey); "mailboxData.receiversPubKey is not matching with our key. That must not happen.");
mailboxMap.remove(decryptedMsgWithPubKey); removeMailboxData((ExpirableMailboxPayload) mailboxData.expirablePayload, mailboxData.receiversPubKey);
log.trace("Removed successfully protectedExpirableData."); mailboxMap.remove(decryptedMsgWithPubKey);
log.trace("Removed successfully protectedExpirableData.");
}
} else {
log.warn("decryptedMsgWithPubKey not found in mailboxMap. That should never happen." +
"\ndecryptedMsgWithPubKey={}\nmailboxMap={}", decryptedMsgWithPubKey, mailboxMap);
} }
} }

View file

@ -26,6 +26,7 @@ public final class DecryptedMsgWithPubKey implements MailMessage {
// That object is sent over the wire, so we need to take care of version compatibility. // That object is sent over the wire, so we need to take care of version compatibility.
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION; private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
private final int networkId = Version.NETWORK_ID;
public final Message message; public final Message message;
public final PublicKey signaturePubKey; public final PublicKey signaturePubKey;
@ -36,7 +37,7 @@ public final class DecryptedMsgWithPubKey implements MailMessage {
@Override @Override
public int networkId() { public int networkId() {
return Version.NETWORK_ID; return networkId;
} }
@Override @Override

View file

@ -35,7 +35,6 @@ public class Connection implements MessageListener {
private static final int SOCKET_TIMEOUT = 30 * 60 * 1000; // 30 min. private static final int SOCKET_TIMEOUT = 30 * 60 * 1000; // 30 min.
private InputHandler inputHandler; private InputHandler inputHandler;
private volatile boolean isAuthenticated; private volatile boolean isAuthenticated;
private String connectionId;
public static int getMaxMsgSize() { public static int getMaxMsgSize() {
return MAX_MSG_SIZE; return MAX_MSG_SIZE;
@ -48,7 +47,7 @@ public class Connection implements MessageListener {
private final String portInfo; private final String portInfo;
private final String uid; private final String uid;
private final ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); private final ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
public final String objectId = super.toString().split("@")[1]; public final String objectId;
// set in init // set in init
private ObjectOutputStream objectOutputStream; private ObjectOutputStream objectOutputStream;
@ -76,6 +75,8 @@ public class Connection implements MessageListener {
this.messageListener = messageListener; this.messageListener = messageListener;
this.connectionListener = connectionListener; this.connectionListener = connectionListener;
objectId = super.toString().split("@")[1];
Log.traceCall(); Log.traceCall();
uid = UUID.randomUUID().toString(); uid = UUID.randomUUID().toString();
if (socket.getLocalPort() == 0) if (socket.getLocalPort() == 0)
@ -335,10 +336,6 @@ public class Connection implements MessageListener {
'}'; '}';
} }
public String getConnectionId() {
return connectionId;
}
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// SharedSpace // SharedSpace
@ -379,12 +376,23 @@ public class Connection implements MessageListener {
public void reportIllegalRequest(IllegalRequest illegalRequest) { public void reportIllegalRequest(IllegalRequest illegalRequest) {
Log.traceCall(); Log.traceCall();
log.warn("We got reported an illegal request " + illegalRequest); log.warn("We got reported an illegal request " + illegalRequest);
int prevCounter = illegalRequests.get(illegalRequest); int violations;
if (prevCounter > illegalRequest.maxTolerance) { if (illegalRequests.contains(illegalRequest))
log.warn("We close connection as we received too many illegal requests.\n" + illegalRequests.toString()); violations = illegalRequests.get(illegalRequest);
connection.shutDown(false); else
violations = 0;
violations++;
illegalRequests.put(illegalRequest, violations);
if (violations >= illegalRequest.maxTolerance) {
log.warn("We close connection as we received too many invalid requests.\n" +
"violations={}\n" +
"illegalRequest={}\n" +
"illegalRequests={}", violations, illegalRequest, illegalRequests.toString());
shutDown(false);
} else { } else {
illegalRequests.put(illegalRequest, ++prevCounter); illegalRequests.put(illegalRequest, ++violations);
} }
} }
@ -406,15 +414,15 @@ public class Connection implements MessageListener {
e.printStackTrace(); e.printStackTrace();
} }
if (!stopped) { shutDown(false);
stopped = true;
connection.shutDown(false);
}
} }
public void shutDown(boolean sendCloseConnectionMessage) { public void shutDown(boolean sendCloseConnectionMessage) {
Log.traceCall(); Log.traceCall();
connection.shutDown(sendCloseConnectionMessage); if (!stopped) {
stopped = true;
connection.shutDown(sendCloseConnectionMessage);
}
} }
@ -422,8 +430,8 @@ public class Connection implements MessageListener {
return socket; return socket;
} }
public String getConnectionId() { public String getConnectionInfo() {
return connection.getConnectionId(); return connection.toString();
} }
public void stop() { public void stop() {
@ -483,9 +491,9 @@ public class Connection implements MessageListener {
Thread.currentThread().setName("InputHandler-" + portInfo); Thread.currentThread().setName("InputHandler-" + portInfo);
while (!stopped && !Thread.currentThread().isInterrupted()) { while (!stopped && !Thread.currentThread().isInterrupted()) {
try { try {
log.trace("InputHandler waiting for incoming messages connection=" + sharedSpace.getConnectionId()); log.trace("InputHandler waiting for incoming messages connection=" + sharedSpace.getConnectionInfo());
Object rawInputObject = objectInputStream.readObject(); Object rawInputObject = objectInputStream.readObject();
log.info("New data arrived at inputHandler of connection=" + sharedSpace.getConnectionId() log.info("New data arrived at inputHandler of connection=" + sharedSpace.getConnectionInfo()
+ " rawInputObject " + rawInputObject); + " rawInputObject " + rawInputObject);
int size = ByteArrayUtils.objectToByteArray(rawInputObject).length; int size = ByteArrayUtils.objectToByteArray(rawInputObject).length;

View file

@ -1,10 +1,11 @@
package io.bitsquare.p2p.network; package io.bitsquare.p2p.network;
public enum IllegalRequest { public enum IllegalRequest {
// TODO check for needed allowed tolerance
MaxSizeExceeded(1), MaxSizeExceeded(1),
NotAuthenticated(2), NotAuthenticated(1),
InvalidDataType(2), InvalidDataType(1),
WrongNetworkId(2); WrongNetworkId(1);
public final int maxTolerance; public final int maxTolerance;

View file

@ -7,8 +7,10 @@ public final class CloseConnectionMessage implements Message {
// That object is sent over the wire, so we need to take care of version compatibility. // That object is sent over the wire, so we need to take care of version compatibility.
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION; private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
private final int networkId = Version.NETWORK_ID;
@Override @Override
public int networkId() { public int networkId() {
return Version.NETWORK_ID; return networkId;
} }
} }

View file

@ -4,8 +4,10 @@ import io.bitsquare.app.Version;
import io.bitsquare.p2p.Message; import io.bitsquare.p2p.Message;
public abstract class AuthenticationMessage implements Message { public abstract class AuthenticationMessage implements Message {
private final int networkId = Version.NETWORK_ID;
@Override @Override
public int networkId() { public int networkId() {
return Version.NETWORK_ID; return networkId;
} }
} }

View file

@ -4,8 +4,10 @@ import io.bitsquare.app.Version;
import io.bitsquare.p2p.Message; import io.bitsquare.p2p.Message;
public abstract class MaintenanceMessage implements Message { public abstract class MaintenanceMessage implements Message {
private final int networkId = Version.NETWORK_ID;
@Override @Override
public int networkId() { public int networkId() {
return Version.NETWORK_ID; return networkId;
} }
} }

View file

@ -14,6 +14,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -29,8 +31,10 @@ public class SeedNode {
private Set<Address> seedNodes; private Set<Address> seedNodes;
private P2PService p2PService; private P2PService p2PService;
private boolean stopped; private boolean stopped;
private final String defaultUserDataDir;
public SeedNode() { public SeedNode(String defaultUserDataDir) {
this.defaultUserDataDir = defaultUserDataDir;
Log.traceCall(); Log.traceCall();
} }
@ -39,59 +43,73 @@ public class SeedNode {
// API // API
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// args: myAddress (incl. port) BitcoinNetworkId maxConnections useLocalhost seedNodes (separated with |) // args: myAddress (incl. port) bitcoinNetworkId maxConnections useLocalhost seedNodes (separated with |)
// 2. and 3. args are optional // 2. and 3. args are optional
// eg. lmvdenjkyvx2ovga.onion:8001 0 20 false eo5ay2lyzrfvx2nr.onion:8002|si3uu56adkyqkldl.onion:8003 // eg. lmvdenjkyvx2ovga.onion:8001 0 20 false eo5ay2lyzrfvx2nr.onion:8002|si3uu56adkyqkldl.onion:8003
// or when using localhost: localhost:8001 2 20 true localhost:8002|localhost:8003 // or when using localhost: localhost:8001 2 20 true localhost:8002|localhost:8003
// BitcoinNetworkId: The id for the bitcoin network (Mainnet = 0, TestNet = 1, Regtest = 2) // BitcoinNetworkId: The id for the bitcoin network (Mainnet = 0, TestNet = 1, Regtest = 2)
public void processArgs(String[] args) { public void processArgs(String[] args) {
Log.traceCall(); Log.traceCall();
if (args.length > 0) { try {
String arg0 = args[0]; if (args.length > 0) {
checkArgument(arg0.contains(":") && arg0.split(":").length == 2 && arg0.split(":")[1].length() == 4, "Wrong program argument"); String arg0 = args[0];
mySeedNodeAddress = new Address(arg0); checkArgument(arg0.contains(":") && arg0.split(":").length == 2 && arg0.split(":")[1].length() > 3, "Wrong program argument: " + arg0);
if (args.length > 1) { mySeedNodeAddress = new Address(arg0);
String arg1 = args[1]; if (args.length > 1) {
int networkId = Integer.parseInt(arg1); String arg1 = args[1];
checkArgument(networkId > -1 && networkId < 3, "networkId out of scope (Mainnet = 0, TestNet = 1, Regtest = 2)"); int networkId = Integer.parseInt(arg1);
Version.NETWORK_ID = networkId; checkArgument(networkId > -1 && networkId < 3,
if (args.length > 2) { "networkId out of scope (Mainnet = 0, TestNet = 1, Regtest = 2)");
String arg2 = args[2]; Version.NETWORK_ID = networkId;
int maxConnections = Integer.parseInt(arg2); if (args.length > 2) {
checkArgument(maxConnections < 1000, "maxConnections seems to be a bit too high..."); String arg2 = args[2];
PeerGroup.setMaxConnections(maxConnections); int maxConnections = Integer.parseInt(arg2);
} else { checkArgument(maxConnections < 1000, "maxConnections seems to be a bit too high...");
// we keep default a higher connection size for seed nodes PeerGroup.setMaxConnections(maxConnections);
PeerGroup.setMaxConnections(50); } else {
} // we keep default a higher connection size for seed nodes
if (args.length > 3) { PeerGroup.setMaxConnections(50);
String arg3 = args[3]; }
checkArgument(arg3.equals("true") || arg3.equals("false")); if (args.length > 3) {
useLocalhost = ("true").equals(arg3); String arg3 = args[3];
} checkArgument(arg3.equals("true") || arg3.equals("false"));
if (args.length > 4) { useLocalhost = ("true").equals(arg3);
String arg4 = args[4]; }
checkArgument(arg4.contains(":") && arg4.split(":").length > 1 && arg4.split(":")[1].length() > 3, "Wrong program argument"); if (args.length > 4) {
List<String> list = Arrays.asList(arg4.split("|")); String arg4 = args[4];
seedNodes = new HashSet<>(); checkArgument(arg4.contains(":") && arg4.split(":").length > 1 && arg4.split(":")[1].length() > 3,
list.forEach(e -> { "Wrong program argument");
checkArgument(e.contains(":") && e.split(":").length == 2 && e.split(":")[1].length() == 4, "Wrong program argument"); List<String> list = Arrays.asList(arg4.split("|"));
seedNodes.add(new Address(e)); seedNodes = new HashSet<>();
}); list.forEach(e -> {
seedNodes.remove(mySeedNodeAddress); checkArgument(e.contains(":") && e.split(":").length == 2 && e.split(":")[1].length() == 4,
} else if (args.length > 5) { "Wrong program argument");
log.error("Too many program arguments." + seedNodes.add(new Address(e));
"\nProgram arguments: myAddress (incl. port) BitcoinNetworkId maxConnections useLocalhost seedNodes (separated with |)"); });
seedNodes.remove(mySeedNodeAddress);
} else if (args.length > 5) {
log.error("Too many program arguments." +
"\nProgram arguments: myAddress (incl. port) bitcoinNetworkId " +
"maxConnections useLocalhost seedNodes (separated with |)");
}
} }
} }
} catch (Throwable t) {
shutDown();
} }
} }
public void createAndStartP2PService() { public void createAndStartP2PService() {
createAndStartP2PService(null, null, mySeedNodeAddress, useLocalhost, seedNodes, null); createAndStartP2PService(null, null, mySeedNodeAddress, useLocalhost, Version.NETWORK_ID, seedNodes, null);
} }
public void createAndStartP2PService(EncryptionService encryptionService, KeyRing keyRing, Address mySeedNodeAddress, boolean useLocalhost, @Nullable Set<Address> seedNodes, @Nullable P2PServiceListener listener) { public void createAndStartP2PService(EncryptionService encryptionService,
KeyRing keyRing,
Address mySeedNodeAddress,
boolean useLocalhost,
int networkId,
@Nullable Set<Address> seedNodes,
@Nullable P2PServiceListener listener) {
Log.traceCall(); Log.traceCall();
SeedNodesRepository seedNodesRepository = new SeedNodesRepository(); SeedNodesRepository seedNodesRepository = new SeedNodesRepository();
if (seedNodes != null && !seedNodes.isEmpty()) { if (seedNodes != null && !seedNodes.isEmpty()) {
@ -100,8 +118,18 @@ public class SeedNode {
else else
seedNodesRepository.setTorSeedNodeAddresses(seedNodes); seedNodesRepository.setTorSeedNodeAddresses(seedNodes);
} }
Path seedNodePath = Paths.get(defaultUserDataDir,
"Bitsquare_seed_node_" + String.valueOf(mySeedNodeAddress.getFullAddress().replace(":", "_")));
File storageDir = Paths.get(seedNodePath.toString(), "db").toFile();
File torDir = Paths.get(seedNodePath.toString(), "tor").toFile();
p2PService = new P2PService(seedNodesRepository, mySeedNodeAddress.port, new File("bitsquare_seed_node_" + mySeedNodeAddress.port), useLocalhost, encryptionService, keyRing, new File("dummy")); if (storageDir.mkdirs())
log.info("Created storageDir at " + storageDir.getAbsolutePath());
if (torDir.mkdirs())
log.info("Created torDir at " + torDir.getAbsolutePath());
p2PService = new P2PService(seedNodesRepository, mySeedNodeAddress.port, torDir,
useLocalhost, networkId, encryptionService, keyRing, storageDir);
p2PService.removeMySeedNodeAddressFromList(mySeedNodeAddress); p2PService.removeMySeedNodeAddressFromList(mySeedNodeAddress);
p2PService.start(listener); p2PService.start(listener);
} }

View file

@ -4,33 +4,53 @@ import com.google.common.collect.Sets;
import io.bitsquare.p2p.Address; import io.bitsquare.p2p.Address;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
public class SeedNodesRepository { public class SeedNodesRepository {
// mainnet use port 8000
// testnet use port 8001
// regtest use port 8002
private Set<Address> torSeedNodeAddresses = Sets.newHashSet( private Set<Address> torSeedNodeAddresses = Sets.newHashSet(
// mainnet
new Address("lmvdenjkyvx2ovga.onion:8000"),
new Address("eo5ay2lyzrfvx2nr.onion:8000"),
new Address("si3uu56adkyqkldl.onion:8000"),
// testnet
new Address("lmvdenjkyvx2ovga.onion:8001"), new Address("lmvdenjkyvx2ovga.onion:8001"),
new Address("eo5ay2lyzrfvx2nr.onion:8001"),
new Address("si3uu56adkyqkldl.onion:8001"),
// regtest
new Address("lmvdenjkyvx2ovga.onion:8002"),
new Address("eo5ay2lyzrfvx2nr.onion:8002"), new Address("eo5ay2lyzrfvx2nr.onion:8002"),
new Address("si3uu56adkyqkldl.onion:8003") new Address("si3uu56adkyqkldl.onion:8002")
); );
private Set<Address> localhostSeedNodeAddresses = Sets.newHashSet( private Set<Address> localhostSeedNodeAddresses = Sets.newHashSet(
new Address("localhost:8001"), // mainnet
new Address("localhost:8002"), new Address("localhost:2000"),
new Address("localhost:8003") new Address("localhost:3000"),
new Address("localhost:4000"),
// testnet
new Address("localhost:2001"),
new Address("localhost:3001"),
new Address("localhost:4001"),
// regtest
new Address("localhost:2002"),
new Address("localhost:3002"),
new Address("localhost:4002")
); );
public Set<Address> getTorSeedNodeAddresses() { public Set<Address> geSeedNodeAddresses(boolean useLocalhost, int networkId) {
return torSeedNodeAddresses; String networkIdAsString = String.valueOf(networkId);
} Set<Address> addresses = useLocalhost ? localhostSeedNodeAddresses : torSeedNodeAddresses;
return addresses.stream()
public Set<Address> geSeedNodeAddresses(boolean useLocalhost) { .filter(e -> String.valueOf(e.port).endsWith(networkIdAsString)).collect(Collectors.toSet());
return useLocalhost ? localhostSeedNodeAddresses : torSeedNodeAddresses;
}
public Set<Address> getLocalhostSeedNodeAddresses() {
return localhostSeedNodeAddresses;
} }
public void setTorSeedNodeAddresses(Set<Address> torSeedNodeAddresses) { public void setTorSeedNodeAddresses(Set<Address> torSeedNodeAddresses) {

View file

@ -28,10 +28,10 @@ import java.io.File;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.KeyPair; import java.security.KeyPair;
import java.security.PublicKey; import java.security.PublicKey;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.CopyOnWriteArraySet;
// Run in UserThread // Run in UserThread
@ -42,10 +42,10 @@ public class ProtectedExpirableDataStorage implements MessageListener {
public static int CHECK_TTL_INTERVAL = 10 * 60 * 1000; public static int CHECK_TTL_INTERVAL = 10 * 60 * 1000;
private final PeerGroup peerGroup; private final PeerGroup peerGroup;
private final Map<BigInteger, ProtectedData> map = new ConcurrentHashMap<>(); private final Map<BigInteger, ProtectedData> map = new HashMap<>();
private final CopyOnWriteArraySet<HashMapChangedListener> hashMapChangedListeners = new CopyOnWriteArraySet<>(); private final CopyOnWriteArraySet<HashMapChangedListener> hashMapChangedListeners = new CopyOnWriteArraySet<>();
private ConcurrentHashMap<BigInteger, Integer> sequenceNumberMap = new ConcurrentHashMap<>(); private HashMap<BigInteger, Integer> sequenceNumberMap = new HashMap<>();
private final Storage<ConcurrentHashMap> storage; private final Storage<HashMap> storage;
private final Timer timer = new Timer(); private final Timer timer = new Timer();
private volatile boolean shutDownInProgress; private volatile boolean shutDownInProgress;
@ -65,7 +65,7 @@ public class ProtectedExpirableDataStorage implements MessageListener {
private void init() { private void init() {
Log.traceCall(); Log.traceCall();
ConcurrentHashMap<BigInteger, Integer> persisted = storage.initAndGetPersisted(sequenceNumberMap, "sequenceNumberMap"); HashMap<BigInteger, Integer> persisted = storage.initAndGetPersisted(sequenceNumberMap, "sequenceNumberMap");
if (persisted != null) { if (persisted != null) {
sequenceNumberMap = persisted; sequenceNumberMap = persisted;
} }

View file

@ -4,8 +4,10 @@ import io.bitsquare.app.Version;
import io.bitsquare.p2p.Message; import io.bitsquare.p2p.Message;
public abstract class DataBroadcastMessage implements Message { public abstract class DataBroadcastMessage implements Message {
private final int networkId = Version.NETWORK_ID;
@Override @Override
public int networkId() { public int networkId() {
return Version.NETWORK_ID; return networkId;
} }
} }

View file

@ -7,11 +7,13 @@ public final class GetDataRequest implements Message {
// That object is sent over the wire, so we need to take care of version compatibility. // That object is sent over the wire, so we need to take care of version compatibility.
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION; private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
private final int networkId = Version.NETWORK_ID;
public GetDataRequest() { public GetDataRequest() {
} }
@Override @Override
public int networkId() { public int networkId() {
return Version.NETWORK_ID; return networkId;
} }
} }

View file

@ -9,7 +9,8 @@ import java.util.HashSet;
public final class GetDataResponse implements Message { public final class GetDataResponse implements Message {
// That object is sent over the wire, so we need to take care of version compatibility. // That object is sent over the wire, so we need to take care of version compatibility.
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION; private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
private final int networkId = Version.NETWORK_ID;
public final HashSet<ProtectedData> set; public final HashSet<ProtectedData> set;
public GetDataResponse(HashSet<ProtectedData> set) { public GetDataResponse(HashSet<ProtectedData> set) {
@ -18,7 +19,7 @@ public final class GetDataResponse implements Message {
@Override @Override
public int networkId() { public int networkId() {
return Version.NETWORK_ID; return networkId;
} }
@Override @Override

View file

@ -84,6 +84,7 @@ public class EncryptionServiceTests {
class TestMessage implements MailboxMessage { class TestMessage implements MailboxMessage {
public String data = "test"; public String data = "test";
private final int networkId = Version.NETWORK_ID;
public TestMessage(String data) { public TestMessage(String data) {
this.data = data; this.data = data;
@ -96,6 +97,6 @@ class TestMessage implements MailboxMessage {
@Override @Override
public int networkId() { public int networkId() {
return Version.NETWORK_ID; return networkId;
} }
} }

View file

@ -70,44 +70,47 @@ public class TestUtils {
seedNodes.add(new Address("localhost:8002")); seedNodes.add(new Address("localhost:8002"));
seedNodes.add(new Address("localhost:8003")); seedNodes.add(new Address("localhost:8003"));
sleepTime = 100; sleepTime = 100;
seedNode = new SeedNode(); seedNode = new SeedNode("test_dummy_dir");
} else { } else {
seedNodes.add(new Address("3omjuxn7z73pxoee.onion:8001")); seedNodes.add(new Address("3omjuxn7z73pxoee.onion:8001"));
seedNodes.add(new Address("j24fxqyghjetgpdx.onion:8002")); seedNodes.add(new Address("j24fxqyghjetgpdx.onion:8002"));
seedNodes.add(new Address("45367tl6unwec6kw.onion:8003")); seedNodes.add(new Address("45367tl6unwec6kw.onion:8003"));
sleepTime = 10000; sleepTime = 10000;
seedNode = new SeedNode(); seedNode = new SeedNode("test_dummy_dir");
} }
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
seedNode.createAndStartP2PService(encryptionService, keyRing, new Address("localhost", port), useLocalhost, seedNodes, new P2PServiceListener() { seedNode.createAndStartP2PService(encryptionService, keyRing, new Address("localhost", port), useLocalhost, 2,
@Override seedNodes, new P2PServiceListener() {
public void onRequestingDataCompleted() { @Override
} public void onRequestingDataCompleted() {
}
@Override @Override
public void onFirstPeerAuthenticated() { public void onFirstPeerAuthenticated() {
} }
@Override @Override
public void onTorNodeReady() { public void onTorNodeReady() {
} }
@Override @Override
public void onHiddenServicePublished() { public void onHiddenServicePublished() {
latch.countDown(); latch.countDown();
} }
@Override @Override
public void onSetupFailed(Throwable throwable) { public void onSetupFailed(Throwable throwable) {
} }
}); });
latch.await(); latch.await();
Thread.sleep(sleepTime); Thread.sleep(sleepTime);
return seedNode; return seedNode;
} }
public static P2PService getAndAuthenticateP2PService(int port, EncryptionService encryptionService, KeyRing keyRing, boolean useLocalhost, Set<Address> seedNodes) throws InterruptedException { public static P2PService getAndAuthenticateP2PService(int port, EncryptionService encryptionService, KeyRing keyRing,
boolean useLocalhost, Set<Address> seedNodes)
throws InterruptedException {
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
SeedNodesRepository seedNodesRepository = new SeedNodesRepository(); SeedNodesRepository seedNodesRepository = new SeedNodesRepository();
if (seedNodes != null && !seedNodes.isEmpty()) { if (seedNodes != null && !seedNodes.isEmpty()) {
@ -117,7 +120,8 @@ public class TestUtils {
seedNodesRepository.setTorSeedNodeAddresses(seedNodes); seedNodesRepository.setTorSeedNodeAddresses(seedNodes);
} }
P2PService p2PService = new P2PService(seedNodesRepository, port, new File("seed_node_" + port), useLocalhost, encryptionService, keyRing, new File("dummy")); P2PService p2PService = new P2PService(seedNodesRepository, port, new File("seed_node_" + port), useLocalhost, 2,
encryptionService, keyRing, new File("dummy"));
p2PService.start(new P2PServiceListener() { p2PService.start(new P2PServiceListener() {
@Override @Override
public void onRequestingDataCompleted() { public void onRequestingDataCompleted() {

View file

@ -6,6 +6,7 @@ import io.bitsquare.p2p.messaging.MailboxMessage;
import io.bitsquare.p2p.storage.data.ExpirablePayload; import io.bitsquare.p2p.storage.data.ExpirablePayload;
public class MockMailboxMessage implements MailboxMessage, ExpirablePayload { public class MockMailboxMessage implements MailboxMessage, ExpirablePayload {
private final int networkId = Version.NETWORK_ID;
public String msg; public String msg;
public Address senderAddress; public Address senderAddress;
public long ttl; public long ttl;
@ -17,7 +18,7 @@ public class MockMailboxMessage implements MailboxMessage, ExpirablePayload {
@Override @Override
public int networkId() { public int networkId() {
return Version.NETWORK_ID; return networkId;
} }
@Override @Override

View file

@ -7,6 +7,7 @@ import io.bitsquare.p2p.storage.data.ExpirablePayload;
public class MockMessage implements Message, ExpirablePayload { public class MockMessage implements Message, ExpirablePayload {
public String msg; public String msg;
public long ttl; public long ttl;
private final int networkId = Version.NETWORK_ID;
public MockMessage(String msg) { public MockMessage(String msg) {
this.msg = msg; this.msg = msg;
@ -14,7 +15,7 @@ public class MockMessage implements Message, ExpirablePayload {
@Override @Override
public int networkId() { public int networkId() {
return Version.NETWORK_ID; return networkId;
} }
@Override @Override

View file

@ -81,33 +81,34 @@ public class PeerGroupTest {
seedNodes = new HashSet<>(); seedNodes = new HashSet<>();
Address address = new Address("localhost:8001"); Address address = new Address("localhost:8001");
seedNodes.add(address); seedNodes.add(address);
seedNode1 = new SeedNode(); seedNode1 = new SeedNode("test_dummy_dir");
latch = new CountDownLatch(2); latch = new CountDownLatch(2);
seedNode1.createAndStartP2PService(null, null, address, useLocalhost, seedNodes, new P2PServiceListener() { seedNode1.createAndStartP2PService(null, null, address, useLocalhost, 2,
@Override seedNodes, new P2PServiceListener() {
public void onRequestingDataCompleted() { @Override
latch.countDown(); public void onRequestingDataCompleted() {
} latch.countDown();
}
@Override @Override
public void onTorNodeReady() { public void onTorNodeReady() {
} }
@Override @Override
public void onFirstPeerAuthenticated() { public void onFirstPeerAuthenticated() {
} }
@Override @Override
public void onHiddenServicePublished() { public void onHiddenServicePublished() {
latch.countDown(); latch.countDown();
} }
@Override @Override
public void onSetupFailed(Throwable throwable) { public void onSetupFailed(Throwable throwable) {
} }
}); });
P2PService p2PService1 = seedNode1.getP2PService(); P2PService p2PService1 = seedNode1.getP2PService();
latch.await(); latch.await();
Thread.sleep(500); Thread.sleep(500);
@ -126,8 +127,8 @@ public class PeerGroupTest {
latch = new CountDownLatch(6); latch = new CountDownLatch(6);
seedNode1 = new SeedNode(); seedNode1 = new SeedNode("test_dummy_dir");
seedNode1.createAndStartP2PService(null, null, address1, useLocalhost, seedNodes, new P2PServiceListener() { seedNode1.createAndStartP2PService(null, null, address1, useLocalhost, 2, seedNodes, new P2PServiceListener() {
@Override @Override
public void onRequestingDataCompleted() { public void onRequestingDataCompleted() {
latch.countDown(); latch.countDown();
@ -157,8 +158,8 @@ public class PeerGroupTest {
Thread.sleep(500); Thread.sleep(500);
seedNode2 = new SeedNode(); seedNode2 = new SeedNode("test_dummy_dir");
seedNode2.createAndStartP2PService(null, null, address2, useLocalhost, seedNodes, new P2PServiceListener() { seedNode2.createAndStartP2PService(null, null, address2, useLocalhost, 2, seedNodes, new P2PServiceListener() {
@Override @Override
public void onRequestingDataCompleted() { public void onRequestingDataCompleted() {
latch.countDown(); latch.countDown();
@ -382,10 +383,10 @@ public class PeerGroupTest {
} }
private SeedNode getAndStartSeedNode(int port) throws InterruptedException { private SeedNode getAndStartSeedNode(int port) throws InterruptedException {
SeedNode seedNode = new SeedNode(); SeedNode seedNode = new SeedNode("test_dummy_dir");
latch = new CountDownLatch(1); latch = new CountDownLatch(1);
seedNode.createAndStartP2PService(null, null, new Address("localhost", port), useLocalhost, seedNodes, new P2PServiceListener() { seedNode.createAndStartP2PService(null, null, new Address("localhost", port), useLocalhost, 2, seedNodes, new P2PServiceListener() {
@Override @Override
public void onRequestingDataCompleted() { public void onRequestingDataCompleted() {
latch.countDown(); latch.countDown();

View file

@ -1,6 +1,7 @@
package io.bitsquare.p2p.seed; package io.bitsquare.p2p.seed;
import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.google.common.util.concurrent.ThreadFactoryBuilder;
import io.bitsquare.app.BitsquareEnvironment;
import io.bitsquare.app.Log; import io.bitsquare.app.Log;
import io.bitsquare.common.UserThread; import io.bitsquare.common.UserThread;
import org.bitcoinj.crypto.DRMWorkaround; import org.bitcoinj.crypto.DRMWorkaround;
@ -47,7 +48,7 @@ public class SeedNodeMain {
UserThread.setExecutor(Executors.newSingleThreadExecutor(threadFactory)); UserThread.setExecutor(Executors.newSingleThreadExecutor(threadFactory));
UserThread.execute(() -> { UserThread.execute(() -> {
try { try {
seedNode = new SeedNode(); seedNode = new SeedNode(BitsquareEnvironment.defaultUserDataDir());
seedNode.processArgs(args); seedNode.processArgs(args);
seedNode.createAndStartP2PService(); seedNode.createAndStartP2PService();
} catch (Throwable t) { } catch (Throwable t) {