@@ -62,7 +62,6 @@ class WalletViewModel @Inject constructor(
6262 companion object {
6363 private const val TAG = " WalletViewModel"
6464 private val TIMEOUT_RESTORE_WAIT = 30 .seconds
65- private const val CHANNEL_RECOVERY_RESTART_DELAY_MS = 500L
6665 }
6766
6867 val lightningState = lightningRepo.lightningState
@@ -267,8 +266,11 @@ class WalletViewModel @Inject constructor(
267266
268267 waitForRestoreIfNeeded()
269268
270- val channelMigration = buildChannelMigrationIfAvailable()
271- startNode(walletIndex, channelMigration)
269+ val allMonitorsRetrieved = fetchOrphanedChannelMonitorsIfNeeded()
270+ val channelMigration = buildChannelMigrationIfAvailable(
271+ isOrphanedRecovery = allMonitorsRetrieved != null ,
272+ )
273+ startNode(walletIndex, channelMigration, allMonitorsRetrieved)
272274 } finally {
273275 isStarting = false
274276 }
@@ -282,17 +284,19 @@ class WalletViewModel @Inject constructor(
282284 } ? : Logger .warn(" waitForRestoreIfNeeded timeout, proceeding anyway" , context = TAG )
283285 }
284286
285- private fun buildChannelMigrationIfAvailable (): ChannelDataMigration ? =
287+ private fun buildChannelMigrationIfAvailable (isOrphanedRecovery : Boolean = false ): ChannelDataMigration ? =
286288 migrationService.peekPendingChannelMigration()?.let { migration ->
287289 ChannelDataMigration (
288- channelManager = migration.channelManager.map { it.toUByte() },
290+ // don't overwrite channel manager for orphaned recovery, we only need the monitors for the sweep
291+ channelManager = if (isOrphanedRecovery) null else migration.channelManager.map { it.toUByte() },
289292 channelMonitors = migration.channelMonitors.map { monitor -> monitor.map { it.toUByte() } },
290293 )
291294 }
292295
293296 private suspend fun startNode (
294297 walletIndex : Int = 0,
295298 channelMigration : ChannelDataMigration ? ,
299+ allMonitorsRetrieved : Boolean? = null,
296300 ) {
297301 lightningRepo.start(walletIndex, channelMigration = channelMigration)
298302 .onSuccess {
@@ -306,7 +310,9 @@ class WalletViewModel @Inject constructor(
306310 if (_restoreState .value.isIdle()) {
307311 walletRepo.refreshBip21()
308312 }
309- checkForOrphanedChannelMonitorRecovery()
313+ if (allMonitorsRetrieved == true ) {
314+ migrationService.markChannelRecoveryChecked()
315+ }
310316 }
311317 .onFailure {
312318 Logger .error(" Node startup error" , it, context = TAG )
@@ -328,48 +334,17 @@ class WalletViewModel @Inject constructor(
328334 }
329335 }
330336
331- private suspend fun checkForOrphanedChannelMonitorRecovery () {
332- if (migrationService.isChannelRecoveryChecked()) return
333-
334- Logger .info(" Running one-time channel monitor recovery check" , context = TAG )
337+ private suspend fun fetchOrphanedChannelMonitorsIfNeeded (): Boolean? {
338+ if (migrationService.isChannelRecoveryChecked()) return null
339+ if (migrationService.peekPendingChannelMigration() != null ) return null
335340
336- val allMonitorsRetrieved = runCatching {
337- val allRetrieved = migrationService.fetchRNRemoteLdkData()
338- val channelMigration = buildChannelMigrationIfAvailable()
339-
340- if (channelMigration == null ) {
341- Logger .info(" No channel monitors found on RN backup" , context = TAG )
342- return @runCatching allRetrieved
343- }
344-
345- Logger .info(
346- " Found ${channelMigration.channelMonitors.size} monitors on RN backup, attempting recovery" ,
347- context = TAG ,
348- )
349-
350- lightningRepo.stop().onFailure {
351- Logger .error(" Failed to stop node for channel recovery" , it, context = TAG )
352- }
353- delay(CHANNEL_RECOVERY_RESTART_DELAY_MS )
354- lightningRepo.start(channelMigration = channelMigration, shouldRetry = false )
355- .onSuccess {
356- migrationService.consumePendingChannelMigration()
357- walletRepo.syncNodeAndWallet()
358- walletRepo.syncBalances()
359- Logger .info(" Channel monitor recovery complete" , context = TAG )
360- }
361- .onFailure {
362- Logger .error(" Failed to restart node after channel recovery" , it, context = TAG )
363- }
341+ Logger .info(" Running pre-startup channel monitor recovery check" , context = TAG )
364342
365- allRetrieved
343+ return runCatching {
344+ migrationService.fetchRNRemoteLdkData()
345+ }.onFailure {
346+ Logger .error(" Pre-startup channel monitor fetch failed" , it, context = TAG )
366347 }.getOrDefault(false )
367-
368- if (allMonitorsRetrieved) {
369- migrationService.markChannelRecoveryChecked()
370- } else {
371- Logger .warn(" Some monitors failed to download, will retry on next startup" , context = TAG )
372- }
373348 }
374349
375350 fun stop () {
0 commit comments