From eb832348a6c0ba94b2ebcdc139ed9022b67a62ca Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 8 Jan 2026 21:08:56 +0100 Subject: [PATCH 1/3] Fix backwards compatibility of `NodeMetrics` reads In commit dd55d4758d8ea0b71312de574fd42fa25fc5f5d0 we started ignoring the legacy `latest_channel_monitor_archival_height` field of `NodeMetrics`. However, we erroneously started reading it as `Option`, though, given it's an optional field, it should have been read as a plain `u32` that might or might not be present. Here we fix this error. --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index d9bca4551..1b19864dd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1837,7 +1837,7 @@ impl_writeable_tlv_based!(NodeMetrics, { (6, latest_rgs_snapshot_timestamp, option), (8, latest_node_announcement_broadcast_timestamp, option), // 10 used to be latest_channel_monitor_archival_height - (10, _legacy_latest_channel_monitor_archival_height, (legacy, Option, |_: &NodeMetrics| None::> )), + (10, _legacy_latest_channel_monitor_archival_height, (legacy, u32, |_: &NodeMetrics| None::> )), }); pub(crate) fn total_anchor_channels_reserve_sats( From 06a8108aff12196210728b0078453641a9aa85aa Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 8 Jan 2026 21:16:18 +0100 Subject: [PATCH 2/3] Add backwards compatibility test for non-VSS We previously added a test asserting backwards compatibility for nodes reinitializing from a VSS backend. However, given VSS tests are only continously run in CI we here add the same test using the default SQLite backend, ensuring backwards compatibility breakage is also checked when running tests locally. --- Cargo.toml | 4 +-- tests/integration_tests_rust.rs | 59 +++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cc2a4b194..4f8c0ed7b 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -88,6 +88,7 @@ lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = " proptest = "1.0.0" regex = "1.5.6" criterion = { version = "0.7.0", features = ["async_tokio"] } +ldk-node-062 = { package = "ldk-node", version = "=0.6.2" } [target.'cfg(not(no_download))'.dev-dependencies] electrsd = { version = "0.36.1", default-features = false, features = ["legacy", "esplora_a33e97e1", "corepc-node_27_2"] } @@ -103,9 +104,6 @@ clightningrpc = { version = "0.3.0-beta.8", default-features = false } lnd_grpc_rust = { version = "2.10.0", default-features = false } tokio = { version = "1.37", features = ["fs"] } -[target.'cfg(vss_test)'.dev-dependencies] -ldk-node-062 = { package = "ldk-node", version = "=0.6.2" } - [build-dependencies] uniffi = { version = "0.28.3", features = ["build"], optional = true } diff --git a/tests/integration_tests_rust.rs b/tests/integration_tests_rust.rs index 4d2a17422..4b82d1f4f 100644 --- a/tests/integration_tests_rust.rs +++ b/tests/integration_tests_rust.rs @@ -27,6 +27,7 @@ use common::{ TestSyncStore, }; use ldk_node::config::{AsyncPaymentsRole, EsploraSyncConfig}; +use ldk_node::entropy::NodeEntropy; use ldk_node::liquidity::LSPS2ServiceConfig; use ldk_node::payment::{ ConfirmationStatus, PaymentDetails, PaymentDirection, PaymentKind, PaymentStatus, @@ -2436,3 +2437,61 @@ async fn payment_persistence_after_restart() { restarted_node_a.stop().unwrap(); } + +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn persistence_backwards_compatibility() { + let (bitcoind, electrsd) = common::setup_bitcoind_and_electrsd(); + let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap()); + + let storage_path = common::random_storage_path().to_str().unwrap().to_owned(); + let seed_bytes = [42u8; 64]; + let node_entropy = NodeEntropy::from_seed_bytes(seed_bytes); + + // Setup a v0.6.2 `Node` + let (old_balance, old_node_id) = { + let mut builder_old = ldk_node_062::Builder::new(); + builder_old.set_network(bitcoin::Network::Regtest); + builder_old.set_storage_dir_path(storage_path.clone()); + builder_old.set_entropy_seed_bytes(seed_bytes); + builder_old.set_chain_source_esplora(esplora_url.clone(), None); + let node_old = builder_old.build().unwrap(); + + node_old.start().unwrap(); + let addr_old = node_old.onchain_payment().new_address().unwrap(); + common::premine_and_distribute_funds( + &bitcoind.client, + &electrsd.client, + vec![addr_old], + bitcoin::Amount::from_sat(100_000), + ) + .await; + node_old.sync_wallets().unwrap(); + + let balance = node_old.list_balances().spendable_onchain_balance_sats; + assert!(balance > 0); + let node_id = node_old.node_id(); + + node_old.stop().unwrap(); + + (balance, node_id) + }; + + // Now ensure we can still reinit from the same backend. + let mut builder_new = Builder::new(); + builder_new.set_network(bitcoin::Network::Regtest); + builder_new.set_storage_dir_path(storage_path); + builder_new.set_chain_source_esplora(esplora_url, None); + + let node_new = builder_new.build(node_entropy).unwrap(); + + node_new.start().unwrap(); + node_new.sync_wallets().unwrap(); + + let new_balance = node_new.list_balances().spendable_onchain_balance_sats; + let new_node_id = node_new.node_id(); + + assert_eq!(old_node_id, new_node_id); + assert_eq!(old_balance, new_balance); + + node_new.stop().unwrap(); +} From 93b6b4256c36be814e0c0af92d15297a4345887e Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 8 Jan 2026 21:18:48 +0100 Subject: [PATCH 3/3] Drop unused `Watch` import --- src/builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/builder.rs b/src/builder.rs index 187f780d2..c1acf71d4 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -20,7 +20,7 @@ use bitcoin::key::Secp256k1; use bitcoin::secp256k1::PublicKey; use bitcoin::{BlockHash, Network}; use bitcoin_payment_instructions::onion_message_resolver::LDKOnionMessageDNSSECHrnResolver; -use lightning::chain::{chainmonitor, BestBlock, Watch}; +use lightning::chain::{chainmonitor, BestBlock}; use lightning::ln::channelmanager::{self, ChainParameters, ChannelManagerReadArgs}; use lightning::ln::msgs::{RoutingMessageHandler, SocketAddress}; use lightning::ln::peer_handler::{IgnoringMessageHandler, MessageHandler};