Skip to content

Commit

Permalink
Merge pull request #214 from synonymdev/force-close-fix
Browse files Browse the repository at this point in the history
Force close fix
  • Loading branch information
Jasonvdb authored Feb 23, 2024
2 parents b5a382c + 1bd22d2 commit da47bd8
Show file tree
Hide file tree
Showing 8 changed files with 16 additions and 188 deletions.
2 changes: 1 addition & 1 deletion example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -753,4 +753,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: 940323d07de591a59a2ab39fc0ef7b7d6dc89c0d

COCOAPODS: 1.14.3
COCOAPODS: 1.15.2
20 changes: 2 additions & 18 deletions lib/android/src/main/java/com/reactnativeldk/LdkModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ enum class LdkFileNames(val fileName: String) {
Scorer("scorer.bin"),
PaymentsClaimed("payments_claimed.json"),
PaymentsSent("payments_sent.json"),
ChannelOpenedWithCustomKeysManager("channel_opened_with_custom_keys_manager.json"),
}

class LdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
Expand Down Expand Up @@ -502,23 +501,6 @@ class LdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMod
currentBlockchainHeight = blockHeight

handleResolve(promise, LdkCallbackResponses.channel_manager_init_success)

//TODO remove after a few updates
//Temp function as original file was named incorrectly and doesn't match ios or backup server
//*******************************
if (accountStoragePath != "") {
val wrongName = "channels_opened_with_custom_keys_manager.json"
val correctName = LdkFileNames.ChannelOpenedWithCustomKeysManager.fileName
try {
if (File(accountStoragePath + "/" + wrongName).exists()) {
File(accountStoragePath + "/" + wrongName).renameTo(File(accountStoragePath + "/" + correctName))
BackupClient.addToPersistQueue(BackupClient.Label.MISC(correctName), File(accountStoragePath + "/" + correctName).readBytes())
}
} catch (e: Exception) {
LdkEventEmitter.send(EventTypes.native_log, "Error could not rename channel list file")
}
}
//*******************************
}
@ReactMethod
fun restart(promise: Promise) {
Expand Down Expand Up @@ -737,6 +719,8 @@ class LdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMod
)
}

LdkEventEmitter.send(EventTypes.native_log, "Spending ${ldkOutputs.count()} outputs")

