mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-08-10 07:30:05 -04:00
manage monero connections from ui #623
use tor for all monero connections by default renames from btc to xmr updated translations
This commit is contained in:
parent
1faedc8121
commit
06be2a4829
45 changed files with 681 additions and 663 deletions
|
@ -1,10 +1,13 @@
|
|||
package haveno.core.api;
|
||||
|
||||
import haveno.common.app.DevEnv;
|
||||
import haveno.common.config.BaseCurrencyNetwork;
|
||||
import haveno.common.config.Config;
|
||||
import haveno.core.trade.HavenoUtils;
|
||||
import haveno.core.user.Preferences;
|
||||
import haveno.core.xmr.model.EncryptedConnectionList;
|
||||
import haveno.core.xmr.nodes.XmrNodes;
|
||||
import haveno.core.xmr.nodes.XmrNodesSetupPreferences;
|
||||
import haveno.core.xmr.nodes.XmrNodes.XmrNode;
|
||||
import haveno.core.xmr.setup.DownloadListener;
|
||||
import haveno.core.xmr.setup.WalletsSetup;
|
||||
import haveno.network.Socks5ProxyProvider;
|
||||
|
@ -32,10 +35,7 @@ import monero.daemon.model.MoneroPeer;
|
|||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -50,38 +50,14 @@ public final class CoreMoneroConnectionsService {
|
|||
private static final long MIN_ERROR_LOG_PERIOD_MS = 300000; // minimum period between logging errors fetching daemon info
|
||||
private static Long lastErrorTimestamp;
|
||||
|
||||
// default Monero nodes
|
||||
private static final Map<BaseCurrencyNetwork, List<MoneroRpcConnection>> DEFAULT_CONNECTIONS;
|
||||
static {
|
||||
DEFAULT_CONNECTIONS = new HashMap<BaseCurrencyNetwork, List<MoneroRpcConnection>>();
|
||||
DEFAULT_CONNECTIONS.put(BaseCurrencyNetwork.XMR_LOCAL, Arrays.asList(
|
||||
new MoneroRpcConnection("http://127.0.0.1:28081").setPriority(1)
|
||||
));
|
||||
DEFAULT_CONNECTIONS.put(BaseCurrencyNetwork.XMR_STAGENET, Arrays.asList(
|
||||
new MoneroRpcConnection("http://127.0.0.1:38081").setPriority(1), // localhost is first priority, use loopback address 127.0.0.1 to match url used by local node service
|
||||
new MoneroRpcConnection("http://127.0.0.1:39081").setPriority(2), // from makefile: `monerod-stagenet-custom`
|
||||
new MoneroRpcConnection("http://45.63.8.26:38081").setPriority(2), // hosted by haveno
|
||||
new MoneroRpcConnection("http://stagenet.community.rino.io:38081").setPriority(2),
|
||||
new MoneroRpcConnection("http://stagenet.melo.tools:38081").setPriority(2),
|
||||
new MoneroRpcConnection("http://node.sethforprivacy.com:38089").setPriority(2),
|
||||
new MoneroRpcConnection("http://node2.sethforprivacy.com:38089").setPriority(2),
|
||||
new MoneroRpcConnection("http://plowsof3t5hogddwabaeiyrno25efmzfxyro2vligremt7sxpsclfaid.onion:38089").setPriority(2)
|
||||
));
|
||||
DEFAULT_CONNECTIONS.put(BaseCurrencyNetwork.XMR_MAINNET, Arrays.asList(
|
||||
new MoneroRpcConnection("http://127.0.0.1:18081").setPriority(1),
|
||||
new MoneroRpcConnection("http://node.community.rino.io:18081").setPriority(2),
|
||||
new MoneroRpcConnection("http://xmr-node.cakewallet.com:18081").setPriority(2),
|
||||
new MoneroRpcConnection("http://xmr-node-eu.cakewallet.com:18081").setPriority(2),
|
||||
new MoneroRpcConnection("http://xmr-node-usa-east.cakewallet.com:18081").setPriority(2),
|
||||
new MoneroRpcConnection("http://xmr-node-uk.cakewallet.com:18081").setPriority(2),
|
||||
new MoneroRpcConnection("http://node.sethforprivacy.com:18089").setPriority(2)
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
private final Object lock = new Object();
|
||||
private final Config config;
|
||||
private final CoreContext coreContext;
|
||||
private final Preferences preferences;
|
||||
private final CoreAccountService accountService;
|
||||
private final XmrNodes xmrNodes;
|
||||
private final CoreMoneroNodeService nodeService;
|
||||
private final MoneroConnectionManager connectionManager;
|
||||
private final EncryptedConnectionList connectionList;
|
||||
|
@ -103,15 +79,19 @@ public final class CoreMoneroConnectionsService {
|
|||
public CoreMoneroConnectionsService(P2PService p2PService,
|
||||
Config config,
|
||||
CoreContext coreContext,
|
||||
Preferences preferences,
|
||||
WalletsSetup walletsSetup,
|
||||
CoreAccountService accountService,
|
||||
XmrNodes xmrNodes,
|
||||
CoreMoneroNodeService nodeService,
|
||||
MoneroConnectionManager connectionManager,
|
||||
EncryptedConnectionList connectionList,
|
||||
Socks5ProxyProvider socks5ProxyProvider) {
|
||||
this.config = config;
|
||||
this.coreContext = coreContext;
|
||||
this.preferences = preferences;
|
||||
this.accountService = accountService;
|
||||
this.xmrNodes = xmrNodes;
|
||||
this.nodeService = nodeService;
|
||||
this.connectionManager = connectionManager;
|
||||
this.connectionList = connectionList;
|
||||
|
@ -178,7 +158,7 @@ public final class CoreMoneroConnectionsService {
|
|||
public void addConnection(MoneroRpcConnection connection) {
|
||||
synchronized (lock) {
|
||||
accountService.checkAccountOpen();
|
||||
connectionList.addConnection(connection);
|
||||
if (coreContext.isApiUser()) connectionList.addConnection(connection);
|
||||
connectionManager.addConnection(connection);
|
||||
}
|
||||
}
|
||||
|
@ -342,7 +322,7 @@ public final class CoreMoneroConnectionsService {
|
|||
if (isConnectionLocal()) {
|
||||
if (lastInfo != null && (lastInfo.isBusySyncing() || (lastInfo.getHeightWithoutBootstrap() != null && lastInfo.getHeightWithoutBootstrap() > 0 && lastInfo.getHeightWithoutBootstrap() < lastInfo.getHeight()))) return REFRESH_PERIOD_HTTP_MS; // refresh slower if syncing or bootstrapped
|
||||
else return REFRESH_PERIOD_LOCAL_MS; // TODO: announce faster refresh after done syncing
|
||||
} else if (getConnection().isOnion()) {
|
||||
} else if (useProxy(getConnection())) {
|
||||
return REFRESH_PERIOD_ONION_MS;
|
||||
} else {
|
||||
return REFRESH_PERIOD_HTTP_MS;
|
||||
|
@ -350,6 +330,10 @@ public final class CoreMoneroConnectionsService {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean useProxy(MoneroRpcConnection connection) {
|
||||
return connection.isOnion() || (preferences.isUseTorForMonero() && !HavenoUtils.isLocalHost(connection.getUri()));
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
|
||||
// initialize connections
|
||||
|
@ -384,35 +368,61 @@ public final class CoreMoneroConnectionsService {
|
|||
connectionManager.reset();
|
||||
connectionManager.setTimeout(REFRESH_PERIOD_HTTP_MS);
|
||||
|
||||
// load connections
|
||||
log.info("TOR proxy URI: " + getProxyUri());
|
||||
for (MoneroRpcConnection connection : connectionList.getConnections()) {
|
||||
if (connection.isOnion()) connection.setProxyUri(getProxyUri());
|
||||
connectionManager.addConnection(connection);
|
||||
}
|
||||
log.info("Read " + connectionList.getConnections().size() + " connections from disk");
|
||||
// load previous or default connections
|
||||
if (coreContext.isApiUser()) {
|
||||
|
||||
// add default connections
|
||||
for (MoneroRpcConnection connection : DEFAULT_CONNECTIONS.get(Config.baseCurrencyNetwork())) {
|
||||
if (connectionList.hasConnection(connection.getUri())) continue;
|
||||
if (connection.isOnion()) connection.setProxyUri(getProxyUri());
|
||||
addConnection(connection);
|
||||
// load previous connections
|
||||
for (MoneroRpcConnection connection : connectionList.getConnections()) connectionManager.addConnection(connection);
|
||||
log.info("Read " + connectionList.getConnections().size() + " previous connections from disk");
|
||||
|
||||
// add default connections
|
||||
for (XmrNode node : xmrNodes.getAllXmrNodes()) {
|
||||
if (node.hasClearNetAddress()) {
|
||||
MoneroRpcConnection connection = new MoneroRpcConnection(node.getAddress() + ":" + node.getPort()).setPriority(node.getPriority());
|
||||
if (!connectionList.hasConnection(connection.getUri())) addConnection(connection);
|
||||
}
|
||||
if (node.hasOnionAddress()) {
|
||||
MoneroRpcConnection connection = new MoneroRpcConnection(node.getOnionAddress() + ":" + node.getPort()).setPriority(node.getPriority());
|
||||
if (!connectionList.hasConnection(connection.getUri())) addConnection(connection);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
// add default connections
|
||||
for (XmrNode node : xmrNodes.selectPreferredNodes(new XmrNodesSetupPreferences(preferences))) {
|
||||
if (node.hasClearNetAddress()) {
|
||||
MoneroRpcConnection connection = new MoneroRpcConnection(node.getAddress() + ":" + node.getPort()).setPriority(node.getPriority());
|
||||
addConnection(connection);
|
||||
}
|
||||
if (node.hasOnionAddress()) {
|
||||
MoneroRpcConnection connection = new MoneroRpcConnection(node.getOnionAddress() + ":" + node.getPort()).setPriority(node.getPriority());
|
||||
addConnection(connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// restore last used connection if unconfigured and present
|
||||
Optional<String> currentConnectionUri = null;
|
||||
// set current connection
|
||||
Optional<String> currentConnectionUri = Optional.empty();
|
||||
if ("".equals(config.xmrNode)) {
|
||||
currentConnectionUri = connectionList.getCurrentConnectionUri();
|
||||
if (currentConnectionUri.isPresent()) connectionManager.setConnection(currentConnectionUri.get());
|
||||
if (coreContext.isApiUser() && connectionList.getCurrentConnectionUri().isPresent()) {
|
||||
currentConnectionUri = connectionList.getCurrentConnectionUri();
|
||||
connectionManager.setConnection(currentConnectionUri.get());
|
||||
}
|
||||
} else if (!isInitialized) {
|
||||
|
||||
// set monero connection from startup arguments
|
||||
MoneroRpcConnection connection = new MoneroRpcConnection(config.xmrNode, config.xmrNodeUsername, config.xmrNodePassword).setPriority(1);
|
||||
if (connection.isOnion()) connection.setProxyUri(getProxyUri());
|
||||
if (useProxy(connection)) connection.setProxyUri(getProxyUri());
|
||||
connectionManager.setConnection(connection);
|
||||
currentConnectionUri = Optional.of(connection.getUri());
|
||||
}
|
||||
|
||||
// set connection proxies
|
||||
log.info("TOR proxy URI: " + getProxyUri());
|
||||
for (MoneroRpcConnection connection : connectionManager.getConnections()) {
|
||||
if (useProxy(connection)) connection.setProxyUri(getProxyUri());
|
||||
}
|
||||
|
||||
// restore configuration
|
||||
if ("".equals(config.xmrNode)) connectionManager.setAutoSwitch(connectionList.getAutoSwitch());
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ public class WalletAppSetup {
|
|||
this.connectionService = connectionService;
|
||||
this.config = config;
|
||||
this.preferences = preferences;
|
||||
this.useTorForBTC.set(preferences.getUseTorForBitcoinJ());
|
||||
this.useTorForBTC.set(preferences.getUseTorForMonero());
|
||||
}
|
||||
|
||||
void init(@Nullable Consumer<String> chainFileLockedExceptionHandler,
|
||||
|
@ -259,9 +259,9 @@ public class WalletAppSetup {
|
|||
|
||||
private String getBtcNetworkAsString() {
|
||||
String postFix;
|
||||
if (config.ignoreLocalBtcNode)
|
||||
if (config.ignoreLocalXmrNode)
|
||||
postFix = " " + Res.get("mainView.footer.localhostBitcoinNode");
|
||||
else if (preferences.getUseTorForBitcoinJ())
|
||||
else if (preferences.getUseTorForMonero())
|
||||
postFix = " " + Res.get("mainView.footer.usingTor");
|
||||
else
|
||||
postFix = "";
|
||||
|
|
|
@ -53,7 +53,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
|
|||
private final List<String> seedNodes;
|
||||
private final List<String> priceRelayNodes;
|
||||
private final boolean preventPublicBtcNetwork;
|
||||
private final List<String> btcNodes;
|
||||
private final List<String> xmrNodes;
|
||||
// SignatureAsBase64 is not set initially as we use the serialized data for signing. We set it after signature is
|
||||
// created by cloning the object with a non-null sig.
|
||||
@Nullable
|
||||
|
@ -104,7 +104,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
|
|||
filter.getSeedNodes(),
|
||||
filter.getPriceRelayNodes(),
|
||||
filter.isPreventPublicBtcNetwork(),
|
||||
filter.getBtcNodes(),
|
||||
filter.getXmrNodes(),
|
||||
filter.getDisableTradeBelowVersion(),
|
||||
filter.getMediators(),
|
||||
filter.getRefundAgents(),
|
||||
|
@ -134,7 +134,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
|
|||
filter.getSeedNodes(),
|
||||
filter.getPriceRelayNodes(),
|
||||
filter.isPreventPublicBtcNetwork(),
|
||||
filter.getBtcNodes(),
|
||||
filter.getXmrNodes(),
|
||||
filter.getDisableTradeBelowVersion(),
|
||||
filter.getMediators(),
|
||||
filter.getRefundAgents(),
|
||||
|
@ -162,7 +162,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
|
|||
List<String> seedNodes,
|
||||
List<String> priceRelayNodes,
|
||||
boolean preventPublicBtcNetwork,
|
||||
List<String> btcNodes,
|
||||
List<String> xmrNodes,
|
||||
String disableTradeBelowVersion,
|
||||
List<String> mediators,
|
||||
List<String> refundAgents,
|
||||
|
@ -185,7 +185,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
|
|||
seedNodes,
|
||||
priceRelayNodes,
|
||||
preventPublicBtcNetwork,
|
||||
btcNodes,
|
||||
xmrNodes,
|
||||
disableTradeBelowVersion,
|
||||
mediators,
|
||||
refundAgents,
|
||||
|
@ -219,7 +219,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
|
|||
List<String> seedNodes,
|
||||
List<String> priceRelayNodes,
|
||||
boolean preventPublicBtcNetwork,
|
||||
List<String> btcNodes,
|
||||
List<String> xmrNodes,
|
||||
String disableTradeBelowVersion,
|
||||
List<String> mediators,
|
||||
List<String> refundAgents,
|
||||
|
@ -245,7 +245,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
|
|||
this.seedNodes = seedNodes;
|
||||
this.priceRelayNodes = priceRelayNodes;
|
||||
this.preventPublicBtcNetwork = preventPublicBtcNetwork;
|
||||
this.btcNodes = btcNodes;
|
||||
this.xmrNodes = xmrNodes;
|
||||
this.disableTradeBelowVersion = disableTradeBelowVersion;
|
||||
this.mediators = mediators;
|
||||
this.refundAgents = refundAgents;
|
||||
|
@ -286,7 +286,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
|
|||
.addAllSeedNodes(seedNodes)
|
||||
.addAllPriceRelayNodes(priceRelayNodes)
|
||||
.setPreventPublicBtcNetwork(preventPublicBtcNetwork)
|
||||
.addAllBtcNodes(btcNodes)
|
||||
.addAllXmrNodes(xmrNodes)
|
||||
.setDisableTradeBelowVersion(disableTradeBelowVersion)
|
||||
.addAllMediators(mediators)
|
||||
.addAllRefundAgents(refundAgents)
|
||||
|
@ -323,7 +323,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
|
|||
ProtoUtil.protocolStringListToList(proto.getSeedNodesList()),
|
||||
ProtoUtil.protocolStringListToList(proto.getPriceRelayNodesList()),
|
||||
proto.getPreventPublicBtcNetwork(),
|
||||
ProtoUtil.protocolStringListToList(proto.getBtcNodesList()),
|
||||
ProtoUtil.protocolStringListToList(proto.getXmrNodesList()),
|
||||
proto.getDisableTradeBelowVersion(),
|
||||
ProtoUtil.protocolStringListToList(proto.getMediatorsList()),
|
||||
ProtoUtil.protocolStringListToList(proto.getRefundAgentsList()),
|
||||
|
@ -366,7 +366,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
|
|||
",\n seedNodes=" + seedNodes +
|
||||
",\n priceRelayNodes=" + priceRelayNodes +
|
||||
",\n preventPublicBtcNetwork=" + preventPublicBtcNetwork +
|
||||
",\n btcNodes=" + btcNodes +
|
||||
",\n xmrNodes=" + xmrNodes +
|
||||
",\n signatureAsBase64='" + signatureAsBase64 + '\'' +
|
||||
",\n signerPubKeyAsHex='" + signerPubKeyAsHex + '\'' +
|
||||
",\n ownerPubKeyBytes=" + Utilities.bytesAsHexString(ownerPubKeyBytes) +
|
||||
|
|
|
@ -28,7 +28,7 @@ import haveno.core.payment.payload.PaymentMethod;
|
|||
import haveno.core.provider.ProvidersRepository;
|
||||
import haveno.core.user.Preferences;
|
||||
import haveno.core.user.User;
|
||||
import haveno.core.xmr.nodes.BtcNodes;
|
||||
import haveno.core.xmr.nodes.XmrNodes;
|
||||
import haveno.network.p2p.NodeAddress;
|
||||
import haveno.network.p2p.P2PService;
|
||||
import haveno.network.p2p.P2PServiceListener;
|
||||
|
@ -69,7 +69,7 @@ import static org.bitcoinj.core.Utils.HEX;
|
|||
public class FilterManager {
|
||||
private static final String BANNED_PRICE_RELAY_NODES = "bannedPriceRelayNodes";
|
||||
private static final String BANNED_SEED_NODES = "bannedSeedNodes";
|
||||
private static final String BANNED_BTC_NODES = "bannedBtcNodes";
|
||||
private static final String BANNED_XMR_NODES = "bannedXmrNodes";
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Listener
|
||||
|
@ -497,7 +497,7 @@ public class FilterManager {
|
|||
// nodes at the next startup and don't update the list in the P2P network domain.
|
||||
// We persist it to the property file which is read before any other initialisation.
|
||||
saveBannedNodes(BANNED_SEED_NODES, newFilter.getSeedNodes());
|
||||
saveBannedNodes(BANNED_BTC_NODES, newFilter.getBtcNodes());
|
||||
saveBannedNodes(BANNED_XMR_NODES, newFilter.getXmrNodes());
|
||||
|
||||
// Banned price relay nodes we can apply at runtime
|
||||
List<String> priceRelayNodes = newFilter.getPriceRelayNodes();
|
||||
|
@ -508,8 +508,8 @@ public class FilterManager {
|
|||
|
||||
//TODO should be moved to client with listening on onFilterAdded
|
||||
if (newFilter.isPreventPublicBtcNetwork() &&
|
||||
preferences.getBitcoinNodesOptionOrdinal() == BtcNodes.BitcoinNodesOption.PUBLIC.ordinal()) {
|
||||
preferences.setBitcoinNodesOptionOrdinal(BtcNodes.BitcoinNodesOption.PROVIDED.ordinal());
|
||||
preferences.getMoneroNodesOptionOrdinal() == XmrNodes.MoneroNodesOption.PUBLIC.ordinal()) {
|
||||
preferences.setMoneroNodesOptionOrdinal(XmrNodes.MoneroNodesOption.PROVIDED.ordinal());
|
||||
}
|
||||
|
||||
listeners.forEach(e -> e.onFilterAdded(newFilter));
|
||||
|
@ -541,7 +541,7 @@ public class FilterManager {
|
|||
|
||||
// Clears options files from banned nodes
|
||||
private void clearBannedNodes() {
|
||||
saveBannedNodes(BANNED_BTC_NODES, null);
|
||||
saveBannedNodes(BANNED_XMR_NODES, null);
|
||||
saveBannedNodes(BANNED_SEED_NODES, null);
|
||||
saveBannedNodes(BANNED_PRICE_RELAY_NODES, null);
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ import haveno.core.locale.TradeCurrency;
|
|||
import haveno.core.payment.PaymentAccount;
|
||||
import haveno.core.payment.PaymentAccountUtil;
|
||||
import haveno.core.xmr.MoneroNodeSettings;
|
||||
import haveno.core.xmr.nodes.BtcNodes;
|
||||
import haveno.core.xmr.nodes.XmrNodes;
|
||||
import haveno.core.xmr.nodes.LocalBitcoinNode;
|
||||
import haveno.core.xmr.wallet.Restrictions;
|
||||
import haveno.network.p2p.network.BridgeAddressProvider;
|
||||
|
@ -154,7 +154,7 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
|
|||
private final PersistenceManager<PreferencesPayload> persistenceManager;
|
||||
private final Config config;
|
||||
private final LocalBitcoinNode localBitcoinNode;
|
||||
private final String btcNodesFromOptions;
|
||||
private final String xmrNodesFromOptions;
|
||||
@Getter
|
||||
private final BooleanProperty useStandbyModeProperty = new SimpleBooleanProperty(prefPayload.isUseStandbyMode());
|
||||
|
||||
|
@ -166,12 +166,12 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
|
|||
public Preferences(PersistenceManager<PreferencesPayload> persistenceManager,
|
||||
Config config,
|
||||
LocalBitcoinNode localBitcoinNode,
|
||||
@Named(Config.BTC_NODES) String btcNodesFromOptions) {
|
||||
@Named(Config.XMR_NODES) String xmrNodesFromOptions) {
|
||||
|
||||
this.persistenceManager = persistenceManager;
|
||||
this.config = config;
|
||||
this.localBitcoinNode = localBitcoinNode;
|
||||
this.btcNodesFromOptions = btcNodesFromOptions;
|
||||
this.xmrNodesFromOptions = xmrNodesFromOptions;
|
||||
|
||||
useAnimationsProperty.addListener((ov) -> {
|
||||
prefPayload.setUseAnimations(useAnimationsProperty.get());
|
||||
|
@ -303,16 +303,16 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
|
|||
dontShowAgainMapAsObservable.putAll(getDontShowAgainMap());
|
||||
|
||||
// Override settings with options if set
|
||||
if (config.useTorForBtcOptionSetExplicitly)
|
||||
setUseTorForBitcoinJ(config.useTorForBtc);
|
||||
if (config.useTorForXmrOptionSetExplicitly)
|
||||
setUseTorForMonero(config.useTorForXmr);
|
||||
|
||||
if (btcNodesFromOptions != null && !btcNodesFromOptions.isEmpty()) {
|
||||
if (getBitcoinNodes() != null && !getBitcoinNodes().equals(btcNodesFromOptions)) {
|
||||
if (xmrNodesFromOptions != null && !xmrNodesFromOptions.isEmpty()) {
|
||||
if (getMoneroNodes() != null && !getMoneroNodes().equals(xmrNodesFromOptions)) {
|
||||
log.warn("The Bitcoin node(s) from the program argument and the one(s) persisted in the UI are different. " +
|
||||
"The Bitcoin node(s) {} from the program argument will be used.", btcNodesFromOptions);
|
||||
"The Bitcoin node(s) {} from the program argument will be used.", xmrNodesFromOptions);
|
||||
}
|
||||
setBitcoinNodes(btcNodesFromOptions);
|
||||
setBitcoinNodesOptionOrdinal(BtcNodes.BitcoinNodesOption.CUSTOM.ordinal());
|
||||
setMoneroNodes(xmrNodesFromOptions);
|
||||
setMoneroNodesOptionOrdinal(XmrNodes.MoneroNodesOption.CUSTOM.ordinal());
|
||||
}
|
||||
|
||||
if (prefPayload.getIgnoreDustThreshold() < Restrictions.getMinNonDustOutput().value) {
|
||||
|
@ -492,8 +492,8 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
|
|||
}
|
||||
}
|
||||
|
||||
public void setUseTorForBitcoinJ(boolean useTorForBitcoinJ) {
|
||||
prefPayload.setUseTorForBitcoinJ(useTorForBitcoinJ);
|
||||
public void setUseTorForMonero(boolean useTorForMonero) {
|
||||
prefPayload.setUseTorForMonero(useTorForMonero);
|
||||
requestPersistence();
|
||||
}
|
||||
|
||||
|
@ -577,8 +577,8 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
|
|||
requestPersistence();
|
||||
}
|
||||
|
||||
public void setBitcoinNodes(String bitcoinNodes) {
|
||||
prefPayload.setBitcoinNodes(bitcoinNodes);
|
||||
public void setMoneroNodes(String bitcoinNodes) {
|
||||
prefPayload.setMoneroNodes(bitcoinNodes);
|
||||
requestPersistence();
|
||||
}
|
||||
|
||||
|
@ -663,8 +663,8 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
|
|||
persistenceManager.forcePersistNow();
|
||||
}
|
||||
|
||||
public void setBitcoinNodesOptionOrdinal(int bitcoinNodesOptionOrdinal) {
|
||||
prefPayload.setBitcoinNodesOptionOrdinal(bitcoinNodesOptionOrdinal);
|
||||
public void setMoneroNodesOptionOrdinal(int bitcoinNodesOptionOrdinal) {
|
||||
prefPayload.setMoneroNodesOptionOrdinal(bitcoinNodesOptionOrdinal);
|
||||
requestPersistence();
|
||||
}
|
||||
|
||||
|
@ -793,18 +793,8 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
|
|||
return !prefPayload.getDontShowAgainMap().containsKey(key) || !prefPayload.getDontShowAgainMap().get(key);
|
||||
}
|
||||
|
||||
public boolean getUseTorForBitcoinJ() {
|
||||
// We override the useTorForBitcoinJ and set it to false if we will use a
|
||||
// localhost Bitcoin node or if we are not on mainnet, unless the useTorForBtc
|
||||
// parameter is explicitly provided. On testnet there are very few Bitcoin tor
|
||||
// nodes and we don't provide tor nodes.
|
||||
|
||||
if ((!Config.baseCurrencyNetwork().isMainnet()
|
||||
|| localBitcoinNode.shouldBeUsed())
|
||||
&& !config.useTorForBtcOptionSetExplicitly)
|
||||
return false;
|
||||
else
|
||||
return prefPayload.isUseTorForBitcoinJ();
|
||||
public boolean getUseTorForMonero() {
|
||||
return prefPayload.isUseTorForMonero();
|
||||
}
|
||||
|
||||
public double getBuyerSecurityDepositAsPercent(PaymentAccount paymentAccount) {
|
||||
|
@ -869,7 +859,7 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
|
|||
|
||||
void setPreferredTradeCurrency(TradeCurrency preferredTradeCurrency);
|
||||
|
||||
void setUseTorForBitcoinJ(boolean useTorForBitcoinJ);
|
||||
void setUseTorForMonero(boolean useTorForMonero);
|
||||
|
||||
void setShowOwnOffersInOfferBook(boolean showOwnOffersInOfferBook);
|
||||
|
||||
|
@ -899,7 +889,7 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
|
|||
|
||||
void setSortMarketCurrenciesNumerically(boolean sortMarketCurrenciesNumerically);
|
||||
|
||||
void setBitcoinNodes(String bitcoinNodes);
|
||||
void setMoneroNodes(String bitcoinNodes);
|
||||
|
||||
void setUseCustomWithdrawalTxFee(boolean useCustomWithdrawalTxFee);
|
||||
|
||||
|
@ -931,7 +921,7 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
|
|||
|
||||
void setCustomBridges(String customBridges);
|
||||
|
||||
void setBitcoinNodesOptionOrdinal(int bitcoinNodesOption);
|
||||
void setMoneroNodesOptionOrdinal(int bitcoinNodesOption);
|
||||
|
||||
void setReferralId(String referralId);
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ package haveno.core.user;
|
|||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.protobuf.Message;
|
||||
|
||||
import haveno.common.proto.ProtoUtil;
|
||||
import haveno.common.proto.persistable.PersistableEnvelope;
|
||||
import haveno.core.locale.Country;
|
||||
|
@ -57,7 +58,7 @@ public final class PreferencesPayload implements PersistableEnvelope {
|
|||
private boolean autoSelectArbitrators = true;
|
||||
private Map<String, Boolean> dontShowAgainMap = new HashMap<>();
|
||||
private boolean tacAccepted;
|
||||
private boolean useTorForBitcoinJ = true;
|
||||
private boolean useTorForMonero = true;
|
||||
private boolean showOwnOffersInOfferBook = true;
|
||||
@Nullable
|
||||
private TradeCurrency preferredTradeCurrency;
|
||||
|
@ -81,8 +82,8 @@ public final class PreferencesPayload implements PersistableEnvelope {
|
|||
private boolean sortMarketCurrenciesNumerically = true;
|
||||
private boolean usePercentageBasedPrice = true;
|
||||
private Map<String, String> peerTagMap = new HashMap<>();
|
||||
// custom btc nodes
|
||||
private String bitcoinNodes = "";
|
||||
// custom xmr nodes
|
||||
private String moneroNodes = "";
|
||||
private List<String> ignoreTradersList = new ArrayList<>();
|
||||
private String directoryChooserPath;
|
||||
|
||||
|
@ -96,7 +97,7 @@ public final class PreferencesPayload implements PersistableEnvelope {
|
|||
private int torTransportOrdinal;
|
||||
@Nullable
|
||||
private String customBridges;
|
||||
private int bitcoinNodesOptionOrdinal;
|
||||
private int moneroNodesOptionOrdinal;
|
||||
@Nullable
|
||||
private String referralId;
|
||||
@Nullable
|
||||
|
@ -159,7 +160,7 @@ public final class PreferencesPayload implements PersistableEnvelope {
|
|||
.setAutoSelectArbitrators(autoSelectArbitrators)
|
||||
.putAllDontShowAgainMap(dontShowAgainMap)
|
||||
.setTacAccepted(tacAccepted)
|
||||
.setUseTorForBitcoinJ(useTorForBitcoinJ)
|
||||
.setUseTorForMonero(useTorForMonero)
|
||||
.setShowOwnOffersInOfferBook(showOwnOffersInOfferBook)
|
||||
.setWithdrawalTxFeeInVbytes(withdrawalTxFeeInVbytes)
|
||||
.setUseCustomWithdrawalTxFee(useCustomWithdrawalTxFee)
|
||||
|
@ -169,14 +170,14 @@ public final class PreferencesPayload implements PersistableEnvelope {
|
|||
.setSortMarketCurrenciesNumerically(sortMarketCurrenciesNumerically)
|
||||
.setUsePercentageBasedPrice(usePercentageBasedPrice)
|
||||
.putAllPeerTagMap(peerTagMap)
|
||||
.setBitcoinNodes(bitcoinNodes)
|
||||
.setMoneroNodes(moneroNodes)
|
||||
.addAllIgnoreTradersList(ignoreTradersList)
|
||||
.setDirectoryChooserPath(directoryChooserPath)
|
||||
.setUseAnimations(useAnimations)
|
||||
.setCssTheme(cssTheme)
|
||||
.setBridgeOptionOrdinal(bridgeOptionOrdinal)
|
||||
.setTorTransportOrdinal(torTransportOrdinal)
|
||||
.setBitcoinNodesOptionOrdinal(bitcoinNodesOptionOrdinal)
|
||||
.setMoneroNodesOptionOrdinal(moneroNodesOptionOrdinal)
|
||||
.setUseSoundForMobileNotifications(useSoundForMobileNotifications)
|
||||
.setUseTradeNotifications(useTradeNotifications)
|
||||
.setUseMarketNotifications(useMarketNotifications)
|
||||
|
@ -241,7 +242,7 @@ public final class PreferencesPayload implements PersistableEnvelope {
|
|||
proto.getAutoSelectArbitrators(),
|
||||
Maps.newHashMap(proto.getDontShowAgainMapMap()),
|
||||
proto.getTacAccepted(),
|
||||
proto.getUseTorForBitcoinJ(),
|
||||
proto.getUseTorForMonero(),
|
||||
proto.getShowOwnOffersInOfferBook(),
|
||||
proto.hasPreferredTradeCurrency() ? TradeCurrency.fromProto(proto.getPreferredTradeCurrency()) : null,
|
||||
proto.getWithdrawalTxFeeInVbytes(),
|
||||
|
@ -258,7 +259,7 @@ public final class PreferencesPayload implements PersistableEnvelope {
|
|||
proto.getSortMarketCurrenciesNumerically(),
|
||||
proto.getUsePercentageBasedPrice(),
|
||||
Maps.newHashMap(proto.getPeerTagMapMap()),
|
||||
proto.getBitcoinNodes(),
|
||||
proto.getMoneroNodes(),
|
||||
proto.getIgnoreTradersListList(),
|
||||
proto.getDirectoryChooserPath(),
|
||||
proto.getUseAnimations(),
|
||||
|
@ -268,7 +269,7 @@ public final class PreferencesPayload implements PersistableEnvelope {
|
|||
proto.getBridgeOptionOrdinal(),
|
||||
proto.getTorTransportOrdinal(),
|
||||
ProtoUtil.stringOrNullFromProto(proto.getCustomBridges()),
|
||||
proto.getBitcoinNodesOptionOrdinal(),
|
||||
proto.getMoneroNodesOptionOrdinal(),
|
||||
proto.getReferralId().isEmpty() ? null : proto.getReferralId(),
|
||||
proto.getPhoneKeyAndToken().isEmpty() ? null : proto.getPhoneKeyAndToken(),
|
||||
proto.getUseSoundForMobileNotifications(),
|
||||
|
|
|
@ -27,7 +27,7 @@ import haveno.core.provider.price.PriceFeedService;
|
|||
import haveno.core.xmr.model.AddressEntryList;
|
||||
import haveno.core.xmr.model.EncryptedConnectionList;
|
||||
import haveno.core.xmr.model.XmrAddressEntryList;
|
||||
import haveno.core.xmr.nodes.BtcNodes;
|
||||
import haveno.core.xmr.nodes.XmrNodes;
|
||||
import haveno.core.xmr.setup.RegTestHost;
|
||||
import haveno.core.xmr.setup.WalletsSetup;
|
||||
import haveno.core.xmr.wallet.BtcWalletService;
|
||||
|
@ -74,7 +74,7 @@ public class MoneroModule extends AppModule {
|
|||
bindConstant().annotatedWith(named(Config.XMR_NODE)).to(config.xmrNode);
|
||||
bindConstant().annotatedWith(named(Config.XMR_NODE_USERNAME)).to(config.xmrNodeUsername);
|
||||
bindConstant().annotatedWith(named(Config.XMR_NODE_PASSWORD)).to(config.xmrNodePassword);
|
||||
bindConstant().annotatedWith(named(Config.BTC_NODES)).to(config.btcNodes);
|
||||
bindConstant().annotatedWith(named(Config.XMR_NODES)).to(config.xmrNodes);
|
||||
bindConstant().annotatedWith(named(Config.USER_AGENT)).to(config.userAgent);
|
||||
bindConstant().annotatedWith(named(Config.NUM_CONNECTIONS_FOR_BTC)).to(config.numConnectionsForBtc);
|
||||
bindConstant().annotatedWith(named(Config.USE_ALL_PROVIDED_NODES)).to(config.useAllProvidedNodes);
|
||||
|
@ -89,7 +89,7 @@ public class MoneroModule extends AppModule {
|
|||
bind(BtcWalletService.class).in(Singleton.class);
|
||||
bind(TradeWalletService.class).in(Singleton.class);
|
||||
bind(NonBsqCoinSelector.class).in(Singleton.class);
|
||||
bind(BtcNodes.class).in(Singleton.class);
|
||||
bind(XmrNodes.class).in(Singleton.class);
|
||||
bind(Balances.class).in(Singleton.class);
|
||||
|
||||
bind(ProvidersRepository.class).in(Singleton.class);
|
||||
|
|
|
@ -148,7 +148,7 @@ public class EncryptedConnectionList implements PersistableEnvelope, PersistedDa
|
|||
writeLock.unlock();
|
||||
}
|
||||
if (currentValue != null) {
|
||||
throw new IllegalStateException(String.format("There exists already an connection for \"%s\"", connection.getUri()));
|
||||
throw new IllegalStateException(String.format("There exists already a connection for \"%s\"", connection.getUri()));
|
||||
}
|
||||
requestPersistence();
|
||||
}
|
||||
|
|
|
@ -1,178 +0,0 @@
|
|||
/*
|
||||
* This file is part of Haveno.
|
||||
*
|
||||
* Haveno 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.
|
||||
*
|
||||
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package haveno.core.xmr.nodes;
|
||||
|
||||
import haveno.common.config.Config;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
// Managed here: https://github.com/bisq-network/roles/issues/39
|
||||
@Slf4j
|
||||
public class BtcNodes {
|
||||
|
||||
public enum BitcoinNodesOption {
|
||||
PROVIDED,
|
||||
CUSTOM,
|
||||
PUBLIC
|
||||
}
|
||||
|
||||
// For other base currencies or testnet we ignore provided nodes
|
||||
public List<BtcNode> getProvidedBtcNodes() {
|
||||
return useProvidedBtcNodes() ?
|
||||
Arrays.asList(
|
||||
// emzy
|
||||
new BtcNode("btcnode1.emzy.de", "emzybtc3ewh7zihpkdvuwlgxrhzcxy2p5fvjggp7ngjbxcytxvt4rjid.onion", "167.86.90.239", BtcNode.DEFAULT_PORT, "@emzy"),
|
||||
new BtcNode("btcnode2.emzy.de", "emzybtc25oddoa2prol2znpz2axnrg6k77xwgirmhv7igoiucddsxiad.onion", "62.171.129.32", BtcNode.DEFAULT_PORT, "@emzy"),
|
||||
new BtcNode("btcnode3.emzy.de", "emzybtc5bnpb2o6gh54oquiox54o4r7yn4a2wiiwzrjonlouaibm2zid.onion", "136.243.53.40", BtcNode.DEFAULT_PORT, "@emzy"),
|
||||
new BtcNode("btcnode4.emzy.de", "emzybtc454ewbviqnmgtgx3rgublsgkk23r4onbhidcv36wremue4kqd.onion", "135.181.215.237", BtcNode.DEFAULT_PORT, "@emzy"),
|
||||
|
||||
// ripcurlx
|
||||
new BtcNode("bitcoin.christophatteneder.com", "catlnkpdm454ecngktyo4z22m5dlcvfvgzz4nt5l36eeczecrafslkqd.onion", "174.138.35.229", BtcNode.DEFAULT_PORT, "@Christoph"),
|
||||
|
||||
// mrosseel
|
||||
new BtcNode("btc.vante.me", "bsqbtctulf2g4jtjsdfgl2ed7qs6zz5wqx27qnyiik7laockryvszqqd.onion", "94.23.21.80", BtcNode.DEFAULT_PORT, "@miker"),
|
||||
new BtcNode("btc2.vante.me", "bsqbtcparrfihlwolt4xgjbf4cgqckvrvsfyvy6vhiqrnh4w6ghixoid.onion", "94.23.205.110", BtcNode.DEFAULT_PORT, "@miker"),
|
||||
|
||||
// sqrrm
|
||||
new BtcNode("btc1.sqrrm.net", "jygcc54etaubgdpcvzgbihjaqbc37cstpvum5sjzvka4bibkp4wrgnqd.onion", "185.25.48.184", BtcNode.DEFAULT_PORT, "@sqrrm"),
|
||||
new BtcNode("btc2.sqrrm.net", "h32haomoe52ljz6qopedsocvotvoj5lm2zmecfhdhawb3flbsf64l2qd.onion", "81.171.22.143", BtcNode.DEFAULT_PORT, "@sqrrm"),
|
||||
|
||||
// KanoczTomas
|
||||
new BtcNode("btc.ispol.sk", "mbm6ffx6j5ygi2ck.onion", "193.58.196.212", BtcNode.DEFAULT_PORT, "@KanoczTomas"),
|
||||
|
||||
// Devin Bileck
|
||||
new BtcNode("btc1.haveno.services", "devinbtctu7uctl7hly2juu3thbgeivfnvw3ckj3phy6nyvpnx66yeyd.onion", "172.105.21.216", BtcNode.DEFAULT_PORT, "@devinbileck"),
|
||||
new BtcNode("btc2.haveno.services", "devinbtcyk643iruzfpaxw3on2jket7rbjmwygm42dmdyub3ietrbmid.onion", "173.255.240.205", BtcNode.DEFAULT_PORT, "@devinbileck"),
|
||||
new BtcNode(null, "devinbtcmwkuitvxl3tfi5of4zau46ymeannkjv6fpnylkgf3q5fa3id.onion", null, BtcNode.DEFAULT_PORT, "@devinbileck"),
|
||||
|
||||
// m52go
|
||||
new BtcNode(null, "rss2u4embqa6fzuaiuvpp6szklkdckrcfgv6zer3ngclkzclvstywjyd.onion", null, BtcNode.DEFAULT_PORT, "@m52go"),
|
||||
// wiz
|
||||
new BtcNode("node130.hnl.wiz.biz", "wizbit5555bsslwv4ctronnsgk5vh2w2pdx7v7eyuivlyuoteejk7lid.onion", "103.99.168.130", BtcNode.DEFAULT_PORT, "@wiz"),
|
||||
new BtcNode("node140.hnl.wiz.biz", "jto2jfbsxhb6yvhcrrjddrgbakte6tgsy3c3z3prss64gndgvovvosyd.onion", "103.99.168.140", BtcNode.DEFAULT_PORT, "@wiz"),
|
||||
new BtcNode("node210.fmt.wiz.biz", "rfqmn3qe36uaptkxhdvi74p4hyrzhir6vhmzb2hqryxodig4gue2zbyd.onion", "103.99.170.210", BtcNode.DEFAULT_PORT, "@wiz"),
|
||||
new BtcNode("node220.fmt.wiz.biz", "azbpsh4arqlm6442wfimy7qr65bmha2zhgjg7wbaji6vvaug53hur2qd.onion", "103.99.170.220", BtcNode.DEFAULT_PORT, "@wiz")
|
||||
) :
|
||||
new ArrayList<>();
|
||||
}
|
||||
|
||||
public boolean useProvidedBtcNodes() {
|
||||
return Config.baseCurrencyNetwork().isMainnet();
|
||||
}
|
||||
|
||||
public static List<BtcNodes.BtcNode> toBtcNodesList(Collection<String> nodes) {
|
||||
return nodes.stream()
|
||||
.filter(e -> !e.isEmpty())
|
||||
.map(BtcNodes.BtcNode::fromFullAddress)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@EqualsAndHashCode
|
||||
@Getter
|
||||
public static class BtcNode {
|
||||
private static final int DEFAULT_PORT = Config.baseCurrencyNetworkParameters().getPort(); //8333
|
||||
|
||||
@Nullable
|
||||
private final String onionAddress;
|
||||
@Nullable
|
||||
private final String hostName;
|
||||
@Nullable
|
||||
private final String operator; // null in case the user provides a list of custom btc nodes
|
||||
@Nullable
|
||||
private final String address; // IPv4 address
|
||||
private int port = DEFAULT_PORT;
|
||||
|
||||
/**
|
||||
* @param fullAddress [IPv4 address:port or onion:port]
|
||||
* @return BtcNode instance
|
||||
*/
|
||||
public static BtcNode fromFullAddress(String fullAddress) {
|
||||
String[] parts = fullAddress.split("]");
|
||||
checkArgument(parts.length > 0);
|
||||
String host = "";
|
||||
int port = DEFAULT_PORT;
|
||||
if (parts[0].contains("[") && parts[0].contains(":")) {
|
||||
// IPv6 address and optional port number
|
||||
// address part delimited by square brackets e.g. [2a01:123:456:789::2]:8333
|
||||
host = parts[0].replace("[", "").replace("]", "");
|
||||
if (parts.length == 2)
|
||||
port = Integer.parseInt(parts[1].replace(":", ""));
|
||||
} else if (parts[0].contains(":") && !parts[0].contains(".")) {
|
||||
// IPv6 address only; not delimited by square brackets
|
||||
host = parts[0];
|
||||
} else if (parts[0].contains(".")) {
|
||||
// address and an optional port number
|
||||
// e.g. 127.0.0.1:8333 or abcdef123xyz.onion:9999
|
||||
parts = fullAddress.split(":");
|
||||
checkArgument(parts.length > 0);
|
||||
host = parts[0];
|
||||
if (parts.length == 2)
|
||||
port = Integer.parseInt(parts[1]);
|
||||
}
|
||||
|
||||
checkArgument(host.length() > 0, "BtcNode address format not recognised");
|
||||
return host.contains(".onion") ? new BtcNode(null, host, null, port, null) : new BtcNode(null, null, host, port, null);
|
||||
}
|
||||
|
||||
public BtcNode(@Nullable String hostName,
|
||||
@Nullable String onionAddress,
|
||||
@Nullable String address,
|
||||
int port,
|
||||
@Nullable String operator) {
|
||||
this.hostName = hostName;
|
||||
this.onionAddress = onionAddress;
|
||||
this.address = address;
|
||||
this.port = port;
|
||||
this.operator = operator;
|
||||
}
|
||||
|
||||
public boolean hasOnionAddress() {
|
||||
return onionAddress != null;
|
||||
}
|
||||
|
||||
public String getHostNameOrAddress() {
|
||||
if (hostName != null)
|
||||
return hostName;
|
||||
else
|
||||
return address;
|
||||
}
|
||||
|
||||
public boolean hasClearNetAddress() {
|
||||
return hostName != null || address != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "onionAddress='" + onionAddress + '\'' +
|
||||
", hostName='" + hostName + '\'' +
|
||||
", address='" + address + '\'' +
|
||||
", port='" + port + '\'' +
|
||||
", operator='" + operator;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@ import java.net.Socket;
|
|||
/**
|
||||
* Detects whether a Bitcoin node is running on localhost and contains logic for when to
|
||||
* ignore it. The query methods lazily trigger the needed checks and cache the results.
|
||||
* @see haveno.common.config.Config#ignoreLocalBtcNode
|
||||
* @see haveno.common.config.Config#ignoreLocalXmrNode
|
||||
*/
|
||||
@Singleton
|
||||
public class LocalBitcoinNode {
|
||||
|
@ -49,7 +49,7 @@ public class LocalBitcoinNode {
|
|||
*/
|
||||
public boolean shouldBeIgnored() {
|
||||
BaseCurrencyNetwork baseCurrencyNetwork = config.baseCurrencyNetwork;
|
||||
return config.ignoreLocalBtcNode;
|
||||
return config.ignoreLocalXmrNode;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -30,8 +30,8 @@ import org.slf4j.LoggerFactory;
|
|||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
public class BtcNetworkConfig {
|
||||
private static final Logger log = LoggerFactory.getLogger(BtcNetworkConfig.class);
|
||||
public class XmrNetworkConfig {
|
||||
private static final Logger log = LoggerFactory.getLogger(XmrNetworkConfig.class);
|
||||
|
||||
@Nullable
|
||||
private final Socks5Proxy proxy;
|
||||
|
@ -39,7 +39,7 @@ public class BtcNetworkConfig {
|
|||
private final NetworkParameters parameters;
|
||||
private final int socks5DiscoverMode;
|
||||
|
||||
public BtcNetworkConfig(WalletConfig delegate, NetworkParameters parameters, int socks5DiscoverMode,
|
||||
public XmrNetworkConfig(WalletConfig delegate, NetworkParameters parameters, int socks5DiscoverMode,
|
||||
@Nullable Socks5Proxy proxy) {
|
||||
this.delegate = delegate;
|
||||
this.parameters = parameters;
|
|
@ -18,7 +18,7 @@
|
|||
package haveno.core.xmr.nodes;
|
||||
|
||||
import com.runjva.sourceforge.jsocks.protocol.Socks5Proxy;
|
||||
import haveno.core.xmr.nodes.BtcNodes.BtcNode;
|
||||
import haveno.core.xmr.nodes.XmrNodes.XmrNode;
|
||||
import haveno.network.DnsLookupException;
|
||||
import haveno.network.DnsLookupTor;
|
||||
import org.bitcoinj.core.PeerAddress;
|
||||
|
@ -32,28 +32,28 @@ import java.net.InetSocketAddress;
|
|||
import java.net.UnknownHostException;
|
||||
import java.util.Objects;
|
||||
|
||||
class BtcNodeConverter {
|
||||
private static final Logger log = LoggerFactory.getLogger(BtcNodeConverter.class);
|
||||
class XmrNodeConverter {
|
||||
private static final Logger log = LoggerFactory.getLogger(XmrNodeConverter.class);
|
||||
|
||||
private final Facade facade;
|
||||
|
||||
BtcNodeConverter() {
|
||||
XmrNodeConverter() {
|
||||
this.facade = new Facade();
|
||||
}
|
||||
|
||||
BtcNodeConverter(Facade facade) {
|
||||
XmrNodeConverter(Facade facade) {
|
||||
this.facade = facade;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
PeerAddress convertOnionHost(BtcNode node) {
|
||||
PeerAddress convertOnionHost(XmrNode node) {
|
||||
// no DNS lookup for onion addresses
|
||||
String onionAddress = Objects.requireNonNull(node.getOnionAddress());
|
||||
return new PeerAddress(onionAddress, node.getPort());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
PeerAddress convertClearNode(BtcNode node) {
|
||||
PeerAddress convertClearNode(XmrNode node) {
|
||||
int port = node.getPort();
|
||||
|
||||
PeerAddress result = create(node.getHostNameOrAddress(), port);
|
||||
|
@ -69,7 +69,7 @@ class BtcNodeConverter {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
PeerAddress convertWithTor(BtcNode node, Socks5Proxy proxy) {
|
||||
PeerAddress convertWithTor(XmrNode node, Socks5Proxy proxy) {
|
||||
int port = node.getPort();
|
||||
|
||||
PeerAddress result = create(proxy, node.getHostNameOrAddress(), port);
|
192
core/src/main/java/haveno/core/xmr/nodes/XmrNodes.java
Normal file
192
core/src/main/java/haveno/core/xmr/nodes/XmrNodes.java
Normal file
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* This file is part of Haveno.
|
||||
*
|
||||
* Haveno 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.
|
||||
*
|
||||
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package haveno.core.xmr.nodes;
|
||||
|
||||
import haveno.common.config.Config;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
@Slf4j
|
||||
public class XmrNodes {
|
||||
|
||||
// TODO: rename to XmrNodeType ?
|
||||
public enum MoneroNodesOption {
|
||||
PROVIDED,
|
||||
CUSTOM,
|
||||
PUBLIC
|
||||
}
|
||||
|
||||
public List<XmrNode> selectPreferredNodes(XmrNodesSetupPreferences xmrNodesSetupPreferences) {
|
||||
return xmrNodesSetupPreferences.selectPreferredNodes(this);
|
||||
}
|
||||
|
||||
// TODO: always using null hostname
|
||||
public List<XmrNode> getAllXmrNodes() {
|
||||
switch (Config.baseCurrencyNetwork()) {
|
||||
case XMR_LOCAL:
|
||||
return Arrays.asList(
|
||||
new XmrNode(MoneroNodesOption.PROVIDED, null, null, "127.0.0.1", 28081, 1, "@local")
|
||||
);
|
||||
case XMR_STAGENET:
|
||||
return Arrays.asList(
|
||||
new XmrNode(MoneroNodesOption.PROVIDED, null, null, "127.0.0.1", 38081, 1, "@local"),
|
||||
new XmrNode(MoneroNodesOption.PROVIDED, null, null, "127.0.0.1", 39081, 1, "@local"),
|
||||
new XmrNode(MoneroNodesOption.PROVIDED, null, null, "45.63.8.26", 38081, 1, "@haveno"),
|
||||
new XmrNode(MoneroNodesOption.PROVIDED, null, null, "stagenet.community.rino.io", 38081, 2, "@RINOwallet"),
|
||||
new XmrNode(MoneroNodesOption.PUBLIC, null, null, "stagenet.melo.tools", 38081, 2, null),
|
||||
new XmrNode(MoneroNodesOption.PUBLIC, null, null, "node.sethforprivacy.com", 38089, 2, null),
|
||||
new XmrNode(MoneroNodesOption.PUBLIC, null, null, "node2.sethforprivacy.com", 38089, 2, null),
|
||||
new XmrNode(MoneroNodesOption.PUBLIC, null, "plowsof3t5hogddwabaeiyrno25efmzfxyro2vligremt7sxpsclfaid.onion", null, 38089, 2, null)
|
||||
);
|
||||
case XMR_MAINNET:
|
||||
return Arrays.asList(
|
||||
new XmrNode(MoneroNodesOption.PROVIDED, null, null, "127.0.0.1", 18081, 1, "@local"),
|
||||
new XmrNode(MoneroNodesOption.PROVIDED, null, null, "xmr-node.cakewallet.com", 18081, 1, "@cakewallet"),
|
||||
new XmrNode(MoneroNodesOption.PUBLIC, null, null, "node.community.rino.io", 18081, 2, "@RINOwallet"),
|
||||
new XmrNode(MoneroNodesOption.PUBLIC, null, null, "xmr-node-eu.cakewallet.com", 18081, 2, "@cakewallet"),
|
||||
new XmrNode(MoneroNodesOption.PUBLIC, null, null, "xmr-node-usa-east.cakewallet.com", 18081, 2, "@cakewallet"),
|
||||
new XmrNode(MoneroNodesOption.PUBLIC, null, null, "xmr-node-uk.cakewallet.com", 18081, 2, "@cakewallet"),
|
||||
new XmrNode(MoneroNodesOption.PUBLIC, null, null, "node.sethforprivacy.com", 18089, 2, "@sethforprivacy")
|
||||
);
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected base currency network: " + Config.baseCurrencyNetwork());
|
||||
}
|
||||
}
|
||||
|
||||
public List<XmrNode> getProvidedXmrNodes() {
|
||||
return getXmrNodes(MoneroNodesOption.PROVIDED);
|
||||
}
|
||||
|
||||
public List<XmrNode> getPublicXmrNodes() {
|
||||
return getXmrNodes(MoneroNodesOption.PUBLIC);
|
||||
}
|
||||
|
||||
private List<XmrNode> getXmrNodes(MoneroNodesOption type) {
|
||||
List<XmrNode> nodes = new ArrayList<>();
|
||||
for (XmrNode node : getAllXmrNodes()) if (node.getType() == type) nodes.add(node);
|
||||
return nodes;
|
||||
}
|
||||
|
||||
public static List<XmrNodes.XmrNode> toCustomXmrNodesList(Collection<String> nodes) {
|
||||
return nodes.stream()
|
||||
.filter(e -> !e.isEmpty())
|
||||
.map(XmrNodes.XmrNode::fromFullAddress)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@EqualsAndHashCode
|
||||
@Getter
|
||||
public static class XmrNode {
|
||||
private static final int DEFAULT_PORT = Config.baseCurrencyNetworkParameters().getPort();
|
||||
|
||||
private final MoneroNodesOption type;
|
||||
@Nullable
|
||||
private final String onionAddress;
|
||||
@Nullable
|
||||
private final String hostName;
|
||||
@Nullable
|
||||
private final String operator; // null in case the user provides a list of custom btc nodes
|
||||
@Nullable
|
||||
private final String address; // IPv4 address
|
||||
private int port = DEFAULT_PORT;
|
||||
private int priority = 0;
|
||||
|
||||
/**
|
||||
* @param fullAddress [IPv4 address:port or onion:port]
|
||||
* @return XmrNode instance
|
||||
*/
|
||||
public static XmrNode fromFullAddress(String fullAddress) {
|
||||
String[] parts = fullAddress.split("]");
|
||||
checkArgument(parts.length > 0);
|
||||
String host = "";
|
||||
int port = DEFAULT_PORT;
|
||||
if (parts[0].contains("[") && parts[0].contains(":")) {
|
||||
// IPv6 address and optional port number
|
||||
// address part delimited by square brackets e.g. [2a01:123:456:789::2]:8333
|
||||
host = parts[0].replace("[", "").replace("]", "");
|
||||
if (parts.length == 2)
|
||||
port = Integer.parseInt(parts[1].replace(":", ""));
|
||||
} else if (parts[0].contains(":") && !parts[0].contains(".")) {
|
||||
// IPv6 address only; not delimited by square brackets
|
||||
host = parts[0];
|
||||
} else if (parts[0].contains(".")) {
|
||||
// address and an optional port number
|
||||
// e.g. 127.0.0.1:8333 or abcdef123xyz.onion:9999
|
||||
parts = fullAddress.split(":");
|
||||
checkArgument(parts.length > 0);
|
||||
host = parts[0];
|
||||
if (parts.length == 2)
|
||||
port = Integer.parseInt(parts[1]);
|
||||
}
|
||||
|
||||
checkArgument(host.length() > 0, "XmrNode address format not recognised");
|
||||
return host.contains(".onion") ? new XmrNode(MoneroNodesOption.CUSTOM, null, host, null, port, null, null) : new XmrNode(MoneroNodesOption.CUSTOM, null, null, host, port, null, null);
|
||||
}
|
||||
|
||||
public XmrNode(MoneroNodesOption type,
|
||||
@Nullable String hostName,
|
||||
@Nullable String onionAddress,
|
||||
@Nullable String address,
|
||||
int port,
|
||||
Integer priority,
|
||||
@Nullable String operator) {
|
||||
this.type = type;
|
||||
this.hostName = hostName;
|
||||
this.onionAddress = onionAddress;
|
||||
this.address = address;
|
||||
this.port = port;
|
||||
this.priority = priority == null ? 0 : priority;
|
||||
this.operator = operator;
|
||||
}
|
||||
|
||||
public boolean hasOnionAddress() {
|
||||
return onionAddress != null;
|
||||
}
|
||||
|
||||
public String getHostNameOrAddress() {
|
||||
if (hostName != null)
|
||||
return hostName;
|
||||
else
|
||||
return address;
|
||||
}
|
||||
|
||||
public boolean hasClearNetAddress() {
|
||||
return hostName != null || address != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "onionAddress='" + onionAddress + '\'' +
|
||||
", hostName='" + hostName + '\'' +
|
||||
", address='" + address + '\'' +
|
||||
", port='" + port + '\'' +
|
||||
", priority='" + priority + '\'' +
|
||||
", operator='" + operator;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,15 +27,15 @@ import java.util.Optional;
|
|||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class BtcNodesRepository {
|
||||
private final BtcNodeConverter converter;
|
||||
private final List<BtcNodes.BtcNode> nodes;
|
||||
public class XmrNodesRepository {
|
||||
private final XmrNodeConverter converter;
|
||||
private final List<XmrNodes.XmrNode> nodes;
|
||||
|
||||
public BtcNodesRepository(List<BtcNodes.BtcNode> nodes) {
|
||||
this(new BtcNodeConverter(), nodes);
|
||||
public XmrNodesRepository(List<XmrNodes.XmrNode> nodes) {
|
||||
this(new XmrNodeConverter(), nodes);
|
||||
}
|
||||
|
||||
public BtcNodesRepository(BtcNodeConverter converter, List<BtcNodes.BtcNode> nodes) {
|
||||
public XmrNodesRepository(XmrNodeConverter converter, List<XmrNodes.XmrNode> nodes) {
|
||||
this.converter = converter;
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
@ -61,21 +61,21 @@ public class BtcNodesRepository {
|
|||
|
||||
private List<PeerAddress> getClearNodes() {
|
||||
return nodes.stream()
|
||||
.filter(BtcNodes.BtcNode::hasClearNetAddress)
|
||||
.filter(XmrNodes.XmrNode::hasClearNetAddress)
|
||||
.flatMap(node -> nullableAsStream(converter.convertClearNode(node)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<PeerAddress> getOnionHosts() {
|
||||
return nodes.stream()
|
||||
.filter(BtcNodes.BtcNode::hasOnionAddress)
|
||||
.filter(XmrNodes.XmrNode::hasOnionAddress)
|
||||
.flatMap(node -> nullableAsStream(converter.convertOnionHost(node)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<PeerAddress> getClearNodesBehindProxy(Socks5Proxy proxy) {
|
||||
return nodes.stream()
|
||||
.filter(BtcNodes.BtcNode::hasClearNetAddress)
|
||||
.filter(XmrNodes.XmrNode::hasClearNetAddress)
|
||||
.flatMap(node -> nullableAsStream(converter.convertWithTor(node, proxy)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
|
@ -23,42 +23,41 @@ import haveno.core.user.Preferences;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
public class BtcNodesSetupPreferences {
|
||||
private static final Logger log = LoggerFactory.getLogger(BtcNodesSetupPreferences.class);
|
||||
public class XmrNodesSetupPreferences {
|
||||
private static final Logger log = LoggerFactory.getLogger(XmrNodesSetupPreferences.class);
|
||||
|
||||
private final Preferences preferences;
|
||||
|
||||
public BtcNodesSetupPreferences(Preferences preferences) {
|
||||
public XmrNodesSetupPreferences(Preferences preferences) {
|
||||
this.preferences = preferences;
|
||||
}
|
||||
|
||||
public List<BtcNodes.BtcNode> selectPreferredNodes(BtcNodes nodes) {
|
||||
List<BtcNodes.BtcNode> result;
|
||||
public List<XmrNodes.XmrNode> selectPreferredNodes(XmrNodes nodes) {
|
||||
List<XmrNodes.XmrNode> result;
|
||||
|
||||
BtcNodes.BitcoinNodesOption nodesOption = BtcNodes.BitcoinNodesOption.values()[preferences.getBitcoinNodesOptionOrdinal()];
|
||||
XmrNodes.MoneroNodesOption nodesOption = XmrNodes.MoneroNodesOption.values()[preferences.getMoneroNodesOptionOrdinal()];
|
||||
switch (nodesOption) {
|
||||
case CUSTOM:
|
||||
String bitcoinNodes = preferences.getBitcoinNodes();
|
||||
String bitcoinNodes = preferences.getMoneroNodes();
|
||||
Set<String> distinctNodes = Utilities.commaSeparatedListToSet(bitcoinNodes, false);
|
||||
result = BtcNodes.toBtcNodesList(distinctNodes);
|
||||
result = XmrNodes.toCustomXmrNodesList(distinctNodes);
|
||||
if (result.isEmpty()) {
|
||||
log.warn("Custom nodes is set but no valid nodes are provided. " +
|
||||
"We fall back to provided nodes option.");
|
||||
preferences.setBitcoinNodesOptionOrdinal(BtcNodes.BitcoinNodesOption.PROVIDED.ordinal());
|
||||
result = nodes.getProvidedBtcNodes();
|
||||
preferences.setMoneroNodesOptionOrdinal(XmrNodes.MoneroNodesOption.PROVIDED.ordinal());
|
||||
result = nodes.getAllXmrNodes();
|
||||
}
|
||||
break;
|
||||
case PUBLIC:
|
||||
result = Collections.emptyList();
|
||||
result = nodes.getPublicXmrNodes();
|
||||
break;
|
||||
case PROVIDED:
|
||||
default:
|
||||
result = nodes.getProvidedBtcNodes();
|
||||
result = nodes.getAllXmrNodes();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -66,11 +65,11 @@ public class BtcNodesSetupPreferences {
|
|||
}
|
||||
|
||||
public boolean isUseCustomNodes() {
|
||||
return BtcNodes.BitcoinNodesOption.CUSTOM.ordinal() == preferences.getBitcoinNodesOptionOrdinal();
|
||||
return XmrNodes.MoneroNodesOption.CUSTOM.ordinal() == preferences.getMoneroNodesOptionOrdinal();
|
||||
}
|
||||
|
||||
public int calculateMinBroadcastConnections(List<BtcNodes.BtcNode> nodes) {
|
||||
BtcNodes.BitcoinNodesOption nodesOption = BtcNodes.BitcoinNodesOption.values()[preferences.getBitcoinNodesOptionOrdinal()];
|
||||
public int calculateMinBroadcastConnections(List<XmrNodes.XmrNode> nodes) {
|
||||
XmrNodes.MoneroNodesOption nodesOption = XmrNodes.MoneroNodesOption.values()[preferences.getMoneroNodesOptionOrdinal()];
|
||||
int result;
|
||||
switch (nodesOption) {
|
||||
case CUSTOM:
|
|
@ -33,11 +33,11 @@ import haveno.core.user.Preferences;
|
|||
import haveno.core.xmr.exceptions.InvalidHostException;
|
||||
import haveno.core.xmr.model.AddressEntry;
|
||||
import haveno.core.xmr.model.AddressEntryList;
|
||||
import haveno.core.xmr.nodes.BtcNetworkConfig;
|
||||
import haveno.core.xmr.nodes.BtcNodes;
|
||||
import haveno.core.xmr.nodes.BtcNodes.BtcNode;
|
||||
import haveno.core.xmr.nodes.BtcNodesRepository;
|
||||
import haveno.core.xmr.nodes.BtcNodesSetupPreferences;
|
||||
import haveno.core.xmr.nodes.XmrNetworkConfig;
|
||||
import haveno.core.xmr.nodes.XmrNodes;
|
||||
import haveno.core.xmr.nodes.XmrNodes.XmrNode;
|
||||
import haveno.core.xmr.nodes.XmrNodesRepository;
|
||||
import haveno.core.xmr.nodes.XmrNodesSetupPreferences;
|
||||
import haveno.core.xmr.nodes.LocalBitcoinNode;
|
||||
import haveno.network.Socks5MultiDiscovery;
|
||||
import haveno.network.Socks5ProxyProvider;
|
||||
|
@ -101,7 +101,7 @@ public class WalletsSetup {
|
|||
private final Socks5ProxyProvider socks5ProxyProvider;
|
||||
private final Config config;
|
||||
private final LocalBitcoinNode localBitcoinNode;
|
||||
private final BtcNodes btcNodes;
|
||||
private final XmrNodes xmrNodes;
|
||||
private final int numConnectionsForBtc;
|
||||
private final String userAgent;
|
||||
private final NetworkParameters params;
|
||||
|
@ -127,7 +127,7 @@ public class WalletsSetup {
|
|||
Socks5ProxyProvider socks5ProxyProvider,
|
||||
Config config,
|
||||
LocalBitcoinNode localBitcoinNode,
|
||||
BtcNodes btcNodes,
|
||||
XmrNodes xmrNodes,
|
||||
@Named(Config.USER_AGENT) String userAgent,
|
||||
@Named(Config.WALLET_DIR) File walletDir,
|
||||
@Named(Config.USE_ALL_PROVIDED_NODES) boolean useAllProvidedNodes,
|
||||
|
@ -139,7 +139,7 @@ public class WalletsSetup {
|
|||
this.socks5ProxyProvider = socks5ProxyProvider;
|
||||
this.config = config;
|
||||
this.localBitcoinNode = localBitcoinNode;
|
||||
this.btcNodes = btcNodes;
|
||||
this.xmrNodes = xmrNodes;
|
||||
this.numConnectionsForBtc = numConnectionsForBtc;
|
||||
this.useAllProvidedNodes = useAllProvidedNodes;
|
||||
this.userAgent = userAgent;
|
||||
|
@ -171,7 +171,7 @@ public class WalletsSetup {
|
|||
|
||||
backupWallets();
|
||||
|
||||
final Socks5Proxy socks5Proxy = preferences.getUseTorForBitcoinJ() ? socks5ProxyProvider.getSocks5Proxy() : null;
|
||||
final Socks5Proxy socks5Proxy = preferences.getUseTorForMonero() ? socks5ProxyProvider.getSocks5Proxy() : null;
|
||||
log.info("Socks5Proxy for bitcoinj: socks5Proxy=" + socks5Proxy);
|
||||
|
||||
walletConfig = new WalletConfig(params, walletDir, "haveno") {
|
||||
|
@ -195,7 +195,7 @@ public class WalletsSetup {
|
|||
};
|
||||
walletConfig.setSocks5Proxy(socks5Proxy);
|
||||
walletConfig.setConfig(config);
|
||||
walletConfig.setLocalBitcoinNode(localBitcoinNode);
|
||||
walletConfig.setLocalBitcoinNode(localBitcoinNode); // TODO: adapt to xmr or remove
|
||||
walletConfig.setUserAgent(userAgent, Version.VERSION);
|
||||
walletConfig.setNumConnectionsForBtc(numConnectionsForBtc);
|
||||
|
||||
|
@ -213,7 +213,7 @@ public class WalletsSetup {
|
|||
walletConfig.setCheckpoints(getClass().getResourceAsStream(checkpointsPath));
|
||||
}
|
||||
|
||||
|
||||
// TODO: update this for xmr
|
||||
if (params.getId().equals(NetworkParameters.ID_REGTEST)) {
|
||||
walletConfig.setMinBroadcastConnections(1);
|
||||
if (regTestHost == RegTestHost.LOCALHOST) {
|
||||
|
@ -235,7 +235,7 @@ public class WalletsSetup {
|
|||
walletConfig.connectToLocalHost();
|
||||
} else {
|
||||
try {
|
||||
configPeerNodes(socks5Proxy);
|
||||
//configPeerNodes(socks5Proxy);
|
||||
} catch (IllegalArgumentException e) {
|
||||
timeoutTimer.stop();
|
||||
walletsSetupFailed.set(true);
|
||||
|
@ -329,14 +329,14 @@ public class WalletsSetup {
|
|||
private void configPeerNodes(@Nullable Socks5Proxy proxy) {
|
||||
walletConfig.setMinBroadcastConnections(MIN_BROADCAST_CONNECTIONS);
|
||||
|
||||
BtcNodesSetupPreferences btcNodesSetupPreferences = new BtcNodesSetupPreferences(preferences);
|
||||
List<BtcNode> nodes = btcNodesSetupPreferences.selectPreferredNodes(btcNodes);
|
||||
XmrNodesSetupPreferences xmrNodesSetupPreferences = new XmrNodesSetupPreferences(preferences);
|
||||
List<XmrNode> nodes = xmrNodesSetupPreferences.selectPreferredNodes(xmrNodes);
|
||||
|
||||
BtcNodesRepository repository = new BtcNodesRepository(nodes);
|
||||
boolean isUseClearNodesWithProxies = (useAllProvidedNodes || btcNodesSetupPreferences.isUseCustomNodes());
|
||||
XmrNodesRepository repository = new XmrNodesRepository(nodes);
|
||||
boolean isUseClearNodesWithProxies = (useAllProvidedNodes || xmrNodesSetupPreferences.isUseCustomNodes());
|
||||
List<PeerAddress> peers = repository.getPeerAddresses(proxy, isUseClearNodesWithProxies);
|
||||
|
||||
BtcNetworkConfig networkConfig = new BtcNetworkConfig(walletConfig, params, socks5DiscoverMode, proxy);
|
||||
XmrNetworkConfig networkConfig = new XmrNetworkConfig(walletConfig, params, socks5DiscoverMode, proxy);
|
||||
networkConfig.proposePeers(peers);
|
||||
}
|
||||
|
||||
|
|
|
@ -626,6 +626,8 @@ public class XmrWalletService {
|
|||
// sync wallet if open
|
||||
if (wallet != null) {
|
||||
log.info("Monero wallet uri={}, path={}", wallet.getRpcConnection().getUri(), wallet.getPath());
|
||||
int numAttempts = 0;
|
||||
int maxAttempts = 2;
|
||||
while (!HavenoUtils.havenoSetup.getWalletInitialized().get()) {
|
||||
try {
|
||||
|
||||
|
@ -648,8 +650,17 @@ public class XmrWalletService {
|
|||
// save but skip backup on initialization
|
||||
saveMainWallet(false);
|
||||
} catch (Exception e) {
|
||||
log.warn("Error syncing main wallet: {}. Trying again in {} seconds", e.getMessage(), connectionsService.getRefreshPeriodMs() / 1000);
|
||||
GenUtils.waitFor(connectionsService.getRefreshPeriodMs());
|
||||
log.warn("Error syncing main wallet: {}", e.getMessage());
|
||||
numAttempts++;
|
||||
if (numAttempts < maxAttempts) {
|
||||
log.warn("Trying again in {} seconds", connectionsService.getRefreshPeriodMs() / 1000);
|
||||
GenUtils.waitFor(connectionsService.getRefreshPeriodMs());
|
||||
} else {
|
||||
log.warn("Failed to sync main wallet after {} attempts. Opening app without syncing", maxAttempts);
|
||||
HavenoUtils.havenoSetup.getWalletInitialized().set(true);
|
||||
saveMainWallet(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -735,9 +746,10 @@ public class XmrWalletService {
|
|||
if (connection != null) {
|
||||
cmd.add("--daemon-address");
|
||||
cmd.add(connection.getUri());
|
||||
if (connection.isOnion() && connection.getProxyUri() != null) {
|
||||
if (connection.getProxyUri() != null) {
|
||||
cmd.add("--proxy");
|
||||
cmd.add(connection.getProxyUri());
|
||||
if (!connection.isOnion()) cmd.add("--daemon-ssl-allow-any-cert"); // necessary to use proxy with clearnet mmonerod
|
||||
}
|
||||
if (connection.getUsername() != null) {
|
||||
cmd.add("--daemon-login");
|
||||
|
@ -1015,10 +1027,10 @@ public class XmrWalletService {
|
|||
|
||||
public List<MoneroTxWallet> getTxsWithIncomingOutputs(Integer subaddressIndex) {
|
||||
List<MoneroTxWallet> txs = wallet.getTxs(new MoneroTxQuery().setIncludeOutputs(true));
|
||||
return getTxsWithIncomingOutputs(txs, subaddressIndex);
|
||||
return getTxsWithIncomingOutputs(subaddressIndex, txs);
|
||||
}
|
||||
|
||||
public static List<MoneroTxWallet> getTxsWithIncomingOutputs(List<MoneroTxWallet> txs, Integer subaddressIndex) {
|
||||
public static List<MoneroTxWallet> getTxsWithIncomingOutputs(Integer subaddressIndex, List<MoneroTxWallet> txs) {
|
||||
List<MoneroTxWallet> incomingTxs = new ArrayList<>();
|
||||
for (MoneroTxWallet tx : txs) {
|
||||
boolean isIncoming = false;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue