Skip to content

Commit

Permalink
fix: spend recovered outputs script checks unconfirmed and confirmed …
Browse files Browse the repository at this point in the history
…broadcasted txs
  • Loading branch information
Jasonvdb committed Aug 16, 2024
1 parent 0f68c43 commit 79c075f
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 34 deletions.
26 changes: 18 additions & 8 deletions lib/android/src/main/java/com/reactnativeldk/LdkModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1228,7 +1228,7 @@ class LdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMod
}

@ReactMethod
fun spendRecoveredForceCloseOutputs(transaction: String, confirmationHeight: Double, changeDestinationScript: String, promise: Promise) {
fun spendRecoveredForceCloseOutputs(transaction: String, confirmationHeight: Double, changeDestinationScript: String, useInner: Boolean, promise: Promise) {
if (channelStoragePath == "") {
return handleReject(promise, LdkErrors.init_storage_path)
}
Expand Down Expand Up @@ -1270,13 +1270,23 @@ class LdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMod
continue
}

val res = keysManager!!.spend_spendable_outputs(
descriptors,
emptyArray(),
changeDestinationScript.hexa(),
feeEstimator.onChainSweep,
Option_u32Z.none()
)
val res = if (useInner) {
keysManager!!.inner.spend_spendable_outputs(
descriptors,
emptyArray(),
changeDestinationScript.hexa(),
feeEstimator.onChainSweep,
Option_u32Z.none()
)
} else {
keysManager!!.spend_spendable_outputs(
descriptors,
emptyArray(),
changeDestinationScript.hexa(),
feeEstimator.onChainSweep,
Option_u32Z.none()
)
}

if (res.is_ok) {
txs.pushHexString((res as Result_TransactionNoneZ.Result_TransactionNoneZ_OK).res)
Expand Down
1 change: 1 addition & 0 deletions lib/ios/Ldk.m
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ @interface RCT_EXTERN_MODULE(Ldk, NSObject)
RCT_EXTERN_METHOD(spendRecoveredForceCloseOutputs:(NSString *)transaction
confirmationHeight:(NSInteger *)confirmationHeight
changeDestinationScript:(NSString *)changeDestinationScript
useInner:(BOOL *)useInner
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject)
RCT_EXTERN_METHOD(nodeSign:(NSString *)message
Expand Down
15 changes: 11 additions & 4 deletions lib/ios/Ldk.swift
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ class Ldk: NSObject {
currentBlockchainHeight = blockHeight
addForegroundObserver()
startDroppedPeerTimer()

return handleResolve(resolve, .channel_manager_init_success)
}

Expand Down Expand Up @@ -659,7 +659,7 @@ class Ldk: NSObject {
guard let self else { return }

LdkEventEmitter.shared.send(withEvent: .native_log, body: "Starting timer to check for dropped peers")

droppedPeerTimer = Timer.scheduledTimer(
timeInterval: 5.0,
target: self,
Expand Down Expand Up @@ -1385,7 +1385,7 @@ class Ldk: NSObject {
}

@objc
func spendRecoveredForceCloseOutputs(_ transaction: NSString, confirmationHeight: NSInteger, changeDestinationScript: NSString, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
func spendRecoveredForceCloseOutputs(_ transaction: NSString, confirmationHeight: NSInteger, changeDestinationScript: NSString, useInner: Bool, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {

guard let channelStoragePath = Ldk.channelStoragePath, let keysManager, let channelManager else {
return handleReject(reject, .init_storage_path)
Expand Down Expand Up @@ -1428,7 +1428,14 @@ class Ldk: NSObject {
continue
}

let res = keysManager.spendSpendableOutputs(
let res = useInner ? keysManager.inner.spendSpendableOutputs(
descriptors: descriptors,
outputs: [],
changeDestinationScript: String(changeDestinationScript).hexaBytes,
feerateSatPer1000Weight: feeEstimator.getEstSatPer1000Weight(confirmationTarget: .OnChainSweep),
locktime: nil)
:
keysManager.spendSpendableOutputs(
descriptors: descriptors,
outputs: [],
changeDestinationScript: String(changeDestinationScript).hexaBytes,
Expand Down
2 changes: 2 additions & 0 deletions lib/src/ldk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1249,12 +1249,14 @@ class LDK {
transaction,
confirmationHeight,
changeDestinationScript,
useInner,
}: TSpendRecoveredForceCloseOutputsReq): Promise<Result<string[]>> {
try {
const res = await NativeLDK.spendRecoveredForceCloseOutputs(
transaction,
confirmationHeight,
changeDestinationScript,
useInner,
);
this.writeDebugToLog('spendRecoveredForceCloseOutputs', res);
return ok(res);
Expand Down
62 changes: 41 additions & 21 deletions lib/src/lightning-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1637,14 +1637,26 @@ class LightningManager {
* Returns previously broadcasted transactions saved in storgare.
* @returns {Promise<TLdkBroadcastedTransactions>}
*/
async getLdkBroadcastedTxs(): Promise<TLdkBroadcastedTransactions> {
async getLdkBroadcastedTxs(
includeConfirmed: boolean = false,
): Promise<TLdkBroadcastedTransactions> {
let txs: TLdkBroadcastedTransactions = [];
const res = await ldk.readFromFile({
fileName: ELdkFiles.broadcasted_transactions,
});
if (res.isOk()) {
return parseData(res.value.content, []);
txs = parseData(res.value.content, []);
}
return [];

if (includeConfirmed) {
const confirmedRes = await ldk.readFromFile({
fileName: ELdkFiles.confirmed_broadcasted_transactions,
});
if (confirmedRes.isOk()) {
txs = txs.concat(parseData(confirmedRes.value.content, []));
}
}
return txs;
}

async cleanupBroadcastedTxs(): Promise<void> {
Expand Down Expand Up @@ -1766,33 +1778,41 @@ class LightningManager {
return err('Unable to retrieve change_destination_script.');
}

const txs = await this.getLdkBroadcastedTxs();
const txs = await this.getLdkBroadcastedTxs(true);
if (!txs.length) {
return ok('No outputs to reconstruct as no cached transactions found.');
}

let txsToBroadcast = 0;
for (const hexTx of txs) {
const tx = bitcoin.Transaction.fromHex(hexTx);
const txData = await this.getTransactionData(tx.getId());

const txsRes = await ldk.spendRecoveredForceCloseOutputs({
transaction: hexTx,
confirmationHeight: txData?.height ?? 0,
changeDestinationScript,
});
const processTxs = async (useInner: boolean): Promise<void> => {
for (const hexTx of txs) {
const tx = bitcoin.Transaction.fromHex(hexTx);
const txData = await this.getTransactionData(tx.getId());

if (txsRes.isErr()) {
await ldk.writeToLogFile('error', txsRes.error.message);
console.error(txsRes.error.message);
continue;
}
const txsRes = await ldk.spendRecoveredForceCloseOutputs({
transaction: hexTx,
confirmationHeight: txData?.height ?? 0,
changeDestinationScript,
useInner,
});

if (txsRes.isErr()) {
await ldk.writeToLogFile('error', txsRes.error.message);
console.error(txsRes.error.message);
continue;
}

for (const createdTx of txsRes.value) {
txsToBroadcast++;
await this.broadcastTransaction(createdTx);
for (const createdTx of txsRes.value) {
txsToBroadcast++;
await this.broadcastTransaction(createdTx);
}
}
}
};

//Process first using the inner (ldk keychain) and then using the custom keychain
await processTxs(true);
await processTxs(false);

return ok(`Attempting to reconstruct ${txsToBroadcast} transactions.`);
}
Expand Down
3 changes: 2 additions & 1 deletion lib/src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ export type TChannel = {
balance_sat: number;
counterparty_node_id: string;
funding_txid?: string;
funding_output_index? : number;
funding_output_index?: number;
channel_type?: string;
user_channel_id: string;
confirmations_required?: number;
Expand Down Expand Up @@ -613,6 +613,7 @@ export type TSpendRecoveredForceCloseOutputsReq = {
transaction: string;
confirmationHeight: number;
changeDestinationScript: string;
useInner: boolean;
};

export type TBackupServerDetails = {
Expand Down

0 comments on commit 79c075f

Please sign in to comment.