@@ -931,9 +931,15 @@ enum CandidateRouteHop<'a> {
931
931
info : DirectedChannelInfo < ' a > ,
932
932
short_channel_id : u64 ,
933
933
} ,
934
- /// A hop to the payee found in the payment invoice, though not necessarily a direct channel.
934
+ /// A hop to the payee found in the BOLT 11 payment invoice, though not necessarily a direct
935
+ /// channel.
935
936
PrivateHop {
936
937
hint : & ' a RouteHintHop ,
938
+ } ,
939
+ /// The payee's identity is concealed behind blinded paths provided in a BOLT 12 invoice.
940
+ Blinded {
941
+ hint : & ' a ( BlindedPayInfo , BlindedPath ) ,
942
+ hint_idx : usize ,
937
943
}
938
944
}
939
945
@@ -943,6 +949,7 @@ impl<'a> CandidateRouteHop<'a> {
943
949
CandidateRouteHop :: FirstHop { details } => Some ( details. get_outbound_payment_scid ( ) . unwrap ( ) ) ,
944
950
CandidateRouteHop :: PublicHop { short_channel_id, .. } => Some ( * short_channel_id) ,
945
951
CandidateRouteHop :: PrivateHop { hint } => Some ( hint. short_channel_id ) ,
952
+ CandidateRouteHop :: Blinded { .. } => None ,
946
953
}
947
954
}
948
955
@@ -952,6 +959,7 @@ impl<'a> CandidateRouteHop<'a> {
952
959
CandidateRouteHop :: FirstHop { details } => details. counterparty . features . to_context ( ) ,
953
960
CandidateRouteHop :: PublicHop { info, .. } => info. channel ( ) . features . clone ( ) ,
954
961
CandidateRouteHop :: PrivateHop { .. } => ChannelFeatures :: empty ( ) ,
962
+ CandidateRouteHop :: Blinded { .. } => ChannelFeatures :: empty ( ) ,
955
963
}
956
964
}
957
965
@@ -960,6 +968,8 @@ impl<'a> CandidateRouteHop<'a> {
960
968
CandidateRouteHop :: FirstHop { .. } => 0 ,
961
969
CandidateRouteHop :: PublicHop { info, .. } => info. direction ( ) . cltv_expiry_delta as u32 ,
962
970
CandidateRouteHop :: PrivateHop { hint } => hint. cltv_expiry_delta as u32 ,
971
+ CandidateRouteHop :: Blinded { hint, .. } =>
972
+ if hint. 1 . blinded_hops . len ( ) == 1 { 0 } else { hint. 0 . cltv_expiry_delta as u32 }
963
973
}
964
974
}
965
975
@@ -968,6 +978,8 @@ impl<'a> CandidateRouteHop<'a> {
968
978
CandidateRouteHop :: FirstHop { details } => details. next_outbound_htlc_minimum_msat ,
969
979
CandidateRouteHop :: PublicHop { info, .. } => info. direction ( ) . htlc_minimum_msat ,
970
980
CandidateRouteHop :: PrivateHop { hint } => hint. htlc_minimum_msat . unwrap_or ( 0 ) ,
981
+ CandidateRouteHop :: Blinded { hint, .. } =>
982
+ if hint. 1 . blinded_hops . len ( ) == 1 { 0 } else { hint. 0 . htlc_minimum_msat }
971
983
}
972
984
}
973
985
@@ -978,6 +990,17 @@ impl<'a> CandidateRouteHop<'a> {
978
990
} ,
979
991
CandidateRouteHop :: PublicHop { info, .. } => info. direction ( ) . fees ,
980
992
CandidateRouteHop :: PrivateHop { hint } => hint. fees ,
993
+ CandidateRouteHop :: Blinded { hint, .. } => {
994
+ if hint. 1 . blinded_hops . len ( ) == 1 {
995
+ RoutingFees { base_msat : 0 , proportional_millionths : 0 }
996
+ } else {
997
+ RoutingFees {
998
+ base_msat : hint. 0 . fee_base_msat ,
999
+ proportional_millionths :
1000
+ hint. 0 . fee_proportional_millionths
1001
+ }
1002
+ }
1003
+ }
981
1004
}
982
1005
}
983
1006
@@ -991,10 +1014,17 @@ impl<'a> CandidateRouteHop<'a> {
991
1014
EffectiveCapacity :: HintMaxHTLC { amount_msat : * max } ,
992
1015
CandidateRouteHop :: PrivateHop { hint : RouteHintHop { htlc_maximum_msat : None , .. } } =>
993
1016
EffectiveCapacity :: Infinite ,
1017
+ CandidateRouteHop :: Blinded { hint, .. } =>
1018
+ EffectiveCapacity :: HintMaxHTLC {
1019
+ amount_msat : if hint. 1 . blinded_hops . len ( ) == 1 { u64:: max_value ( ) }
1020
+ else { hint. 0 . htlc_maximum_msat }
1021
+ } ,
994
1022
}
995
1023
}
1024
+
996
1025
fn id ( & self , channel_direction : bool /* src_node_id < target_node_id */ ) -> CandidateHopId {
997
1026
match self {
1027
+ CandidateRouteHop :: Blinded { hint_idx, .. } => CandidateHopId :: Blinded ( * hint_idx) ,
998
1028
_ => CandidateHopId :: Clear ( ( self . short_channel_id ( ) . unwrap ( ) , channel_direction) ) ,
999
1029
}
1000
1030
}
@@ -1251,6 +1281,12 @@ struct LoggedCandidateHop<'a>(&'a CandidateRouteHop<'a>);
1251
1281
impl < ' a > fmt:: Display for LoggedCandidateHop < ' a > {
1252
1282
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1253
1283
match self . 0 {
1284
+ CandidateRouteHop :: Blinded { hint, .. } => {
1285
+ "blinded route hint with introduction node id " . fmt ( f) ?;
1286
+ hint. 1 . introduction_node_id . fmt ( f) ?;
1287
+ " and blinding point " . fmt ( f) ?;
1288
+ hint. 1 . blinding_point . fmt ( f)
1289
+ } ,
1254
1290
_ => {
1255
1291
"SCID " . fmt ( f) ?;
1256
1292
self . 0 . short_channel_id ( ) . unwrap ( ) . fmt ( f)
0 commit comments