Skip to content

Commit e7d5c53

Browse files
committed
Add non-vector cryptography tests [expound]
1 parent c7e97d6 commit e7d5c53

File tree

1 file changed

+181
-0
lines changed

1 file changed

+181
-0
lines changed

lightning/src/ln/onion_utils.rs

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2501,6 +2501,187 @@ mod tests {
25012501
assert_eq!(decrypted_failure.onion_error_code, Some(0x400f));
25022502
}
25032503

2504+
#[test]
2505+
fn test_trampoline_onion_decryption() {
2506+
// In this test, we construct a dummy path that uses Trampoline hops, and ensure that the
2507+
// correct shared secrets are used to decrypt the error packets. The actual path configuration
2508+
// is not particularly relevant.
2509+
2510+
let dummy_amt_msat = 150_000_000;
2511+
2512+
let path = Path {
2513+
hops: vec![
2514+
// Bob
2515+
RouteHop {
2516+
pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()).unwrap(),
2517+
node_features: NodeFeatures::empty(),
2518+
short_channel_id: 0,
2519+
channel_features: ChannelFeatures::empty(),
2520+
fee_msat: 3_000,
2521+
cltv_expiry_delta: 24,
2522+
maybe_announced_channel: false,
2523+
},
2524+
2525+
// Carol
2526+
RouteHop {
2527+
pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007").unwrap()).unwrap(),
2528+
node_features: NodeFeatures::empty(),
2529+
short_channel_id: (572330 << 40) + (42 << 16) + 2821,
2530+
channel_features: ChannelFeatures::empty(),
2531+
fee_msat: 153_000,
2532+
cltv_expiry_delta: 0,
2533+
maybe_announced_channel: false,
2534+
},
2535+
],
2536+
blinded_tail: Some(BlindedTail {
2537+
trampoline_hops: vec![
2538+
// Carol's pubkey
2539+
TrampolineHop {
2540+
pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007").unwrap()).unwrap(),
2541+
node_features: Features::empty(),
2542+
fee_msat: 2_500,
2543+
cltv_expiry_delta: 24,
2544+
},
2545+
// Dave's pubkey
2546+
TrampolineHop {
2547+
pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("020e2dbadcc2005e859819ddebbe88a834ae8a6d2b049233c07335f15cd1dc5f22").unwrap()).unwrap(),
2548+
node_features: Features::empty(),
2549+
fee_msat: 2_500,
2550+
cltv_expiry_delta: 24,
2551+
},
2552+
// Emily's pubkey (the intro node needs to be duplicated)
2553+
TrampolineHop {
2554+
pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()).unwrap(),
2555+
node_features: Features::empty(),
2556+
fee_msat: 150_500,
2557+
cltv_expiry_delta: 36,
2558+
}
2559+
],
2560+
hops: vec![
2561+
// Emily's blinded node id
2562+
BlindedHop {
2563+
blinded_node_id: PublicKey::from_slice(&<Vec<u8>>::from_hex("0295d40514096a8be54859e7dfe947b376eaafea8afe5cb4eb2c13ff857ed0b4be").unwrap()).unwrap(),
2564+
encrypted_payload: vec![],
2565+
},
2566+
// Forrest's blinded node id
2567+
BlindedHop {
2568+
blinded_node_id: PublicKey::from_slice(&<Vec<u8>>::from_hex("020e2dbadcc2005e859819ddebbe88a834ae8a6d2b049233c07335f15cd1dc5f22").unwrap()).unwrap(),
2569+
encrypted_payload: vec![],
2570+
}
2571+
],
2572+
blinding_point: PublicKey::from_slice(&<Vec<u8>>::from_hex("02988face71e92c345a068f740191fd8e53be14f0bb957ef730d3c5f76087b960e").unwrap()).unwrap(),
2573+
excess_final_cltv_expiry_delta: 0,
2574+
final_value_msat: dummy_amt_msat
2575+
}),
2576+
};
2577+
2578+
// all dummy values
2579+
let secp_ctx = Secp256k1::new();
2580+
let session_priv = get_test_session_key();
2581+
2582+
let trampoline_onion_keys = construct_trampoline_onion_keys(
2583+
&secp_ctx,
2584+
&path.blinded_tail.as_ref().unwrap(),
2585+
&session_priv,
2586+
)
2587+
.unwrap();
2588+
2589+
let outer_onion_keys = {
2590+
let session_priv_hash = Sha256::hash(&session_priv.secret_bytes()).to_byte_array();
2591+
let outer_session_priv = SecretKey::from_slice(&session_priv_hash[..]).unwrap();
2592+
construct_onion_keys(&Secp256k1::new(), &path, &outer_session_priv).unwrap()
2593+
};
2594+
2595+
let logger: Arc<TestLogger> = Arc::new(TestLogger::new());
2596+
let htlc_source = HTLCSource::OutboundRoute {
2597+
path,
2598+
session_priv,
2599+
first_hop_htlc_msat: dummy_amt_msat,
2600+
payment_id: PaymentId([1; 32]),
2601+
};
2602+
2603+
{
2604+
let error_code = 0x2002;
2605+
let onion_error = super::build_failure_packet(
2606+
outer_onion_keys[0].shared_secret.as_ref(),
2607+
error_code,
2608+
&[0; 0],
2609+
);
2610+
let first_hop_error_packet = super::encrypt_failure_packet(
2611+
outer_onion_keys[0].shared_secret.as_ref(),
2612+
&onion_error.encode()[..],
2613+
);
2614+
2615+
let decrypted_failure = process_onion_failure(
2616+
&secp_ctx,
2617+
&logger,
2618+
&htlc_source,
2619+
first_hop_error_packet.data,
2620+
None,
2621+
);
2622+
assert_eq!(decrypted_failure.onion_error_code, Some(error_code));
2623+
};
2624+
2625+
{
2626+
let error_code = 0x2003;
2627+
let onion_error = super::build_failure_packet(
2628+
outer_onion_keys[1].shared_secret.as_ref(),
2629+
error_code,
2630+
&[0; 0],
2631+
);
2632+
let error_packet_1 = super::encrypt_failure_packet(
2633+
outer_onion_keys[1].shared_secret.as_ref(),
2634+
&onion_error.encode()[..],
2635+
);
2636+
2637+
let trampoline_outer_hop_error_packet = super::encrypt_failure_packet(
2638+
outer_onion_keys[0].shared_secret.as_ref(),
2639+
&error_packet_1.data[..],
2640+
);
2641+
2642+
let decrypted_failure = process_onion_failure(
2643+
&secp_ctx,
2644+
&logger,
2645+
&htlc_source,
2646+
trampoline_outer_hop_error_packet.data,
2647+
None,
2648+
);
2649+
assert_eq!(decrypted_failure.onion_error_code, Some(error_code));
2650+
};
2651+
2652+
{
2653+
let error_code = 0x2004;
2654+
let onion_error = super::build_failure_packet(
2655+
trampoline_onion_keys[0].shared_secret.as_ref(),
2656+
error_code,
2657+
&[0; 0],
2658+
);
2659+
let error_packet_t0 = super::encrypt_failure_packet(
2660+
trampoline_onion_keys[0].shared_secret.as_ref(),
2661+
&onion_error.encode()[..],
2662+
);
2663+
2664+
let error_packet_1 = super::encrypt_failure_packet(
2665+
outer_onion_keys[1].shared_secret.as_ref(),
2666+
&error_packet_t0.data[..],
2667+
);
2668+
2669+
let trampoline_inner_hop_error_packet = super::encrypt_failure_packet(
2670+
outer_onion_keys[0].shared_secret.as_ref(),
2671+
&error_packet_1.data[..],
2672+
);
2673+
2674+
let decrypted_failure = process_onion_failure(
2675+
&secp_ctx,
2676+
&logger,
2677+
&htlc_source,
2678+
trampoline_inner_hop_error_packet.data,
2679+
None,
2680+
);
2681+
assert_eq!(decrypted_failure.onion_error_code, Some(error_code));
2682+
}
2683+
}
2684+
25042685
#[test]
25052686
fn test_non_attributable_failure_packet_onion() {
25062687
// Create a failure packet with bogus data.

0 commit comments

Comments
 (0)