Skip to content

Commit dc952fb

Browse files
committed
Introduce RecipientData in ReceiveTlvs
1. New Enum for Enhanced Data Handling: - Introduced the `RecipientData` enum, which allows the node to include additional data along with the `reply_path` sent to the counterparty. - The node anticipates receiving this data back for further processing. 2. Variants in RecipientData: - The `RecipientData` enum includes two variants. - One of the variants, `OffersContext`, holds the `payment_id` of the associated Outbound BOLT12 Payment. 3. Future Usage: - This enum will be utilized in a subsequent commit to abandon outbound payments that have failed to complete for various reasons.
1 parent 07f3380 commit dc952fb

File tree

5 files changed

+129
-25
lines changed

5 files changed

+129
-25
lines changed

lightning/src/blinded_path/message.rs

Lines changed: 96 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
1414
use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
1515

16+
use crate::ln::channelmanager::PaymentId;
17+
use crate::ln::msgs::DecodeError;
1618
#[allow(unused_imports)]
1719
use crate::prelude::*;
1820

@@ -24,7 +26,7 @@ use crate::ln::onion_utils;
2426
use crate::onion_message::packet::ControlTlvs;
2527
use crate::sign::{NodeSigner, Recipient};
2628
use crate::crypto::streams::ChaChaPolyReadAdapter;
27-
use crate::util::ser::{FixedLengthReader, LengthReadableArgs, Writeable, Writer};
29+
use crate::util::ser::{FixedLengthReader, LengthReadableArgs, Readable, Writeable, Writer};
2830

2931
use core::mem;
3032
use core::ops::Deref;
@@ -50,14 +52,6 @@ pub(crate) struct ForwardTlvs {
5052
pub(crate) next_blinding_override: Option<PublicKey>,
5153
}
5254

53-
/// Similar to [`ForwardTlvs`], but these TLVs are for the final node.
54-
pub(crate) struct ReceiveTlvs {
55-
/// If `path_id` is `Some`, it is used to identify the blinded path that this onion message is
56-
/// sending to. This is useful for receivers to check that said blinded path is being used in
57-
/// the right context.
58-
pub(crate) path_id: Option<[u8; 32]>,
59-
}
60-
6155
impl Writeable for ForwardTlvs {
6256
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
6357
let (next_node_id, short_channel_id) = match self.next_hop {
@@ -74,16 +68,106 @@ impl Writeable for ForwardTlvs {
7468
}
7569
}
7670

71+
/// Similar to [`ForwardTlvs`], but these TLVs are for the final node.
72+
pub(crate) struct ReceiveTlvs {
73+
pub tlvs: Option<RecipientData>
74+
}
75+
76+
impl ReceiveTlvs {
77+
pub fn new(tlvs: Option<RecipientData>) -> Self {
78+
ReceiveTlvs { tlvs }
79+
}
80+
}
81+
82+
/// Represents additional data appended along with the sent reply path.
83+
///
84+
/// This data can be utilized by the final recipient for further processing
85+
/// upon receiving it back.
86+
#[derive(Clone, Debug)]
87+
pub enum RecipientData {
88+
/// Represents the data specific to [`OffersMessage`]
89+
///
90+
/// [`OffersMessage`]: crate::onion_message::offers::OffersMessage
91+
OffersContext(OffersData),
92+
93+
/// Represents the data appended with Custom Onion Message.
94+
CustomContext(Vec<u8>),
95+
}
96+
97+
/// Contains the data specific to [`OffersMessage`]
98+
///
99+
/// [`OffersMessage`]: crate::onion_message::offers::OffersMessage
100+
#[derive(Clone, Debug)]
101+
pub struct OffersData {
102+
/// Payment ID of the outbound BOLT12 payment.
103+
pub payment_id: Option<PaymentId>
104+
}
105+
106+
impl RecipientData {
107+
/// Creates a new RecipientData::OffersContext instance.
108+
pub fn new_for_offers(payment_id: Option<PaymentId>) -> Self {
109+
RecipientData::OffersContext(OffersData {
110+
payment_id,
111+
})
112+
}
113+
114+
/// Creates a new RecipientData::CustomContext instance.
115+
pub fn new_for_custom(data: Vec<u8>) -> Self {
116+
RecipientData::CustomContext(data)
117+
}
118+
}
119+
120+
impl Writeable for RecipientData {
121+
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
122+
match self {
123+
RecipientData::OffersContext(offers_data) => {
124+
1u8.write(writer)?; // Identifier for OffersContext
125+
offers_data.payment_id.write(writer)?; // Write the payment_id
126+
}
127+
RecipientData::CustomContext(data) => {
128+
2u8.write(writer)?; // Identifier for CustomContext
129+
data.write(writer)?; // Write the custom data
130+
}
131+
}
132+
Ok(())
133+
}
134+
}
135+
136+
impl Readable for RecipientData {
137+
fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
138+
let type_id = u8::read(r)?;
139+
match type_id {
140+
1u8 => {
141+
let payment_id = Option::<PaymentId>::read(r)?;
142+
Ok(RecipientData::new_for_offers(payment_id))
143+
}
144+
2u8 => {
145+
let data = Vec::<u8>::read(r)?;
146+
Ok(RecipientData::new_for_custom(data))
147+
}
148+
_ => Err(DecodeError::InvalidValue),
149+
}
150+
}
151+
}
152+
77153
impl Writeable for ReceiveTlvs {
78154
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
79-
// TODO: write padding
80155
encode_tlv_stream!(writer, {
81-
(6, self.path_id, option),
156+
(6, self.tlvs, option),
82157
});
83158
Ok(())
84159
}
85160
}
86161

