Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(lightning): Attempt Restart In syncLdk #170

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ PODS:
- React-jsinspector (0.70.6)
- React-logger (0.70.6):
- glog
- react-native-ldk (0.0.109):
- react-native-ldk (0.0.110):
- React
- react-native-randombytes (3.6.1):
- React-Core
Expand Down Expand Up @@ -593,7 +593,7 @@ SPEC CHECKSUMS:
React-jsiexecutor: b4a65947391c658450151275aa406f2b8263178f
React-jsinspector: 60769e5a0a6d4b32294a2456077f59d0266f9a8b
React-logger: 1623c216abaa88974afce404dc8f479406bbc3a0
react-native-ldk: 3c1cd457a2372ef3eda9fbe144f4cdf6bc1fd6c3
react-native-ldk: a69156c3ff99495ef8fb518b4c873418608fc7c1
react-native-randombytes: 421f1c7d48c0af8dbcd471b0324393ebf8fe7846
react-native-tcp-socket: c1b7297619616b4c9caae6889bcb0aba78086989
React-perflogger: 8c79399b0500a30ee8152d0f9f11beae7fc36595
Expand Down
2 changes: 1 addition & 1 deletion lib/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@synonymdev/react-native-ldk",
"title": "React Native LDK",
"version": "0.0.109",
"version": "0.0.110",
"description": "React Native wrapper for LDK",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
Expand Down
106 changes: 91 additions & 15 deletions lib/src/lightning-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -474,20 +474,46 @@ class LightningManager {
/**
* Fetches current best block and sends to LDK to update both channelManager and chainMonitor.
* Also watches transactions and outputs for confirmed and unconfirmed transactions and updates LDK.
* @param {number} [timeout] Timeout to set for each async function in this method. Potential overall timeout may be greater.
* @param {boolean} [attemptRestart] Will attempt to restart LDK if an error or timeout occurs.
* @returns {Promise<Result<string>>}
*/
async syncLdk(): Promise<Result<string>> {
async syncLdk({
timeout = 15000,
attemptRestart = true,
}: {
timeout?: number;
attemptRestart?: boolean;
} = {}): Promise<Result<string>> {
// Check that the getBestBlock method has been provided.
if (!this.getBestBlock) {
return err('No getBestBlock method provided.');
}
const bestBlock = await this.getBestBlock();
const height = bestBlock?.height;
const bestBlock = await promiseTimeout<THeader>(
timeout,
this.getBestBlock(),
);
if (!bestBlock?.height) {
if (attemptRestart) {
return await this.attemptRestart();
} else {
return err('Unable to get best block in syncLdk method.');
}
}
const height = bestBlock.height;

//Don't update unnecessarily
if (this.currentBlock.hash !== bestBlock?.hash) {
const syncToTip = await ldk.syncToTip(bestBlock);
const syncToTip = await promiseTimeout<Result<string>>(
timeout,
ldk.syncToTip(bestBlock),
);
if (syncToTip.isErr()) {
return syncToTip;
if (attemptRestart) {
return await this.attemptRestart();
} else {
return syncToTip;
}
}

this.currentBlock = bestBlock;
Expand All @@ -496,29 +522,76 @@ class LightningManager {
let channels: TChannel[] = [];
if (this.watchTxs.length > 0) {
// Get fresh array of channels.
const listChannelsResponse = await ldk.listChannels();
const listChannelsResponse = await promiseTimeout<Result<TChannel[]>>(
timeout,
ldk.listChannels(),
);
if (listChannelsResponse.isOk()) {
channels = listChannelsResponse.value;
}
}

// Iterate over watch transactions/outputs and set whether they are confirmed or unconfirmed.
await this.checkWatchTxs(this.watchTxs, channels, bestBlock);
await this.checkWatchOutputs(this.watchOutputs);
await this.checkUnconfirmedTransactions();
const r1 = await promiseTimeout<Result<string>>(
timeout,
this.checkWatchTxs(this.watchTxs, channels, bestBlock),
);
if (r1.isErr()) {
if (attemptRestart) {
return await this.attemptRestart();
} else {
return r1;
}
}
const r2 = await promiseTimeout<Result<string>>(
timeout,
this.checkWatchOutputs(this.watchOutputs),
);
if (r2.isErr()) {
if (attemptRestart) {
return await this.attemptRestart();
} else {
return r2;
}
}
const r3 = await promiseTimeout<Result<string>>(
timeout,
this.checkUnconfirmedTransactions(),
);
if (r3.isErr()) {
if (attemptRestart) {
return await this.attemptRestart();
} else {
return r3;
}
}

return ok(`Synced to block ${height}`);
}

/**
* Attempts to Restart and Sync LDK
* @param {number} [timeout]
* @returns {Promise<Result<string>>}
*/
attemptRestart = async (timeout = 15000): Promise<Result<string>> => {
const r = await promiseTimeout<Result<string>>(timeout, ldk.restart());
if (r.isErr()) {
return r;
}
return await this.syncLdk({
attemptRestart: false,
});
};

checkWatchTxs = async (
watchTxs: TRegisterTxEvent[],
channels: TChannel[],
bestBlock: THeader,
): Promise<void> => {
): Promise<Result<string>> => {
const height = bestBlock?.height;
if (!height) {
console.log('No height provided');
return;
return err('No height provided');
}
await Promise.all(
watchTxs.map(async (watchTxData) => {
Expand All @@ -533,7 +606,7 @@ class LightningManager {
//Watch TX was never confirmed so there's no need to unconfirm it.
return;
}
if (!txData.transaction) {
if (!txData?.transaction) {
console.log(
'Unable to retrieve transaction data from the getTransactionData method.',
);
Expand Down Expand Up @@ -564,11 +637,12 @@ class LightningManager {
}
}),
);
return ok('Watch transactions checked');
};

checkWatchOutputs = async (
watchOutputs: TRegisterOutputEvent[],
): Promise<void> => {
): Promise<Result<string>> => {
await Promise.all(
watchOutputs.map(async ({ index, script_pubkey }) => {
const transactions = await this.getScriptPubKeyHistory(script_pubkey);
Expand Down Expand Up @@ -630,6 +704,7 @@ class LightningManager {
);
}),
);
return ok('Watch outputs checked');
};

/**
Expand Down Expand Up @@ -1127,7 +1202,7 @@ class LightningManager {
}
};

checkUnconfirmedTransactions = async (): Promise<void> => {
checkUnconfirmedTransactions = async (): Promise<Result<string>> => {
let needsToSync = false;
let newUnconfirmedTxs: TLdkUnconfirmedTransactions = [];
await Promise.all(
Expand Down Expand Up @@ -1171,6 +1246,7 @@ class LightningManager {
if (needsToSync) {
await this.syncLdk();
}
return ok('Unconfirmed transactions checked');
};

/**
Expand Down