diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 0aed68957..be1bfafbe 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -1,7 +1,6 @@ object Versions { const val lightningKmp = "1.8.4" const val secp256k1 = "0.14.0" - const val torMobile = "0.2.0" const val kotlin = "1.9.22" diff --git a/phoenix-shared/build.gradle.kts b/phoenix-shared/build.gradle.kts index 8f57b666a..fb6ca6c94 100644 --- a/phoenix-shared/build.gradle.kts +++ b/phoenix-shared/build.gradle.kts @@ -59,7 +59,7 @@ kotlin { } } - listOf(iosX64(), iosArm64()).forEach { + listOf(iosX64(), iosArm64(), iosSimulatorArm64()).forEach { it.binaries { framework { optimized = false @@ -89,7 +89,6 @@ kotlin { dependencies { // lightning-kmp api("fr.acinq.lightning:lightning-kmp:${Versions.lightningKmp}") - api("fr.acinq.tor:tor-mobile-kmp:${Versions.torMobile}") // ktor implementation("io.ktor:ktor-client-core:${Versions.ktor}") implementation("io.ktor:ktor-client-json:${Versions.ktor}") diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/PhoenixBusiness.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/PhoenixBusiness.kt index 32271ecd2..bff697301 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/PhoenixBusiness.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/PhoenixBusiness.kt @@ -38,7 +38,6 @@ import fr.acinq.phoenix.db.createAppDbDriver import fr.acinq.phoenix.managers.* import fr.acinq.phoenix.utils.* import fr.acinq.phoenix.utils.logger.PhoenixLoggerConfig -import fr.acinq.tor.Tor import io.ktor.client.* import io.ktor.client.plugins.contentnegotiation.* import io.ktor.serialization.kotlinx.json.* @@ -59,12 +58,7 @@ class PhoenixBusiness( private val tcpSocketBuilder = TcpSocket.Builder() internal val tcpSocketBuilderFactory = suspend { - val isTorEnabled = appConfigurationManager.isTorEnabled.filterNotNull().first() - if (isTorEnabled) { - tcpSocketBuilder.torProxy(loggerFactory) - } else { - tcpSocketBuilder - } + tcpSocketBuilder } internal val httpClient by lazy { @@ -97,7 +91,6 @@ class PhoenixBusiness( val notificationsManager by lazy { NotificationsManager(this) } val contactsManager by lazy { ContactsManager(this) } val blockchainExplorer by lazy { BlockchainExplorer(chain) } - val tor by lazy { Tor(getApplicationCacheDirectoryPath(ctx), TorHelper.torLogger(loggerFactory)) } val sendManager by lazy { SendManager(this) } fun start(startupParams: StartupParams) { diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/AppConnectionsDaemon.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/AppConnectionsDaemon.kt index fb0062dfd..767d1a291 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/AppConnectionsDaemon.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/AppConnectionsDaemon.kt @@ -7,12 +7,9 @@ import fr.acinq.lightning.utils.Connection import fr.acinq.lightning.utils.ServerAddress import fr.acinq.phoenix.PhoenixBusiness import fr.acinq.phoenix.data.ElectrumConfig -import fr.acinq.phoenix.utils.TorHelper.connectionState import fr.acinq.lightning.logging.debug import fr.acinq.lightning.logging.error import fr.acinq.lightning.logging.info -import fr.acinq.tor.Tor -import fr.acinq.tor.TorState import kotlinx.coroutines.* import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.ReceiveChannel @@ -35,7 +32,6 @@ class AppConnectionsDaemon( private val currencyManager: CurrencyManager, private val networkMonitor: NetworkMonitor, private val tcpSocketBuilder: suspend () -> TcpSocket.Builder, - private val tor: Tor, private val electrumClient: ElectrumClient, ) : CoroutineScope by MainScope() { @@ -47,7 +43,6 @@ class AppConnectionsDaemon( currencyManager = business.currencyManager, networkMonitor = business.networkMonitor, tcpSocketBuilder = business.tcpSocketBuilderFactory, - tor = business.tor, electrumClient = business.electrumClient ) @@ -55,7 +50,6 @@ class AppConnectionsDaemon( private var peerConnectionJob: Job? = null private var electrumConnectionJob: Job? = null - private var torConnectionJob: Job? = null private var httpControlFlowEnabled: Boolean = false private data class TrafficControl( @@ -193,51 +187,6 @@ class AppConnectionsDaemon( } } - // Tor state monitor - launch { - tor.state.collect { - val newValue = it == TorState.RUNNING - logger.debug { "torIsAvailable = $newValue" } - torControlChanges.send { copy(torIsAvailable = newValue) } - peerControlChanges.send { copy(torIsAvailable = newValue) } - electrumControlChanges.send { copy(torIsAvailable = newValue) } - httpApiControlChanges.send { copy(torIsAvailable = newValue) } - } - } - - // Tor - launch { - torControlFlow.collect { - when { - it.internetIsAvailable && it.disconnectCount <= 0 && it.torIsEnabled -> { - if (torConnectionJob == null) { - logger.info { "starting tor" } - torConnectionJob = connectionLoop( - name = "Tor", - statusStateFlow = tor.state.connectionState(this), - ) { - try { - tor.startInProperScope(this) - } catch (t: Throwable) { - logger.error(t) { "tor cannot be started: ${t.message}" } - } - } - } - } - else -> { - torConnectionJob?.let { - logger.info { "shutting down tor" } - it.cancel() - tor.stop() - torConnectionJob = null - // Tor runs it's own process, and needs time to shutdown before restarting. - delay(500) - } - } - } - } - } - // Peer launch { var configVersion = 0 @@ -522,6 +471,3 @@ class AppConnectionsDaemon( } } } - -/** The start function must run on a different dispatcher depending on the platform. */ -expect suspend fun Tor.startInProperScope(scope: CoroutineScope) diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/ConnectionsManager.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/ConnectionsManager.kt index 2d8d33879..bf74daa93 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/ConnectionsManager.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/ConnectionsManager.kt @@ -4,8 +4,6 @@ import fr.acinq.lightning.blockchain.electrum.ElectrumClient import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.lightning.utils.Connection import fr.acinq.phoenix.PhoenixBusiness -import fr.acinq.phoenix.utils.TorHelper.connectionState -import fr.acinq.tor.Tor import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import plus @@ -30,17 +28,13 @@ class ConnectionsManager( peerManager: PeerManager, electrumClient: ElectrumClient, networkMonitor: NetworkMonitor, - appConfigurationManager: AppConfigurationManager, - tor: Tor ): CoroutineScope { constructor(business: PhoenixBusiness): this( loggerFactory = business.loggerFactory, peerManager = business.peerManager, electrumClient = business.electrumClient, - networkMonitor = business.networkMonitor, - appConfigurationManager = business.appConfigurationManager, - tor = business.tor + networkMonitor = business.networkMonitor ) val log = loggerFactory.newLogger(this::class) @@ -52,10 +46,8 @@ class ConnectionsManager( combine( peer.connectionState, electrumClient.connectionStatus, - networkMonitor.networkState, - appConfigurationManager.isTorEnabled.filterNotNull(), - tor.state.connectionState(this) - ) { peerState, electrumStatus, internetState, torEnabled, torState -> + networkMonitor.networkState + ) { peerState, electrumStatus, internetState -> Connections( peer = peerState, electrum = electrumStatus.toConnectionState(), @@ -63,8 +55,8 @@ class ConnectionsManager( NetworkState.Available -> Connection.ESTABLISHED NetworkState.NotAvailable -> Connection.CLOSED(reason = null) }, - tor = if (torEnabled) torState else Connection.CLOSED(reason = null), - torEnabled = torEnabled + tor = Connection.CLOSED(reason = null), + torEnabled = false ) } }.stateIn( diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/Socks5Proxy.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/Socks5Proxy.kt deleted file mode 100644 index 43dfc592c..000000000 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/Socks5Proxy.kt +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2022 ACINQ SAS - * - * 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 fr.acinq.phoenix.utils - -import fr.acinq.lightning.io.TcpSocket -import fr.acinq.lightning.logging.LoggerFactory -import fr.acinq.lightning.logging.info -import fr.acinq.tor.Tor -import fr.acinq.tor.socks.socks5Handshake - -class Socks5Proxy( - private val socketBuilder: TcpSocket.Builder, - loggerFactory: LoggerFactory, - private val proxyHost: String, - private val proxyPort: Int -): TcpSocket.Builder { - - val logger = loggerFactory.newLogger(this::class) - - override suspend fun connect( - host: String, - port: Int, - tls: TcpSocket.TLS, - loggerFactory: LoggerFactory, - ): TcpSocket { - val socket = socketBuilder.connect(proxyHost, proxyPort, TcpSocket.TLS.DISABLED, loggerFactory) - val (cHost, cPort) = socks5Handshake( - destinationHost = host, - destinationPort = port, - receive = { socket.receiveFully(it, offset = 0, length = it.size) }, - send = { socket.send(it, offset = 0, length = it.size, flush = true) } - ) - logger.info { "connected through socks5 to $cHost:$cPort" } - val updatedTls = when (tls) { - is TcpSocket.TLS.TRUSTED_CERTIFICATES -> - TcpSocket.TLS.TRUSTED_CERTIFICATES(tls.expectedHostName ?: host) - else -> tls - } - return socket.startTls(updatedTls) - } -} - -fun TcpSocket.Builder.torProxy( - loggerFactory: LoggerFactory -) = Socks5Proxy( - socketBuilder = this, - loggerFactory = loggerFactory, - proxyHost = Tor.SOCKS_ADDRESS, - proxyPort = Tor.SOCKS_PORT -) diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/TorHelper.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/TorHelper.kt deleted file mode 100644 index d87d3254e..000000000 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/TorHelper.kt +++ /dev/null @@ -1,40 +0,0 @@ -package fr.acinq.phoenix.utils - -import fr.acinq.lightning.utils.Connection -import fr.acinq.lightning.logging.LoggerFactory -import fr.acinq.lightning.logging.debug -import fr.acinq.lightning.logging.error -import fr.acinq.lightning.logging.info -import fr.acinq.lightning.logging.warning -import fr.acinq.tor.Tor -import fr.acinq.tor.TorState -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.stateIn - - -object TorHelper { - fun torLogger(loggerFactory: LoggerFactory): (Tor.LogLevel, String) -> Unit { - val logger = loggerFactory.newLogger("Tor") - return { level, message -> - when (level) { - Tor.LogLevel.DEBUG -> logger.debug { message } - Tor.LogLevel.NOTICE -> logger.info { message } - Tor.LogLevel.WARN -> logger.warning { message } - Tor.LogLevel.ERR -> logger.error { message } - } - } - } - - suspend fun StateFlow.connectionState(scope: CoroutineScope) = flow { - collect { torState -> - val newState = when (torState) { - TorState.STARTING -> Connection.ESTABLISHING - TorState.RUNNING -> Connection.ESTABLISHED - TorState.STOPPED -> Connection.CLOSED(null) - } - emit(newState) - } - }.stateIn(scope) -} \ No newline at end of file diff --git a/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/managers/AppConnectionsDaemon.kt b/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/managers/AppConnectionsDaemon.kt deleted file mode 100644 index e282b8182..000000000 --- a/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/managers/AppConnectionsDaemon.kt +++ /dev/null @@ -1,16 +0,0 @@ -package fr.acinq.phoenix.managers - -import fr.acinq.tor.Tor -import kotlinx.coroutines.* - -@OptIn(ExperimentalStdlibApi::class) -actual suspend fun Tor.startInProperScope(scope: CoroutineScope) { - val currentDispatcher = scope.coroutineContext[CoroutineDispatcher.Key] - if (currentDispatcher != Dispatchers.Main) { - // on iOS, we must run tor operations on the main thread, to prevent issues with frozen objects. - // TODO: remove this once we moved to the new memory model - this.start(CoroutineScope(scope.coroutineContext.job + Dispatchers.Main)) - } else { - this.start(scope) - } -} \ No newline at end of file