Skip to content

Commit 55098b4

Browse files
committed
Introduce custom TLV support for OnionMessage
1 parent 78ac48c commit 55098b4

File tree

4 files changed

+45
-8
lines changed

4 files changed

+45
-8
lines changed

lightning/src/blinded_path/message.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ pub(crate) struct ForwardTlvs {
2222
/// Senders to a blinded path use this value to concatenate the route they find to the
2323
/// introduction node with the blinded path.
2424
pub(crate) next_blinding_override: Option<PublicKey>,
25+
/// Custom Tlvs
26+
pub(crate) custom_tlvs: Vec<(u64, Vec<u8>)>,
2527
}
2628

2729
/// Similar to [`ForwardTlvs`], but these TLVs are for the final node.
@@ -30,6 +32,8 @@ pub(crate) struct ReceiveTlvs {
3032
/// sending to. This is useful for receivers to check that said blinded path is being used in
3133
/// the right context.
3234
pub(crate) path_id: Option<[u8; 32]>,
35+
/// Custom Tlvs
36+
pub(crate) custom_tlvs: Vec<(u64, Vec<u8>)>,
3337
}
3438

3539
impl Writeable for ForwardTlvs {
@@ -60,9 +64,9 @@ pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
6064
let blinded_tlvs = unblinded_path.iter()
6165
.skip(1) // The first node's TLVs contains the next node's pubkey
6266
.map(|pk| {
63-
ControlTlvs::Forward(ForwardTlvs { next_node_id: *pk, next_blinding_override: None })
67+
ControlTlvs::Forward(ForwardTlvs { next_node_id: *pk, next_blinding_override: None, custom_tlvs: Vec::new() })
6468
})
65-
.chain(core::iter::once(ControlTlvs::Receive(ReceiveTlvs { path_id: None })));
69+
.chain(core::iter::once(ControlTlvs::Receive(ReceiveTlvs { path_id: None, custom_tlvs: Vec::new() })));
6670

6771
utils::construct_blinded_hops(secp_ctx, unblinded_path.iter(), blinded_tlvs, session_priv)
6872
}
@@ -80,7 +84,7 @@ pub(crate) fn advance_path_by_one<NS: Deref, T: secp256k1::Signing + secp256k1::
8084
match ChaChaPolyReadAdapter::read(&mut reader, rho) {
8185
Ok(ChaChaPolyReadAdapter { readable: ControlTlvs::Forward(ForwardTlvs {
8286
mut next_node_id, next_blinding_override,
83-
})}) => {
87+
custom_tlvs})}) => {
8488
let mut new_blinding_point = match next_blinding_override {
8589
Some(blinding_point) => blinding_point,
8690
None => {

lightning/src/onion_message/messenger.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -627,13 +627,13 @@ where
627627
(control_tlvs_ss, custom_handler.deref(), logger.deref())
628628
) {
629629
Ok((Payload::Receive::<ParsedOnionMessageContents<<<CMH as Deref>::Target as CustomOnionMessageHandler>::CustomMessage>> {
630-
message, control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { path_id }), reply_path,
630+
message, control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { path_id, custom_tlvs}), reply_path,
631631
}, None)) => {
632632
Ok(PeeledOnion::Receive(message, path_id, reply_path))
633633
},
634634
Ok((Payload::Forward(ForwardControlTlvs::Unblinded(ForwardTlvs {
635-
next_node_id, next_blinding_override
636-
})), Some((next_hop_hmac, new_packet_bytes)))) => {
635+
next_node_id, next_blinding_override,
636+
custom_tlvs})), Some((next_hop_hmac, new_packet_bytes)))) => {
637637
// TODO: we need to check whether `next_node_id` is our node, in which case this is a dummy
638638
// blinded hop and this onion message is destined for us. In this situation, we should keep
639639
// unwrapping the onion layers to get to the final payload. Since we don't have the option
@@ -1109,6 +1109,7 @@ fn packet_payloads_and_keys<T: OnionMessageContents, S: secp256k1::Signing + sec
11091109
ForwardTlvs {
11101110
next_node_id: unblinded_pk_opt.unwrap(),
11111111
next_blinding_override: None,
1112+
custom_tlvs: Vec::new(),
11121113
}
11131114
)), ss));
11141115
}
@@ -1119,6 +1120,7 @@ fn packet_payloads_and_keys<T: OnionMessageContents, S: secp256k1::Signing + sec
11191120
payloads.push((Payload::Forward(ForwardControlTlvs::Unblinded(ForwardTlvs {
11201121
next_node_id: intro_node_id,
11211122
next_blinding_override: Some(blinding_pt),
1123+
custom_tlvs: Vec::new()
11221124
})), control_tlvs_ss));
11231125
}
11241126
}
@@ -1152,7 +1154,7 @@ fn packet_payloads_and_keys<T: OnionMessageContents, S: secp256k1::Signing + sec
11521154
}, prev_control_tlvs_ss.unwrap()));
11531155
} else {
11541156
payloads.push((Payload::Receive {
1155-
control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { path_id: None, }),
1157+
control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { path_id: None, custom_tlvs: Vec::new()}),
11561158
reply_path: reply_path.take(),
11571159
message,
11581160
}, prev_control_tlvs_ss.unwrap()));

