@@ -967,7 +967,7 @@ where
967
967
let mut htlc_msat = * first_hop_htlc_msat;
968
968
let mut _error_code_ret = None ;
969
969
let mut _error_packet_ret = None ;
970
- let mut is_from_final_node = false ;
970
+ let mut is_from_final_non_blinded_node = false ;
971
971
972
972
const BADONION : u16 = 0x8000 ;
973
973
const PERM : u16 = 0x4000 ;
@@ -976,41 +976,72 @@ where
976
976
977
977
enum ErrorHop < ' a > {
978
978
RouteHop ( & ' a RouteHop ) ,
979
+ TrampolineHop ( & ' a TrampolineHop ) ,
979
980
}
980
981
981
982
impl < ' a > ErrorHop < ' a > {
982
983
fn fee_msat ( & self ) -> u64 {
983
984
match self {
984
985
ErrorHop :: RouteHop ( rh) => rh. fee_msat ,
986
+ ErrorHop :: TrampolineHop ( th) => th. fee_msat ,
985
987
}
986
988
}
987
989
988
990
fn pubkey ( & self ) -> & PublicKey {
989
991
match self {
990
992
ErrorHop :: RouteHop ( rh) => rh. node_pubkey ( ) ,
993
+ ErrorHop :: TrampolineHop ( th) => th. node_pubkey ( ) ,
991
994
}
992
995
}
993
996
994
997
fn short_channel_id ( & self ) -> Option < u64 > {
995
998
match self {
996
999
ErrorHop :: RouteHop ( rh) => Some ( rh. short_channel_id ) ,
1000
+ ErrorHop :: TrampolineHop ( _) => None ,
997
1001
}
998
1002
}
999
1003
}
1000
1004
1005
+ let outer_session_priv = path. has_trampoline_hops ( ) . then ( || {
1006
+ // if we have Trampoline hops, the outer onion session_priv is a hash of the inner one
1007
+ let session_priv_hash = Sha256 :: hash ( & session_priv. secret_bytes ( ) ) . to_byte_array ( ) ;
1008
+ SecretKey :: from_slice ( & session_priv_hash[ ..] ) . expect ( "You broke SHA-256!" )
1009
+ } ) ;
1010
+
1001
1011
let num_blinded_hops = path. blinded_tail . as_ref ( ) . map_or ( 0 , |bt| bt. hops . len ( ) ) ;
1012
+
1013
+ // We are first collecting all the unblinded `RouteHop`s inside `onion_keys`. Then, if applicable,
1014
+ // we will add all the `TrampolineHop`s, and finally, the blinded hops.
1002
1015
let mut onion_keys = Vec :: with_capacity ( path. hops . len ( ) + num_blinded_hops) ;
1003
1016
construct_onion_keys_generic_callback (
1004
1017
secp_ctx,
1005
1018
& path. hops ,
1006
- path. blinded_tail . as_ref ( ) ,
1007
- session_priv,
1019
+ // if we have Trampoline hops, the blinded hops are part of the inner Trampoline onion
1020
+ if path. has_trampoline_hops ( ) { None } else { path. blinded_tail . as_ref ( ) } ,
1021
+ outer_session_priv. as_ref ( ) . unwrap_or ( session_priv) ,
1008
1022
|shared_secret, _, _, route_hop_option : Option < & RouteHop > , _| {
1009
1023
onion_keys. push ( ( route_hop_option. map ( |rh| ErrorHop :: RouteHop ( rh) ) , shared_secret) )
1010
1024
} ,
1011
1025
)
1012
1026
. expect ( "Route we used spontaneously grew invalid keys in the middle of it?" ) ;
1013
1027
1028
+ if path. has_trampoline_hops ( ) {
1029
+ construct_onion_keys_generic_callback (
1030
+ secp_ctx,
1031
+ // Trampoline hops are part of the blinded tail, so this can never panic
1032
+ & path. blinded_tail . as_ref ( ) . unwrap ( ) . trampoline_hops ,
1033
+ path. blinded_tail . as_ref ( ) ,
1034
+ session_priv,
1035
+ |shared_secret, _, _, trampoline_hop_option : Option < & TrampolineHop > , _| {
1036
+ onion_keys. push ( (
1037
+ trampoline_hop_option. map ( |th| ErrorHop :: TrampolineHop ( th) ) ,
1038
+ shared_secret,
1039
+ ) )
1040
+ } ,
1041
+ )
1042
+ . expect ( "Route we used spontaneously grew invalid keys in the middle of it?" ) ;
1043
+ }
1044
+
1014
1045
// Handle packed channel/node updates for passing back for the route handler
1015
1046
let mut iterator = onion_keys. into_iter ( ) . peekable ( ) ;
1016
1047
while let Some ( ( route_hop_option, shared_secret) ) = iterator. next ( ) {
@@ -1032,12 +1063,12 @@ where
1032
1063
1033
1064
// The failing hop includes either the inbound channel to the recipient or the outbound channel
1034
1065
// from the current hop (i.e., the next hop's inbound channel).
1035
- // For 1-hop blinded paths, the final `path.hops ` entry is the recipient.
1066
+ // For 1-hop blinded paths, the final `ErrorHop ` entry is the recipient.
1036
1067
// In our case that means that if we're on the last iteration, and there is no more than one
1037
1068
// blinded hop, the current iteration references the last non-blinded hop.
1038
1069
let next_hop = iterator. peek ( ) ;
1039
- is_from_final_node = next_hop. is_none ( ) && num_blinded_hops <= 1 ;
1040
- let failing_route_hop = if is_from_final_node {
1070
+ is_from_final_non_blinded_node = next_hop. is_none ( ) && num_blinded_hops <= 1 ;
1071
+ let failing_route_hop = if is_from_final_non_blinded_node {
1041
1072
route_hop
1042
1073
} else {
1043
1074
match next_hop {
@@ -1102,7 +1133,7 @@ where
1102
1133
res = Some ( FailureLearnings {
1103
1134
network_update,
1104
1135
short_channel_id,
1105
- payment_failed_permanently : is_from_final_node ,
1136
+ payment_failed_permanently : is_from_final_non_blinded_node ,
1106
1137
failed_within_blinded_path : false ,
1107
1138
} ) ;
1108
1139
break ;
@@ -1124,7 +1155,7 @@ where
1124
1155
res = Some ( FailureLearnings {
1125
1156
network_update,
1126
1157
short_channel_id,
1127
- payment_failed_permanently : is_from_final_node ,
1158
+ payment_failed_permanently : is_from_final_non_blinded_node ,
1128
1159
failed_within_blinded_path : false ,
1129
1160
} ) ;
1130
1161
break ;
@@ -1141,7 +1172,7 @@ where
1141
1172
let payment_failed = match error_code & 0xff {
1142
1173
15 | 16 | 17 | 18 | 19 | 23 => true ,
1143
1174
_ => false ,
1144
- } && is_from_final_node ; // PERM bit observed below even if this error is from the intermediate nodes
1175
+ } && is_from_final_non_blinded_node ; // PERM bit observed below even if this error is from the intermediate nodes
1145
1176
1146
1177
let mut network_update = None ;
1147
1178
let mut short_channel_id = None ;
@@ -1226,7 +1257,7 @@ where
1226
1257
res = Some ( FailureLearnings {
1227
1258
network_update,
1228
1259
short_channel_id,
1229
- payment_failed_permanently : error_code & PERM == PERM && is_from_final_node ,
1260
+ payment_failed_permanently : error_code & PERM == PERM && is_from_final_non_blinded_node ,
1230
1261
failed_within_blinded_path : false ,
1231
1262
} ) ;
1232
1263
@@ -1285,7 +1316,7 @@ where
1285
1316
DecodedOnionFailure {
1286
1317
network_update : None ,
1287
1318
short_channel_id : None ,
1288
- payment_failed_permanently : is_from_final_node ,
1319
+ payment_failed_permanently : is_from_final_non_blinded_node ,
1289
1320
failed_within_blinded_path : false ,
1290
1321
#[ cfg( any( test, feature = "_test_utils" ) ) ]
1291
1322
onion_error_code : None ,
0 commit comments