@@ -939,10 +939,24 @@ enum CandidateRouteHop<'a> {
939
939
info : DirectedChannelInfo < ' a > ,
940
940
short_channel_id : u64 ,
941
941
} ,
942
- /// A hop to the payee found in the payment invoice, though not necessarily a direct channel.
942
+ /// A hop to the payee found in the BOLT 11 payment invoice, though not necessarily a direct
943
+ /// channel.
943
944
PrivateHop {
944
945
hint : & ' a RouteHintHop ,
945
- }
946
+ } ,
947
+ /// The payee's identity is concealed behind blinded paths provided in a BOLT 12 invoice.
948
+ Blinded {
949
+ hint : & ' a ( BlindedPayInfo , BlindedPath ) ,
950
+ hint_idx : usize ,
951
+ } ,
952
+ /// Similar to [`Self::Blinded`], but the path here has 1 blinded hop. `BlindedPayInfo` provided
953
+ /// for 1-hop blinded paths is ignored because it is meant to apply to the hops *between* the
954
+ /// introduction node and the destination. Useful for tracking that we need to include a blinded
955
+ /// path at the end of our [`Route`].
956
+ OneHopBlinded {
957
+ hint : & ' a ( BlindedPayInfo , BlindedPath ) ,
958
+ hint_idx : usize ,
959
+ } ,
946
960
}
947
961
948
962
impl < ' a > CandidateRouteHop < ' a > {
@@ -951,6 +965,8 @@ impl<'a> CandidateRouteHop<'a> {
951
965
CandidateRouteHop :: FirstHop { details } => Some ( details. get_outbound_payment_scid ( ) . unwrap ( ) ) ,
952
966
CandidateRouteHop :: PublicHop { short_channel_id, .. } => Some ( * short_channel_id) ,
953
967
CandidateRouteHop :: PrivateHop { hint } => Some ( hint. short_channel_id ) ,
968
+ CandidateRouteHop :: Blinded { .. } => None ,
969
+ CandidateRouteHop :: OneHopBlinded { .. } => None ,
954
970
}
955
971
}
956
972
@@ -960,6 +976,8 @@ impl<'a> CandidateRouteHop<'a> {
960
976
CandidateRouteHop :: FirstHop { details } => details. counterparty . features . to_context ( ) ,
961
977
CandidateRouteHop :: PublicHop { info, .. } => info. channel ( ) . features . clone ( ) ,
962
978
CandidateRouteHop :: PrivateHop { .. } => ChannelFeatures :: empty ( ) ,
979
+ CandidateRouteHop :: Blinded { .. } => ChannelFeatures :: empty ( ) ,
980
+ CandidateRouteHop :: OneHopBlinded { .. } => ChannelFeatures :: empty ( ) ,
963
981
}
964
982
}
965
983
@@ -968,6 +986,8 @@ impl<'a> CandidateRouteHop<'a> {
968
986
CandidateRouteHop :: FirstHop { .. } => 0 ,
969
987
CandidateRouteHop :: PublicHop { info, .. } => info. direction ( ) . cltv_expiry_delta as u32 ,
970
988
CandidateRouteHop :: PrivateHop { hint } => hint. cltv_expiry_delta as u32 ,
989
+ CandidateRouteHop :: Blinded { hint, .. } => hint. 0 . cltv_expiry_delta as u32 ,
990
+ CandidateRouteHop :: OneHopBlinded { .. } => 0 ,
971
991
}
972
992
}
973
993
@@ -976,6 +996,8 @@ impl<'a> CandidateRouteHop<'a> {
976
996
CandidateRouteHop :: FirstHop { details } => details. next_outbound_htlc_minimum_msat ,
977
997
CandidateRouteHop :: PublicHop { info, .. } => info. direction ( ) . htlc_minimum_msat ,
978
998
CandidateRouteHop :: PrivateHop { hint } => hint. htlc_minimum_msat . unwrap_or ( 0 ) ,
999
+ CandidateRouteHop :: Blinded { hint, .. } => hint. 0 . htlc_minimum_msat ,
1000
+ CandidateRouteHop :: OneHopBlinded { .. } => 0 ,
979
1001
}
980
1002
}
981
1003
@@ -986,6 +1008,14 @@ impl<'a> CandidateRouteHop<'a> {
986
1008
} ,
987
1009
CandidateRouteHop :: PublicHop { info, .. } => info. direction ( ) . fees ,
988
1010
CandidateRouteHop :: PrivateHop { hint } => hint. fees ,
1011
+ CandidateRouteHop :: Blinded { hint, .. } => {
1012
+ RoutingFees {
1013
+ base_msat : hint. 0 . fee_base_msat ,
1014
+ proportional_millionths : hint. 0 . fee_proportional_millionths
1015
+ }
1016
+ } ,
1017
+ CandidateRouteHop :: OneHopBlinded { .. } =>
1018
+ RoutingFees { base_msat : 0 , proportional_millionths : 0 } ,
989
1019
}
990
1020
}
991
1021
@@ -999,10 +1029,16 @@ impl<'a> CandidateRouteHop<'a> {
999
1029
EffectiveCapacity :: HintMaxHTLC { amount_msat : * max } ,
1000
1030
CandidateRouteHop :: PrivateHop { hint : RouteHintHop { htlc_maximum_msat : None , .. } } =>
1001
1031
EffectiveCapacity :: Infinite ,
1032
+ CandidateRouteHop :: Blinded { hint, .. } =>
1033
+ EffectiveCapacity :: HintMaxHTLC { amount_msat : hint. 0 . htlc_maximum_msat } ,
1034
+ CandidateRouteHop :: OneHopBlinded { .. } => EffectiveCapacity :: Infinite ,
1002
1035
}
1003
1036
}
1037
+
1004
1038
fn id ( & self , channel_direction : bool /* src_node_id < target_node_id */ ) -> CandidateHopId {
1005
1039
match self {
1040
+ CandidateRouteHop :: Blinded { hint_idx, .. } => CandidateHopId :: Blinded ( * hint_idx) ,
1041
+ CandidateRouteHop :: OneHopBlinded { hint_idx, .. } => CandidateHopId :: Blinded ( * hint_idx) ,
1006
1042
_ => CandidateHopId :: Clear ( ( self . short_channel_id ( ) . unwrap ( ) , channel_direction) ) ,
1007
1043
}
1008
1044
}
@@ -1259,6 +1295,12 @@ struct LoggedCandidateHop<'a>(&'a CandidateRouteHop<'a>);
1259
1295
impl < ' a > fmt:: Display for LoggedCandidateHop < ' a > {
1260
1296
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1261
1297
match self . 0 {
1298
+ CandidateRouteHop :: Blinded { hint, .. } | CandidateRouteHop :: OneHopBlinded { hint, .. } => {
1299
+ "blinded route hint with introduction node id " . fmt ( f) ?;
1300
+ hint. 1 . introduction_node_id . fmt ( f) ?;
1301
+ " and blinding point " . fmt ( f) ?;
1302
+ hint. 1 . blinding_point . fmt ( f)
1303
+ } ,
1262
1304
_ => {
1263
1305
"SCID " . fmt ( f) ?;
1264
1306
self . 0 . short_channel_id ( ) . unwrap ( ) . fmt ( f)
0 commit comments