Skip to content

Commit 1eb05c5

Browse files
Support (de)serializing Path::blinded_tails in Routes
1 parent bc08cdd commit 1eb05c5

File tree

3 files changed

+99
-5
lines changed

3 files changed

+99
-5
lines changed

lightning/src/routing/router.rs

Lines changed: 88 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -357,14 +357,25 @@ impl Writeable for Route {
357357
fn write<W: crate::util::ser::Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
358358
write_ver_prefix!(writer, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
359359
(self.paths.len() as u64).write(writer)?;
360+
let mut blinded_tails = Vec::new();
360361
for path in self.paths.iter() {
361362
(path.hops.len() as u8).write(writer)?;
362-
for hop in path.hops.iter() {
363+
for (idx, hop) in path.hops.iter().enumerate() {
363364
hop.write(writer)?;
365+
if let Some(blinded_tail) = &path.blinded_tail {
366+
if blinded_tails.is_empty() {
367+
blinded_tails = Vec::with_capacity(path.hops.len());
368+
for _ in 0..idx {
369+
blinded_tails.push(None);
370+
}
371+
}
372+
blinded_tails.push(Some(blinded_tail));
373+
} else if !blinded_tails.is_empty() { blinded_tails.push(None); }
364374
}
365375
}
366376
write_tlv_fields!(writer, {
367377
(1, self.payment_params, option),
378+
(2, blinded_tails, optional_vec),
368379
});
369380
Ok(())
370381
}
@@ -388,10 +399,17 @@ impl Readable for Route {
388399
cmp::min(min_final_cltv_expiry_delta, hops.last().unwrap().cltv_expiry_delta);
389400
paths.push(Path { hops, blinded_tail: None });
390401
}
391-
let mut payment_params = None;
392-
read_tlv_fields!(reader, {
402+
_init_and_read_tlv_fields!(reader, {
393403
(1, payment_params, (option: ReadableArgs, min_final_cltv_expiry_delta)),
404+
(2, blinded_tails, optional_vec),
394405
});
406+
let blinded_tails = blinded_tails.unwrap_or(Vec::new());
407+
if blinded_tails.len() != 0 {
408+
if blinded_tails.len() != paths.len() { return Err(DecodeError::InvalidValue) }
409+
for (mut path, blinded_tail_opt) in paths.iter_mut().zip(blinded_tails.into_iter()) {
410+
if let Some(blinded_tail) = blinded_tail_opt { path.blinded_tail = Some(blinded_tail); }
411+
}
412+
}
395413
Ok(Route { paths, payment_params })
396414
}
397415
}
@@ -2244,10 +2262,11 @@ fn build_route_from_hops_internal<L: Deref>(
22442262

22452263
#[cfg(test)]
22462264
mod tests {
2265+
use crate::blinded_path::{BlindedHop, BlindedPath};
22472266
use crate::routing::gossip::{NetworkGraph, P2PGossipSync, NodeId, EffectiveCapacity};
22482267
use crate::routing::utxo::UtxoResult;
22492268
use crate::routing::router::{get_route, build_route_from_hops_internal, add_random_cltv_offset, default_node_features,
2250-
Path, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees,
2269+
BlindedTail, Path, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees,
22512270
DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, MAX_PATH_LENGTH_ESTIMATE};
22522271
use crate::routing::scoring::{ChannelUsage, FixedPenaltyScorer, Score, ProbabilisticScorer, ProbabilisticScoringParameters};
22532272
use crate::routing::test_utils::{add_channel, add_or_update_node, build_graph, build_line_graph, id_to_feature_flags, get_nodes, update_channel};
@@ -2259,8 +2278,9 @@ mod tests {
22592278
use crate::util::config::UserConfig;
22602279
use crate::util::test_utils as ln_test_utils;
22612280
use crate::util::chacha20::ChaCha20;
2281+
use crate::util::ser::{Readable, Writeable};
22622282
#[cfg(c_bindings)]
2263-
use crate::util::ser::{Writeable, Writer};
2283+
use crate::util::ser::Writer;
22642284

22652285
use bitcoin::hashes::Hash;
22662286
use bitcoin::network::constants::Network;
@@ -2274,6 +2294,7 @@ mod tests {
22742294
use bitcoin::secp256k1::{PublicKey,SecretKey};
22752295
use bitcoin::secp256k1::Secp256k1;
22762296

2297+
use crate::io::Cursor;
22772298
use crate::prelude::*;
22782299
use crate::sync::Arc;
22792300

@@ -5744,6 +5765,68 @@ mod tests {
57445765
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes);
57455766
assert!(route.is_ok());
57465767
}
5768+
5769+
#[test]
5770+
fn blinded_route_ser() {
5771+
let blinded_path_1 = BlindedPath {
5772+
introduction_node_id: ln_test_utils::pubkey(42),
5773+
blinding_point: ln_test_utils::pubkey(43),
5774+
blinded_hops: vec![
5775+
BlindedHop { blinded_node_id: ln_test_utils::pubkey(44), encrypted_payload: Vec::new() },
5776+
BlindedHop { blinded_node_id: ln_test_utils::pubkey(45), encrypted_payload: Vec::new() }
5777+
],
5778+
};
5779+
let blinded_path_2 = BlindedPath {
5780+
introduction_node_id: ln_test_utils::pubkey(46),
5781+
blinding_point: ln_test_utils::pubkey(47),
5782+
blinded_hops: vec![
5783+
BlindedHop { blinded_node_id: ln_test_utils::pubkey(48), encrypted_payload: Vec::new() },
5784+
BlindedHop { blinded_node_id: ln_test_utils::pubkey(49), encrypted_payload: Vec::new() }
5785+
],
5786+
};
5787+
// (De)serialize a Route with 1 blinded path out of two total paths.
5788+
let mut route = Route { paths: vec![Path {
5789+
hops: vec![RouteHop {
5790+
pubkey: ln_test_utils::pubkey(50),
5791+
node_features: NodeFeatures::empty(),
5792+
short_channel_id: 42,
5793+
channel_features: ChannelFeatures::empty(),
5794+
fee_msat: 100,
5795+
cltv_expiry_delta: 0,
5796+
}],
5797+
blinded_tail: Some(BlindedTail {
5798+
hops: blinded_path_1.blinded_hops,
5799+
blinding_point: blinded_path_1.blinding_point,
5800+
final_cltv_expiry_delta: 40,
5801+
final_value_msat: 100,
5802+
})}, Path {
5803+
hops: vec![RouteHop {
5804+
pubkey: ln_test_utils::pubkey(51),
5805+
node_features: NodeFeatures::empty(),
5806+
short_channel_id: 43,
5807+
channel_features: ChannelFeatures::empty(),
5808+
fee_msat: 100,
5809+
cltv_expiry_delta: 0,
5810+
}], blinded_tail: None }],
5811+
payment_params: None,
5812+
};
5813+
let encoded_route = route.encode();
5814+
let decoded_route: Route = Readable::read(&mut Cursor::new(&encoded_route[..])).unwrap();
5815+
assert_eq!(decoded_route.paths[0].blinded_tail, route.paths[0].blinded_tail);
5816+
assert_eq!(decoded_route.paths[1].blinded_tail, route.paths[1].blinded_tail);
5817+
5818+
// (De)serialize a Route with two paths, each containing a blinded tail.
5819+
route.paths[1].blinded_tail = Some(BlindedTail {
5820+
hops: blinded_path_2.blinded_hops,
5821+
blinding_point: blinded_path_2.blinding_point,
5822+
final_cltv_expiry_delta: 41,
5823+
final_value_msat: 101,
5824+
});
5825+
let encoded_route = route.encode();
5826+
let decoded_route: Route = Readable::read(&mut Cursor::new(&encoded_route[..])).unwrap();
5827+
assert_eq!(decoded_route.paths[0].blinded_tail, route.paths[0].blinded_tail);
5828+
assert_eq!(decoded_route.paths[1].blinded_tail, route.paths[1].blinded_tail);
5829+
}
57475830
}
57485831

57495832
#[cfg(all(test, not(feature = "no-std")))]

lightning/src/util/ser.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,8 @@ impl Readable for Vec<u8> {
814814
impl_for_vec!(ecdsa::Signature);
815815
impl_for_vec!(crate::ln::channelmanager::MonitorUpdateCompletionAction);
816816
impl_for_vec!((A, B), A, B);
817+
impl_writeable_for_vec!(&crate::routing::router::BlindedTail);
818+
impl_readable_for_vec!(crate::routing::router::BlindedTail);
817819

818820
impl Writeable for Script {
819821
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {

lightning/src/util/test_utils.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,15 @@ use crate::chain::keysinterface::{InMemorySigner, Recipient, EntropySource, Node
6060
use std::time::{SystemTime, UNIX_EPOCH};
6161
use bitcoin::Sequence;
6262

63+
pub fn pubkey(byte: u8) -> PublicKey {
64+
let secp_ctx = Secp256k1::new();
65+
PublicKey::from_secret_key(&secp_ctx, &privkey(byte))
66+
}
67+
68+
pub fn privkey(byte: u8) -> SecretKey {
69+
SecretKey::from_slice(&[byte; 32]).unwrap()
70+
}
71+
6372
pub struct TestVecWriter(pub Vec<u8>);
6473
impl Writer for TestVecWriter {
6574
fn write_all(&mut self, buf: &[u8]) -> Result<(), io::Error> {

0 commit comments

Comments
 (0)