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): Limit lm.start Calls #182

Merged
merged 1 commit into from
Oct 17, 2023
Merged
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
79 changes: 65 additions & 14 deletions lib/src/lightning-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@
private forceSync: boolean = false;
private pendingSyncPromises: Array<(result: Result<string>) => void> = [];

private isStarting: boolean = false;
private pendingStartPromises: Array<(result: Result<string>) => void> = [];
private previousAccountName: string = '';

constructor() {
// Step 0: Subscribe to all events
ldk.onEvent(EEventTypes.native_log, (line) => {
Expand Down Expand Up @@ -236,6 +240,33 @@
return ok('Storage set');
}

/**
* Resolves all pending start promises with the provided result.
* @private
* @param {Result<string>} result
* @returns {void}
*/
private resolveAllPendingStartPromises(result: Result<string>): void {
while (this.pendingStartPromises.length > 0) {
const resolve = this.pendingStartPromises.shift();
if (resolve) {
resolve(result);
}
}
}

/**
* Sets isStarting to false, resolves all start promises and returns error.
* @private
* @param {Err<string>} e
* @returns {Promise<Result<string>>}
*/
private handleStartError = (e: Err<string>): Result<string> => {
this.isStarting = false;
this.resolveAllPendingStartPromises(e);
return e;
};

/**
* Spins up and syncs all processes
* @param {string} seed
Expand Down Expand Up @@ -281,6 +312,19 @@
return err('getTransactionPosition is not set in start method.');
}

// Retry start method if presented with a new account name.
if (this.previousAccountName !== account.name) {
this.isStarting = false;
this.previousAccountName = account.name;
}

if (this.isStarting) {
return new Promise<Result<string>>((resolve) => {
this.pendingStartPromises.push(resolve);
});
}
this.isStarting = true;

// Ensure the start params function as expected.
const paramCheckResponse = await startParamCheck({
account,
Expand All @@ -294,7 +338,7 @@
network,
});
if (paramCheckResponse.isErr()) {
return err(paramCheckResponse.error.message);
return this.handleStartError(paramCheckResponse);
}

this.getBestBlock = getBestBlock;
Expand All @@ -313,14 +357,16 @@
this.trustedZeroConfPeers = trustedZeroConfPeers;

if (!this.baseStoragePath) {
return err(
'baseStoragePath required for wallet persistence. Call setBaseStoragePath(path) first.',
return this.handleStartError(
err(
'baseStoragePath required for wallet persistence. Call setBaseStoragePath(path) first.',
),
);
}

const storageSetRes = await this.setStorage(account);
if (storageSetRes.isErr()) {
return err(storageSetRes.error);
return this.handleStartError(storageSetRes);
}

//Validate we didn't change the seed for this account if one exists
Expand All @@ -338,15 +384,17 @@
remotePersist: false,
});
if (writeRes.isErr()) {
return err(writeRes.error);
return this.handleStartError(err(writeRes.error));
}
} else {
return err(readSeed.error);
return this.handleStartError(err(readSeed.error));
}
} else {
//Cannot start an existing node with a different seed
if (readSeed.value.content !== account.seed) {
return err('Seed for current node cannot be changed.');
return this.handleStartError(
err('Seed for current node cannot be changed.'),
);
}
}

Expand All @@ -358,7 +406,7 @@
details: backupServerDetails,
});
if (backupSetupRes.isErr()) {
return err(backupSetupRes.error);
return this.handleStartError(err(backupSetupRes.error));
}
}

Expand Down Expand Up @@ -390,13 +438,13 @@
// Step 5: Initialize the ChainMonitor
const chainMonitorRes = await ldk.initChainMonitor();
if (chainMonitorRes.isErr()) {
return chainMonitorRes;
return this.handleStartError(chainMonitorRes);
}

// Step 6: Initialize the KeysManager
const keysManager = await ldk.initKeysManager(this.account.seed);
if (keysManager.isErr()) {
return keysManager;
return this.handleStartError(keysManager);
}

// Step 7: Read ChannelMonitors state from disk
Expand All @@ -413,22 +461,22 @@
rapidGossipSyncUrl,
});
if (networkGraphRes.isErr()) {
return networkGraphRes;
return this.handleStartError(networkGraphRes);
}

// Step 8: Initialize the UserConfig ChannelManager
const confRes = await ldk.initUserConfig(userConfig);

if (confRes.isErr()) {
return confRes;
return this.handleStartError(confRes);
}

const channelManagerRes = await ldk.initChannelManager({
network: this.network,
bestBlock,
});
if (channelManagerRes.isErr()) {
return channelManagerRes;
return this.handleStartError(channelManagerRes);
}

// Attempt to abandon any stored payment ids.
Expand Down Expand Up @@ -468,7 +516,10 @@
//Writes node state to log files
ldk.nodeStateDump().catch(console.error);

return ok('Node running');
this.isStarting = false;
const result = ok('Node started');
this.resolveAllPendingStartPromises(result);
return result;
}

async setStorage(account: TAccount): Promise<Result<string>> {
Expand Down Expand Up @@ -1961,7 +2012,7 @@
}

private onChannelManagerPendingHtlcsForwardable(
res: TChannelManagerPendingHtlcsForwardable,

Check warning on line 2015 in lib/src/lightning-manager.ts

View workflow job for this annotation

GitHub Actions / Run lint check

'res' is defined but never used. Allowed unused args must match /^_/u
): void {
ldk.processPendingHtlcForwards().catch(console.error);
}
Expand Down
Loading