Skip to content

Commit 74712af

Browse files
committed
Parse v2 gossip.
1 parent 2701bc5 commit 74712af

File tree

1 file changed

+154
-12
lines changed

1 file changed

+154
-12
lines changed

lightning-rapid-gossip-sync/src/processing.rs

+154-12
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,8 @@ use core::sync::atomic::Ordering;
55
use bitcoin::blockdata::constants::ChainHash;
66
use bitcoin::secp256k1::PublicKey;
77

8-
use lightning::ln::msgs::{
9-
DecodeError, ErrorAction, LightningError, UnsignedChannelUpdate,
10-
};
11-
use lightning::routing::gossip::NetworkGraph;
8+
use lightning::ln::msgs::{DecodeError, ErrorAction, LightningError, SocketAddress, UnsignedChannelUpdate, UnsignedNodeAnnouncement};
9+
use lightning::routing::gossip::{NetworkGraph, NodeAlias, NodeId};
1210
use lightning::util::logger::Logger;
1311
use lightning::{log_debug, log_warn, log_trace, log_given_level, log_gossip};
1412
use lightning::util::ser::{BigSize, Readable};
@@ -21,12 +19,14 @@ use std::time::{SystemTime, UNIX_EPOCH};
2119

2220
#[cfg(all(not(feature = "std"), not(test)))]
2321
use alloc::{vec::Vec, borrow::ToOwned};
22+
use lightning::ln::features::NodeFeatures;
23+
use lightning::util::hash_tables::HashMap;
2424

2525
/// The purpose of this prefix is to identify the serialization format, should other rapid gossip
2626
/// sync formats arise in the future.
2727
///
2828
/// The fourth byte is the protocol version in case our format gets updated.
29-
const GOSSIP_PREFIX: [u8; 4] = [76, 68, 75, 1];
29+
const GOSSIP_PREFIX: [u8; 3] = [76, 68, 75];
3030

