13
13
14
14
use bitcoin:: secp256k1:: { self , PublicKey , Secp256k1 , SecretKey } ;
15
15
16
+ use crate :: ln:: channelmanager:: PaymentId ;
17
+ use crate :: ln:: msgs:: DecodeError ;
16
18
#[ allow( unused_imports) ]
17
19
use crate :: prelude:: * ;
18
20
@@ -24,7 +26,7 @@ use crate::ln::onion_utils;
24
26
use crate :: onion_message:: packet:: ControlTlvs ;
25
27
use crate :: sign:: { NodeSigner , Recipient } ;
26
28
use crate :: crypto:: streams:: ChaChaPolyReadAdapter ;
27
- use crate :: util:: ser:: { FixedLengthReader , LengthReadableArgs , Writeable , Writer } ;
29
+ use crate :: util:: ser:: { FixedLengthReader , LengthReadableArgs , Readable , Writeable , Writer } ;
28
30
29
31
use core:: mem;
30
32
use core:: ops:: Deref ;
@@ -50,14 +52,6 @@ pub(crate) struct ForwardTlvs {
50
52
pub ( crate ) next_blinding_override : Option < PublicKey > ,
51
53
}
52
54
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
-
61
55
impl Writeable for ForwardTlvs {
62
56
fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , io:: Error > {
63
57
let ( next_node_id, short_channel_id) = match self . next_hop {
@@ -74,16 +68,106 @@ impl Writeable for ForwardTlvs {
74
68
}
75
69
}
76
70
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
+
77
153
impl Writeable for ReceiveTlvs {
78
154
fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , io:: Error > {
79
- // TODO: write padding
80
155
encode_tlv_stream ! ( writer, {
81
- ( 6 , self . path_id , option) ,
156
+ ( 6 , self . tlvs , option) ,
82
157
} ) ;
83
158
Ok ( ( ) )
84
159
}
85
160
}
86
161
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
+
87
171
/// Construct blinded onion message hops for the given `intermediate_nodes` and `recipient_node_id`.
88
172
pub ( super ) fn blinded_hops < T : secp256k1:: Signing + secp256k1:: Verification > (
89
173
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>(
99
183
None => NextMessageHop :: NodeId ( * pubkey) ,
100
184
} )
101
185
. 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 ) ) ) ) ;
103
187
104
188
utils:: construct_blinded_hops ( secp_ctx, pks, tlvs, session_priv)
105
189
}
0 commit comments