@@ -939,10 +939,24 @@ enum CandidateRouteHop<'a> {
939939 info : DirectedChannelInfo < ' a > ,
940940 short_channel_id : u64 ,
941941 } ,
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.
943944 PrivateHop {
944945 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+ } ,
946960}
947961
948962impl < ' a > CandidateRouteHop < ' a > {
@@ -951,6 +965,8 @@ impl<'a> CandidateRouteHop<'a> {
951965 CandidateRouteHop :: FirstHop { details } => Some ( details. get_outbound_payment_scid ( ) . unwrap ( ) ) ,
952966 CandidateRouteHop :: PublicHop { short_channel_id, .. } => Some ( * short_channel_id) ,
953967 CandidateRouteHop :: PrivateHop { hint } => Some ( hint. short_channel_id ) ,
968+ CandidateRouteHop :: Blinded { .. } => None ,
969+ CandidateRouteHop :: OneHopBlinded { .. } => None ,
954970 }
955971 }
956972
@@ -960,6 +976,8 @@ impl<'a> CandidateRouteHop<'a> {
960976 CandidateRouteHop :: FirstHop { details } => details. counterparty . features . to_context ( ) ,
961977 CandidateRouteHop :: PublicHop { info, .. } => info. channel ( ) . features . clone ( ) ,
962978 CandidateRouteHop :: PrivateHop { .. } => ChannelFeatures :: empty ( ) ,
979+ CandidateRouteHop :: Blinded { .. } => ChannelFeatures :: empty ( ) ,
980+ CandidateRouteHop :: OneHopBlinded { .. } => ChannelFeatures :: empty ( ) ,
963981 }
964982 }
965983
@@ -968,6 +986,8 @@ impl<'a> CandidateRouteHop<'a> {
968986 CandidateRouteHop :: FirstHop { .. } => 0 ,
969987 CandidateRouteHop :: PublicHop { info, .. } => info. direction ( ) . cltv_expiry_delta as u32 ,
970988 CandidateRouteHop :: PrivateHop { hint } => hint. cltv_expiry_delta as u32 ,
989+ CandidateRouteHop :: Blinded { hint, .. } => hint. 0 . cltv_expiry_delta as u32 ,
990+ CandidateRouteHop :: OneHopBlinded { .. } => 0 ,
971991 }
972992 }
973993
@@ -976,6 +996,8 @@ impl<'a> CandidateRouteHop<'a> {
976996 CandidateRouteHop :: FirstHop { details } => details. next_outbound_htlc_minimum_msat ,
977997 CandidateRouteHop :: PublicHop { info, .. } => info. direction ( ) . htlc_minimum_msat ,
978998 CandidateRouteHop :: PrivateHop { hint } => hint. htlc_minimum_msat . unwrap_or ( 0 ) ,
999+ CandidateRouteHop :: Blinded { hint, .. } => hint. 0 . htlc_minimum_msat ,
1000+ CandidateRouteHop :: OneHopBlinded { .. } => 0 ,
9791001 }
9801002 }
9811003
@@ -986,6 +1008,14 @@ impl<'a> CandidateRouteHop<'a> {
9861008 } ,
9871009 CandidateRouteHop :: PublicHop { info, .. } => info. direction ( ) . fees ,
9881010 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 } ,
9891019 }
9901020 }
9911021
@@ -999,10 +1029,16 @@ impl<'a> CandidateRouteHop<'a> {
9991029 EffectiveCapacity :: HintMaxHTLC { amount_msat : * max } ,
10001030 CandidateRouteHop :: PrivateHop { hint : RouteHintHop { htlc_maximum_msat : None , .. } } =>
10011031 EffectiveCapacity :: Infinite ,
1032+ CandidateRouteHop :: Blinded { hint, .. } =>
1033+ EffectiveCapacity :: HintMaxHTLC { amount_msat : hint. 0 . htlc_maximum_msat } ,
1034+ CandidateRouteHop :: OneHopBlinded { .. } => EffectiveCapacity :: Infinite ,
10021035 }
10031036 }
1037+
10041038 fn id ( & self , channel_direction : bool /* src_node_id < target_node_id */ ) -> CandidateHopId {
10051039 match self {
1040+ CandidateRouteHop :: Blinded { hint_idx, .. } => CandidateHopId :: Blinded ( * hint_idx) ,
1041+ CandidateRouteHop :: OneHopBlinded { hint_idx, .. } => CandidateHopId :: Blinded ( * hint_idx) ,
10061042 _ => CandidateHopId :: Clear ( ( self . short_channel_id ( ) . unwrap ( ) , channel_direction) ) ,
10071043 }
10081044 }
@@ -1259,6 +1295,12 @@ struct LoggedCandidateHop<'a>(&'a CandidateRouteHop<'a>);
12591295impl < ' a > fmt:: Display for LoggedCandidateHop < ' a > {
12601296 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
12611297 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+ } ,
12621304 _ => {
12631305 "SCID " . fmt ( f) ?;
12641306 self . 0 . short_channel_id ( ) . unwrap ( ) . fmt ( f)
0 commit comments