val res = keysManager!!.spend_spendable_outputs(
ldkDescriptors.toTypedArray(),
ldkOutputs.toTypedArray(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.reactnativeldk.classes

import com.reactnativeldk.EventTypes
import com.reactnativeldk.LdkEventEmitter
import org.ldk.structs.KeysManager
import org.ldk.structs.Option_u32Z
import org.ldk.structs.Result_CVec_u8ZNoneZ
Expand Down Expand Up @@ -42,6 +44,8 @@ class CustomKeysManager(
it as? SpendableOutputDescriptor.StaticOutput == null
}.toTypedArray()

LdkEventEmitter.send(EventTypes.native_log, "Spending ${onlyNonStatic.count()} non static outputs")

return inner.spend_spendable_outputs(
onlyNonStatic,
outputs,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,6 @@ class LdkChannelManagerPersister: ChannelManagerConstructor.EventHandler {
}

(event as? Event.SpendableOutputs)?.let { spendableOutputs ->
if (channelWasOpenedWithNewCustomKeysManager((spendableOutputs.channel_id as Option_ThirtyTwoBytesZ.Some).some)) {
return
}

val body = Arguments.createMap()
val outputs = Arguments.createArray()
spendableOutputs.outputs.iterator().forEach {
Expand Down Expand Up @@ -190,11 +186,9 @@ class LdkChannelManagerPersister: ChannelManagerConstructor.EventHandler {
}

(event as? Event.ChannelReady)?.let { channelReady ->
persistChannelOpenedWithNewCustomKeysManager(channelReady.channel_id)
}

(event as? Event.ChannelPending)?.let { channelPending ->
persistChannelOpenedWithNewCustomKeysManager(channelPending.channel_id)
}
}

Expand Down Expand Up @@ -315,58 +309,4 @@ class LdkChannelManagerPersister: ChannelManagerConstructor.EventHandler {
BackupClient.addToPersistQueue(BackupClient.Label.MISC(LdkFileNames.PaymentsSent.fileName), JSONArray(payments).toString().toByteArray())
File(LdkModule.accountStoragePath + "/" + LdkFileNames.PaymentsSent.fileName).writeText(JSONArray(payments).toString())
}

// If a channel was opened with the new custom keys manager then spendable outputs from a channel close will already be spendable by the on chain wallet and there is no need to sweep.
// TODO remove all these checks at some point in the future once certain all old channels opened prior to this update have been long closed.
private fun persistChannelOpenedWithNewCustomKeysManager(channelId: ByteArray) {
if (LdkModule.accountStoragePath == "") {
LdkEventEmitter.send(EventTypes.native_log, "Error. Failed to persist channel opened with new custom keys manager to disk (No set storage)")
return
}

val id = channelId.hexEncodedString()
val existingIds = ArrayList<String>()
try {
if (File(LdkModule.accountStoragePath + "/" + LdkFileNames.ChannelOpenedWithCustomKeysManager.fileName).exists()) {
val data = File(LdkModule.accountStoragePath + "/" + LdkFileNames.ChannelOpenedWithCustomKeysManager.fileName).readBytes()
val existingIdsArray = JSONArray(String(data))
for (i in 0 until existingIdsArray.length()) {
existingIds.add(existingIdsArray.getString(i))
}
}

if (!existingIds.contains(id)) {
existingIds.add(id)

File(LdkModule.accountStoragePath + "/" + LdkFileNames.ChannelOpenedWithCustomKeysManager.fileName).writeText(JSONArray(existingIds).toString())

BackupClient.addToPersistQueue(BackupClient.Label.MISC(LdkFileNames.ChannelOpenedWithCustomKeysManager.fileName), JSONArray(existingIds).toString().toByteArray())
}
} catch (e: Exception) {
LdkEventEmitter.send(EventTypes.native_log, "Error could not read existing ChannelOpenedWithNewCustomKeysManager")
}
}

private fun channelWasOpenedWithNewCustomKeysManager(channelId: ByteArray): Boolean {
if (LdkModule.accountStoragePath == "") {
LdkEventEmitter.send(EventTypes.native_log, "Error. Failed to check if channel was opened with new custom keys manager (No set storage)")
return false
}

val id = channelId.hexEncodedString()
val existingIds = ArrayList<String>()
try {
if (File(LdkModule.accountStoragePath + "/" + LdkFileNames.ChannelOpenedWithCustomKeysManager.fileName).exists()) {
val data = File(LdkModule.accountStoragePath + "/" + LdkFileNames.ChannelOpenedWithCustomKeysManager.fileName).readBytes()
val existingIdsArray = JSONArray(String(data))
for (i in 0 until existingIdsArray.length()) {
existingIds.add(existingIdsArray.getString(i))
}
}
} catch (e: Exception) {
LdkEventEmitter.send(EventTypes.native_log, "Error could not read existing ChannelOpenedWithNewCustomKeysManager")
}

return existingIds.contains(id)
}
}
5 changes: 4 additions & 1 deletion lib/ios/Classes/CustomKeysManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,15 @@ class CustomKeysManager {
func spendSpendableOutputs(descriptors: [SpendableOutputDescriptor], outputs: [Bindings.TxOut], changeDestinationScript: [UInt8], feerateSatPer1000Weight: UInt32, locktime: UInt32?) -> Result_TransactionNoneZ {
let onlyNonStatic: [SpendableOutputDescriptor] = descriptors.filter { desc in
if desc.getValueType() == .StaticOutput {
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Skipping static output: \(Data(desc.getValueAsStaticOutput()?.getOutput().getScriptPubkey() ?? []).hexEncodedString())")
return false
}

return true
}


LdkEventEmitter.shared.send(withEvent: .native_log, body: "Spending \(onlyNonStatic.count) non static outputs")

let res = self.inner.spendSpendableOutputs(
descriptors: onlyNonStatic,
outputs: outputs,
Expand Down
92 changes: 2 additions & 90 deletions lib/ios/Classes/LdkChannelManagerPersister.swift
Original file line number Diff line number Diff line change
Expand Up @@ -195,15 +195,6 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
return handleEventError(event)
}

if let channelId = spendableOutputs.getChannelId() {
// Ensure channel was NOT opened with custom destination script. For existing channels (prior custom keys manager) we have to still sweep the output back to onchain wallet.
// This check and channel_manager_spendable_outputs event can probably be removed in the future.
guard !channelWasOpenedWithNewCustomKeysManager(channelId: channelId) else {
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Skipping event channel_manager_spendable_outputs as channel (\(Data(channelId).hexEncodedString()) was opened with new custom keys manager")
return
}
}

LdkEventEmitter.shared.send(
withEvent: .channel_manager_spendable_outputs,
body: [
Expand Down Expand Up @@ -293,18 +284,10 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
persistPaymentClaimed(body)
return
case .ChannelReady:
guard let readyChannel = event.getValueAsChannelReady() else {
return handleEventError(event)
}

persistChannelOpenedWithNewCustomKeysManager(channelId: readyChannel.getChannelId())
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Unused Persister event: ChannelReady")
return
case .ChannelPending:
guard let pendingChannel = event.getValueAsChannelPending() else {
return handleEventError(event)
}

persistChannelOpenedWithNewCustomKeysManager(channelId: pendingChannel.getChannelId())
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Unused Persister event: ChannelPending")
return
case .BumpTransaction:
guard let bumpTransaction = event.getValueAsBumpTransaction() else {
Expand Down Expand Up @@ -496,75 +479,4 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error writing payment sent to file: \(error)")
}
}


/// If a channel was opened with the new custom keys manager then spendable outputs from a channel close will already be spendable by the on chain wallet and there is no need to sweep.
/// TODO remove all these checks at some point in the future once certain all old channels opened prior to this update have been long closed.
/// - Parameter channelId: channel ID
func persistChannelOpenedWithNewCustomKeysManager(channelId: [UInt8]) {
guard let channelIdStorage = Ldk.accountStoragePath?.appendingPathComponent(LdkFileNames.channel_opened_with_custom_keys_manager.rawValue) else {
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error. Failed to persist ChannelOpenedWithNewCustomKeysManager")
return
}

let id = Data(channelId).hexEncodedString()
var existingIds: [String] = []
do {
if FileManager.default.fileExists(atPath: channelIdStorage.path) {
let data = try Data(contentsOf: URL(fileURLWithPath: channelIdStorage.path), options: .mappedIfSafe)

if let existingContent = try JSONSerialization.jsonObject(with: data, options: []) as? [String] {
existingIds = existingContent
} else {
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error could not read existing ChannelOpenedWithNewCustomKeysManager")
}
}


if !existingIds.contains(id) {
existingIds.append(id)

guard let jsonData = try? JSONSerialization.data(withJSONObject: existingIds, options: []) else {
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error could not serialize sent payments")
return
}

guard let jsonString = String(data: jsonData, encoding: .utf8) else {
return
}

try jsonString.write(to: channelIdStorage, atomically: true, encoding: .utf8)

BackupClient.addToPersistQueue(.misc(fileName: LdkFileNames.channel_opened_with_custom_keys_manager.rawValue), [UInt8](jsonData))
}
} catch {
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error could not read existing ChannelOpenedWithNewCustomKeysManager")
}
}

func channelWasOpenedWithNewCustomKeysManager(channelId: [UInt8]) -> Bool {
guard let channelIdStorage = Ldk.accountStoragePath?.appendingPathComponent(LdkFileNames.channel_opened_with_custom_keys_manager.rawValue) else {
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error. Failed to persist ChannelOpenedWithNewCustomKeysManager")
return false
}

let id = Data(channelId).hexEncodedString()
var existingIds: [String] = []

do {
if FileManager.default.fileExists(atPath: channelIdStorage.path) {
let data = try Data(contentsOf: URL(fileURLWithPath: channelIdStorage.path), options: .mappedIfSafe)

if let existingContent = try JSONSerialization.jsonObject(with: data, options: []) as? [String] {
existingIds = existingContent
} else {
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error could not read existing ChannelOpenedWithNewCustomKeysManager")
}
}
} catch {
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error could not read existing ChannelOpenedWithNewCustomKeysManager")
}

return existingIds.contains(id)
}
}
18 changes: 3 additions & 15 deletions lib/ios/Ldk.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ enum LdkFileNames: String, CaseIterable {
case scorer = "scorer.bin"
case payments_claimed = "payments_claimed.json"
case payments_sent = "payments_sent.json"
case channel_opened_with_custom_keys_manager = "channel_opened_with_custom_keys_manager.json"
}

@objc(Ldk)
Expand Down Expand Up @@ -496,19 +495,6 @@ class Ldk: NSObject {
currentBlockchainTipHash = blockHash
currentBlockchainHeight = blockHeight
addForegroundObserver()

//TODO temp update to make sure file that wasn't being backuped up now is at least once. Can be removed in a few updates.
//*******************************
Task {
if let channelsOpenedWithCustomKeysManagerFile = Ldk.accountStoragePath?.appendingPathComponent(LdkFileNames.channel_opened_with_custom_keys_manager.rawValue) {
if FileManager.default.fileExists(atPath: channelsOpenedWithCustomKeysManagerFile.path) {
if let data = try? Data(contentsOf: URL(fileURLWithPath: channelsOpenedWithCustomKeysManagerFile.path), options: .mappedIfSafe) {
BackupClient.addToPersistQueue(.misc(fileName: LdkFileNames.channel_opened_with_custom_keys_manager.rawValue), [UInt8](data))
}
}
}
}
//*******************************

return handleResolve(resolve, .channel_manager_init_success)
}
Expand Down Expand Up @@ -811,7 +797,9 @@ class Ldk: NSObject {
ldkOutputs.append(TxOut(scriptPubkey: (d["script_pubkey"] as! String).hexaBytes, value: d["value"] as! UInt64))
}

let res = keysManager.inner.spendSpendableOutputs(
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Spending \(ldkOutputs.count) output/s")

let res = keysManager.spendSpendableOutputs(
descriptors: ldkDescriptors,
outputs: ldkOutputs,
changeDestinationScript: String(changeDestinationScript).hexaBytes,
Expand Down
3 changes: 0 additions & 3 deletions lib/src/lightning-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1837,9 +1837,6 @@ class LightningManager {
private async onChannelManagerSpendableOutputs(
res: TChannelManagerSpendableOutputs,
): Promise<void> {
console.warn(
'onChannelManagerSpendableOutputs deprecated. You should only be seeing this if recently closed channel was opened prior to custom keys manager.',
);
const spendableOutputs = await this.getLdkSpendableOutputs();
res.outputsSerialized.forEach((o) => {
if (!spendableOutputs.includes(o)) {
Expand Down

0 comments on commit da47bd8

Please sign in to comment.