Skip to content

Commit 206ab82

Browse files
authored
Merge pull request #3007 from arik-so/arik/trampoline/2024-04-trampoline-blinded-hop-serialization
Serialize blinded Trampoline hops
2 parents e0838be + d111981 commit 206ab82

File tree

1 file changed

+122
-6
lines changed

1 file changed

+122
-6
lines changed

lightning/src/ln/msgs.rs

+122-6
Original file line numberDiff line numberDiff line change
@@ -1746,9 +1746,9 @@ pub struct FinalOnionHopData {
17461746

17471747
mod fuzzy_internal_msgs {
17481748
use bitcoin::secp256k1::PublicKey;
1749-
use crate::blinded_path::payment::{PaymentConstraints, PaymentContext, PaymentRelay};
1749+
use crate::blinded_path::payment::{BlindedPaymentPath, PaymentConstraints, PaymentContext, PaymentRelay};
17501750
use crate::types::payment::{PaymentPreimage, PaymentSecret};
1751-
use crate::types::features::BlindedHopFeatures;
1751+
use crate::types::features::{BlindedHopFeatures, Bolt12InvoiceFeatures};
17521752
use super::{FinalOnionHopData, TrampolineOnionPacket};
17531753

17541754
#[allow(unused_imports)]
@@ -1830,14 +1830,41 @@ mod fuzzy_internal_msgs {
18301830
}
18311831
}
18321832

1833-
pub(crate) enum OutboundTrampolinePayload {
1833+
pub(crate) enum OutboundTrampolinePayload<'a> {
18341834
#[allow(unused)]
18351835
Forward {
18361836
/// The value, in msat, of the payment after this hop's fee is deducted.
18371837
amt_to_forward: u64,
18381838
outgoing_cltv_value: u32,
1839-
/// The node id to which the trampoline node must find a route
1839+
/// The node id to which the trampoline node must find a route.
18401840
outgoing_node_id: PublicKey,
1841+
},
1842+
#[allow(unused)]
1843+
/// This is the last Trampoline hop, whereupon the Trampoline forward mechanism is exited,
1844+
/// and payment data is relayed using non-Trampoline blinded hops
1845+
LegacyBlindedPathEntry {
1846+
/// The value, in msat, of the payment after this hop's fee is deducted.
1847+
amt_to_forward: u64,
1848+
outgoing_cltv_value: u32,
1849+
/// List of blinded path options the last trampoline hop may choose to route through.
1850+
payment_paths: Vec<BlindedPaymentPath>,
1851+
/// If applicable, features of the BOLT12 invoice being paid.
1852+
invoice_features: Option<Bolt12InvoiceFeatures>,
1853+
},
1854+
#[allow(unused)]
1855+
BlindedForward {
1856+
encrypted_tlvs: &'a Vec<u8>,
1857+
intro_node_blinding_point: Option<PublicKey>,
1858+
},
1859+
#[allow(unused)]
1860+
BlindedReceive {
1861+
sender_intended_htlc_amt_msat: u64,
1862+
total_msat: u64,
1863+
cltv_expiry_height: u32,
1864+
encrypted_tlvs: &'a Vec<u8>,
1865+
intro_node_blinding_point: Option<PublicKey>, // Set if the introduction node of the blinded path is the final node
1866+
keysend_preimage: Option<PaymentPreimage>,
1867+
custom_tlvs: &'a Vec<(u64, Vec<u8>)>,
18411868
}
18421869
}
18431870

@@ -2754,7 +2781,7 @@ impl<'a> Writeable for OutboundOnionPayload<'a> {
27542781
}
27552782
}
27562783

