Skip to content

Commit f250ec2

Browse files
authored
Merge pull request #784 from synonymdev/fix/custom-channels-migration
fix: reconnect custom channel peers after migration
2 parents b57417d + 716cadc commit f250ec2

3 files changed

Lines changed: 61 additions & 0 deletions

File tree

app/src/main/java/to/bitkit/services/MigrationService.kt

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ class MigrationService @Inject constructor(
9292
private const val RN_PENDING_METADATA_KEY = "rnPendingMetadata"
9393
private const val RN_PENDING_TRANSFERS_KEY = "rnPendingTransfers"
9494
private const val RN_PENDING_BOOSTS_KEY = "rnPendingBoosts"
95+
private const val RN_DID_ATTEMPT_PEER_RECOVERY_KEY = "rnDidAttemptMigrationPeerRecovery"
9596
private const val OPENING_CURLY_BRACE = "{"
9697
private const val MMKV_ROOT = "persist:root"
9798
private const val RN_WALLET_NAME = "wallet0"
@@ -1253,6 +1254,44 @@ class MigrationService @Inject constructor(
12531254
Logger.info("RN migration completed, marked for post-migration sync", context = TAG)
12541255
}
12551256

1257+
private suspend fun isRnMigrationCompleted(): Boolean {
1258+
val key = stringPreferencesKey(RN_MIGRATION_COMPLETED_KEY)
1259+
return rnMigrationStore.data.first()[key] == "true"
1260+
}
1261+
1262+
private suspend fun didAttemptPeerRecovery(): Boolean {
1263+
val key = stringPreferencesKey(RN_DID_ATTEMPT_PEER_RECOVERY_KEY)
1264+
return rnMigrationStore.data.first()[key] == "true"
1265+
}
1266+
1267+
private suspend fun setDidAttemptPeerRecovery() {
1268+
val key = stringPreferencesKey(RN_DID_ATTEMPT_PEER_RECOVERY_KEY)
1269+
rnMigrationStore.edit { it[key] = "true" }
1270+
}
1271+
1272+
suspend fun tryFetchMigrationPeersFromBackup(): List<String> {
1273+
if (!isRnMigrationCompleted()) return emptyList()
1274+
if (didAttemptPeerRecovery()) return emptyList()
1275+
1276+
setDidAttemptPeerRecovery()
1277+
1278+
return runCatching {
1279+
val data = rnBackupClient.retrieve("peers", fileGroup = "ldk") ?: return emptyList()
1280+
val peers = json.decodeFromString<List<BackupPeerEntry>>(String(data))
1281+
if (peers.isEmpty()) return emptyList()
1282+
1283+
val trustedIds = Env.trustedLnPeers.map { it.nodeId }.toSet()
1284+
val uris = peers
1285+
.filter { it.pubKey !in trustedIds }
1286+
.map { "${it.pubKey}@${it.address}:${it.port}" }
1287+
1288+
Logger.info("Migration peer recovery: fetched ${uris.size} peer(s) from remote backup", context = TAG)
1289+
uris
1290+
}.onFailure {
1291+
Logger.warn("Migration peer recovery failed (will not retry)", it, context = TAG)
1292+
}.getOrDefault(emptyList())
1293+
}
1294+
12561295
suspend fun cleanupAfterMigration() {
12571296
clearPersistedMigrationData()
12581297
setNeedsPostMigrationSync(false)
@@ -2120,6 +2159,13 @@ data class RNWidgetsWithOptions(
21202159
val widgetOptions: Map<String, ByteArray>,
21212160
)
21222161

2162+
@Serializable
2163+
data class BackupPeerEntry(
2164+
val pubKey: String,
2165+
val address: String,
2166+
val port: UShort,
2167+
)
2168+
21232169
private val Context.rnMigrationDataStore: DataStore<Preferences> by preferencesDataStore("rn_migration")
21242170
private val Context.rnKeychainDataStore: DataStore<Preferences> by preferencesDataStore("RN_KEYCHAIN")
21252171

app/src/main/java/to/bitkit/viewmodels/WalletViewModel.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import org.lightningdevkit.ldknode.PeerDetails
2626
import to.bitkit.R
2727
import to.bitkit.data.SettingsStore
2828
import to.bitkit.di.BgDispatcher
29+
import to.bitkit.ext.of
2930
import to.bitkit.models.Toast
3031
import to.bitkit.repositories.BackupRepo
3132
import to.bitkit.repositories.BlocktankRepo
@@ -291,6 +292,7 @@ class WalletViewModel @Inject constructor(
291292
migrationService.consumePendingChannelMigration()
292293
}
293294
walletRepo.setWalletExistsState()
295+
connectMigrationPeers()
294296
walletRepo.syncBalances()
295297
if (_restoreState.value.isIdle()) {
296298
walletRepo.refreshBip21()
@@ -304,6 +306,18 @@ class WalletViewModel @Inject constructor(
304306
}
305307
}
306308

309+
private suspend fun connectMigrationPeers() {
310+
val peerUris = migrationService.tryFetchMigrationPeersFromBackup()
311+
for (uri in peerUris) {
312+
runCatching {
313+
val peer = PeerDetails.of(uri)
314+
lightningRepo.connectPeer(peer)
315+
}.onFailure {
316+
Logger.error("Failed to connect migration peer: $uri", it, context = TAG)
317+
}
318+
}
319+
}
320+
307321
fun stop() {
308322
if (!walletExists) return
309323

app/src/test/java/to/bitkit/ui/WalletViewModelTest.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class WalletViewModelTest : BaseUnitTest() {
5757
whenever(walletRepo.walletState).thenReturn(walletState)
5858
whenever(lightningRepo.lightningState).thenReturn(lightningState)
5959
whenever(migrationService.isMigrationChecked()).thenReturn(true)
60+
whenever(migrationService.tryFetchMigrationPeersFromBackup()).thenReturn(emptyList())
6061
whenever(connectivityRepo.isOnline).thenReturn(isOnline)
6162

6263
sut = WalletViewModel(

0 commit comments

Comments
 (0)