@@ -19,7 +19,7 @@ use crate::ln::channel::EXPIRE_PREV_CONFIG_TICKS;
1919use crate :: ln:: channelmanager:: { HTLCForwardInfo , FailureCode , CLTV_FAR_FAR_AWAY , DISABLE_GOSSIP_TICKS , MIN_CLTV_EXPIRY_DELTA , PendingAddHTLCInfo , PendingHTLCInfo , PendingHTLCRouting , PaymentId , RecipientOnionFields } ;
2020use crate :: ln:: onion_utils;
2121use crate :: routing:: gossip:: { NetworkUpdate , RoutingFees } ;
22- use crate :: routing:: router:: { get_route, PaymentParameters , Route , RouteParameters , RouteHint , RouteHintHop } ;
22+ use crate :: routing:: router:: { get_route, PaymentParameters , Route , RouteParameters , RouteHint , RouteHintHop , Path , TrampolineHop , BlindedTail } ;
2323use crate :: types:: features:: { InitFeatures , Bolt11InvoiceFeatures } ;
2424use crate :: ln:: functional_test_utils:: test_default_channel_config;
2525use crate :: ln:: msgs;
@@ -40,9 +40,11 @@ use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
4040
4141use crate :: io;
4242use crate :: prelude:: * ;
43- use bitcoin:: hex:: FromHex ;
44-
43+ use bitcoin:: hex:: { DisplayHex , FromHex } ;
44+ use types:: features:: Features ;
45+ use crate :: blinded_path:: BlindedHop ;
4546use crate :: ln:: functional_test_utils:: * ;
47+ use crate :: ln:: onion_utils:: { construct_trampoline_onion_keys, construct_trampoline_onion_packet} ;
4648
4749fn run_onion_failure_test < F1 , F2 > ( _name : & str , test_case : u8 , nodes : & Vec < Node > , route : & Route , payment_hash : & PaymentHash , payment_secret : & PaymentSecret , callback_msg : F1 , callback_node : F2 , expected_retryable : bool , expected_error_code : Option < u16 > , expected_channel_update : Option < NetworkUpdate > , expected_short_channel_id : Option < u64 > )
4850 where F1 : for < ' a > FnMut ( & ' a mut msgs:: UpdateAddHTLC ) ,
@@ -1001,6 +1003,85 @@ fn test_trampoline_onion_payload_serialization() {
10011003 assert_eq ! ( carol_payload_hex, "2e020405f5e10004030c35000e2102edabbd16b41c8371b92ef2f04c1185b4f03b6dcd52ba9b78d9d7c89c8f221145" ) ;
10021004}
10031005
1006+ #[ test]
1007+ fn test_trampoline_onion_payload_construction_vectors ( ) {
1008+ // As per https://github.com/lightning/bolts/blob/fa0594ac2af3531d734f1d707a146d6e13679451/bolt04/trampoline-to-blinded-path-payment-onion-test.json#L251
1009+
1010+ let trampoline_payload_carol = OutboundTrampolinePayload :: Forward {
1011+ amt_to_forward : 150_150_500 ,
1012+ outgoing_cltv_value : 800_036 ,
1013+ outgoing_node_id : PublicKey :: from_slice ( & <Vec < u8 > >:: from_hex ( "032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991" ) . unwrap ( ) ) . unwrap ( ) ,
1014+ } ;
1015+ let carol_payload = trampoline_payload_carol. encode ( ) . to_lower_hex_string ( ) ;
1016+ assert_eq ! ( carol_payload, "2e020408f31d6404030c35240e21032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991" ) ;
1017+
1018+ let trampoline_payload_dave = OutboundTrampolinePayload :: BlindedForward {
1019+ encrypted_tlvs : & <Vec < u8 > >:: from_hex ( "0ccf3c8a58deaa603f657ee2a5ed9d604eb5c8ca1e5f801989afa8f3ea6d789bbdde2c7e7a1ef9ca8c38d2c54760febad8446d3f273ddb537569ef56613846ccd3aba78a" ) . unwrap ( ) ,
1020+ intro_node_blinding_point : Some ( PublicKey :: from_slice ( & <Vec < u8 > >:: from_hex ( "02988face71e92c345a068f740191fd8e53be14f0bb957ef730d3c5f76087b960e" ) . unwrap ( ) ) . unwrap ( ) ) ,
1021+ } ;
1022+ let dave_payload = trampoline_payload_dave. encode ( ) . to_lower_hex_string ( ) ;
1023+ assert_eq ! ( dave_payload, "690a440ccf3c8a58deaa603f657ee2a5ed9d604eb5c8ca1e5f801989afa8f3ea6d789bbdde2c7e7a1ef9ca8c38d2c54760febad8446d3f273ddb537569ef56613846ccd3aba78a0c2102988face71e92c345a068f740191fd8e53be14f0bb957ef730d3c5f76087b960e" ) ;
1024+
1025+ let trampoline_payload_eve = OutboundTrampolinePayload :: BlindedReceive {
1026+ sender_intended_htlc_amt_msat : 150_000_000 ,
1027+ total_msat : 150_000_000 ,
1028+ cltv_expiry_height : 800_000 ,
1029+ encrypted_tlvs : & <Vec < u8 > >:: from_hex ( "bcd747394fbd4d99588da075a623316e15a576df5bc785cccc7cd6ec7b398acce6faf520175f9ec920f2ef261cdb83dc28cc3a0eeb970107b3306489bf771ef5b1213bca811d345285405861d08a655b6c237fa247a8b4491beee20c878a60e9816492026d8feb9dafa84585b253978db6a0aa2945df5ef445c61e801fb82f43d5f00716baf9fc9b3de50bc22950a36bda8fc27bfb1242e5860c7e687438d4133e058770361a19b6c271a2a07788d34dccc27e39b9829b061a4d960eac4a2c2b0f4de506c24f9af3868c0aff6dda27281c" ) . unwrap ( ) ,
1030+ intro_node_blinding_point : None ,
1031+ keysend_preimage : None ,
1032+ custom_tlvs : & vec ! [ ] ,
1033+ } ;
1034+ let eve_payload = trampoline_payload_eve. encode ( ) . to_lower_hex_string ( ) ;
1035+ assert_eq ! ( eve_payload, "e4020408f0d18004030c35000ad1bcd747394fbd4d99588da075a623316e15a576df5bc785cccc7cd6ec7b398acce6faf520175f9ec920f2ef261cdb83dc28cc3a0eeb970107b3306489bf771ef5b1213bca811d345285405861d08a655b6c237fa247a8b4491beee20c878a60e9816492026d8feb9dafa84585b253978db6a0aa2945df5ef445c61e801fb82f43d5f00716baf9fc9b3de50bc22950a36bda8fc27bfb1242e5860c7e687438d4133e058770361a19b6c271a2a07788d34dccc27e39b9829b061a4d960eac4a2c2b0f4de506c24f9af3868c0aff6dda27281c120408f0d180" ) ;
1036+
1037+ let trampoline_payloads = vec ! [ trampoline_payload_carol, trampoline_payload_dave, trampoline_payload_eve] ;
1038+
1039+ let trampoline_session_key = SecretKey :: from_slice ( & <Vec < u8 > >:: from_hex ( "a64feb81abd58e473df290e9e1c07dc3e56114495cadf33191f44ba5448ebe99" ) . unwrap ( ) ) . unwrap ( ) ;
1040+ let associated_data_slice = SecretKey :: from_slice ( & <Vec < u8 > >:: from_hex ( "e89bc505e84aaca09613833fc58c9069078fb43bfbea0488f34eec9db99b5f82" ) . unwrap ( ) ) . unwrap ( ) ;
1041+ let associated_data = PaymentHash ( associated_data_slice. secret_bytes ( ) ) ;
1042+
1043+ let trampoline_hops = Path {
1044+ hops : vec ! [ ] ,
1045+ trampoline_hops : vec ! [
1046+ // Carol's pubkey
1047+ TrampolineHop {
1048+ pubkey: PublicKey :: from_slice( & <Vec <u8 >>:: from_hex( "027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007" ) . unwrap( ) ) . unwrap( ) ,
1049+ node_features: Features :: empty( ) ,
1050+ fee_msat: 0 ,
1051+ cltv_expiry_delta: 0 ,
1052+ } ,
1053+ // Dave's pubkey (the intro node needs to be duplicated)
1054+ TrampolineHop {
1055+ pubkey: PublicKey :: from_slice( & <Vec <u8 >>:: from_hex( "032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991" ) . unwrap( ) ) . unwrap( ) ,
1056+ node_features: Features :: empty( ) ,
1057+ fee_msat: 0 ,
1058+ cltv_expiry_delta: 0 ,
1059+ }
1060+ ] ,
1061+ blinded_tail : Some ( BlindedTail {
1062+ hops : vec ! [
1063+ BlindedHop {
1064+ blinded_node_id: PublicKey :: from_slice( & <Vec <u8 >>:: from_hex( "0295d40514096a8be54859e7dfe947b376eaafea8afe5cb4eb2c13ff857ed0b4be" ) . unwrap( ) ) . unwrap( ) ,
1065+ encrypted_payload: vec![ ] ,
1066+ } ,
1067+ BlindedHop {
1068+ blinded_node_id: PublicKey :: from_slice( & <Vec <u8 >>:: from_hex( "020e2dbadcc2005e859819ddebbe88a834ae8a6d2b049233c07335f15cd1dc5f22" ) . unwrap( ) ) . unwrap( ) ,
1069+ encrypted_payload: vec![ ] ,
1070+ }
1071+ ] ,
1072+ blinding_point : PublicKey :: from_slice ( & <Vec < u8 > >:: from_hex ( "02988face71e92c345a068f740191fd8e53be14f0bb957ef730d3c5f76087b960e" ) . unwrap ( ) ) . unwrap ( ) ,
1073+ excess_final_cltv_expiry_delta : 0 ,
1074+ final_value_msat : 0 ,
1075+ final_hop_supports_trampoline : false ,
1076+ } ) ,
1077+ } ;
1078+
1079+ let trampoline_onion_keys = construct_trampoline_onion_keys ( & Secp256k1 :: new ( ) , & trampoline_hops, & trampoline_session_key) . unwrap ( ) ;
1080+ let trampoline_onion_packet = construct_trampoline_onion_packet ( trampoline_payloads, trampoline_onion_keys, [ 0u8 ; 32 ] , & associated_data, None ) . unwrap ( ) ;
1081+ let trampoline_onion_packet_hex = trampoline_onion_packet. encode ( ) . to_lower_hex_string ( ) ;
1082+ assert_eq ! ( trampoline_onion_packet_hex, "0002bc59a9abc893d75a8d4f56a6572f9a3507323a8de22abe0496ea8d37da166a8b4bba0e560f1a9deb602bfd98fe9167141d0b61d669df90c0149096d505b85d3d02806e6c12caeb308b878b6bc7f1b15839c038a6443cd3bec3a94c2293165375555f6d7720862b525930f41fddcc02260d197abd93fb58e60835fd97d9dc14e7979c12f59df08517b02e3e4d50e1817de4271df66d522c4e9675df71c635c4176a8381bc22b342ff4e9031cede87f74cc039fca74aa0a3786bc1db2e158a9a520ecb99667ef9a6bbfaf5f0e06f81c27ca48134ba2103229145937c5dc7b8ecc5201d6aeb592e78faa3c05d3a035df77628f0be9b1af3ef7d386dd5cc87b20778f47ebd40dbfcf12b9071c5d7112ab84c3e0c5c14867e684d09a18bc93ac47d73b7343e3403ef6e3b70366835988920e7d772c3719d3596e53c29c4017cb6938421a557ce81b4bb26701c25bf622d4c69f1359dc85857a375c5c74987a4d3152f66987001c68a50c4bf9e0b1dab4ad1a64b0535319bbf6c4fbe4f9c50cb65f5ef887bfb91b0a57c0f86ba3d91cbeea1607fb0c12c6c75d03bbb0d3a3019c40597027f5eebca23083e50ec79d41b1152131853525bf3fc13fb0be62c2e3ce733f59671eee5c4064863fb92ae74be9ca68b9c716f9519fd268478ee27d91d466b0de51404de3226b74217d28250ead9d2c95411e0230570f547d4cc7c1d589791623131aa73965dccc5aa17ec12b442215ce5d346df664d799190df5dd04a13" ) ;
1083+ }
1084+
10041085fn do_test_fail_htlc_backwards_with_reason ( failure_code : FailureCode ) {
10051086
10061087 let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
0 commit comments