lightning/src/onion_message/packet.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,12 +282,22 @@ pub(crate) enum ControlTlvs {
282282

283283
impl Readable for ControlTlvs {
284284
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
285-
_init_and_read_tlv_stream!(r, {
285+
let mut custom_tlvs = Vec::new();
286+
287+
let tlv_len = BigSize::read(r)?;
288+
let rd = FixedLengthReader::new(r, tlv_len.0);
289+
_init_and_read_tlv_stream_with_custom_tlv_decode!(rd, {
286290
(1, _padding, option),
287291
(2, _short_channel_id, option),
288292
(4, next_node_id, option),
289293
(6, path_id, option),
290294
(8, next_blinding_override, option),
295+
}, |msg_type: u64, msg_reader: &mut FixedLengthReader<_>| -> Result<bool, DecodeError> {
296+
if msg_type < 1 << 16 { return Ok(false) }
297+
let mut value = Vec::new();
298+
msg_reader.read_to_end(&mut value)?;
299+
custom_tlvs.push((msg_type, value));
300+
Ok(true)
291301
});
292302
let _padding: Option<Padding> = _padding;
293303
let _short_channel_id: Option<u64> = _short_channel_id;
@@ -299,10 +309,12 @@ impl Readable for ControlTlvs {
299309
ControlTlvs::Forward(ForwardTlvs {
300310
next_node_id: next_node_id.unwrap(),
301311
next_blinding_override,
312+
custom_tlvs,
302313
})
303314
} else if valid_recv_fmt {
304315
ControlTlvs::Receive(ReceiveTlvs {
305316
path_id,
317+
custom_tlvs,
306318
})
307319
} else {
308320
return Err(DecodeError::InvalidValue)

lightning/src/util/ser_macros.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,7 @@ macro_rules! decode_tlv_stream {
472472
///
473473
/// [`FixedLengthReader`]: crate::util::ser::FixedLengthReader
474474
/// [`DecodeError`]: crate::ln::msgs::DecodeError
475+
#[macro_export]
475476
macro_rules! decode_tlv_stream_with_custom_tlv_decode {
476477
($stream: expr, {$(($type: expr, $field: ident, $fieldty: tt)),* $(,)*}
477478
$(, $decode_custom_tlv: expr)?) => { {
@@ -825,6 +826,24 @@ macro_rules! _init_and_read_tlv_stream {
825826
}
826827
}
827828

829+
/// Equivalent to running [`_init_tlv_field_var`] then [`decode_tlv_stream_with_custom_tlv_decode`].
830+
///
831+
/// If any unused values are read, their type MUST be specified or else `rustc` will read them as an
832+
/// `i64`.
833+
834+
macro_rules! _init_and_read_tlv_stream_with_custom_tlv_decode {
835+
($reader: ident, {$(($type: expr, $field: ident, $fieldty: tt)),* $(,)*}
836+
$(, $decode_custom_tlv: expr)?) => {
837+
$(
838+
$crate::_init_tlv_field_var!($field, $fieldty);
839+
)*
840+
841+
$crate::decode_tlv_stream_with_custom_tlv_decode!(
842+
$reader, {$(($type, $field, $fieldty)),*} $(, $decode_custom_tlv)?
843+
);
844+
}
845+
}
846+
828847
/// Implements [`Readable`]/[`Writeable`] for a struct storing it as a set of TLVs
829848
/// If `$fieldty` is `required`, then `$field` is a required field that is not an [`Option`] nor a [`Vec`].
830849
/// If `$fieldty` is `(default_value, $default)`, then `$field` will be set to `$default` if not present.

0 commit comments

Comments
 (0)