162+
impl Readable for ReceiveTlvs {
163+
fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
164+
_init_and_read_tlv_stream!(r, {
165+
(6, tlvs, option),
166+
});
167+
Ok(ReceiveTlvs { tlvs })
168+
}
169+
}
170+
87171
/// Construct blinded onion message hops for the given `intermediate_nodes` and `recipient_node_id`.
88172
pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
89173
secp_ctx: &Secp256k1<T>, intermediate_nodes: &[ForwardNode], recipient_node_id: PublicKey,
@@ -99,7 +183,7 @@ pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
99183
None => NextMessageHop::NodeId(*pubkey),
100184
})
101185
.map(|next_hop| ControlTlvs::Forward(ForwardTlvs { next_hop, next_blinding_override: None }))
102-
.chain(core::iter::once(ControlTlvs::Receive(ReceiveTlvs { path_id: None })));
186+
.chain(core::iter::once(ControlTlvs::Receive(ReceiveTlvs::new(None))));
103187

104188
utils::construct_blinded_hops(secp_ctx, pks, tlvs, session_priv)
105189
}

lightning/src/onion_message/messenger.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use bitcoin::hashes::sha256::Hash as Sha256;
1616
use bitcoin::secp256k1::{self, PublicKey, Scalar, Secp256k1, SecretKey};
1717

