Skip to content
Merged
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: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ bitcoin-payment-instructions = { version = "0.5.0", default-features = false, fe
"http",
] }
# Branch: https://github.com/moneydevkit/ldk-node/commits/lsp-0.7.0_accept-underpaying-htlcs_with_timing_logs
ldk-node = { default-features = false, git = "https://github.com/moneydevkit/ldk-node.git", rev = "11790803d7da219cb8dd0a03e6ea021ef122d2c4" }
ldk-node = { default-features = false, git = "https://github.com/moneydevkit/ldk-node.git", rev = "4974e8fb7c32486e9eb4b384cbac8ea690518b42" }
#ldk-node = { path = "../ldk-node" }

napi = { version = "2", features = ["napi4"] }
napi-derive = "2"
tokio = { version = "1", features = ["rt-multi-thread"] }
Expand Down
1 change: 1 addition & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export declare class MdkNode {
* snapshot will be updated from the last known sync point.
*/
syncRgs(doFullSync: boolean): number
updateChainTip(): void
receivePayment(minThresholdMs: number, quietThresholdMs: number): Array<ReceivedPayment>
getInvoice(amount: number, description: string, expirySecs: number): PaymentMetadata
/**
Expand Down
35 changes: 24 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,14 @@ impl MdkNode {
})
}

#[napi]
pub fn update_chain_tip(&self) -> napi::Result<()> {
self
.node
.update_chain_tip()
.map_err(|e| napi::Error::from_reason(format!("Failed to update chain tip: {e}")))
}

#[napi]
pub fn receive_payment(
&self,
Expand Down Expand Up @@ -784,21 +792,16 @@ impl MdkNode {

#[napi]
pub fn get_invoice(&self, amount: i64, description: String, expiry_secs: i64) -> PaymentMetadata {
if let Err(err) = self.node.start() {
eprintln!("[lightning-js] Failed to start node for get_invoice: {err}");
panic!("failed to start node for get_invoice: {err}");
}
if let Err(err) = self.node.sync_wallets() {
eprintln!("[lightning-js] Failed to sync wallets: {err}");
panic!("failed to sync wallets: {err}");
// Lightweight chain tip update ensures highest_seen_timestamp is current
// for correct invoice expiry calculation. ~200ms vs seconds for full sync_wallets.
eprintln!("[lightning-js] to update chain tip for get_invoice");
if let Err(err) = self.node.update_chain_tip() {
eprintln!("[lightning-js] Failed to update chain tip for get_invoice: {err}");
// Non-fatal: invoice will still work if timestamp is recent enough (2h buffer)
}
Comment on lines +798 to 801
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Propagate chain-tip update failures before issuing invoices

This code swallows update_chain_tip() failures even though the surrounding comment says the chain tip is needed for correct invoice-expiry calculation; when tip refresh fails after the node has been offline (for example during a temporary chain-source outage), invoice creation can proceed with stale chain time and produce invoices that are already near expiry or invalid for the requested expiry_secs. The previous start()+sync_wallets() flow failed fast in this scenario, so this should return an error (or fall back to a stronger sync) instead of continuing silently.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 2h buffer means it's fine if the node was recently active, but if esplora is down AND the last persisted state is >2h old, we'd silently issue near-expired or invalid invoices. 🤔

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be performed during pings right so it is likely that the state will remain fresh. Maybe we can also leverage that to detect issues here since I think we are using the ping as a healthcheck right? So if the ping syncs are failing we should notify ourselves.


let result = self.get_invoice_impl(Some(amount), description, expiry_secs);

if let Err(err) = self.node.stop() {
eprintln!("[lightning-js] Failed to stop node after get_invoice: {err}");
}

result.unwrap()
}

Expand Down Expand Up @@ -855,6 +858,10 @@ impl MdkNode {
description: String,
expiry_secs: i64,
) -> PaymentMetadata {
if let Err(err) = self.node.update_chain_tip() {
eprintln!("[lightning-js] Failed to update chain tip for get_invoice_with_scid: {err}");
}

let bolt11_invoice_description =
Bolt11InvoiceDescription::Direct(Description::new(description).unwrap());

Expand Down Expand Up @@ -893,6 +900,12 @@ impl MdkNode {
description: String,
expiry_secs: i64,
) -> PaymentMetadata {
if let Err(err) = self.node.update_chain_tip() {
eprintln!(
"[lightning-js] Failed to update chain tip for get_variable_amount_jit_invoice_with_scid: {err}"
);
}

let bolt11_invoice_description =
Bolt11InvoiceDescription::Direct(Description::new(description).unwrap());

Expand Down