@@ -17,7 +17,9 @@ use super::async_payments::AsyncPaymentsMessage;
1717use super :: dns_resolution:: DNSResolverMessage ;
1818use super :: messenger:: CustomOnionMessageHandler ;
1919use super :: offers:: OffersMessage ;
20- use crate :: blinded_path:: message:: { BlindedMessagePath , ForwardTlvs , NextMessageHop , ReceiveTlvs } ;
20+ use crate :: blinded_path:: message:: {
21+ BlindedMessagePath , DummyTlv , ForwardTlvs , NextMessageHop , ReceiveTlvs ,
22+ } ;
2123use crate :: crypto:: streams:: { ChaChaDualPolyReadAdapter , ChaChaPolyWriteAdapter } ;
2224use crate :: ln:: msgs:: DecodeError ;
2325use crate :: ln:: onion_utils;
@@ -112,6 +114,13 @@ impl LengthReadable for Packet {
112114pub ( super ) enum Payload < T : OnionMessageContents > {
113115 /// This payload is for an intermediate hop.
114116 Forward ( ForwardControlTlvs ) ,
117+ /// This payload is a dummy hop, and is intended to be peeled.
118+ Dummy {
119+ /// The [`DummyControlTlvs`] were authenticated with the additional key that was
120+ /// provided to [`ReadableArgs::read`].
121+ control_tlvs_authenticated : bool ,
122+ control_tlvs : DummyControlTlvs ,
123+ } ,
115124 /// This payload is for the final hop.
116125 Receive {
117126 /// The [`ReceiveControlTlvs`] were authenticated with the additional key which was
@@ -212,6 +221,9 @@ pub(super) enum ForwardControlTlvs {
212221 Unblinded ( ForwardTlvs ) ,
213222}
214223
224+ /// Dummy control TLVs, used for dummy hops.
225+ pub ( super ) struct DummyControlTlvs ( pub ( super ) DummyTlv ) ;
226+
215227/// Receive control TLVs in their blinded and unblinded form.
216228pub ( super ) enum ReceiveControlTlvs {
217229 /// See [`ForwardControlTlvs::Blinded`].
@@ -243,6 +255,13 @@ impl<T: OnionMessageContents> Writeable for (Payload<T>, [u8; 32]) {
243255 let write_adapter = ChaChaPolyWriteAdapter :: new ( self . 1 , & control_tlvs) ;
244256 _encode_varint_length_prefixed_tlv ! ( w, { ( 4 , write_adapter, required) } )
245257 } ,
258+ Payload :: Dummy {
259+ control_tlvs : DummyControlTlvs ( control_tlvs) ,
260+ control_tlvs_authenticated : _,
261+ } => {
262+ let write_adapter = ChaChaPolyWriteAdapter :: new ( self . 1 , & control_tlvs) ;
263+ _encode_varint_length_prefixed_tlv ! ( w, { ( 4 , write_adapter, required) } )
264+ } ,
246265 Payload :: Receive {
247266 control_tlvs : ReceiveControlTlvs :: Unblinded ( control_tlvs) ,
248267 reply_path,
@@ -323,6 +342,12 @@ impl<H: CustomOnionMessageHandler + ?Sized, L: Logger + ?Sized>
323342 }
324343 Ok ( Payload :: Forward ( ForwardControlTlvs :: Unblinded ( tlvs) ) )
325344 } ,
345+ Some ( ChaChaDualPolyReadAdapter { readable : ControlTlvs :: Dummy ( tlvs) , used_aad } ) => {
346+ Ok ( Payload :: Dummy {
347+ control_tlvs_authenticated : used_aad,
348+ control_tlvs : DummyControlTlvs ( tlvs) ,
349+ } )
350+ } ,
326351 Some ( ChaChaDualPolyReadAdapter { readable : ControlTlvs :: Receive ( tlvs) , used_aad } ) => {
327352 Ok ( Payload :: Receive {
328353 control_tlvs : ReceiveControlTlvs :: Unblinded ( tlvs) ,
@@ -342,6 +367,8 @@ impl<H: CustomOnionMessageHandler + ?Sized, L: Logger + ?Sized>
342367pub ( crate ) enum ControlTlvs {
343368 /// This onion message is intended to be forwarded.
344369 Forward ( ForwardTlvs ) ,
370+ /// This onion message is a dummy, and is intended to be peeled.
371+ Dummy ( DummyTlv ) ,
345372 /// This onion message is intended to be received.
346373 Receive ( ReceiveTlvs ) ,
347374}
@@ -357,6 +384,7 @@ impl Readable for ControlTlvs {
357384 ( 4 , next_node_id, option) ,
358385 ( 8 , next_blinding_override, option) ,
359386 ( 65537 , context, option) ,
387+ ( 65539 , is_dummy, option) ,
360388 } ) ;
361389
362390 let next_hop = match ( short_channel_id, next_node_id) {
@@ -366,18 +394,13 @@ impl Readable for ControlTlvs {
366394 ( None , None ) => None ,
367395 } ;
368396
369- let valid_fwd_fmt = next_hop. is_some ( ) ;
370- let valid_recv_fmt = next_hop. is_none ( ) && next_blinding_override. is_none ( ) ;
371-
372- let payload_fmt = if valid_fwd_fmt {
373- ControlTlvs :: Forward ( ForwardTlvs {
374- next_hop : next_hop. unwrap ( ) ,
375- next_blinding_override,
376- } )
377- } else if valid_recv_fmt {
378- ControlTlvs :: Receive ( ReceiveTlvs { context } )
379- } else {
380- return Err ( DecodeError :: InvalidValue ) ;
397+ let payload_fmt = match ( next_hop, next_blinding_override, is_dummy) {
398+ ( Some ( hop) , _, None ) => {
399+ ControlTlvs :: Forward ( ForwardTlvs { next_hop : hop, next_blinding_override } )
400+ } ,
401+ ( None , None , Some ( ( ) ) ) => ControlTlvs :: Dummy ( DummyTlv { } ) ,
402+ ( None , None , None ) => ControlTlvs :: Receive ( ReceiveTlvs { context } ) ,
403+ _ => return Err ( DecodeError :: InvalidValue ) ,
381404 } ;
382405
383406 Ok ( payload_fmt)
@@ -388,6 +411,7 @@ impl Writeable for ControlTlvs {
388411 fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
389412 match self {
390413 Self :: Forward ( tlvs) => tlvs. write ( w) ,
414+ Self :: Dummy ( tlvs) => tlvs. write ( w) ,
391415 Self :: Receive ( tlvs) => tlvs. write ( w) ,
392416 }
393417 }
0 commit comments