From ce7e890913ae60c9b2923b7f85e72459c78f1714 Mon Sep 17 00:00:00 2001 From: Philipp Walter Date: Tue, 28 Oct 2025 14:04:35 +0100 Subject: [PATCH] Revert "fix: prevent channel monitor loss when remote backup fails" --- .../reactnativeldk/classes/LdkPersister.kt | 38 +++++++------ lib/ios/Classes/LdkPersist.swift | 53 +++++++++++-------- lib/package.json | 2 +- 3 files changed, 54 insertions(+), 39 deletions(-) diff --git a/lib/android/src/main/java/com/reactnativeldk/classes/LdkPersister.kt b/lib/android/src/main/java/com/reactnativeldk/classes/LdkPersister.kt index d0c13b1d..687febd9 100644 --- a/lib/android/src/main/java/com/reactnativeldk/classes/LdkPersister.kt +++ b/lib/android/src/main/java/com/reactnativeldk/classes/LdkPersister.kt @@ -23,12 +23,29 @@ class LdkPersister { val isNew = !file.exists() - // Always write locally first - val serialized = data.write() - file.writeBytes(serialized) + if (BackupClient.skipRemoteBackup) { + file.writeBytes(data.write()) + if (isNew) { + LdkEventEmitter.send(EventTypes.new_channel, body) + } + return ChannelMonitorUpdateStatus.LDKChannelMonitorUpdateStatus_Completed + } + + BackupClient.addToPersistQueue(BackupClient.Label.CHANNEL_MONITOR(channelId=channelId), data.write()) { error -> + if (error != null) { + LdkEventEmitter.send(EventTypes.native_log, "Failed to persist channel (${channelId}) to remote backup: $error") + return@addToPersistQueue + } + + try { + file.writeBytes(data.write()) + } catch (e: Exception) { + //If this fails we can't do much but LDK will retry on startup + LdkEventEmitter.send(EventTypes.native_log, "Failed to locally persist channel (${channelId}) to disk") + return@addToPersistQueue + } - // Update chain monitor on main thread to avoid threading issues - LdkModule.reactContext?.runOnUiThread { + //Update chain monitor with successful persist val res = LdkModule.chainMonitor?.channel_monitor_updated(channelFundingOutpoint, data._latest_update_id) if (res == null || !res.is_ok) { LdkEventEmitter.send(EventTypes.native_log, "Failed to update chain monitor with persisted channel (${channelId})") @@ -40,16 +57,7 @@ class LdkPersister { } } - // Kick off remote backup asynchronously; never block/skip local persist - if (!BackupClient.skipRemoteBackup) { - BackupClient.addToPersistQueue(BackupClient.Label.CHANNEL_MONITOR(channelId=channelId), serialized) { error -> - if (error != null) { - LdkEventEmitter.send(EventTypes.native_log, "Failed to persist channel (${channelId}) to remote backup: $error") - } - } - } - - return ChannelMonitorUpdateStatus.LDKChannelMonitorUpdateStatus_Completed + return ChannelMonitorUpdateStatus.LDKChannelMonitorUpdateStatus_InProgress } catch (e: Exception) { return ChannelMonitorUpdateStatus.LDKChannelMonitorUpdateStatus_UnrecoverableError } diff --git a/lib/ios/Classes/LdkPersist.swift b/lib/ios/Classes/LdkPersist.swift index 371be000..40c0b542 100644 --- a/lib/ios/Classes/LdkPersist.swift +++ b/lib/ios/Classes/LdkPersist.swift @@ -27,17 +27,33 @@ class LdkPersister: Persist { } let isNew = !FileManager().fileExists(atPath: channelStoragePath.path) - - // Always write locally first - let serialized = Data(data.write()) - try serialized.write(to: channelStoragePath) - - // Notify chain monitor on main thread to avoid threading issues - DispatchQueue.main.async { - let res = Ldk.chainMonitor?.channelMonitorUpdated( - fundingTxo: channelFundingOutpoint, - completedUpdateId: data.getLatestUpdateId() - ) + + // If we're not remotely backing up no need to update status later + if BackupClient.skipRemoteBackup { + try Data(data.write()).write(to: channelStoragePath) + if isNew { + LdkEventEmitter.shared.send(withEvent: .new_channel, body: body) + } + return ChannelMonitorUpdateStatus.Completed + } + + BackupClient.addToPersistQueue(.channelMonitor(id: channelIdHex), data.write()) { error in + if let error { + LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error. Failed persist channel on remote server (\(channelIdHex)). \(error.localizedDescription)") + return + } + + // Callback for when the persist queue queue entry is processed + do { + try Data(data.write()).write(to: channelStoragePath) + } catch { + // If this fails we can't do much but LDK will retry on startup + LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error. Failed to locally persist channel (\(channelIdHex)). \(error.localizedDescription)") + return + } + + // Update chainmonitor with successful persist + let res = Ldk.chainMonitor?.channelMonitorUpdated(fundingTxo: channelFundingOutpoint, completedUpdateId: data.getLatestUpdateId()) if let error = res?.getError() { LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error. Failed to update chain monitor for channel (\(channelIdHex)) Error \(error.getValueType()).") } else { @@ -47,19 +63,10 @@ class LdkPersister: Persist { } } } - - // Kick off remote backup asynchronously; log but never block/skip local persist - if !BackupClient.skipRemoteBackup { - BackupClient.addToPersistQueue(.channelMonitor(id: channelIdHex), [UInt8](serialized)) { error in - if let error { - LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error. Failed persist channel on remote server (\(channelIdHex)). \(error.localizedDescription)") - } - } - } - - return ChannelMonitorUpdateStatus.Completed + + return ChannelMonitorUpdateStatus.InProgress } catch { - LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error. Failed to locally persist channel (\(channelIdHex)). \(error.localizedDescription)") + LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error. Failed to persist channel (\(channelIdHex)) to disk Error \(error.localizedDescription).") return ChannelMonitorUpdateStatus.UnrecoverableError } } diff --git a/lib/package.json b/lib/package.json index 8bf4b949..fed8f707 100644 --- a/lib/package.json +++ b/lib/package.json @@ -1,7 +1,7 @@ { "name": "@synonymdev/react-native-ldk", "title": "React Native LDK", - "version": "0.0.161", + "version": "0.0.160", "description": "React Native wrapper for LDK", "main": "./dist/index.js", "types": "./dist/index.d.ts",