3131
/// Maximum vector allocation capacity for distinct node IDs. This constraint is necessary to
3232
/// avoid malicious updates being able to trigger excessive memory allocation.
@@ -59,13 +59,22 @@ impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L
5959
current_time_unix: Option<u64>
6060
) -> Result<u32, GraphSyncError> {
6161
log_trace!(self.logger, "Processing RGS data...");
62-
let mut prefix = [0u8; 4];
63-
read_cursor.read_exact(&mut prefix)?;
62+
let mut protocol_prefix = [0u8; 3];
63+
let mut version_prefix = [0u8; 1];
6464

65-
if prefix != GOSSIP_PREFIX {
65+
read_cursor.read_exact(&mut protocol_prefix)?;
66+
if protocol_prefix != GOSSIP_PREFIX {
6667
return Err(DecodeError::UnknownVersion.into());
6768
}
6869

70+
read_cursor.read_exact(&mut version_prefix)?;
71+
let version = version_prefix[0];
72+
if version != 1 && version != 2 {
73+
return Err(DecodeError::UnknownVersion.into());
74+
}
75+
76+
let parse_node_details = version == 2;
77+
6978
let chain_hash: ChainHash = Readable::read(read_cursor)?;
7079
let ng_chain_hash = self.network_graph.get_chain_hash();
7180
if chain_hash != ng_chain_hash {
@@ -88,14 +97,84 @@ impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L
8897
// backdate the applied timestamp by a week
8998
let backdated_timestamp = latest_seen_timestamp.saturating_sub(24 * 3600 * 7);
9099

100+
let mut default_node_features = Vec::new();
101+
if parse_node_details {
102+
let default_feature_count: u8 = Readable::read(read_cursor)?;
103+
for _ in 0..default_feature_count {
104+
let current_default_feature: NodeFeatures = Readable::read(read_cursor)?;
105+
default_node_features.push(current_default_feature);
106+
}
107+
};
108+
91109
let node_id_count: u32 = Readable::read(read_cursor)?;
92110
let mut node_ids: Vec<PublicKey> = Vec::with_capacity(core::cmp::min(
93111
node_id_count,
94112
MAX_INITIAL_NODE_ID_VECTOR_CAPACITY,
95113
) as usize);
114+
let mut node_modifications: HashMap<PublicKey, UnsignedNodeAnnouncement> = HashMap::default();
96115
for _ in 0..node_id_count {
97-
let current_node_id = Readable::read(read_cursor)?;
98-
node_ids.push(current_node_id);
116+
if parse_node_details {
117+
let mut pubkey_bytes = [0u8; 33];
118+
read_cursor.read_exact(&mut pubkey_bytes)?;
119+
let node_detail_flag = pubkey_bytes[0];
120+
let has_address_details = (node_detail_flag & (1 << 2)) > 0;
121+
let feature_detail_marker = (node_detail_flag & (0b111 << 3)) >> 3;
122+
let has_additional_data = (node_detail_flag & (1 << 7)) > 0;
123+
let key_parity = node_detail_flag & 0b_0000_0011;
124+
pubkey_bytes[0] = key_parity;
125+
let current_node_id = PublicKey::from_slice(&pubkey_bytes).unwrap();
126+
node_ids.push(current_node_id);
127+
128+
let mut unsigned_node_announcement = UnsignedNodeAnnouncement {
129+
features: NodeFeatures::empty(),
130+
timestamp: 0,
131+
node_id: NodeId::from_pubkey(&current_node_id),
132+
rgb: [0, 0, 0],
133+
alias: NodeAlias([0u8; 32]),
134+
addresses: Vec::new(),
135+
excess_address_data: Vec::new(),
136+
excess_data: Vec::new(),
137+
};
138+
139+
if has_address_details {
140+
let address_count: u8 = Readable::read(read_cursor)?;
141+
let mut node_addresses: Vec<SocketAddress> = Vec::new();
142+
for _ in 0..address_count {
143+
let current_byte_count: u8 = Readable::read(read_cursor)?;
144+
let mut address_bytes = vec![0u8; current_byte_count as usize];
145+
read_cursor.read_exact(&mut address_bytes).unwrap();
146+
147+
let mut address_cursor = io::Cursor::new(&address_bytes);
148+
if let Ok(current_address) = Readable::read(&mut address_cursor) {
149+
node_addresses.push(current_address);
150+
}
151+
}
152+
unsigned_node_announcement.addresses = node_addresses;
153+
}
154+
155+
if feature_detail_marker > 0 {
156+
if feature_detail_marker < 7 {
157+
let feature_index = (feature_detail_marker - 1) as usize;
158+
unsigned_node_announcement.features = default_node_features[feature_index].clone();
159+
} else {
160+
let node_features: NodeFeatures = Readable::read(read_cursor)?;
161+
unsigned_node_announcement.features = node_features;
162+
}
163+
}
164+
165+
if feature_detail_marker > 0 || has_address_details {
166+
node_modifications.insert(current_node_id, unsigned_node_announcement);
167+
}
168+
169+
if has_additional_data {
170+
// forwards compatibility
171+
let _additional_data: Vec<u8> = Readable::read(read_cursor)?;
172+
}
173+
174+
} else {
175+
let current_node_id = Readable::read(read_cursor)?;
176+
node_ids.push(current_node_id);
177+
}
99178
}
100179

101180
let network_graph = &self.network_graph;
@@ -114,6 +193,7 @@ impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L
114193

115194
let node_id_1_index: BigSize = Readable::read(read_cursor)?;
116195
let node_id_2_index: BigSize = Readable::read(read_cursor)?;
196+
let has_additional_data = (node_id_2_index.0 & (1 << 63)) > 0;
117197

118198
if max(node_id_1_index.0, node_id_2_index.0) >= node_id_count as u64 {
119199
return Err(DecodeError::InvalidValue.into());
@@ -139,6 +219,18 @@ impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L
139219
return Err(lightning_error.into());
140220
}
141221
}
222+
223+
if version >= 2 && has_additional_data {
224+
// forwards compatibility
225+
let _additional_data: Vec<u8> = Readable::read(read_cursor)?;
226+
}
227+
228+
if let Some(modification) = node_modifications.remove(&node_id_1) {
229+
network_graph.update_node_from_unsigned_announcement(&modification)?;
230+
}
231+
if let Some(modification) = node_modifications.remove(&node_id_2) {
232+
network_graph.update_node_from_unsigned_announcement(&modification)?;
233+
}
142234
}
143235

144236
previous_scid = 0; // updates start at a new scid
@@ -157,6 +249,8 @@ impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L
157249
let default_fee_proportional_millionths: u32 = Readable::read(&mut read_cursor)?;
158250
let default_htlc_maximum_msat: u64 = Readable::read(&mut read_cursor)?;
159251

252+
let mut previous_channel_direction = None;
253+
160254
for _ in 0..update_count {
161255
let scid_delta: BigSize = Readable::read(read_cursor)?;
162256
let short_channel_id = previous_scid
@@ -166,6 +260,18 @@ impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L
166260

167261
let channel_flags: u8 = Readable::read(read_cursor)?;
168262

263+
if version >= 2 {
264+
let direction = (channel_flags & 1) == 1;
265+
let is_same_direction_update = Some(direction) == previous_channel_direction;
266+
previous_channel_direction = Some(direction);
267+
268+
if scid_delta.0 == 0 && is_same_direction_update {
269+
// this is additional data for forwards compatibility
270+
let _additional_data: Vec<u8> = Readable::read(read_cursor)?;
271+
continue;
272+
}
273+
}
274+
169275
// flags are always sent in full, and hence always need updating
170276
let standard_channel_flags = channel_flags & 0b_0000_0011;
171277

@@ -265,7 +371,7 @@ mod tests {
265371
#[cfg(feature = "std")]
266372
use lightning::ln::msgs::DecodeError;
267373

268-
use lightning::routing::gossip::NetworkGraph;
374+
use lightning::routing::gossip::{NetworkGraph, NodeId};
269375
use lightning::util::test_utils::TestLogger;
270376

271377
use crate::processing::STALE_RGS_UPDATE_AGE_LIMIT_SECS;
@@ -322,6 +428,42 @@ mod tests {
322428
}
323429
}
324430

431+
#[test]
432+
fn node_data_update_succeeds_with_v2() {
433+
let logger = TestLogger::new();
434+
let network_graph = NetworkGraph::new(Network::Bitcoin, &logger);
435+
436+
let example_input = vec![
437+
76, 68, 75, 2, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
438+
79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 102, 87, 151, 80,
439+
1, 0, 2, 23, 48, 0, 0, 0, 3, 15, 27, 132, 197, 86, 123, 18, 100, 64, 153, 93, 62, 213,
440+
170, 186, 5, 101, 215, 30, 24, 52, 96, 72, 25, 255, 156, 23, 245, 233, 213, 221, 7, 143,
441+
5, 14, 5, 10, 103, 111, 111, 103, 108, 101, 46, 99, 111, 109, 1, 187, 13, 3, 1, 2, 3, 4,
442+
5, 6, 7, 8, 9, 10, 11, 12, 38, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
443+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 3, 0, 4, 7, 1, 127, 0, 0, 1, 37, 163,
444+
19, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 57, 2, 77, 75, 108, 209, 54,
445+
16, 50, 202, 155, 210, 174, 185, 217, 0, 170, 77, 69, 217, 234, 216, 10, 201, 66, 51,
446+
116, 196, 81, 167, 37, 77, 7, 102, 2, 83, 31, 230, 6, 129, 52, 80, 61, 39, 35, 19, 50,
447+
39, 200, 103, 172, 143, 166, 200, 60, 83, 126, 154, 68, 195, 197, 189, 189, 203, 31,
448+
227, 55, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
449+
6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1
450+
];
451+
452+
let rapid_sync = RapidGossipSync::new(&network_graph, &logger);
453+
let update_result = rapid_sync.update_network_graph_no_std(&example_input[..], None);
454+
assert!(update_result.is_ok());
455+
456+
let read_only_graph = network_graph.read_only();
457+
let nodes = read_only_graph.nodes();
458+
assert_eq!(nodes.len(), 2);
459+
460+
let node_id = NodeId::from_slice(&[3, 27, 132, 197, 86, 123, 18, 100, 64, 153, 93, 62, 213, 170, 186, 5, 101, 215, 30, 24, 52, 96, 72, 25, 255, 156, 23, 245, 233, 213, 221, 7, 143]).unwrap();
461+
let node = nodes.get(&node_id).unwrap();
462+
let announcement_info = node.announcement_info.as_ref().unwrap();
463+
let addresses = announcement_info.addresses();
464+
assert_eq!(addresses.len(), 5);
465+
}
466+
325467
#[test]
326468
#[cfg(feature = "std")]
327469
fn incremental_only_update_ignores_missing_channel() {
@@ -645,7 +787,7 @@ mod tests {
645787
#[cfg(feature = "std")]
646788
pub fn update_fails_with_unknown_version() {
647789
let unknown_version_input = vec![
648-
76, 68, 75, 2, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
790+
76, 68, 75, 3, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
649791
79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
650792
0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
651793
187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,

0 commit comments

Comments
 (0)