Skip to content

Commit f0b466d

Browse files
committed
builder: force full RGS sync on legacy mismatch
When deserializing `NodeMetrics`, keep reading the legacy RGS timestamp field long enough to compare it with `NetworkGraph` during build. If the values diverge, start the next rapid gossip sync from timestamp `0` instead of trusting either partial state. Generated with the assistance of AI. Co-Authored-By: HAL 9000
1 parent 9affc0c commit f0b466d

File tree

2 files changed

+31
-7
lines changed

2 files changed

+31
-7
lines changed

src/builder.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,11 +1161,13 @@ fn build_with_store_internal(
11611161
});
11621162

11631163
// Initialize the status fields.
1164-
let node_metrics = match node_metris_res {
1165-
Ok(metrics) => Arc::new(RwLock::new(metrics)),
1164+
let (node_metrics, legacy_latest_rgs_snapshot_timestamp) = match node_metris_res {
1165+
Ok((metrics, legacy_latest_rgs_snapshot_timestamp)) => {
1166+
(Arc::new(RwLock::new(metrics)), legacy_latest_rgs_snapshot_timestamp)
1167+
},
11661168
Err(e) => {
11671169
if e.kind() == std::io::ErrorKind::NotFound {
1168-
Arc::new(RwLock::new(NodeMetrics::default()))
1170+
(Arc::new(RwLock::new(NodeMetrics::default())), None)
11691171
} else {
11701172
log_error!(logger, "Failed to read node metrics from store: {}", e);
11711173
return Err(BuildError::ReadFailed);
@@ -1647,6 +1649,9 @@ fn build_with_store_internal(
16471649
// Initialize the GossipSource
16481650
// Use the configured gossip source, if the user set one, otherwise default to P2PNetwork.
16491651
let gossip_source_config = gossip_source_config.unwrap_or(&GossipSourceConfig::P2PNetwork);
1652+
let network_graph_rgs_timestamp = network_graph.get_last_rapid_gossip_sync_timestamp();
1653+
let force_full_rgs_sync = legacy_latest_rgs_snapshot_timestamp
1654+
.is_some_and(|legacy_timestamp| network_graph_rgs_timestamp != Some(legacy_timestamp));
16501655

16511656
let gossip_source = match gossip_source_config {
16521657
GossipSourceConfig::P2PNetwork => {
@@ -1660,7 +1665,7 @@ fn build_with_store_internal(
16601665
},
16611666
GossipSourceConfig::RapidGossipSync(rgs_server) => {
16621667
let latest_sync_timestamp =
1663-
network_graph.get_last_rapid_gossip_sync_timestamp().unwrap_or(0);
1668+
if force_full_rgs_sync { 0 } else { network_graph_rgs_timestamp.unwrap_or(0) };
16641669
Arc::new(GossipSource::new_rgs(
16651670
rgs_server.clone(),
16661671
latest_sync_timestamp,

src/io/utils.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use bdk_chain::tx_graph::ChangeSet as BdkTxGraphChangeSet;
2020
use bdk_chain::ConfirmationBlockTime;
2121
use bdk_wallet::ChangeSet as BdkWalletChangeSet;
2222
use bitcoin::Network;
23+
use lightning::_init_and_read_len_prefixed_tlv_fields;
2324
use lightning::ln::msgs::DecodeError;
2425
use lightning::routing::gossip::NetworkGraph;
2526
use lightning::routing::scoring::{
@@ -329,7 +330,7 @@ pub(crate) async fn read_output_sweeper(
329330

330331
pub(crate) async fn read_node_metrics<L: Deref>(
331332
kv_store: &DynStore, logger: L,
332-
) -> Result<NodeMetrics, std::io::Error>
333+
) -> Result<(NodeMetrics, Option<u32>), std::io::Error>
333334
where
334335
L::Target: LdkLogger,
335336
{
@@ -340,10 +341,28 @@ where
340341
NODE_METRICS_KEY,
341342
)
342343
.await?;
343-
NodeMetrics::read(&mut &*reader).map_err(|e| {
344+
let node_metrics = NodeMetrics::read(&mut &*reader).map_err(|e| {
344345
log_error!(logger, "Failed to deserialize NodeMetrics: {}", e);
345346
std::io::Error::new(std::io::ErrorKind::InvalidData, "Failed to deserialize NodeMetrics")
346-
})
347+
})?;
348+
349+
let legacy_latest_rgs_snapshot_timestamp = (|| {
350+
let mut cursor = std::io::Cursor::new(reader.as_slice());
351+
let legacy_reader = &mut cursor;
352+
_init_and_read_len_prefixed_tlv_fields!(legacy_reader, {
353+
(6, latest_rgs_snapshot_timestamp, option),
354+
});
355+
Ok(latest_rgs_snapshot_timestamp)
356+
})()
357+
.map_err(|e| {
358+
log_error!(logger, "Failed to deserialize legacy NodeMetrics RGS state: {}", e);
359+
std::io::Error::new(
360+
std::io::ErrorKind::InvalidData,
361+
"Failed to deserialize NodeMetrics legacy RGS state",
362+
)
363+
})?;
364+
365+
Ok((node_metrics, legacy_latest_rgs_snapshot_timestamp))
347366
}
348367

349368
pub(crate) fn write_node_metrics<L: Deref>(

0 commit comments

Comments
 (0)