upgrade internal tor to 0.4.8.15

This commit is contained in:
Craig Raw 2025-04-17 14:17:26 +02:00
parent be8b56e355
commit 71ac72e9f6
6 changed files with 128 additions and 299 deletions

View file

@ -19,19 +19,6 @@ if(System.getProperty("os.arch") == "aarch64") {
}
def headless = "true".equals(System.getProperty("java.awt.headless"))
def vTor = '4.7.13-4'
def vKmpTor = '1.4.3'
def kmpOs = osName
if(os.macOsX) {
kmpOs = "macos"
} else if(os.windows) {
kmpOs = "mingw"
}
def kmpArch = "x64"
if(System.getProperty("os.arch") == "aarch64") {
kmpArch = "arm64"
}
group "com.sparrowwallet"
version "${sparrowVersion}"
@ -88,25 +75,9 @@ dependencies {
implementation('com.sparrowwallet:hummingbird:1.7.4')
implementation('co.nstant.in:cbor:0.9')
implementation('org.openpnp:openpnp-capture-java:0.0.28-5')
implementation("io.matthewnelson.kotlin-components:kmp-tor:${vTor}-${vKmpTor}") {
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-common'
}
if(kmpOs == "linux" && kmpArch == "arm64") {
implementation("com.sparrowwallet.kmp-tor-binary:kmp-tor-binary-${kmpOs}${kmpArch}-jvm:${vTor}") {
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-common'
}
} else {
implementation("io.matthewnelson.kotlin-components:kmp-tor-binary-${kmpOs}${kmpArch}:${vTor}") {
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-common'
}
}
implementation("io.matthewnelson.kotlin-components:kmp-tor-binary-extract:${vTor}") {
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-common'
}
implementation("io.matthewnelson.kotlin-components:kmp-tor-ext-callback-manager:${vKmpTor}") {
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-common'
}
implementation('org.jetbrains.kotlinx:kotlinx-coroutines-javafx:1.7.1') {
implementation("io.matthewnelson.kmp-tor:runtime:2.2.0")
implementation("io.matthewnelson.kmp-tor:resource-exec-tor-gpl:408.15.0")
implementation('org.jetbrains.kotlinx:kotlinx-coroutines-javafx:1.10.1') {
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-common'
}
implementation('de.codecentric.centerdevice:centerdevice-nsmenufx:2.1.7')
@ -190,6 +161,10 @@ application {
"--add-opens=java.base/java.net=com.sparrowwallet.sparrow",
"--add-opens=java.base/java.io=com.google.gson",
"--add-opens=java.smartcardio/sun.security.smartcardio=com.sparrowwallet.sparrow",
"--add-opens=io.matthewnelson.kmp.tor.resource.geoip/io.matthewnelson.kmp.tor.resource.geoip=io.matthewnelson.kmp.tor.common.core",
"--add-exports=io.matthewnelson.kmp.tor.runtime.ctrl/io.matthewnelson.kmp.tor.runtime.ctrl.internal=io.matthewnelson.kmp.tor.runtime",
"--add-reads=io.matthewnelson.kmp.tor.runtime=io.matthewnelson.kmp.tor.common.core",
"--add-reads=io.matthewnelson.kmp.tor.runtime.ctrl=io.matthewnelson.kmp.process",
"--add-reads=kotlin.stdlib=kotlinx.coroutines.core",
"--add-reads=org.flywaydb.core=java.desktop"]
@ -238,6 +213,10 @@ jlink {
"--add-opens=java.base/java.net=com.sparrowwallet.sparrow",
"--add-opens=java.base/java.io=com.google.gson",
"--add-opens=java.smartcardio/sun.security.smartcardio=com.sparrowwallet.sparrow",
"--add-opens=io.matthewnelson.kmp.tor.resource.geoip/io.matthewnelson.kmp.tor.resource.geoip=io.matthewnelson.kmp.tor.common.core",
"--add-exports=io.matthewnelson.kmp.tor.runtime.ctrl/io.matthewnelson.kmp.tor.runtime.ctrl.internal=io.matthewnelson.kmp.tor.runtime",
"--add-reads=io.matthewnelson.kmp.tor.runtime=io.matthewnelson.kmp.tor.common.core",
"--add-reads=io.matthewnelson.kmp.tor.runtime.ctrl=io.matthewnelson.kmp.process",
"--add-reads=com.sparrowwallet.merged.module=java.desktop",
"--add-reads=com.sparrowwallet.merged.module=java.sql",
"--add-reads=com.sparrowwallet.merged.module=com.sparrowwallet.sparrow",
@ -472,119 +451,6 @@ extraJavaModuleInfo {
exports('net.coobird.thumbnailator')
requires('java.desktop')
}
module("io.matthewnelson.kotlin-components:kmp-tor-jvm", 'kmp.tor.jvm') {
exports('io.matthewnelson.kmp.tor')
requires('kmp.tor.binary.extract.jvm')
requires('kmp.tor.manager.jvm')
requires('kmp.tor.manager.common.jvm')
requires('kmp.tor.controller.common.jvm')
requires('kotlin.stdlib')
requires('kotlinx.coroutines.core')
requires('java.management')
}
if(kmpOs == "linux" && kmpArch == "arm64") {
module("com.sparrowwallet.kmp-tor-binary:kmp-tor-binary-${kmpOs}${kmpArch}-jvm", "kmp.tor.binary.${kmpOs}${kmpArch}") {
exports("io.matthewnelson.kmp.tor.resource.${kmpOs}.${kmpArch}")
exports("kmptor.${kmpOs}.${kmpArch}")
}
} else {
module("io.matthewnelson.kotlin-components:kmp-tor-binary-${kmpOs}${kmpArch}-jvm", "kmp.tor.binary.${kmpOs}${kmpArch}") {
exports("io.matthewnelson.kmp.tor.binary.${kmpOs}.${kmpArch}")
exports("kmptor.${kmpOs}.${kmpArch}")
}
}
module("io.matthewnelson.kotlin-components:kmp-tor-binary-extract-jvm", 'kmp.tor.binary.extract.jvm') {
exports('io.matthewnelson.kmp.tor.binary.extract')
exports('io.matthewnelson.kmp.tor.binary.extract.internal')
requires('kotlin.stdlib')
requires("kmp.tor.binary.${kmpOs}${kmpArch}")
requires('kmp.tor.binary.geoip.jvm')
}
module("io.matthewnelson.kotlin-components:kmp-tor-manager-jvm", 'kmp.tor.manager.jvm') {
exports('io.matthewnelson.kmp.tor.manager')
exports('io.matthewnelson.kmp.tor.manager.util')
requires('kmp.tor.controller.common.jvm')
requires('kmp.tor.manager.common.jvm')
requires('kotlin.stdlib')
requires('kotlinx.coroutines.core')
requires('kotlinx.atomicfu')
requires('kmp.tor.controller.jvm')
requires('kmp.tor.common.jvm')
}
module("io.matthewnelson.kotlin-components:kmp-tor-manager-common-jvm", 'kmp.tor.manager.common.jvm') {
exports('io.matthewnelson.kmp.tor.manager.common')
exports('io.matthewnelson.kmp.tor.manager.common.event')
exports('io.matthewnelson.kmp.tor.manager.common.state')
requires('kmp.tor.controller.common.jvm')
requires('kmp.tor.common.jvm')
requires('kotlin.stdlib')
}
module("io.matthewnelson.kotlin-components:kmp-tor-controller-common-jvm", 'kmp.tor.controller.common.jvm') {
exports('io.matthewnelson.kmp.tor.controller.common.config')
exports('io.matthewnelson.kmp.tor.controller.common.file')
exports('io.matthewnelson.kmp.tor.controller.common.control')
exports('io.matthewnelson.kmp.tor.controller.common.control.usecase')
exports('io.matthewnelson.kmp.tor.controller.common.events')
exports('io.matthewnelson.kmp.tor.controller.common.exceptions')
requires('kmp.tor.common.jvm')
requires('kotlin.stdlib')
requires('kotlinx.atomicfu')
}
module("io.matthewnelson.kotlin-components:kmp-tor-common-jvm", 'kmp.tor.common.jvm') {
exports('io.matthewnelson.kmp.tor.common.address')
requires('parcelize.jvm')
requires('kotlin.stdlib')
}
module("io.matthewnelson.kotlin-components:kmp-tor-controller-jvm", 'kmp.tor.controller.jvm') {
exports('io.matthewnelson.kmp.tor.controller.internal.controller')
requires('kmp.tor.common.jvm')
requires('kmp.tor.controller.common.jvm')
requires('kotlinx.coroutines.core')
requires('kotlin.stdlib')
requires('kotlinx.atomicfu')
requires('encoding.core.jvm')
requires('encoding.base16.jvm')
}
module("io.matthewnelson.kotlin-components:kmp-tor-ext-callback-common-jvm", 'kmp.tor.ext.callback.common.jvm') {
exports('io.matthewnelson.kmp.tor.ext.callback.common')
}
module("io.matthewnelson.kotlin-components:kmp-tor-ext-callback-manager-jvm", 'kmp.tor.ext.callback.manager.jvm') {
exports('io.matthewnelson.kmp.tor.ext.callback.manager')
requires('kmp.tor.manager.jvm')
requires('kmp.tor.ext.callback.common.jvm')
requires('kmp.tor.ext.callback.manager.common.jvm')
requires('kmp.tor.ext.callback.controller.common.jvm')
requires('kmp.tor.manager.common.jvm')
requires('kmp.tor.controller.common.jvm')
requires('kotlin.stdlib')
requires('kotlinx.coroutines.core')
}
module("io.matthewnelson.kotlin-components:kmp-tor-ext-callback-manager-common-jvm", 'kmp.tor.ext.callback.manager.common.jvm') {
exports('io.matthewnelson.kmp.tor.ext.callback.manager.common')
requires('kmp.tor.ext.callback.controller.common.jvm')
}
module("io.matthewnelson.kotlin-components:kmp-tor-ext-callback-controller-common-jvm", 'kmp.tor.ext.callback.controller.common.jvm') {
exports('io.matthewnelson.kmp.tor.ext.callback.controller.common.control')
exports('io.matthewnelson.kmp.tor.ext.callback.controller.common.control.usecase')
}
module("io.matthewnelson.kotlin-components:kmp-tor-binary-geoip-jvm", 'kmp.tor.binary.geoip.jvm') {
exports('io.matthewnelson.kmp.tor.binary.geoip')
exports('kmptor')
}
module("base16-jvm-2.0.0.jar", 'encoding.base16.jvm', "2.0.0") {
exports('io.matthewnelson.encoding.base16')
requires('encoding.core.jvm')
requires('kotlin.stdlib')
}
module("base32-jvm-2.0.0.jar", 'encoding.base32.jvm', "2.0.0")
module("base64-jvm-2.0.0.jar", 'encoding.base64.jvm', "2.0.0")
module("core-jvm-2.0.0.jar", 'encoding.core.jvm', "2.0.0") {
exports('io.matthewnelson.encoding.core')
requires('kotlin.stdlib')
}
module("parcelize-jvm-0.1.2.jar", 'parcelize.jvm', "0.1.2") {
exports('io.matthewnelson.component.parcelize')
}
module('org.jcommander:jcommander', 'org.jcommander') {
exports('com.beust.jcommander')
}

View file

@ -261,7 +261,7 @@ public class AppServices {
}
if(Tor.getDefault() != null) {
Tor.getDefault().getTorManager().destroy(true, success -> {});
Tor.getDefault().close();
}
}

View file

@ -1,134 +1,89 @@
package com.sparrowwallet.sparrow.net;
import com.google.common.net.HostAndPort;
import com.sparrowwallet.drongo.OsType;
import com.sparrowwallet.drongo.IOUtils;
import com.sparrowwallet.sparrow.EventManager;
import com.sparrowwallet.sparrow.event.TorStatusEvent;
import com.sparrowwallet.sparrow.io.Storage;
import io.matthewnelson.kmp.tor.KmpTorLoaderJvm;
import io.matthewnelson.kmp.tor.PlatformInstaller;
import io.matthewnelson.kmp.tor.TorConfigProviderJvm;
import io.matthewnelson.kmp.tor.binary.extract.TorBinaryResource;
import io.matthewnelson.kmp.tor.common.address.Port;
import io.matthewnelson.kmp.tor.common.address.ProxyAddress;
import io.matthewnelson.kmp.tor.controller.common.config.TorConfig;
import io.matthewnelson.kmp.tor.controller.common.file.Path;
import io.matthewnelson.kmp.tor.ext.callback.manager.CallbackTorManager;
import io.matthewnelson.kmp.tor.manager.TorManager;
import io.matthewnelson.kmp.tor.manager.common.event.TorManagerEvent;
import io.matthewnelson.kmp.tor.manager.util.PortUtil;
import org.jetbrains.annotations.NotNull;
import io.matthewnelson.kmp.tor.resource.exec.tor.ResourceLoaderTorExec;
import io.matthewnelson.kmp.tor.runtime.Action;
import io.matthewnelson.kmp.tor.runtime.RuntimeEvent;
import io.matthewnelson.kmp.tor.runtime.TorListeners;
import io.matthewnelson.kmp.tor.runtime.TorRuntime;
import io.matthewnelson.kmp.tor.runtime.core.OnEvent;
import io.matthewnelson.kmp.tor.runtime.core.OnFailure;
import io.matthewnelson.kmp.tor.runtime.core.OnSuccess;
import io.matthewnelson.kmp.tor.runtime.core.TorEvent;
import io.matthewnelson.kmp.tor.runtime.core.ctrl.TorCmd;
import io.matthewnelson.kmp.tor.runtime.core.net.IPSocketAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Closeable;
import java.io.File;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.List;
import java.nio.file.Path;
public class Tor {
public class Tor implements Closeable {
private static final Logger log = LoggerFactory.getLogger(Tor.class);
public static final String TOR_DIR = "tor";
public static final String WORK_DIR = "work";
public static final String CACHE_DIR = "cache";
public static final String OLD_INSTALL_DIR = ".kmptor";
public static final String TOR_ADDRESS_SUFFIX = ".onion";
private static Tor tor;
private final Path path = Path.invoke(Storage.getSparrowHome().getAbsolutePath()).builder().addSegment(TOR_DIR).build();
private final CallbackTorManager instance;
private ProxyAddress socksAddress;
private final TorRuntime instance;
private IPSocketAddress socksAddress;
public Tor() {
OsType osType = OsType.getCurrent();
String arch = System.getProperty("os.arch");
PlatformInstaller installer;
PlatformInstaller.InstallOption installOption = PlatformInstaller.InstallOption.CleanInstallIfMissing;
if(osType == OsType.MACOS) {
if(arch.equals("aarch64")) {
installer = PlatformInstaller.macosArm64(installOption);
} else {
installer = PlatformInstaller.macosX64(installOption);
}
} else if(osType == OsType.WINDOWS) {
installer = PlatformInstaller.mingwX64(installOption);
} else if(osType == OsType.UNIX) {
if(arch.equals("aarch64")) {
TorBinaryResource linuxArm64 = TorBinaryResource.from(TorBinaryResource.OS.Linux, "arm64",
"588496f3164d52b91f17e4db3372d8dfefa6366a8df265eebd4a28d4128992aa",
List.of("libevent-2.1.so.7.gz", "libstdc++.so.6.gz", "libcrypto.so.1.1.gz", "tor.gz", "libssl.so.1.1.gz"));
installer = PlatformInstaller.custom(installOption, linuxArm64);
} else {
installer = PlatformInstaller.linuxX64(installOption);
}
} else {
throw new UnsupportedOperationException("Sparrow's bundled Tor is not supported on " + osType + " " + arch);
public Tor(OnEvent<TorListeners> listener) {
Path path = Path.of(Storage.getSparrowHome().getAbsolutePath()).resolve(TOR_DIR);
File oldInstallDir = path.resolve(WORK_DIR).resolve(OLD_INSTALL_DIR).toFile();
if(oldInstallDir.exists()) {
IOUtils.deleteDirectory(oldInstallDir);
}
TorConfigProviderJvm torConfigProviderJvm = new TorConfigProviderJvm() {
@NotNull
@Override
public Path getWorkDir() {
return path.builder().addSegment("work").build();
}
TorRuntime.Environment env = TorRuntime.Environment.Builder(
path.resolve(WORK_DIR).toFile(),
path.resolve(CACHE_DIR).toFile(),
ResourceLoaderTorExec::getOrCreate
);
@NotNull
@Override
public Path getCacheDir() {
return path.builder().addSegment("cache").build();
}
env.debug = true;
@NotNull
@Override
protected TorConfig provide() {
TorConfig.Builder builder = new TorConfig.Builder();
TorConfig.Setting.DormantCanceledByStartup dormantCanceledByStartup = new TorConfig.Setting.DormantCanceledByStartup();
dormantCanceledByStartup.set(TorConfig.Option.AorTorF.getTrue());
builder.put(dormantCanceledByStartup);
TorConfig.Setting.Ports.Control controlPort = new TorConfig.Setting.Ports.Control();
controlPort.set(TorConfig.Option.AorDorPort.Auto.INSTANCE);
builder.put(controlPort);
return builder.build();
}
};
KmpTorLoaderJvm jvmLoader = new KmpTorLoaderJvm(installer, torConfigProviderJvm);
TorManager torManager = TorManager.newInstance(jvmLoader);
torManager.debug(true);
torManager.addListener(new TorManagerEvent.Listener() {
@Override
public void managerEventWarn(@NotNull String message) {
log.warn(message);
EventManager.get().post(new TorStatusEvent(message));
}
@Override
public void managerEventInfo(@NotNull String message) {
log.info(message);
EventManager.get().post(new TorStatusEvent(message));
}
@Override
public void managerEventDebug(@NotNull String message) {
log.debug(message);
EventManager.get().post(new TorStatusEvent(message));
}
@Override
public void managerEventAddressInfo(@NotNull TorManagerEvent.AddressInfo info) {
if(info.isNull) {
socksAddress = null;
} else {
socksAddress = info.socksInfoToProxyAddress().iterator().next();
instance = TorRuntime.Builder(env, b -> {
RuntimeEvent.entries().forEach(event -> {
switch(event) {
case RuntimeEvent.LOG.ERROR _ -> b.observerStatic(event, OnEvent.Executor.Immediate.INSTANCE, data -> {
log.error(data.toString());
EventManager.get().post(new TorStatusEvent(data.toString()));
});
case RuntimeEvent.LOG.WARN _ -> b.observerStatic(event, OnEvent.Executor.Immediate.INSTANCE, data -> {
log.warn(data.toString());
EventManager.get().post(new TorStatusEvent(data.toString()));
});
case RuntimeEvent.LOG.INFO _ -> b.observerStatic(event, OnEvent.Executor.Immediate.INSTANCE, data -> {
log.info(data.toString());
EventManager.get().post(new TorStatusEvent(data.toString()));
});
case RuntimeEvent.LOG.DEBUG _ -> b.observerStatic(event, OnEvent.Executor.Immediate.INSTANCE, data -> {
log.debug(data.toString());
EventManager.get().post(new TorStatusEvent(data.toString()));
});
case null, default -> b.observerStatic(event, OnEvent.Executor.Immediate.INSTANCE, data -> {
log.trace(data.toString());
});
}
}
});
});
this.instance = new CallbackTorManager(torManager, uncaughtException -> {
log.error("Uncaught exception from CallbackTorManager", uncaughtException);
b.observerStatic(RuntimeEvent.LISTENERS.INSTANCE, new TorSocksClient());
b.observerStatic(RuntimeEvent.LISTENERS.INSTANCE, listener);
b.required(TorEvent.ERR.INSTANCE);
b.required(TorEvent.WARN.INSTANCE);
});
}
@ -140,7 +95,7 @@ public class Tor {
Tor.tor = tor;
}
public CallbackTorManager getTorManager() {
public TorRuntime getTorRuntime() {
return instance;
}
@ -149,14 +104,34 @@ public class Tor {
throw new IllegalStateException("Tor socks proxy is not yet instantiated");
}
return new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(socksAddress.address.getValue(), socksAddress.port.getValue()));
return new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(socksAddress.address.value, socksAddress.port.value));
}
public HostAndPort getProxyHostAndPort() {
return HostAndPort.fromParts(socksAddress.address.getValue(), socksAddress.port.getValue());
return HostAndPort.fromParts(socksAddress.address.value, socksAddress.port.value);
}
public static boolean isRunningExternally() {
return !PortUtil.isTcpPortAvailable(Port.invoke(9050));
public void changeIdentity() {
if(instance != null) {
instance.enqueue(TorCmd.Signal.NewNym.INSTANCE, throwable -> {
log.warn("Failed to signal newnym", throwable);
}, _ -> {
log.info("Signalled newnym for new Tor circuit");
});
}
}
@Override
public void close() {
if(instance != null) {
instance.enqueue(Action.StopDaemon, OnFailure.noOp(), OnSuccess.noOp());
}
}
private class TorSocksClient implements OnEvent<TorListeners> {
@Override
public void invoke(TorListeners torListeners) {
socksAddress = torListeners.socks.isEmpty() ? null : torListeners.socks.iterator().next();
}
}
}

View file

@ -1,10 +1,12 @@
package com.sparrowwallet.sparrow.net;
import io.matthewnelson.kmp.tor.ext.callback.manager.CallbackTorManager;
import io.matthewnelson.kmp.tor.manager.common.event.TorManagerEvent;
import io.matthewnelson.kmp.tor.runtime.Action;
import io.matthewnelson.kmp.tor.runtime.TorListeners;
import io.matthewnelson.kmp.tor.runtime.TorRuntime;
import io.matthewnelson.kmp.tor.runtime.core.OnEvent;
import io.matthewnelson.kmp.tor.runtime.core.ctrl.Reply;
import javafx.concurrent.ScheduledService;
import javafx.concurrent.Task;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -32,37 +34,25 @@ public class TorService extends ScheduledService<Tor> {
protected Tor call() throws Exception {
Tor tor = Tor.getDefault();
if(tor == null) {
tor = new Tor();
CallbackTorManager callbackTorManager = tor.getTorManager();
callbackTorManager.addListener(new TorManagerEvent.Listener() {
@Override
public void managerEventAddressInfo(@NotNull TorManagerEvent.AddressInfo info) {
if(!info.isNull) {
try {
startupLock.lock();
startupCondition.signalAll();
} finally {
startupLock.unlock();
}
}
}
});
callbackTorManager.start(throwable -> {
if(throwable instanceof Exception exception) {
tor = new Tor(new StartupListener());
TorRuntime torRuntime = tor.getTorRuntime();
torRuntime.enqueue(Action.StartDaemon, throwable -> {
if(throwable instanceof Reply.Error replyError && !replyError.replies.isEmpty()) {
startupException = new TorStartupException(replyError.replies.getFirst().message);
} else if(throwable instanceof Exception exception) {
startupException = exception;
} else {
startupException = new Exception(throwable);
}
log.error("Error", throwable);
log.error("Error starting Tor daemon", throwable);
try {
startupLock.lock();
startupCondition.signalAll();
} finally {
startupLock.unlock();
}
}, success -> {
log.info("Tor daemon started successfully");
});
}, _ -> log.info("Tor daemon started successfully"));
try {
startupLock.lock();
@ -82,4 +72,18 @@ public class TorService extends ScheduledService<Tor> {
}
};
}
private class StartupListener implements OnEvent<TorListeners> {
@Override
public void invoke(TorListeners torListeners) {
if(!torListeners.socks.isEmpty()) {
try {
startupLock.lock();
startupCondition.signalAll();
} finally {
startupLock.unlock();
}
}
}
}
}

View file

@ -3,7 +3,6 @@ package com.sparrowwallet.sparrow.net;
import com.google.common.net.HostAndPort;
import com.sparrowwallet.drongo.Utils;
import com.sparrowwallet.sparrow.AppServices;
import io.matthewnelson.kmp.tor.controller.common.control.usecase.TorControlSignal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -13,7 +12,6 @@ import java.net.SocketTimeoutException;
import java.nio.file.AccessDeniedException;
import java.nio.file.FileSystemException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -24,11 +22,7 @@ public class TorUtils {
public static void changeIdentity(HostAndPort proxy) {
if(AppServices.isTorRunning()) {
Tor.getDefault().getTorManager().signal(TorControlSignal.Signal.NewNym, throwable -> {
log.warn("Failed to signal newnym");
}, successEvent -> {
log.info("Signalled newnym for new Tor circuit");
});
Tor.getDefault().changeIdentity();
} else {
HostAndPort control = HostAndPort.fromParts(proxy.getHost(), proxy.getPort() + 1);
try(Socket socket = new Socket(control.getHost(), control.getPort())) {

View file

@ -20,18 +20,8 @@ open module com.sparrowwallet.sparrow {
requires org.jetbrains.annotations;
requires com.fasterxml.jackson.databind;
requires com.fasterxml.jackson.annotation;
requires kotlin.stdlib;
requires kmp.tor.jvm;
requires kmp.tor.binary.extract.jvm;
requires kmp.tor.common.jvm;
requires kmp.tor.controller.common.jvm;
requires kmp.tor.manager.jvm;
requires kmp.tor.manager.common.jvm;
requires kmp.tor.ext.callback.manager.jvm;
requires kmp.tor.ext.callback.common.jvm;
requires kmp.tor.ext.callback.manager.common.jvm;
requires kmp.tor.ext.callback.controller.common.jvm;
requires parcelize.jvm;
requires io.matthewnelson.kmp.tor.runtime;
requires io.matthewnelson.kmp.tor.resource.exec.tor;
requires kotlinx.coroutines.javafx;
requires org.slf4j;
requires com.google.gson;