2757-
impl Writeable for OutboundTrampolinePayload {
2784+
impl<'a> Writeable for OutboundTrampolinePayload<'a> {
27582785
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
27592786
match self {
27602787
Self::Forward { amt_to_forward, outgoing_cltv_value, outgoing_node_id } => {
@@ -2763,6 +2790,41 @@ impl Writeable for OutboundTrampolinePayload {
27632790
(4, HighZeroBytesDroppedBigSize(*outgoing_cltv_value), required),
27642791
(14, outgoing_node_id, required)
27652792
});
2793+
},
2794+
Self::LegacyBlindedPathEntry { amt_to_forward, outgoing_cltv_value, payment_paths, invoice_features } => {
2795+
let mut blinded_path_serialization = [0u8; 2048]; // Fixed-length buffer on the stack
2796+
let serialization_length = {
2797+
let buffer_size = blinded_path_serialization.len();
2798+
let mut blinded_path_slice = &mut blinded_path_serialization[..];
2799+
for current_payment_path in payment_paths {
2800+
current_payment_path.inner_blinded_path().write(&mut blinded_path_slice)?;
2801+
current_payment_path.payinfo.write(&mut blinded_path_slice)?;
2802+
}
2803+
buffer_size - blinded_path_slice.len()
2804+
};
2805+
let blinded_path_serialization = &blinded_path_serialization[..serialization_length];
2806+
_encode_varint_length_prefixed_tlv!(w, {
2807+
(2, HighZeroBytesDroppedBigSize(*amt_to_forward), required),
2808+
(4, HighZeroBytesDroppedBigSize(*outgoing_cltv_value), required),
2809+
(21, invoice_features.as_ref().map(|m| WithoutLength(m)), option),
2810+
(22, WithoutLength(blinded_path_serialization), required)
2811+
});
2812+
},
2813+
Self::BlindedForward { encrypted_tlvs, intro_node_blinding_point} => {
2814+
_encode_varint_length_prefixed_tlv!(w, {
2815+
(10, **encrypted_tlvs, required_vec),
2816+
(12, intro_node_blinding_point, option)
2817+
});
2818+
},
2819+
Self::BlindedReceive { sender_intended_htlc_amt_msat, total_msat, cltv_expiry_height, encrypted_tlvs, intro_node_blinding_point, keysend_preimage, custom_tlvs } => {
2820+
_encode_varint_length_prefixed_tlv!(w, {
2821+
(2, HighZeroBytesDroppedBigSize(*sender_intended_htlc_amt_msat), required),
2822+
(4, HighZeroBytesDroppedBigSize(*cltv_expiry_height), required),
2823+
(10, **encrypted_tlvs, required_vec),
2824+
(12, intro_node_blinding_point, option),
2825+
(18, HighZeroBytesDroppedBigSize(*total_msat), required),
2826+
(20, keysend_preimage, option)
2827+
}, custom_tlvs.iter());
27662828
}
27672829
}
27682830
Ok(())
@@ -3302,7 +3364,7 @@ mod tests {
33023364
use crate::ln::types::ChannelId;
33033365
use crate::types::payment::{PaymentPreimage, PaymentHash, PaymentSecret};
33043366
use crate::types::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
3305-
use crate::ln::msgs::{self, FinalOnionHopData, OnionErrorPacket, CommonOpenChannelFields, CommonAcceptChannelFields, TrampolineOnionPacket};
3367+
use crate::ln::msgs::{self, FinalOnionHopData, OnionErrorPacket, CommonOpenChannelFields, CommonAcceptChannelFields, OutboundTrampolinePayload, TrampolineOnionPacket};
33063368
use crate::ln::msgs::SocketAddress;
33073369
use crate::routing::gossip::{NodeAlias, NodeId};
33083370
use crate::util::ser::{BigSize, FixedLengthReader, Hostname, LengthReadable, Readable, ReadableArgs, TransactionU16LenLimited, Writeable};
@@ -3328,6 +3390,8 @@ mod tests {
33283390

33293391
#[cfg(feature = "std")]
33303392
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
3393+
use types::features::{BlindedHopFeatures, Bolt12InvoiceFeatures};
3394+
use crate::blinded_path::payment::{BlindedPayInfo, BlindedPaymentPath};
33313395
#[cfg(feature = "std")]
33323396
use crate::ln::msgs::SocketAddressParseError;
33333397

@@ -4675,6 +4739,58 @@ mod tests {
46754739
assert_eq!(encoded_trampoline_packet, expected_eclair_trampoline_packet);
46764740
}
46774741

4742+
#[test]
4743+
fn encoding_outbound_trampoline_payload() {
4744+
let mut trampoline_features = Bolt12InvoiceFeatures::empty();
4745+
trampoline_features.set_basic_mpp_optional();
4746+
let introduction_node = PublicKey::from_slice(&<Vec<u8>>::from_hex("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()).unwrap();
4747+
let blinding_point = PublicKey::from_slice(&<Vec<u8>>::from_hex("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()).unwrap();
4748+
let trampoline_payload = OutboundTrampolinePayload::LegacyBlindedPathEntry {
4749+
amt_to_forward: 150_000_000,
4750+
outgoing_cltv_value: 800_000,
4751+
payment_paths: vec![
4752+
BlindedPaymentPath::from_raw(
4753+
introduction_node,
4754+
blinding_point,
4755+
vec![],
4756+
BlindedPayInfo{
4757+
fee_base_msat: 500,
4758+
fee_proportional_millionths: 1_000,
4759+
cltv_expiry_delta: 36,
4760+
htlc_minimum_msat: 1,
4761+
htlc_maximum_msat: 500_000_000,
4762+
features: BlindedHopFeatures::empty(),
4763+
}
4764+
)
4765+
],
4766+
invoice_features: Some(trampoline_features),
4767+
};
4768+
let serialized_payload = trampoline_payload.encode().to_lower_hex_string();
4769+
assert_eq!(serialized_payload, "71020408f0d18004030c35001503020000165f032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e66868099102eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f28368661900000001f4000003e800240000000000000001000000001dcd65000000");
4770+
}
4771+
4772+
#[test]
4773+
fn encode_trampoline_blinded_path_payload() {
4774+
let trampoline_payload_eve = OutboundTrampolinePayload::BlindedReceive {
4775+
sender_intended_htlc_amt_msat: 150_000_000,
4776+
total_msat: 150_000_000,
4777+
cltv_expiry_height: 800_000,
4778+
encrypted_tlvs: &<Vec<u8>>::from_hex("bcd747394fbd4d99588da075a623316e15a576df5bc785cccc7cd6ec7b398acce6faf520175f9ec920f2ef261cdb83dc28cc3a0eeb970107b3306489bf771ef5b1213bca811d345285405861d08a655b6c237fa247a8b4491beee20c878a60e9816492026d8feb9dafa84585b253978db6a0aa2945df5ef445c61e801fb82f43d5f00716baf9fc9b3de50bc22950a36bda8fc27bfb1242e5860c7e687438d4133e058770361a19b6c271a2a07788d34dccc27e39b9829b061a4d960eac4a2c2b0f4de506c24f9af3868c0aff6dda27281c").unwrap(),
4779+
intro_node_blinding_point: None,
4780+
keysend_preimage: None,
4781+
custom_tlvs: &vec![],
4782+
};
4783+
let eve_payload = trampoline_payload_eve.encode().to_lower_hex_string();
4784+
assert_eq!(eve_payload, "e4020408f0d18004030c35000ad1bcd747394fbd4d99588da075a623316e15a576df5bc785cccc7cd6ec7b398acce6faf520175f9ec920f2ef261cdb83dc28cc3a0eeb970107b3306489bf771ef5b1213bca811d345285405861d08a655b6c237fa247a8b4491beee20c878a60e9816492026d8feb9dafa84585b253978db6a0aa2945df5ef445c61e801fb82f43d5f00716baf9fc9b3de50bc22950a36bda8fc27bfb1242e5860c7e687438d4133e058770361a19b6c271a2a07788d34dccc27e39b9829b061a4d960eac4a2c2b0f4de506c24f9af3868c0aff6dda27281c120408f0d180");
4785+
4786+
let trampoline_payload_dave = OutboundTrampolinePayload::BlindedForward {
4787+
encrypted_tlvs: &<Vec<u8>>::from_hex("0ccf3c8a58deaa603f657ee2a5ed9d604eb5c8ca1e5f801989afa8f3ea6d789bbdde2c7e7a1ef9ca8c38d2c54760febad8446d3f273ddb537569ef56613846ccd3aba78a").unwrap(),
4788+
intro_node_blinding_point: Some(PublicKey::from_slice(&<Vec<u8>>::from_hex("02988face71e92c345a068f740191fd8e53be14f0bb957ef730d3c5f76087b960e").unwrap()).unwrap()),
4789+
};
4790+
let dave_payload = trampoline_payload_dave.encode().to_lower_hex_string();
4791+
assert_eq!(dave_payload, "690a440ccf3c8a58deaa603f657ee2a5ed9d604eb5c8ca1e5f801989afa8f3ea6d789bbdde2c7e7a1ef9ca8c38d2c54760febad8446d3f273ddb537569ef56613846ccd3aba78a0c2102988face71e92c345a068f740191fd8e53be14f0bb957ef730d3c5f76087b960e")
4792+
}
4793+
46784794
#[test]
46794795
fn query_channel_range_end_blocknum() {
46804796
let tests: Vec<(u32, u32, u32)> = vec![

0 commit comments

Comments
 (0)