@@ -21,7 +21,6 @@ use crate::ln::channel_state::CounterpartyForwardingInfo;
21
21
use crate :: ln:: features:: BlindedHopFeatures ;
22
22
use crate :: ln:: msgs:: DecodeError ;
23
23
use crate :: ln:: onion_utils;
24
- use crate :: offers:: invoice:: BlindedPayInfo ;
25
24
use crate :: offers:: invoice_request:: InvoiceRequestFields ;
26
25
use crate :: offers:: offer:: OfferId ;
27
26
use crate :: routing:: gossip:: { NodeId , ReadOnlyNetworkGraph } ;
@@ -34,29 +33,59 @@ use core::ops::Deref;
34
33
#[ allow( unused_imports) ]
35
34
use crate :: prelude:: * ;
36
35
37
- /// A blinded path to be used for sending or receiving a payment, hiding the identity of the
38
- /// recipient.
39
- #[ derive( Clone , Debug , Hash , PartialEq , Eq ) ]
40
- pub struct BlindedPaymentPath ( pub ( super ) BlindedPath ) ;
36
+ /// Information needed to route a payment across a [`BlindedPaymentPath`].
37
+ #[ derive( Clone , Debug , Hash , Eq , PartialEq ) ]
38
+ pub struct BlindedPayInfo {
39
+ /// Base fee charged (in millisatoshi) for the entire blinded path.
40
+ pub fee_base_msat : u32 ,
41
41
42
- impl Writeable for BlindedPaymentPath {
43
- fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
44
- self . 0 . write ( w)
45
- }
42
+ /// Liquidity fee charged (in millionths of the amount transferred) for the entire blinded path
43
+ /// (i.e., 10,000 is 1%).
44
+ pub fee_proportional_millionths : u32 ,
45
+
46
+ /// Number of blocks subtracted from an incoming HTLC's `cltv_expiry` for the entire blinded
47
+ /// path.
48
+ pub cltv_expiry_delta : u16 ,
49
+
50
+ /// The minimum HTLC value (in millisatoshi) that is acceptable to all channel peers on the
51
+ /// blinded path from the introduction node to the recipient, accounting for any fees, i.e., as
52
+ /// seen by the recipient.
53
+ pub htlc_minimum_msat : u64 ,
54
+
55
+ /// The maximum HTLC value (in millisatoshi) that is acceptable to all channel peers on the
56
+ /// blinded path from the introduction node to the recipient, accounting for any fees, i.e., as
57
+ /// seen by the recipient.
58
+ pub htlc_maximum_msat : u64 ,
59
+
60
+ /// Features set in `encrypted_data_tlv` for the `encrypted_recipient_data` TLV record in an
61
+ /// onion payload.
62
+ pub features : BlindedHopFeatures ,
46
63
}
47
64
48
- impl Readable for BlindedPaymentPath {
49
- fn read < R : io:: Read > ( r : & mut R ) -> Result < Self , DecodeError > {
50
- Ok ( Self ( BlindedPath :: read ( r) ?) )
51
- }
65
+ impl_writeable ! ( BlindedPayInfo , {
66
+ fee_base_msat,
67
+ fee_proportional_millionths,
68
+ cltv_expiry_delta,
69
+ htlc_minimum_msat,
70
+ htlc_maximum_msat,
71
+ features
72
+ } ) ;
73
+
74
+ /// A blinded path to be used for sending or receiving a payment, hiding the identity of the
75
+ /// recipient.
76
+ #[ derive( Clone , Debug , Hash , PartialEq , Eq ) ]
77
+ pub struct BlindedPaymentPath {
78
+ pub ( super ) inner_path : BlindedPath ,
79
+ /// The [`BlindedPayInfo`] used to pay this blinded path.
80
+ pub payinfo : BlindedPayInfo ,
52
81
}
53
82
54
83
impl BlindedPaymentPath {
55
84
/// Create a one-hop blinded path for a payment.
56
85
pub fn one_hop < ES : Deref , T : secp256k1:: Signing + secp256k1:: Verification > (
57
86
payee_node_id : PublicKey , payee_tlvs : ReceiveTlvs , min_final_cltv_expiry_delta : u16 ,
58
87
entropy_source : ES , secp_ctx : & Secp256k1 < T >
59
- ) -> Result < ( BlindedPayInfo , Self ) , ( ) > where ES :: Target : EntropySource {
88
+ ) -> Result < Self , ( ) > where ES :: Target : EntropySource {
60
89
// This value is not considered in pathfinding for 1-hop blinded paths, because it's intended to
61
90
// be in relation to a specific channel.
62
91
let htlc_maximum_msat = u64:: max_value ( ) ;
@@ -77,7 +106,7 @@ impl BlindedPaymentPath {
77
106
intermediate_nodes : & [ ForwardNode ] , payee_node_id : PublicKey , payee_tlvs : ReceiveTlvs ,
78
107
htlc_maximum_msat : u64 , min_final_cltv_expiry_delta : u16 , entropy_source : ES ,
79
108
secp_ctx : & Secp256k1 < T >
80
- ) -> Result < ( BlindedPayInfo , Self ) , ( ) > where ES :: Target : EntropySource {
109
+ ) -> Result < Self , ( ) > where ES :: Target : EntropySource {
81
110
let introduction_node = IntroductionNode :: NodeId (
82
111
intermediate_nodes. first ( ) . map_or ( payee_node_id, |n| n. node_id )
83
112
) ;
@@ -87,38 +116,41 @@ impl BlindedPaymentPath {
87
116
let blinded_payinfo = compute_payinfo (
88
117
intermediate_nodes, & payee_tlvs, htlc_maximum_msat, min_final_cltv_expiry_delta
89
118
) ?;
90
- Ok ( ( blinded_payinfo, Self ( BlindedPath {
91
- introduction_node,
92
- blinding_point : PublicKey :: from_secret_key ( secp_ctx, & blinding_secret) ,
93
- blinded_hops : blinded_hops (
94
- secp_ctx, intermediate_nodes, payee_node_id, payee_tlvs, & blinding_secret
95
- ) . map_err ( |_| ( ) ) ?,
96
- } ) ) )
119
+ Ok ( Self {
120
+ inner_path : BlindedPath {
121
+ introduction_node,
122
+ blinding_point : PublicKey :: from_secret_key ( secp_ctx, & blinding_secret) ,
123
+ blinded_hops : blinded_hops (
124
+ secp_ctx, intermediate_nodes, payee_node_id, payee_tlvs, & blinding_secret
125
+ ) . map_err ( |_| ( ) ) ?,
126
+ } ,
127
+ payinfo : blinded_payinfo
128
+ } )
97
129
}
98
130
99
131
/// Returns the introduction [`NodeId`] of the blinded path, if it is publicly reachable (i.e.,
100
132
/// it is found in the network graph).
101
133
pub fn public_introduction_node_id < ' a > (
102
134
& self , network_graph : & ' a ReadOnlyNetworkGraph
103
135
) -> Option < & ' a NodeId > {
104
- self . 0 . public_introduction_node_id ( network_graph)
136
+ self . inner_path . public_introduction_node_id ( network_graph)
105
137
}
106
138
107
139
/// The [`IntroductionNode`] of the blinded path.
108
140
pub fn introduction_node ( & self ) -> & IntroductionNode {
109
- & self . 0 . introduction_node
141
+ & self . inner_path . introduction_node
110
142
}
111
143
112
144
/// Used by the [`IntroductionNode`] to decrypt its [`encrypted_payload`] to forward the payment.
113
145
///
114
146
/// [`encrypted_payload`]: BlindedHop::encrypted_payload
115
147
pub fn blinding_point ( & self ) -> PublicKey {
116
- self . 0 . blinding_point
148
+ self . inner_path . blinding_point
117
149
}
118
150
119
151
/// The [`BlindedHop`]s within the blinded path.
120
152
pub fn blinded_hops ( & self ) -> & [ BlindedHop ] {
121
- & self . 0 . blinded_hops
153
+ & self . inner_path . blinded_hops
122
154
}
123
155
124
156
/// Advance the blinded onion payment path by one hop, making the second hop into the new
@@ -133,9 +165,9 @@ impl BlindedPaymentPath {
133
165
NL :: Target : NodeIdLookUp ,
134
166
T : secp256k1:: Signing + secp256k1:: Verification ,
135
167
{
136
- let control_tlvs_ss = node_signer. ecdh ( Recipient :: Node , & self . 0 . blinding_point , None ) ?;
168
+ let control_tlvs_ss = node_signer. ecdh ( Recipient :: Node , & self . inner_path . blinding_point , None ) ?;
137
169
let rho = onion_utils:: gen_rho_from_shared_secret ( & control_tlvs_ss. secret_bytes ( ) ) ;
138
- let encrypted_control_tlvs = & self . 0 . blinded_hops . get ( 0 ) . ok_or ( ( ) ) ?. encrypted_payload ;
170
+ let encrypted_control_tlvs = & self . inner_path . blinded_hops . get ( 0 ) . ok_or ( ( ) ) ?. encrypted_payload ;
139
171
let mut s = Cursor :: new ( encrypted_control_tlvs) ;
140
172
let mut reader = FixedLengthReader :: new ( & mut s, encrypted_control_tlvs. len ( ) as u64 ) ;
141
173
match ChaChaPolyReadAdapter :: read ( & mut reader, rho) {
@@ -147,31 +179,43 @@ impl BlindedPaymentPath {
147
179
None => return Err ( ( ) ) ,
148
180
} ;
149
181
let mut new_blinding_point = onion_utils:: next_hop_pubkey (
150
- secp_ctx, self . 0 . blinding_point , control_tlvs_ss. as_ref ( )
182
+ secp_ctx, self . inner_path . blinding_point , control_tlvs_ss. as_ref ( )
151
183
) . map_err ( |_| ( ) ) ?;
152
- mem:: swap ( & mut self . 0 . blinding_point , & mut new_blinding_point) ;
153
- self . 0 . introduction_node = IntroductionNode :: NodeId ( next_node_id) ;
154
- self . 0 . blinded_hops . remove ( 0 ) ;
184
+ mem:: swap ( & mut self . inner_path . blinding_point , & mut new_blinding_point) ;
185
+ self . inner_path . introduction_node = IntroductionNode :: NodeId ( next_node_id) ;
186
+ self . inner_path . blinded_hops . remove ( 0 ) ;
155
187
Ok ( ( ) )
156
188
} ,
157
189
_ => Err ( ( ) )
158
190
}
159
191
}
160
192
193
+ pub ( crate ) fn inner_blinded_path ( & self ) -> & BlindedPath {
194
+ & self . inner_path
195
+ }
196
+
197
+ pub ( crate ) fn from_parts ( inner_path : BlindedPath , payinfo : BlindedPayInfo ) -> Self {
198
+ Self { inner_path, payinfo }
199
+ }
200
+
161
201
#[ cfg( any( test, fuzzing) ) ]
162
202
pub fn from_raw (
163
- introduction_node_id : PublicKey , blinding_point : PublicKey , blinded_hops : Vec < BlindedHop >
203
+ introduction_node_id : PublicKey , blinding_point : PublicKey , blinded_hops : Vec < BlindedHop > ,
204
+ payinfo : BlindedPayInfo
164
205
) -> Self {
165
- Self ( BlindedPath {
166
- introduction_node : IntroductionNode :: NodeId ( introduction_node_id) ,
167
- blinding_point,
168
- blinded_hops,
169
- } )
206
+ Self {
207
+ inner_path : BlindedPath {
208
+ introduction_node : IntroductionNode :: NodeId ( introduction_node_id) ,
209
+ blinding_point,
210
+ blinded_hops,
211
+ } ,
212
+ payinfo
213
+ }
170
214
}
171
215
172
216
#[ cfg( test) ]
173
217
pub fn clear_blinded_hops ( & mut self ) {
174
- self . 0 . blinded_hops . clear ( )
218
+ self . inner_path . blinded_hops . clear ( )
175
219
}
176
220
}
177
221
0 commit comments