diff --git a/README.md b/README.md index f996bfdea0..3cea86dd30 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,10 @@ Then you can generate coins on demand with the Bitcoin qt client with that comma See: https://bitcoinj.github.io/testing You can change the network mode in the guice module: BitSquareModule.java +We use a fork of the actual TomP2P master branch: https://github.com/ManfredKarrer/TomP2P +You need to check that out as well and deploy it to the local maven repository: +mvn clean install -DskipTests + ### Resources: * Web: http://bitsquare.io diff --git a/pom.xml b/pom.xml index 34e2fb7294..18dbe02c32 100644 --- a/pom.xml +++ b/pom.xml @@ -124,11 +124,13 @@ 0.11.3 + junit diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF index de29527d5c..4a577d5aa6 100644 --- a/src/main/java/META-INF/MANIFEST.MF +++ b/src/main/java/META-INF/MANIFEST.MF @@ -1,3 +1,3 @@ Manifest-Version: 1.0 -Main-Class: io.bitsquare.Relay +Main-Class: io.bitsquare.BootstrapNode_ diff --git a/src/main/java/io/bitsquare/BitSquare.java b/src/main/java/io/bitsquare/BitSquare.java index 559a855de8..710f8d6f23 100644 --- a/src/main/java/io/bitsquare/BitSquare.java +++ b/src/main/java/io/bitsquare/BitSquare.java @@ -38,7 +38,7 @@ public class BitSquare extends Application { private static final Logger log = LoggerFactory.getLogger(BitSquare.class); - public static boolean fillFormsWithDummyData = false; + public static boolean fillFormsWithDummyData = true; private static String APP_NAME = "bitsquare"; private static Stage primaryStage; diff --git a/src/main/java/io/bitsquare/Relay.java b/src/main/java/io/bitsquare/Relay.java deleted file mode 100644 index 5e0e0521df..0000000000 --- a/src/main/java/io/bitsquare/Relay.java +++ /dev/null @@ -1,69 +0,0 @@ -package io.bitsquare; - -import java.io.IOException; -import javafx.application.Application; -import javafx.stage.Stage; -import net.tomp2p.p2p.Peer; -import net.tomp2p.p2p.PeerMaker; -import net.tomp2p.peers.Number160; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerMapChangeListener; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -public class Relay extends Application -{ - private static final Logger log = LoggerFactory.getLogger(Relay.class); - private static final Number160 ID = Number160.createHash(1); - - private static Peer masterPeer = null; - private static int port; - - public static void main(String[] args) - { - if (args != null && args.length == 1) - { - port = new Integer(args[0]); - } - else - { - port = 5001; - } - - launch(args); - } - - @Override - public void start(Stage primaryStage) throws IOException - { - log.trace("Startup: start"); - if (masterPeer == null) - { - masterPeer = new PeerMaker(ID).setPorts(port).makeAndListen(); - // masterPeer = new PeerMaker(ID).setPorts(port).setBagSize(100).makeAndListen(); // setBagSize cause sync problems... - masterPeer.getBroadcastRPC().getConnectionBean().getConnectionReservation().reserve(3).awaitUninterruptibly(); - masterPeer.getConnectionHandler().getPeerBean().getPeerMap().addPeerMapChangeListener(new PeerMapChangeListener() - { - @Override - public void peerInserted(PeerAddress peerAddress) - { - log.info("peerInserted " + peerAddress); - } - - @Override - public void peerRemoved(PeerAddress peerAddress) - { - log.info("peerRemoved " + peerAddress); - } - - @Override - public void peerUpdated(PeerAddress peerAddress) - { - log.info("peerUpdated " + peerAddress); - } - }); - } - } - -} diff --git a/src/main/java/io/bitsquare/SeedNode.java b/src/main/java/io/bitsquare/SeedNode.java new file mode 100644 index 0000000000..eb035c5001 --- /dev/null +++ b/src/main/java/io/bitsquare/SeedNode.java @@ -0,0 +1,174 @@ +package io.bitsquare; + +import io.bitsquare.msg.SeedNodeAddress; +import java.util.List; +import net.tomp2p.dht.PeerBuilderDHT; +import net.tomp2p.futures.BaseFuture; +import net.tomp2p.futures.BaseFutureListener; +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.PeerStatatistic; +import net.tomp2p.relay.FutureRelay; +import net.tomp2p.relay.RelayRPC; +import net.tomp2p.tracker.PeerBuilderTracker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Well known node which is reachable for all peers for bootstrapping. + * There will be several SeedNodes running on several servers. + *