1818
use crate::blinded_path::{BlindedPath, IntroductionNode, NextMessageHop, NodeIdLookUp};
19-
use crate::blinded_path::message::{advance_path_by_one, ForwardNode, ForwardTlvs, ReceiveTlvs};
19+
use crate::blinded_path::message::{advance_path_by_one, ForwardNode, ForwardTlvs, ReceiveTlvs, RecipientData};
2020
use crate::blinded_path::utils;
2121
use crate::events::{Event, EventHandler, EventsProvider};
2222
use crate::sign::{EntropySource, NodeSigner, Recipient};
@@ -329,7 +329,7 @@ impl OnionMessageRecipient {
329329
pub struct Responder {
330330
/// The path along which a response can be sent.
331331
reply_path: BlindedPath,
332-
path_id: Option<[u8; 32]>
332+
path_id: Option<[u8; 32]>,
333333
}
334334

335335
impl_writeable_tlv_based!(Responder, {
@@ -780,7 +780,7 @@ pub enum PeeledOnion<T: OnionMessageContents> {
780780
/// Forwarded onion, with the next node id and a new onion
781781
Forward(NextMessageHop, OnionMessage),
782782
/// Received onion message, with decrypted contents, path_id, and reply path
783-
Receive(ParsedOnionMessageContents<T>, Option<[u8; 32]>, Option<BlindedPath>)
783+
Receive(ParsedOnionMessageContents<T>, Option<RecipientData>, Option<BlindedPath>)
784784
}
785785

786786

@@ -930,9 +930,20 @@ where
930930
(control_tlvs_ss, custom_handler.deref(), logger.deref())
931931
) {
932932
Ok((Payload::Receive::<ParsedOnionMessageContents<<<CMH as Deref>::Target as CustomOnionMessageHandler>::CustomMessage>> {
933-
message, control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { path_id }), reply_path,
933+
message, control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs {tlvs}), reply_path,
934934
}, None)) => {
935-
Ok(PeeledOnion::Receive(message, path_id, reply_path))
935+
match (&message, &tlvs) {
936+
(_, None) => {
937+
Ok(PeeledOnion::Receive(message, None, reply_path))
938+
}
939+
(ParsedOnionMessageContents::Offers(_), Some(RecipientData::OffersContext(_))) => {
940+
Ok(PeeledOnion::Receive(message, tlvs, reply_path))
941+
}
942+
(ParsedOnionMessageContents::Custom(_), Some(RecipientData::CustomContext(_))) => {
943+
Ok(PeeledOnion::Receive(message, tlvs, reply_path))
944+
}
945+
_ => Err(())
946+
}
936947
},
937948
Ok((Payload::Forward(ForwardControlTlvs::Unblinded(ForwardTlvs {
938949
next_hop, next_blinding_override
@@ -1414,7 +1425,8 @@ where
14141425
fn handle_onion_message(&self, peer_node_id: &PublicKey, msg: &OnionMessage) {
14151426
let logger = WithContext::from(&self.logger, Some(*peer_node_id), None, None);
14161427
match self.peel_onion_message(msg) {
1417-
Ok(PeeledOnion::Receive(message, path_id, reply_path)) => {
1428+
Ok(PeeledOnion::Receive(message, _tlvs, reply_path)) => {
1429+
let path_id: Option<[u8; 32]> = None;
14181430
log_trace!(
14191431
logger,
14201432
"Received an onion message with path_id {:02x?} and {} reply_path: {:?}",
@@ -1701,7 +1713,7 @@ fn packet_payloads_and_keys<T: OnionMessageContents, S: secp256k1::Signing + sec
17011713
}, prev_control_tlvs_ss.unwrap()));
17021714
} else {
17031715
payloads.push((Payload::Receive {
1704-
control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { path_id: None, }),
1716+
control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { tlvs: None }),
17051717
reply_path: reply_path.take(),
17061718
message,
17071719
}, prev_control_tlvs_ss.unwrap()));

lightning/src/onion_message/packet.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -302,19 +302,21 @@ impl Readable for ControlTlvs {
302302
(1, _padding, option),
303303
(2, short_channel_id, option),
304304
(4, next_node_id, option),
305-
(6, path_id, option),
305+
(6, tlvs, option),
306306
(8, next_blinding_override, option),
307307
});
308308
let _padding: Option<Padding> = _padding;
309309

310+
let receive_tlvs = tlvs.unwrap_or(ReceiveTlvs { tlvs: None });
311+
310312
let next_hop = match (short_channel_id, next_node_id) {
311313
(Some(_), Some(_)) => return Err(DecodeError::InvalidValue),
312314
(Some(scid), None) => Some(NextMessageHop::ShortChannelId(scid)),
313315
(None, Some(pubkey)) => Some(NextMessageHop::NodeId(pubkey)),
314316
(None, None) => None,
315317
};
316318

317-
let valid_fwd_fmt = next_hop.is_some() && path_id.is_none();
319+
let valid_fwd_fmt = next_hop.is_some();
318320
let valid_recv_fmt = next_hop.is_none() && next_blinding_override.is_none();
319321

320322
let payload_fmt = if valid_fwd_fmt {
@@ -323,9 +325,7 @@ impl Readable for ControlTlvs {
323325
next_blinding_override,
324326
})
325327
} else if valid_recv_fmt {
326-
ControlTlvs::Receive(ReceiveTlvs {
327-
path_id,
328-
})
328+
ControlTlvs::Receive(receive_tlvs)
329329
} else {
330330
return Err(DecodeError::InvalidValue)
331331
};
@@ -338,7 +338,13 @@ impl Writeable for ControlTlvs {
338338
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
339339
match self {
340340
Self::Forward(tlvs) => tlvs.write(w),
341-
Self::Receive(tlvs) => tlvs.write(w),
341+
Self::Receive(tlvs) => {
342+
let tlvs = Some(tlvs);
343+
encode_tlv_stream!(w, {
344+
(6, tlvs, option)
345+
});
346+
Ok(())
347+
}
342348
}
343349
}
344350
}

lightning/src/util/ser.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ impl Writer for LengthCalculatingWriter {
103103
}
104104
}
105105

106+
106107
/// Essentially [`std::io::Take`] but a bit simpler and with a method to walk the underlying stream
107108
/// forward to ensure we always consume exactly the fixed length specified.
108109
///

lightning/src/util/ser_macros.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,7 @@ macro_rules! _decode_tlv_stream_range {
557557
// Finally, read the length and value itself:
558558
let length: ser::BigSize = $crate::util::ser::Readable::read(&mut stream_ref)?;
559559
let mut s = ser::FixedLengthReader::new(&mut stream_ref, length.0);
560+
560561
match typ.0 {
561562
$(_t if $crate::_decode_tlv_stream_match_check!(_t, $type, $fieldty) => {
562563
$crate::_decode_tlv!($stream, s, $field, $fieldty);

0 commit comments

Comments
 (0)