Skip to content

Commit

Permalink
Update for ElectrumClient rework (#418)
Browse files Browse the repository at this point in the history
- connection state is derived from ElectrumConnectionStatus
- the socket builder is moved to the `connect` method
  • Loading branch information
dpad85 authored Sep 13, 2023
1 parent 071e095 commit baff3b0
Show file tree
Hide file tree
Showing 10 changed files with 33 additions and 55 deletions.
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/Versions.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
object Versions {
const val lightningKmp = "1.5.4"
const val lightningKmp = "1.5.5-SNAPSHOT"
const val secp256k1 = "0.7.0"
const val torMobile = "0.2.0"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import fr.acinq.bitcoin.ByteVector32
import fr.acinq.lightning.blockchain.electrum.ElectrumConnectionStatus
import fr.acinq.lightning.blockchain.electrum.getConfirmations
import fr.acinq.lightning.db.*
import fr.acinq.lightning.utils.Connection
import fr.acinq.lightning.utils.msat
import fr.acinq.lightning.utils.sum
import fr.acinq.phoenix.android.LocalBitcoinUnit
Expand All @@ -63,7 +63,7 @@ import fr.acinq.phoenix.utils.extensions.minDepthForFunding
import fr.acinq.phoenix.utils.extensions.state
import io.ktor.http.Url
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import javax.crypto.Cipher
Expand Down Expand Up @@ -599,7 +599,6 @@ private fun ConfirmationView(
onClick = { openLink(context, txUrl) }
)
} else {
val connectionsManager = business.connectionsManager

suspend fun getConfirmations(): Int {
val confirmations = electrumClient.getConfirmations(txId)
Expand All @@ -612,7 +611,7 @@ private fun ConfirmationView(
}

val confirmations by produceState<Int?>(initialValue = null) {
connectionsManager.connections.filter { it.electrum is Connection.ESTABLISHED }.first()
electrumClient.connectionStatus.filterIsInstance<ElectrumConnectionStatus.Connected>().first()
val confirmations = getConfirmations()
value = confirmations
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,8 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import fr.acinq.lightning.utils.mkTree
import fr.acinq.phoenix.android.R
import fr.acinq.phoenix.android.Screen
import fr.acinq.phoenix.android.business
import fr.acinq.phoenix.android.components.Button
import fr.acinq.phoenix.android.components.Card
import fr.acinq.phoenix.android.components.CardHeader
Expand All @@ -47,11 +45,9 @@ import fr.acinq.phoenix.android.components.DefaultScreenLayout
import fr.acinq.phoenix.android.components.SettingButton
import fr.acinq.phoenix.android.navController
import fr.acinq.phoenix.android.navigate
import fr.acinq.phoenix.android.utils.logger
import fr.acinq.phoenix.android.utils.negativeColor
import fr.acinq.phoenix.legacy.utils.LegacyAppStatus
import fr.acinq.phoenix.legacy.utils.LegacyPrefsDatastore
import kotlinx.coroutines.job
import kotlinx.coroutines.launch


Expand Down Expand Up @@ -129,26 +125,9 @@ fun SettingsView() {
},
modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Start
)
val log = logger("DEBUG")
val electrumClient = business.electrumClient
val peerManager = business.peerManager
Button(
text = "Log coroutine tree (DEBUG)",
icon = R.drawable.ic_text,
onClick = {
scope.launch {
val peer = peerManager.getPeer()
log.info { ">>>> coroutines-peer\n${peer.coroutineContext.job.mkTree()}" }
log.info { ">>>> coroutines-electrum\n${electrumClient.coroutineContext.job.mkTree()}" }
}
},
modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Start
)
}
}

Spacer(Modifier.height(32.dp))


}
}
5 changes: 2 additions & 3 deletions phoenix-ios/phoenix-ios/views/inspect/CpfpView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -456,14 +456,13 @@ struct CpfpView: View {

do {
let result = try await Biz.business.electrumClient.kotlin_getConfirmations(txid: onChainPayment.txId)

let confirmations = result?.intValue ?? 0
log.debug("checkConfirmations(): => \(confirmations)")

if confirmations > 0 {
self.txAlreadyMined = true
}

} catch {
log.error("electrumClient.getConfirmations(): \(error)")
}
Expand Down
5 changes: 2 additions & 3 deletions phoenix-ios/phoenix-ios/views/inspect/SummaryView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -658,13 +658,12 @@ struct SummaryView: View {

do {
let result = try await Biz.business.electrumClient.kotlin_getConfirmations(txid: onChainPayment.txId)

let confirmations = result?.intValue ?? 0
log.debug("checkConfirmations(): => \(confirmations)")

self.blockchainConfirmations = confirmations
return confirmations

} catch {
log.error("checkConfirmations(): error: \(error)")
return 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ import org.kodein.log.newLogger
import org.kodein.log.withShortPackageKeepLast
import org.kodein.memory.file.Path
import org.kodein.memory.file.resolve

import kotlin.time.Duration.Companion.seconds

class PhoenixBusiness(
internal val ctx: PlatformContext
Expand Down Expand Up @@ -83,7 +83,7 @@ class PhoenixBusiness(

val chain: NodeParams.Chain = NodeParamsManager.chain

val electrumClient by lazy { ElectrumClient(null, MainScope(), loggerFactory) }
val electrumClient by lazy { ElectrumClient(scope = MainScope(), loggerFactory = loggerFactory, pingInterval = 30.seconds, rpcTimeout = 10.seconds) }
internal val electrumWatcher by lazy { ElectrumWatcher(electrumClient, MainScope(), loggerFactory) }

var appConnectionsDaemon: AppConnectionsDaemon? = null
Expand Down Expand Up @@ -120,7 +120,6 @@ class PhoenixBusiness(
*/
fun stop() {
electrumClient.stop()
electrumClient.cancel()
electrumWatcher.stop()
electrumWatcher.cancel()
appConnectionsDaemon?.cancel()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ class AppElectrumConfigurationController(
combine(
configurationManager.electrumConfig,
appConnectionsDaemon.lastElectrumServerAddress,
electrumClient.connectionState,
electrumClient.connectionStatus,
configurationManager.electrumMessages,
transform = { configState, currentServer, connectionState, message ->
transform = { configState, currentServer, connectionStatus, message ->
ElectrumConfiguration.Model(
configuration = configState,
currentServer = currentServer,
connection = connectionState,
connection = connectionStatus.toConnectionState(),
blockHeight = message?.blockHeight ?: 0,
tipTimestamp = message?.header?.time ?: 0,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import org.kodein.log.LoggerFactory
import org.kodein.log.newLogger
import kotlin.time.Duration
Expand Down Expand Up @@ -292,7 +294,7 @@ class AppConnectionsDaemon(
logger.info { "starting electrum connection loop" }
electrumConnectionJob = connectionLoop(
name = "Electrum",
statusStateFlow = electrumClient.connectionState
statusStateFlow = electrumClient.connectionStatus.map { it.toConnectionState() }.stateIn(this)
) {
val electrumServerAddress: ServerAddress? = configurationManager.electrumConfig.value?.let { electrumConfig ->
when (electrumConfig) {
Expand All @@ -303,10 +305,9 @@ class AppConnectionsDaemon(
if (electrumServerAddress == null) {
logger.info { "ignoring electrum connection opportunity because no server is configured yet" }
} else {
logger.info { "starting actual electrum connection job to server=$electrumServerAddress" }
electrumClient.socketBuilder = tcpSocketBuilder()
try {
electrumClient.connect(electrumServerAddress)
logger.info { "starting actual electrum connection job to server=$electrumServerAddress" }
electrumClient.connect(electrumServerAddress, tcpSocketBuilder())
} catch (e: Exception) {
logger.error(e) { "error when connecting to electrum: "}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,14 @@ class ConnectionsManager(
launch {
combine(
peerManager.getPeer().connectionState,
electrumClient.connectionState,
electrumClient.connectionStatus,
networkMonitor.networkState,
appConfigurationManager.isTorEnabled.filterNotNull(),
tor.state.connectionState(this)
) { peerState, electrumState, internetState, torEnabled, torState ->
) { peerState, electrumStatus, internetState, torEnabled, torState ->
Connections(
peer = peerState,
electrum = electrumState,
electrum = electrumStatus.toConnectionState(),
internet = when (internetState) {
NetworkState.Available -> Connection.ESTABLISHED
NetworkState.NotAvailable -> Connection.CLOSED(reason = null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ class PaymentsManager(
}
}

/** Watches transactions that are unconfirmed, check their confirmation status, and update relevant payments. */
/** Watches transactions that are unconfirmed, checks their confirmation status at each block, and updates relevant payments. */
private suspend fun monitorUnconfirmedTransactions() {
val paymentsDb = paymentsDb()
// We need to recheck anytime either:
Expand All @@ -137,15 +137,17 @@ class PaymentsManager(
paymentsDb.listUnconfirmedTransactions(),
configurationManager.electrumMessages
) { unconfirmedTxs, header ->
Pair(unconfirmedTxs, header)
}.collect { (unconfirmedTxs, _) ->
val unconfirmedTxIds = unconfirmedTxs.map { it.byteVector32() }
log.info { "monitoring unconfirmed txs=$unconfirmedTxIds" }
unconfirmedTxIds.forEach { txId ->
electrumClient.getConfirmations(txId)?.let { conf ->
if (conf > 0) {
log.info { "transaction $txId has $conf confirmations, updating database" }
paymentsDb.setConfirmed(txId)
unconfirmedTxs to header?.blockHeight
}.collect { (unconfirmedTxs, blockHeight) ->
if (blockHeight != null) {
val unconfirmedTxIds = unconfirmedTxs.map { it.byteVector32() }
log.debug { "checking confirmation status of ${unconfirmedTxIds.size} txs at block=$blockHeight" }
unconfirmedTxIds.forEach { txId ->
electrumClient.getConfirmations(txId)?.let { conf ->
if (conf > 0) {
log.info { "transaction $txId has $conf confirmations, updating database" }
paymentsDb.setConfirmed(txId)
}
}
}
}
Expand Down

0 comments on commit baff3b0

Please sign in to comment.