+ * TODO: Alternative bootstrap methods will follow later (save locally list of known nodes reported form other peers,...) + */ +public class SeedNode +{ + private static final Logger log = LoggerFactory.getLogger(SeedNode.class); + + private static final List staticSedNodeAddresses = SeedNodeAddress.StaticSeedNodeAddresses.getAllSeedNodeAddresses(); + + /** + * @param args If no args passed we use localhost, otherwise the param is used as index for selecting an address from seedNodeAddresses + * @throws Exception + */ + public static void main(String[] args) + { + int index = 0; + SeedNode seedNode = new SeedNode(); + if (args.length > 0) + { + // use host index passes as param + int param = Integer.valueOf(args[0]); + if (param < staticSedNodeAddresses.size()) + index = param; + } + try + { + seedNode.startupUsingAddress(new SeedNodeAddress(staticSedNodeAddresses.get(index))); + } catch (Exception e) + { + e.printStackTrace(); + log.error(e.toString()); + } + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Constructor + /////////////////////////////////////////////////////////////////////////////////////////// + + + public SeedNode() + { + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Public Methods + /////////////////////////////////////////////////////////////////////////////////////////// + + public void startupUsingAddress(SeedNodeAddress seedNodeAddress) + { + try + { + Peer peer = new PeerBuilder(Number160.createHash(seedNodeAddress.getId())).ports(seedNodeAddress.getPort()).start(); + + // Need to add all features the clients will use (otherwise msg type is UNKNOWN_ID) + new PeerBuilderDHT(peer).start(); + PeerNAT nodeBehindNat = new PeerBuilderNAT(peer).start(); + new RelayRPC(peer); + new PeerBuilderTracker(peer); + nodeBehindNat.startSetupRelay(new FutureRelay()); + + log.debug("Peer started. " + peer.peerAddress()); + + peer.peerBean().peerMap().addPeerMapChangeListener(new PeerMapChangeListener() + { + @Override + public void peerInserted(PeerAddress peerAddress, boolean verified) + { + log.debug("Peer inserted: peerAddress=" + peerAddress + ", verified=" + verified); + } + + @Override + public void peerRemoved(PeerAddress peerAddress, PeerStatatistic peerStatistics) + { + log.debug("Peer removed: peerAddress=" + peerAddress + ", peerStatistics=" + peerStatistics); + } + + @Override + public void peerUpdated(PeerAddress peerAddress, PeerStatatistic peerStatistics) + { + log.debug("Peer updated: peerAddress=" + peerAddress + ", peerStatistics=" + peerStatistics); + } + }); + + // We keep server in endless loop + for (; ; ) + { + // Optional pinging + boolean pingPeers = false; + if (pingPeers) + { + for (PeerAddress peerAddress : peer.peerBean().peerMap().all()) + { + BaseFuture future = peer.ping().peerAddress(peerAddress).tcpPing().start(); + future.addListener(new BaseFutureListener() + { + @Override + public void operationComplete(BaseFuture future) throws Exception + { + if (future.isSuccess()) + { + log.debug("peer online (TCP):" + peerAddress); + } + else + { + log.debug("offline " + peerAddress); + } + } + + @Override + public void exceptionCaught(Throwable t) throws Exception + { + log.error("exceptionCaught " + t); + } + }); + + future = peer.ping().peerAddress(peerAddress).start(); + future.addListener(new BaseFutureListener() + { + @Override + public void operationComplete(BaseFuture future) throws Exception + { + if (future.isSuccess()) + { + log.debug("peer online (UDP):" + peerAddress); + } + else + { + log.debug("offline " + peerAddress); + } + } + + @Override + public void exceptionCaught(Throwable t) throws Exception + { + log.error("exceptionCaught " + t); + } + }); + } + Thread.sleep(1500); + } + } + } catch (Exception e) + { + log.error("Exception: " + e); + } + } + +} diff --git a/src/main/java/io/bitsquare/btc/BitSquareWallet.java b/src/main/java/io/bitsquare/btc/BitSquareWallet.java index 9f35712e2e..cbcc1d4621 100644 --- a/src/main/java/io/bitsquare/btc/BitSquareWallet.java +++ b/src/main/java/io/bitsquare/btc/BitSquareWallet.java @@ -22,5 +22,4 @@ class BitSquareWallet extends Wallet implements Serializable super(params, keyCrypter); } - } diff --git a/src/main/java/io/bitsquare/btc/WalletFacade.java b/src/main/java/io/bitsquare/btc/WalletFacade.java index 31312cbb3c..f331d9ad84 100644 --- a/src/main/java/io/bitsquare/btc/WalletFacade.java +++ b/src/main/java/io/bitsquare/btc/WalletFacade.java @@ -190,11 +190,9 @@ public class WalletFacade } } - public void shutDown() { wallet.removeEventListener(walletEventListener); - walletAppKit.stopAsync(); } @@ -596,6 +594,7 @@ public class WalletFacade Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx); // we don't allow spending of unconfirmed tx as with fake registrations we would open up doors for spam and market manipulation with fake offers + // so set includePending to false sendRequest.coinSelector = new AddressBasedCoinSelector(params, getRegistrationAddressInfo(), false); sendRequest.changeAddress = getRegistrationAddressInfo().getAddress(); Wallet.SendResult sendResult = wallet.sendCoins(sendRequest); @@ -677,6 +676,8 @@ public class WalletFacade } + // TODO: Trade process - use P2SH instead and optimize data exchange + /////////////////////////////////////////////////////////////////////////////////////////// // Trade process /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/main/java/io/bitsquare/di/BitSquareModule.java b/src/main/java/io/bitsquare/di/BitSquareModule.java index 37a971b055..ac28e5fbf4 100644 --- a/src/main/java/io/bitsquare/di/BitSquareModule.java +++ b/src/main/java/io/bitsquare/di/BitSquareModule.java @@ -15,6 +15,7 @@ import io.bitsquare.btc.FeePolicy; import io.bitsquare.btc.WalletFacade; import io.bitsquare.crypto.CryptoFacade; import io.bitsquare.msg.MessageFacade; +import io.bitsquare.msg.SeedNodeAddress; import io.bitsquare.settings.Settings; import io.bitsquare.storage.Storage; import io.bitsquare.trade.Trading; @@ -52,6 +53,11 @@ public class BitSquareModule extends AbstractModule //bind(String.class).annotatedWith(Names.named("networkType")).toInstance(WalletFacade.TEST_NET); bind(NetworkParameters.class).toProvider(NetworkParametersProvider.class).asEagerSingleton(); bind(BitSquareWalletAppKit.class).toProvider(BitSquareWalletAppKitProvider.class).asEagerSingleton(); + + // bind(Boolean.class).annotatedWith(Names.named("useDiskStorage")).toInstance(new Boolean(true)); + bind(Boolean.class).annotatedWith(Names.named("useDiskStorage")).toInstance(new Boolean(false)); + bind(SeedNodeAddress.StaticSeedNodeAddresses.class).annotatedWith(Names.named("defaultSeedNode")).toInstance(SeedNodeAddress.StaticSeedNodeAddresses.LOCALHOST); + // bind(SeedNodeAddress.StaticSeedNodeAddresses.class).annotatedWith(Names.named("defaultSeedNode")).toInstance(SeedNodeAddress.StaticSeedNodeAddresses.DIGITAL_OCEAN); } } diff --git a/src/main/java/io/bitsquare/gui/MainController.java b/src/main/java/io/bitsquare/gui/MainController.java index c15d72487d..d1cf7a388f 100644 --- a/src/main/java/io/bitsquare/gui/MainController.java +++ b/src/main/java/io/bitsquare/gui/MainController.java @@ -11,6 +11,7 @@ import io.bitsquare.gui.orders.OrdersController; import io.bitsquare.gui.util.Icons; import io.bitsquare.gui.util.Transitions; import io.bitsquare.locale.Localisation; +import io.bitsquare.msg.BootstrapListener; import io.bitsquare.msg.MessageFacade; import io.bitsquare.storage.Storage; import io.bitsquare.trade.Direction; @@ -176,8 +177,24 @@ public class MainController implements Initializable, NavigationController private void init() { + messageFacade.init(new BootstrapListener() + { + @Override + public void onCompleted() + { + messageFacadeInited(); + } - messageFacade.init(); + @Override + public void onFailed(Throwable throwable) + { + + } + }); + } + + private void messageFacadeInited() + { trading.addTakeOfferRequestListener(this::onTakeOfferRequested); diff --git a/src/main/java/io/bitsquare/gui/arbitrators/overview/ArbitratorOverviewController.java b/src/main/java/io/bitsquare/gui/arbitrators/overview/ArbitratorOverviewController.java index 3220ff867d..7013f98054 100644 --- a/src/main/java/io/bitsquare/gui/arbitrators/overview/ArbitratorOverviewController.java +++ b/src/main/java/io/bitsquare/gui/arbitrators/overview/ArbitratorOverviewController.java @@ -26,9 +26,14 @@ import javafx.scene.layout.AnchorPane; import javafx.scene.layout.Pane; import javafx.stage.Stage; import javax.inject.Inject; -import net.tomp2p.peers.Number160; +import net.tomp2p.peers.Number640; import net.tomp2p.storage.Data; +/** + * TODO remove tomp2p dependencies + * import net.tomp2p.peers.Number160; + * import net.tomp2p.storage.Data; + */ @SuppressWarnings({"ALL", "UnusedParameters"}) public class ArbitratorOverviewController implements Initializable, ChildController, NavigationController, ArbitratorListener { @@ -135,7 +140,7 @@ public class ArbitratorOverviewController implements Initializable, ChildControl } @Override - public void onArbitratorsReceived(Map dataMap, boolean success) + public void onArbitratorsReceived(Map dataMap, boolean success) { if (success && dataMap != null) { @@ -145,7 +150,7 @@ public class ArbitratorOverviewController implements Initializable, ChildControl { try { - Object arbitratorDataObject = arbitratorData.getObject(); + Object arbitratorDataObject = arbitratorData.object(); if (arbitratorDataObject instanceof Arbitrator) { Arbitrator arbitrator = (Arbitrator) arbitratorDataObject; diff --git a/src/main/java/io/bitsquare/gui/arbitrators/registration/ArbitratorRegistrationController.java b/src/main/java/io/bitsquare/gui/arbitrators/registration/ArbitratorRegistrationController.java index a26e1d25a3..769349cf8e 100644 --- a/src/main/java/io/bitsquare/gui/arbitrators/registration/ArbitratorRegistrationController.java +++ b/src/main/java/io/bitsquare/gui/arbitrators/registration/ArbitratorRegistrationController.java @@ -22,8 +22,8 @@ import io.bitsquare.msg.MessageFacade; import io.bitsquare.storage.Storage; import io.bitsquare.user.Arbitrator; import io.bitsquare.user.Reputation; +import io.bitsquare.user.User; import io.bitsquare.util.DSAKeyUtil; -import java.io.IOException; import java.math.BigInteger; import java.net.URL; import java.util.*; @@ -48,6 +48,7 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon private final Storage storage; private final WalletFacade walletFacade; private final MessageFacade messageFacade; + private User user; private Arbitrator arbitrator = new Arbitrator(); private ArbitratorProfileController arbitratorProfileController; private boolean isEditMode; @@ -92,11 +93,12 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon /////////////////////////////////////////////////////////////////////////////////////////// @Inject - private ArbitratorRegistrationController(Storage storage, WalletFacade walletFacade, MessageFacade messageFacade) + private ArbitratorRegistrationController(Storage storage, WalletFacade walletFacade, MessageFacade messageFacade, User user) { this.storage = storage; this.walletFacade = walletFacade; this.messageFacade = messageFacade; + this.user = user; } @@ -338,13 +340,7 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon } } - try - { - messageFacade.addArbitrator(arbitrator); - } catch (IOException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } + messageFacade.addArbitrator(arbitrator); } @FXML @@ -474,7 +470,7 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon minArbitrationFeeTextField); String pubKeyAsHex = walletFacade.getArbitratorDepositAddressInfo().getPubKeyAsHexString(); - String messagePubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(messageFacade.getPubKey()); + String messagePubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(user.getMessagePublicKey()); String name = nameTextField.getText(); double maxTradeVolume = BitSquareConverter.stringToDouble(maxTradeVolumeTextField.getText()); diff --git a/src/main/java/io/bitsquare/gui/market/createOffer/CreateOfferController.java b/src/main/java/io/bitsquare/gui/market/createOffer/CreateOfferController.java index aa4e71a636..efb401a1cb 100644 --- a/src/main/java/io/bitsquare/gui/market/createOffer/CreateOfferController.java +++ b/src/main/java/io/bitsquare/gui/market/createOffer/CreateOfferController.java @@ -205,11 +205,9 @@ public class CreateOfferController implements Initializable, ChildController, Hi return; } - log.debug("create offer pubkey " + user.getMessagePubKeyAsHex()); - if (user.getCurrentBankAccount() != null) { - offer = new Offer(user.getMessagePubKeyAsHex(), + offer = new Offer(user.getMessagePublicKey(), direction, BitSquareConverter.stringToDouble(priceTextField.getText()), BtcFormatter.stringValueToSatoshis(amountTextField.getText()), diff --git a/src/main/java/io/bitsquare/gui/market/createOffer/CreateOfferView.fxml b/src/main/java/io/bitsquare/gui/market/createOffer/CreateOfferView.fxml index 3dde43564d..a408b77706 100644 --- a/src/main/java/io/bitsquare/gui/market/createOffer/CreateOfferView.fxml +++ b/src/main/java/io/bitsquare/gui/market/createOffer/CreateOfferView.fxml @@ -42,12 +42,13 @@