mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-20 10:22:18 +01:00
Merge pull request #535 from dan-da/route_bitcoinj_over_jtoryproxy
Route bitcoinj over jtoryproxy
This commit is contained in:
commit
dc06523814
94
core/src/main/java/io/bitsquare/btc/ProxySocketFactory.java
Normal file
94
core/src/main/java/io/bitsquare/btc/ProxySocketFactory.java
Normal file
@ -0,0 +1,94 @@
|
||||
|
||||
/**
|
||||
* Copyright (C) 2010-2014 Leon Blakey <lord.quackstar at gmail.com>
|
||||
*
|
||||
* This file is part of PircBotX.
|
||||
*
|
||||
* PircBotX is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* PircBotX is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* PircBotX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package io.bitsquare.btc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
/**
|
||||
* A basic SocketFactory for creating sockets that connect through the specified
|
||||
* proxy.
|
||||
*
|
||||
* @author Leon Blakey
|
||||
*/
|
||||
public class ProxySocketFactory extends SocketFactory {
|
||||
protected final Proxy proxy;
|
||||
|
||||
/**
|
||||
* Create all sockets with the specified proxy.
|
||||
*
|
||||
* @param proxy An existing proxy
|
||||
*/
|
||||
public ProxySocketFactory(Proxy proxy) {
|
||||
this.proxy = proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience constructor for creating a proxy with the specified host
|
||||
* and port.
|
||||
*
|
||||
* @param proxyType The type of proxy were connecting to
|
||||
* @param hostname The hostname of the proxy server
|
||||
* @param port The port of the proxy server
|
||||
*/
|
||||
public ProxySocketFactory(Proxy.Type proxyType, String hostname, int port) {
|
||||
this.proxy = new Proxy(proxyType, new InetSocketAddress(hostname, port));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket() throws IOException {
|
||||
Socket socket = new Socket(proxy);
|
||||
return socket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String string, int i) throws IOException, UnknownHostException {
|
||||
Socket socket = new Socket(proxy);
|
||||
socket.connect(new InetSocketAddress(string, i));
|
||||
return socket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String string, int i, InetAddress localAddress, int localPort) throws IOException, UnknownHostException {
|
||||
Socket socket = new Socket(proxy);
|
||||
socket.bind(new InetSocketAddress(localAddress, localPort));
|
||||
socket.connect(new InetSocketAddress(string, i));
|
||||
return socket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress ia, int i) throws IOException {
|
||||
Socket socket = new Socket(proxy);
|
||||
socket.connect(new InetSocketAddress(ia, i));
|
||||
return socket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress ia, int i, InetAddress localAddress, int localPort) throws IOException {
|
||||
Socket socket = new Socket(proxy);
|
||||
socket.bind(new InetSocketAddress(localAddress, localPort));
|
||||
socket.connect(new InetSocketAddress(ia, i));
|
||||
return socket;
|
||||
}
|
||||
}
|
178
core/src/main/java/io/bitsquare/btc/SeedPeersSocks5Dns.java
Normal file
178
core/src/main/java/io/bitsquare/btc/SeedPeersSocks5Dns.java
Normal file
@ -0,0 +1,178 @@
|
||||
/**
|
||||
* Copyright 2011 Micheal Swiggs
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.bitsquare.btc;
|
||||
|
||||
import com.runjva.sourceforge.jsocks.protocol.Socks5Proxy;
|
||||
import com.runjva.sourceforge.jsocks.protocol.SocksSocket;
|
||||
|
||||
import org.bitcoinj.net.*;
|
||||
import org.bitcoinj.net.discovery.PeerDiscovery;
|
||||
import org.bitcoinj.net.discovery.PeerDiscoveryException;
|
||||
|
||||
import org.bitcoinj.core.NetworkParameters;
|
||||
import javax.annotation.Nullable;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
/**
|
||||
* SeedPeersSocks5Dns resolves peers via Proxy (Socks5) remote DNS.
|
||||
*/
|
||||
public class SeedPeersSocks5Dns implements PeerDiscovery {
|
||||
private Socks5Proxy proxy;
|
||||
private NetworkParameters params;
|
||||
private InetSocketAddress[] seedAddrs;
|
||||
private InetSocketAddress[] seedAddrsIP;
|
||||
private int pnseedIndex;
|
||||
|
||||
private InetSocketAddress[] seedAddrsResolved;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SeedPeersSocks5Dns.class);
|
||||
|
||||
/**
|
||||
* Supports finding peers by hostname over a socks5 proxy.
|
||||
*
|
||||
* @param Socks5Proxy proxy the socks5 proxy to connect over.
|
||||
* @param NetworkParameters param to be used for seed and port information.
|
||||
*/
|
||||
public SeedPeersSocks5Dns(Socks5Proxy proxy, NetworkParameters params) {
|
||||
|
||||
this.proxy = proxy;
|
||||
this.params = params;
|
||||
this.seedAddrs = convertAddrsString( params.getDnsSeeds(), params.getPort() );
|
||||
|
||||
if( false ) {
|
||||
// This is an example of how .onion servers could be used. Unfortunately there is presently no way
|
||||
// to hand the onion address (or a connected socket) back to bitcoinj without it crashing in PeerAddress.
|
||||
// note: the onion addresses should be added into bitcoinj NetworkParameters classes, eg for mainnet, testnet
|
||||
// not here!
|
||||
this.seedAddrs = new InetSocketAddress[] { InetSocketAddress.createUnresolved( "cajrifqkvalh2ooa.onion", 8333 ),
|
||||
InetSocketAddress.createUnresolved( "bk7yp6epnmcllq72.onion", 8333 )
|
||||
};
|
||||
}
|
||||
|
||||
seedAddrsResolved = new InetSocketAddress[seedAddrs.length];
|
||||
for(int idx = seedAddrs.length; idx < seedAddrsResolved.length; idx ++) {
|
||||
seedAddrsResolved[idx] = seedAddrsIP[idx-seedAddrs.length];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Acts as an iterator, returning the address of each node in the list sequentially.
|
||||
* Once all the list has been iterated, null will be returned for each subsequent query.
|
||||
*
|
||||
* @return InetSocketAddress - The address/port of the next node.
|
||||
* @throws PeerDiscoveryException
|
||||
*/
|
||||
@Nullable
|
||||
public InetSocketAddress getPeer() throws PeerDiscoveryException {
|
||||
try {
|
||||
return nextPeer();
|
||||
} catch (UnknownHostException e) {
|
||||
throw new PeerDiscoveryException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* worker for getPeer()
|
||||
*/
|
||||
@Nullable
|
||||
private InetSocketAddress nextPeer() throws UnknownHostException, PeerDiscoveryException {
|
||||
if (seedAddrs == null || seedAddrs.length == 0) {
|
||||
throw new PeerDiscoveryException("No IP address seeds configured; unable to find any peers");
|
||||
}
|
||||
|
||||
if (pnseedIndex >= seedAddrsResolved.length) {
|
||||
return null;
|
||||
}
|
||||
if( seedAddrsResolved[pnseedIndex] == null ) {
|
||||
seedAddrsResolved[pnseedIndex] = lookup( proxy, seedAddrs[pnseedIndex] );
|
||||
}
|
||||
log.error("SeedPeersSocks5Dns::nextPeer: " + seedAddrsResolved[pnseedIndex] );
|
||||
|
||||
return seedAddrsResolved[pnseedIndex++];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing all the Bitcoin nodes within the list.
|
||||
*/
|
||||
@Override
|
||||
public InetSocketAddress[] getPeers(long timeoutValue, TimeUnit timeoutUnit) throws PeerDiscoveryException {
|
||||
try {
|
||||
return allPeers();
|
||||
} catch (UnknownHostException e) {
|
||||
throw new PeerDiscoveryException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns all seed peers, performs hostname lookups if necessary.
|
||||
*/
|
||||
private InetSocketAddress[] allPeers() throws UnknownHostException {
|
||||
for (int i = 0; i < seedAddrsResolved.length; ++i) {
|
||||
if( seedAddrsResolved[i] == null ) {
|
||||
seedAddrsResolved[i] = lookup( proxy, seedAddrs[i] );
|
||||
}
|
||||
}
|
||||
return seedAddrsResolved;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a hostname via remote DNS over socks5 proxy.
|
||||
*/
|
||||
public static InetSocketAddress lookup( Socks5Proxy proxy, InetSocketAddress addr ) {
|
||||
if( !addr.isUnresolved() ) {
|
||||
return addr;
|
||||
}
|
||||
try {
|
||||
SocksSocket proxySocket = new SocksSocket( proxy, addr.getHostString(), addr.getPort() );
|
||||
InetAddress addrResolved = proxySocket.getInetAddress();
|
||||
proxySocket.close();
|
||||
if( addrResolved != null ) {
|
||||
log.info("Resolved " + addr.getHostString() + " to " + addrResolved.getHostAddress() );
|
||||
return new InetSocketAddress(addrResolved, addr.getPort() );
|
||||
}
|
||||
else {
|
||||
// note: .onion nodes fall in here when proxy is Tor. But they have no IP address.
|
||||
// Unfortunately bitcoinj crashes in PeerAddress if it finds an unresolved address.
|
||||
log.error("Connected to " + addr.getHostString() + ". But did not resolve to address." );
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Error resolving " + addr.getHostString() + ". Exception:\n" + e.toString() );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an array of hostnames to array of unresolved InetSocketAddress
|
||||
*/
|
||||
private InetSocketAddress[] convertAddrsString(String[] addrs, int port) {
|
||||
InetSocketAddress[] list = new InetSocketAddress[addrs.length];
|
||||
for( int i = 0; i < addrs.length; i++) {
|
||||
list[i] = InetSocketAddress.createUnresolved(addrs[i], port);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.btc;
|
||||
|
||||
import com.runjva.sourceforge.jsocks.protocol.Socks5Proxy;
|
||||
|
||||
import org.bitcoinj.core.NetworkParameters;
|
||||
import org.bitcoinj.kits.WalletAppKit;
|
||||
import org.bitcoinj.net.BlockingClientManager;
|
||||
import org.bitcoinj.core.PeerGroup;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.Proxy;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
public class WalletAppKitBitSquare extends WalletAppKit {
|
||||
private Socks5Proxy socks5Proxy;
|
||||
|
||||
/**
|
||||
* Creates a new WalletAppKit, with a newly created {@link Context}. Files will be stored in the given directory.
|
||||
*/
|
||||
public WalletAppKitBitSquare(NetworkParameters params, Socks5Proxy socks5Proxy, File directory, String filePrefix) {
|
||||
super(params, directory, filePrefix);
|
||||
this.socks5Proxy = socks5Proxy;
|
||||
}
|
||||
|
||||
public Socks5Proxy getProxy() {
|
||||
return socks5Proxy;
|
||||
}
|
||||
|
||||
protected PeerGroup createPeerGroup() throws TimeoutException {
|
||||
|
||||
// no proxy case.
|
||||
if(socks5Proxy == null) {
|
||||
return super.createPeerGroup();
|
||||
}
|
||||
|
||||
// proxy case.
|
||||
Proxy proxy = new Proxy ( Proxy.Type.SOCKS,
|
||||
new InetSocketAddress(socks5Proxy.getInetAddress().getHostName(),
|
||||
socks5Proxy.getPort() ) );
|
||||
|
||||
int CONNECT_TIMEOUT_MSEC = 60 * 1000; // same value used in bitcoinj.
|
||||
ProxySocketFactory proxySocketFactory = new ProxySocketFactory(proxy);
|
||||
BlockingClientManager mgr = new BlockingClientManager(proxySocketFactory);
|
||||
PeerGroup peerGroup = new PeerGroup(params, vChain, mgr);
|
||||
|
||||
mgr.setConnectTimeoutMillis(CONNECT_TIMEOUT_MSEC);
|
||||
peerGroup.setConnectTimeoutMillis(CONNECT_TIMEOUT_MSEC);
|
||||
|
||||
// This enables remote DNS lookup of peers over socks5 proxy.
|
||||
// It is slower, but more private.
|
||||
// This could be turned into a user option.
|
||||
this.setDiscovery( new SeedPeersSocks5Dns(socks5Proxy, params) );
|
||||
|
||||
return peerGroup;
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.Service;
|
||||
import com.runjva.sourceforge.jsocks.protocol.Socks5Proxy;
|
||||
import io.bitsquare.btc.listeners.AddressConfidenceListener;
|
||||
import io.bitsquare.btc.listeners.BalanceListener;
|
||||
import io.bitsquare.btc.listeners.TxConfidenceListener;
|
||||
@ -30,6 +31,7 @@ import io.bitsquare.common.UserThread;
|
||||
import io.bitsquare.common.handlers.ErrorMessageHandler;
|
||||
import io.bitsquare.common.handlers.ExceptionHandler;
|
||||
import io.bitsquare.common.handlers.ResultHandler;
|
||||
import io.bitsquare.p2p.NodeAddress;
|
||||
import io.bitsquare.storage.FileUtil;
|
||||
import io.bitsquare.storage.Storage;
|
||||
import io.bitsquare.user.Preferences;
|
||||
@ -54,6 +56,7 @@ import javax.inject.Named;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
@ -91,7 +94,7 @@ public class WalletService {
|
||||
private final UserAgent userAgent;
|
||||
private final boolean useTor;
|
||||
|
||||
private WalletAppKit walletAppKit;
|
||||
private WalletAppKitBitSquare walletAppKit;
|
||||
private Wallet wallet;
|
||||
private final IntegerProperty numPeers = new SimpleIntegerProperty(0);
|
||||
private final ObjectProperty<List<Peer>> connectedPeers = new SimpleObjectProperty<>();
|
||||
@ -147,7 +150,7 @@ public class WalletService {
|
||||
// Public Methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void initialize(@Nullable DeterministicSeed seed, ResultHandler resultHandler, ExceptionHandler exceptionHandler) {
|
||||
public void initialize(@Nullable DeterministicSeed seed, Socks5Proxy proxy, ResultHandler resultHandler, ExceptionHandler exceptionHandler) {
|
||||
// Tell bitcoinj to execute event handlers on the JavaFX UI thread. This keeps things simple and means
|
||||
// we cannot forget to switch threads when adding event handlers. Unfortunately, the DownloadListener
|
||||
// we give to the app kit is currently an exception and runs on a library thread. It'll get fixed in
|
||||
@ -163,7 +166,7 @@ public class WalletService {
|
||||
backupWallet();
|
||||
|
||||
// If seed is non-null it means we are restoring from backup.
|
||||
walletAppKit = new WalletAppKit(params, walletDir, "Bitsquare") {
|
||||
walletAppKit = new WalletAppKitBitSquare(params, proxy, walletDir, "Bitsquare") {
|
||||
@Override
|
||||
protected void onSetupCompleted() {
|
||||
// Don't make the user wait for confirmations for now, as the intention is they're sending it
|
||||
@ -264,13 +267,52 @@ public class WalletService {
|
||||
// 1333 / (2800 + 1333) = 0.32 -> 32 % probability that a pub key is in our wallet
|
||||
walletAppKit.setBloomFilterFalsePositiveRate(0.00005);
|
||||
|
||||
log.debug( "seedNodes: " + seedNodes.toString() );
|
||||
|
||||
// Pass custom seed nodes if set in options
|
||||
if (seedNodes != null && !seedNodes.isEmpty()) {
|
||||
//TODO Check how to pass seed nodes to the wallet kit. Probably via walletAppKit.setPeerNodes
|
||||
|
||||
// todo: this parsing should be more robust,
|
||||
// give validation error if needed.
|
||||
// also: it seems the peer nodes can be overridden in the case
|
||||
// of regtest mode below. is that wanted?
|
||||
String[] nodes = seedNodes.split(",");
|
||||
List<PeerAddress> peerAddressList = new ArrayList<PeerAddress>();
|
||||
for(String node : nodes) {
|
||||
String[] parts = node.split(":");
|
||||
if( parts.length == 2 ) {
|
||||
// note: this will cause a DNS request if hostname used.
|
||||
// note: DNS requests are routed over socks5 proxy, if used.
|
||||
// fixme: .onion hostnames will fail! see comments in SeedPeersSocks5Dns
|
||||
InetSocketAddress addr;
|
||||
if( proxy != null ) {
|
||||
InetSocketAddress unresolved = InetSocketAddress.createUnresolved(parts[0], Integer.parseInt(parts[1]));
|
||||
// proxy remote DNS request happens here.
|
||||
addr = SeedPeersSocks5Dns.lookup( proxy, unresolved );
|
||||
}
|
||||
else {
|
||||
// DNS request happens here. if it fails, addr.isUnresolved() == true.
|
||||
addr = new InetSocketAddress( parts[0], Integer.parseInt(parts[1]) );
|
||||
}
|
||||
// note: isUnresolved check should be removed once we fix PeerAddress
|
||||
if( addr != null && !addr.isUnresolved() ) {
|
||||
peerAddressList.add( new PeerAddress( addr.getAddress(), addr.getPort() ));
|
||||
}
|
||||
}
|
||||
}
|
||||
if(peerAddressList.size() > 0) {
|
||||
PeerAddress peerAddressListFixed[] = new PeerAddress[peerAddressList.size()];
|
||||
log.debug( "seedNodes parsed: " + peerAddressListFixed.toString() );
|
||||
|
||||
walletAppKit.setPeerNodes(peerAddressList.toArray(peerAddressListFixed));
|
||||
}
|
||||
}
|
||||
|
||||
if (useTor && params.getId().equals(NetworkParameters.ID_MAINNET))
|
||||
walletAppKit.useTor();
|
||||
// We do not call walletAppKit.useTor() anymore because that would turn
|
||||
// on orchid Tor, which we do not want. Instead, we create a Tor proxy
|
||||
// later.
|
||||
// if (useTor && params.getId().equals(NetworkParameters.ID_MAINNET))
|
||||
// walletAppKit.useTor();
|
||||
|
||||
// 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.
|
||||
@ -338,7 +380,7 @@ public class WalletService {
|
||||
Context.propagate(ctx);
|
||||
walletAppKit.stopAsync();
|
||||
walletAppKit.awaitTerminated();
|
||||
initialize(seed, resultHandler, exceptionHandler);
|
||||
initialize(seed, walletAppKit.getProxy(), resultHandler, exceptionHandler);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
log.error("Executing task failed. " + t.getMessage());
|
||||
|
@ -18,6 +18,7 @@
|
||||
package io.bitsquare.gui.main;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.runjva.sourceforge.jsocks.protocol.Socks5Proxy;
|
||||
import io.bitsquare.alert.Alert;
|
||||
import io.bitsquare.alert.AlertManager;
|
||||
import io.bitsquare.alert.PrivateNotification;
|
||||
@ -55,6 +56,7 @@ import io.bitsquare.gui.main.overlays.windows.WalletPasswordWindow;
|
||||
import io.bitsquare.gui.util.BSFormatter;
|
||||
import io.bitsquare.locale.CurrencyUtil;
|
||||
import io.bitsquare.locale.TradeCurrency;
|
||||
import io.bitsquare.p2p.NodeAddress;
|
||||
import io.bitsquare.p2p.P2PService;
|
||||
import io.bitsquare.p2p.P2PServiceListener;
|
||||
import io.bitsquare.p2p.network.CloseConnectionReason;
|
||||
@ -234,8 +236,8 @@ public class MainViewModel implements ViewModel {
|
||||
showStartupTimeoutPopup();
|
||||
}, 4, TimeUnit.MINUTES);
|
||||
|
||||
walletInitialized = initBitcoinWallet();
|
||||
p2pNetWorkReady = initP2PNetwork();
|
||||
walletInitialized = initBitcoinWallet();
|
||||
|
||||
// need to store it to not get garbage collected
|
||||
allServicesDone = EasyBind.combine(walletInitialized, p2pNetWorkReady, (a, b) -> a && b);
|
||||
@ -348,6 +350,9 @@ public class MainViewModel implements ViewModel {
|
||||
public void onTorNodeReady() {
|
||||
bootstrapState.set("Tor node created");
|
||||
p2PNetworkIconId.set("image-connection-tor");
|
||||
if( preferences.getUseTorForBitcoinJ() ) {
|
||||
initWalletService();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -422,6 +427,18 @@ public class MainViewModel implements ViewModel {
|
||||
}
|
||||
|
||||
private BooleanProperty initBitcoinWallet() {
|
||||
final BooleanProperty walletInitialized = new SimpleBooleanProperty();
|
||||
|
||||
// We only init wallet service here if not using Tor for bitcoinj.
|
||||
// When using Tor, wallet init must be deferred until Tor is ready.
|
||||
if( !preferences.getUseTorForBitcoinJ() ) {
|
||||
initWalletService();
|
||||
}
|
||||
|
||||
return walletInitialized;
|
||||
}
|
||||
|
||||
private void initWalletService() {
|
||||
ObjectProperty<Throwable> walletServiceException = new SimpleObjectProperty<>();
|
||||
btcInfoBinding = EasyBind.combine(walletService.downloadPercentageProperty(), walletService.numPeersProperty(), walletServiceException,
|
||||
(downloadPercentage, numPeers, exception) -> {
|
||||
@ -461,9 +478,26 @@ public class MainViewModel implements ViewModel {
|
||||
btcInfoBinding.subscribe((observable, oldValue, newValue) -> {
|
||||
btcInfo.set(newValue);
|
||||
});
|
||||
|
||||
Socks5Proxy proxy = null;
|
||||
|
||||
if( preferences.getUseTorForBitcoinJ() ) {
|
||||
// Use p2p service
|
||||
proxy = p2PService.getNetworkNode().getSocksProxy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Uncomment this to wire up user specified proxy via program args or config file.
|
||||
* Could be Tor, i2p, ssh, vpn, etc.
|
||||
if( preferences.getBitcoinProxyHost() != null &&
|
||||
preferences.getBitcoinProxyPort() != null ) {
|
||||
proxy = new Socks5Proxy( preferences.getBitcoinProxyHost(),
|
||||
preferences.getBitcoinProxyPort() );
|
||||
}
|
||||
*/
|
||||
|
||||
final BooleanProperty walletInitialized = new SimpleBooleanProperty();
|
||||
walletService.initialize(null,
|
||||
proxy,
|
||||
() -> {
|
||||
numBtcPeers = walletService.numPeersProperty().get();
|
||||
|
||||
@ -484,7 +518,6 @@ public class MainViewModel implements ViewModel {
|
||||
}
|
||||
},
|
||||
walletServiceException::set);
|
||||
return walletInitialized;
|
||||
}
|
||||
|
||||
private void onAllServicesInitialized() {
|
||||
|
@ -33,6 +33,10 @@ public abstract class TorNode<M extends OnionProxyManager, C extends OnionProxyC
|
||||
log.info("TorSocks running on port " + proxyPort);
|
||||
this.proxy = setupSocksProxy(proxyPort);
|
||||
}
|
||||
|
||||
public Socks5Proxy getSocksProxy() {
|
||||
return proxy;
|
||||
}
|
||||
|
||||
private Socks5Proxy setupSocksProxy(int proxyPort) throws UnknownHostException {
|
||||
Socks5Proxy proxy = new Socks5Proxy(PROXY_LOCALHOST, proxyPort);
|
||||
|
@ -4,5 +4,5 @@ DisableNetwork 1
|
||||
AvoidDiskWrites 1
|
||||
PidFile pid
|
||||
RunAsDaemon 1
|
||||
SafeSocks 1
|
||||
SafeSocks 0
|
||||
SOCKSPort auto
|
||||
|
@ -80,8 +80,7 @@ public class LocalhostNetworkNode extends NetworkNode {
|
||||
protected Socket createSocket(NodeAddress peerNodeAddress) throws IOException {
|
||||
return new Socket(peerNodeAddress.hostName, peerNodeAddress.port);
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Tor delay simulation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1,6 +1,7 @@
|
||||
package io.bitsquare.p2p.network;
|
||||
|
||||
import com.google.common.util.concurrent.*;
|
||||
import com.runjva.sourceforge.jsocks.protocol.Socks5Proxy;
|
||||
import io.bitsquare.app.Log;
|
||||
import io.bitsquare.common.UserThread;
|
||||
import io.bitsquare.common.util.Utilities;
|
||||
@ -213,6 +214,12 @@ public abstract class NetworkNode implements MessageListener {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Socks5Proxy getSocksProxy() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public SettableFuture<Connection> sendMessage(Connection connection, Message message) {
|
||||
Log.traceCall("\n\tmessage=" + StringUtils.abbreviate(message.toString(), 100) + "\n\tconnection=" + connection);
|
||||
// connection.sendMessage might take a bit (compression, write to stream), so we use a thread to not block
|
||||
|
@ -6,6 +6,7 @@ import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import com.msopentech.thali.java.toronionproxy.JavaOnionProxyContext;
|
||||
import com.msopentech.thali.java.toronionproxy.JavaOnionProxyManager;
|
||||
import com.runjva.sourceforge.jsocks.protocol.Socks5Proxy;
|
||||
import io.bitsquare.app.Log;
|
||||
import io.bitsquare.common.Timer;
|
||||
import io.bitsquare.common.UserThread;
|
||||
@ -95,10 +96,15 @@ public class TorNetworkNode extends NetworkNode {
|
||||
|
||||
@Override
|
||||
protected Socket createSocket(NodeAddress peerNodeAddress) throws IOException {
|
||||
checkArgument(peerNodeAddress.hostName.endsWith(".onion"), "PeerAddress is not an onion address");
|
||||
// FIXME: disabling temporarily.
|
||||
// checkArgument(peerNodeAddress.hostName.endsWith(".onion"), "PeerAddress is not an onion address");
|
||||
|
||||
return torNetworkNode.connectToHiddenService(peerNodeAddress.hostName, peerNodeAddress.port);
|
||||
}
|
||||
|
||||
public Socks5Proxy getSocksProxy() {
|
||||
return torNetworkNode != null ? torNetworkNode.getSocksProxy() : null;
|
||||
}
|
||||
|
||||
public void shutDown(@Nullable Runnable shutDownCompleteHandler) {
|
||||
Log.traceCall();
|
||||
|
Loading…
Reference in New Issue
Block a user