2 use std::collections::HashMap;
4 use bitcoin::BlockHash;
5 use lightning::ln::msgs::{UnsignedChannelAnnouncement, UnsignedChannelUpdate};
6 use lightning::util::ser::{BigSize, Writeable};
8 use crate::lookup::{DeltaSet, DirectedUpdateDelta};
10 pub(super) struct SerializationSet {
11 pub(super) announcements: Vec<UnsignedChannelAnnouncement>,
12 pub(super) updates: Vec<UpdateSerialization>,
13 pub(super) full_update_defaults: DefaultUpdateValues,
14 pub(super) latest_seen: u32,
15 pub(super) chain_hash: BlockHash,
18 pub(super) struct DefaultUpdateValues {
19 pub(super) cltv_expiry_delta: u16,
20 pub(super) htlc_minimum_msat: u64,
21 pub(super) fee_base_msat: u32,
22 pub(super) fee_proportional_millionths: u32,
23 pub(super) htlc_maximum_msat: u64,
26 impl Default for DefaultUpdateValues {
27 fn default() -> Self {
32 fee_proportional_millionths: 0,
38 pub(super) struct MutatedProperties {
39 pub(super) flags: bool,
40 pub(super) cltv_expiry_delta: bool,
41 pub(super) htlc_minimum_msat: bool,
42 pub(super) fee_base_msat: bool,
43 pub(super) fee_proportional_millionths: bool,
44 pub(super) htlc_maximum_msat: bool,
47 impl Default for MutatedProperties {
48 fn default() -> Self {
51 cltv_expiry_delta: false,
52 htlc_minimum_msat: false,
54 fee_proportional_millionths: false,
55 htlc_maximum_msat: false,
60 pub(super) struct UpdateSerialization {
61 pub(super) update: UnsignedChannelUpdate,
62 pub(super) mechanism: UpdateSerializationMechanism,
65 impl MutatedProperties {
66 /// Does not include flags because the flag byte is always sent in full
68 let mut mutations = 0;
69 if self.cltv_expiry_delta { mutations += 1; };
70 if self.htlc_minimum_msat { mutations += 1; };
71 if self.fee_base_msat { mutations += 1; };
72 if self.fee_proportional_millionths { mutations += 1; };
73 if self.htlc_maximum_msat { mutations += 1; };
78 pub(super) enum UpdateSerializationMechanism {
80 Incremental(MutatedProperties),
83 struct FullUpdateValueHistograms {
84 cltv_expiry_delta: HashMap<u16, usize>,
85 htlc_minimum_msat: HashMap<u64, usize>,
86 fee_base_msat: HashMap<u32, usize>,
87 fee_proportional_millionths: HashMap<u32, usize>,
88 htlc_maximum_msat: HashMap<u64, usize>,
91 pub(super) fn serialize_delta_set(delta_set: DeltaSet, last_sync_timestamp: u32) -> SerializationSet {
92 let mut serialization_set = SerializationSet {
93 announcements: vec![],
95 full_update_defaults: Default::default(),
96 chain_hash: Default::default(),
100 let mut chain_hash_set = false;
102 let mut full_update_histograms = FullUpdateValueHistograms {
103 cltv_expiry_delta: Default::default(),
104 htlc_minimum_msat: Default::default(),
105 fee_base_msat: Default::default(),
106 fee_proportional_millionths: Default::default(),
107 htlc_maximum_msat: Default::default(),
110 let mut record_full_update_in_histograms = |full_update: &UnsignedChannelUpdate| {
111 *full_update_histograms.cltv_expiry_delta.entry(full_update.cltv_expiry_delta).or_insert(0) += 1;
112 *full_update_histograms.htlc_minimum_msat.entry(full_update.htlc_minimum_msat).or_insert(0) += 1;
113 *full_update_histograms.fee_base_msat.entry(full_update.fee_base_msat).or_insert(0) += 1;
114 *full_update_histograms.fee_proportional_millionths.entry(full_update.fee_proportional_millionths).or_insert(0) += 1;
115 *full_update_histograms.htlc_maximum_msat.entry(full_update.htlc_maximum_msat).or_insert(0) += 1;
118 for (_scid, channel_delta) in delta_set.into_iter() {
120 // any announcement chain hash is gonna be the same value. Just set it from the first one.
121 let channel_announcement_delta = channel_delta.announcement.as_ref().unwrap();
123 chain_hash_set = true;
124 serialization_set.chain_hash = channel_announcement_delta.announcement.chain_hash.clone();
127 let current_announcement_seen = channel_announcement_delta.seen;
128 let is_new_announcement = current_announcement_seen >= last_sync_timestamp;
129 let is_newly_updated_announcement = if let Some(first_update_seen) = channel_delta.first_update_seen {
130 first_update_seen >= last_sync_timestamp
134 let send_announcement = is_new_announcement || is_newly_updated_announcement;
135 if send_announcement {
136 serialization_set.latest_seen = max(serialization_set.latest_seen, current_announcement_seen);
137 serialization_set.announcements.push(channel_delta.announcement.unwrap().announcement);
140 let direction_a_updates = channel_delta.updates.0;
141 let direction_b_updates = channel_delta.updates.1;
143 let mut categorize_directed_update_serialization = |directed_updates: Option<DirectedUpdateDelta>| {
144 if let Some(updates) = directed_updates {
145 if let Some(latest_update_delta) = updates.latest_update_after_seen {
146 let latest_update = latest_update_delta.update;
148 // the returned seen timestamp should be the latest of all the returned
149 // announcements and latest updates
150 serialization_set.latest_seen = max(serialization_set.latest_seen, latest_update_delta.seen);
152 if updates.last_update_before_seen.is_some() {
153 let mutated_properties = updates.mutated_properties;
154 if mutated_properties.len() == 5 {
155 // all five values have changed, it makes more sense to just
156 // serialize the update as a full update instead of as a change
157 // this way, the default values can be computed more efficiently
158 record_full_update_in_histograms(&latest_update);
159 serialization_set.updates.push(UpdateSerialization {
160 update: latest_update,
161 mechanism: UpdateSerializationMechanism::Full,
163 } else if mutated_properties.len() > 0 || mutated_properties.flags {
164 // we don't count flags as mutated properties
165 serialization_set.updates.push(UpdateSerialization {
166 update: latest_update,
167 mechanism: UpdateSerializationMechanism::Incremental(mutated_properties),
171 // serialize the full update
172 record_full_update_in_histograms(&latest_update);
173 serialization_set.updates.push(UpdateSerialization {
174 update: latest_update,
175 mechanism: UpdateSerializationMechanism::Full,
182 categorize_directed_update_serialization(direction_a_updates);
183 categorize_directed_update_serialization(direction_b_updates);
186 let default_update_values = DefaultUpdateValues {
187 cltv_expiry_delta: find_most_common_histogram_entry_with_default(full_update_histograms.cltv_expiry_delta, 0),
188 htlc_minimum_msat: find_most_common_histogram_entry_with_default(full_update_histograms.htlc_minimum_msat, 0),
189 fee_base_msat: find_most_common_histogram_entry_with_default(full_update_histograms.fee_base_msat, 0),
190 fee_proportional_millionths: find_most_common_histogram_entry_with_default(full_update_histograms.fee_proportional_millionths, 0),
191 htlc_maximum_msat: find_most_common_histogram_entry_with_default(full_update_histograms.htlc_maximum_msat, 0),
194 serialization_set.full_update_defaults = default_update_values;
198 pub fn serialize_stripped_channel_announcement(announcement: &UnsignedChannelAnnouncement, node_id_a_index: usize, node_id_b_index: usize, previous_scid: u64) -> Vec<u8> {
199 let mut stripped_announcement = vec![];
201 announcement.features.write(&mut stripped_announcement).unwrap();
203 if previous_scid > announcement.short_channel_id {
204 panic!("unsorted scids!");
206 let scid_delta = BigSize(announcement.short_channel_id - previous_scid);
207 scid_delta.write(&mut stripped_announcement).unwrap();
209 // write indices of node ids rather than the node IDs themselves
210 BigSize(node_id_a_index as u64).write(&mut stripped_announcement).unwrap();
211 BigSize(node_id_b_index as u64).write(&mut stripped_announcement).unwrap();
213 // println!("serialized CA: {}, \n{:?}\n{:?}\n", announcement.short_channel_id, announcement.node_id_1, announcement.node_id_2);
214 stripped_announcement
217 pub(super) fn serialize_stripped_channel_update(update: &UpdateSerialization, default_values: &DefaultUpdateValues, previous_scid: u64) -> Vec<u8> {
218 let latest_update = &update.update;
219 let mut serialized_flags = latest_update.flags;
221 if previous_scid > latest_update.short_channel_id {
222 panic!("unsorted scids!");
225 let mut delta_serialization = Vec::new();
226 let mut prefixed_serialization = Vec::new();
228 match &update.mechanism {
229 UpdateSerializationMechanism::Full => {
230 if latest_update.cltv_expiry_delta != default_values.cltv_expiry_delta {
231 serialized_flags |= 0b_0100_0000;
232 latest_update.cltv_expiry_delta.write(&mut delta_serialization).unwrap();
235 if latest_update.htlc_minimum_msat != default_values.htlc_minimum_msat {
236 serialized_flags |= 0b_0010_0000;
237 latest_update.htlc_minimum_msat.write(&mut delta_serialization).unwrap();
240 if latest_update.fee_base_msat != default_values.fee_base_msat {
241 serialized_flags |= 0b_0001_0000;
242 latest_update.fee_base_msat.write(&mut delta_serialization).unwrap();
245 if latest_update.fee_proportional_millionths != default_values.fee_proportional_millionths {
246 serialized_flags |= 0b_0000_1000;
247 latest_update.fee_proportional_millionths.write(&mut delta_serialization).unwrap();
250 if latest_update.htlc_maximum_msat != default_values.htlc_maximum_msat {
251 serialized_flags |= 0b_0000_0100;
252 latest_update.htlc_maximum_msat.write(&mut delta_serialization).unwrap();
256 UpdateSerializationMechanism::Incremental(mutated_properties) => {
257 // indicate that this update is incremental
258 serialized_flags |= 0b_1000_0000;
260 if mutated_properties.cltv_expiry_delta {
261 serialized_flags |= 0b_0100_0000;
262 latest_update.cltv_expiry_delta.write(&mut delta_serialization).unwrap();
265 if mutated_properties.htlc_minimum_msat {
266 serialized_flags |= 0b_0010_0000;
267 latest_update.htlc_minimum_msat.write(&mut delta_serialization).unwrap();
270 if mutated_properties.fee_base_msat {
271 serialized_flags |= 0b_0001_0000;
272 latest_update.fee_base_msat.write(&mut delta_serialization).unwrap();
275 if mutated_properties.fee_proportional_millionths {
276 serialized_flags |= 0b_0000_1000;
277 latest_update.fee_proportional_millionths.write(&mut delta_serialization).unwrap();
280 if mutated_properties.htlc_maximum_msat {
281 serialized_flags |= 0b_0000_0100;
282 latest_update.htlc_maximum_msat.write(&mut delta_serialization).unwrap();
286 let scid_delta = BigSize(latest_update.short_channel_id - previous_scid);
287 scid_delta.write(&mut prefixed_serialization).unwrap();
289 serialized_flags.write(&mut prefixed_serialization).unwrap();
290 prefixed_serialization.append(&mut delta_serialization);
292 prefixed_serialization
295 pub(super) fn find_most_common_histogram_entry_with_default<T: Copy>(histogram: HashMap<T, usize>, default: T) -> T {
296 let most_frequent_entry = histogram.iter().max_by(|a, b| a.1.cmp(&b.1));
297 if let Some(entry_details) = most_frequent_entry {
299 // .1 is the frequency
300 return entry_details.0.to_owned();
302 // the default should pretty much always be a 0 as T
303 // though for htlc maximum msat it could be a u64::max