@@ -1144,6 +1144,10 @@ where
11441144 . expect ( "Route we used spontaneously grew invalid keys in the middle of it?" ) ;
11451145 }
11461146
1147+ // In the best case, paths can be up to 27 hops. But attribution data can only be conveyed back to the sender from
1148+ // the first 20 hops. Determine the number of hops to be used for attribution data.
1149+ let attributable_hop_count = usize:: min ( path. hops . len ( ) , MAX_HOPS ) ;
1150+
11471151 // Handle packed channel/node updates for passing back for the route handler
11481152 let mut iterator = onion_keys. into_iter ( ) . enumerate ( ) . peekable ( ) ;
11491153 while let Some ( ( route_hop_idx, ( route_hop_option, shared_secret) ) ) = iterator. next ( ) {
@@ -1215,11 +1219,13 @@ where
12151219 // Check attr error HMACs if present.
12161220 if let Some ( ref mut attribution_data) = encrypted_packet. attribution_data {
12171221 // Only consider hops in the regular path for attribution data. Failures in a blinded path are not attributable.
1218- if route_hop_idx < path. hops . len ( ) {
1219- // Calculate position relative to the final hop. The final hop is at position 0. The failure node does not
1220- // need to come from the final node, but we need to look at the chain of HMACs that does include all data up
1221- // to the final node. For a more nearby failure, the verified HMACs will include some zero padding data.
1222- let position = path. hops . len ( ) - route_hop_idx - 1 ;
1222+ if route_hop_idx < attributable_hop_count {
1223+ // Calculate position relative to the last attributable hop. The last attributable hop is at position 0.
1224+ // The failure node does not need to come from the last attributable hop, but we need to look at the
1225+ // chain of HMACs that does include all data up to the last attributable hop. For a more nearby failure,
1226+ // the verified HMACs will include some zero padding data. Failures beyond the last attributable hop
1227+ // will not be attributable.
1228+ let position = attributable_hop_count - route_hop_idx - 1 ;
12231229 let hold_time = attribution_data. verify (
12241230 & encrypted_packet. data ,
12251231 shared_secret. as_ref ( ) ,
@@ -3169,6 +3175,79 @@ mod tests {
31693175 assert_eq ! ( decrypted_failure. short_channel_id, Some ( 0 ) ) ;
31703176 }
31713177
3178+ #[ test]
3179+ fn test_long_route_attributable_failure ( ) {
3180+ // Test a long route that exceeds the reach of attribution data.
3181+
3182+ let secp_ctx = Secp256k1 :: new ( ) ;
3183+ const LEGACY_MAX_HOPS : usize = 27 ;
3184+
3185+ // Construct a route with 27 hops.
3186+ let mut hops = Vec :: new ( ) ;
3187+ for i in 0 ..LEGACY_MAX_HOPS {
3188+ let mut secret_bytes = [ 0 ; 32 ] ;
3189+ secret_bytes[ 0 ] = ( i + 1 ) as u8 ;
3190+ let secret_key = SecretKey :: from_slice ( & secret_bytes) . unwrap ( ) ;
3191+ let pubkey = secret_key. public_key ( & secp_ctx) ;
3192+
3193+ hops. push ( RouteHop {
3194+ pubkey,
3195+ channel_features : ChannelFeatures :: empty ( ) ,
3196+ node_features : NodeFeatures :: empty ( ) ,
3197+ short_channel_id : i as u64 ,
3198+ fee_msat : 0 ,
3199+ cltv_expiry_delta : 0 ,
3200+ maybe_announced_channel : true ,
3201+ } ) ;
3202+ }
3203+ let path = Path { hops, blinded_tail : None } ;
3204+
3205+ // Calculate shared secrets.
3206+ let mut onion_keys = Vec :: new ( ) ;
3207+ let session_key = get_test_session_key ( ) ;
3208+ construct_onion_keys_generic_callback (
3209+ & secp_ctx,
3210+ & path. hops ,
3211+ None ,
3212+ & session_key,
3213+ |shared_secret, _, _, _, _| onion_keys. push ( shared_secret) ,
3214+ )
3215+ . unwrap ( ) ;
3216+
3217+ // Construct the htlc source.
3218+ let logger = TestLogger :: new ( ) ;
3219+ let htlc_source = HTLCSource :: OutboundRoute {
3220+ path,
3221+ session_priv : session_key,
3222+ first_hop_htlc_msat : 0 ,
3223+ payment_id : PaymentId ( [ 1 ; 32 ] ) ,
3224+ } ;
3225+
3226+ // Iterate over all possible failure positions and check that the cases that can be attributed are.
3227+ for failure_pos in 0 ..LEGACY_MAX_HOPS {
3228+ // Create a failure packet with bogus data.
3229+ let packet = vec ! [ 1u8 ; 292 ] ;
3230+ let mut onion_error =
3231+ OnionErrorPacket { data : packet, attribution_data : Some ( AttributionData :: new ( ) ) } ;
3232+
3233+ // Apply the processing that the preceding hops would apply.
3234+ for i in ( 0 ..failure_pos) . rev ( ) {
3235+ let shared_secret = onion_keys[ i] . secret_bytes ( ) ;
3236+ process_failure_packet ( & mut onion_error, & shared_secret, 0 ) ;
3237+ super :: crypt_failure_packet ( & shared_secret, & mut onion_error) ;
3238+ }
3239+
3240+ // Decrypt the failure.
3241+ let decrypted_failure =
3242+ process_onion_failure ( & secp_ctx, & & logger, & htlc_source, onion_error) ;
3243+
3244+ // Expect attribution up to hop 20.
3245+ let expected_failed_chan =
3246+ if failure_pos < MAX_HOPS { Some ( failure_pos as u64 ) } else { None } ;
3247+ assert_eq ! ( decrypted_failure. short_channel_id, expected_failed_chan) ;
3248+ }
3249+ }
3250+
31723251 #[ test]
31733252 fn test_unreadable_failure_packet_onion ( ) {
31743253 // Create a failure packet with a valid hmac but unreadable failure message.
0 commit comments