@@ -19,7 +19,7 @@ use crate::ln::channel::EXPIRE_PREV_CONFIG_TICKS;
19
19
use crate :: ln:: channelmanager:: { HTLCForwardInfo , FailureCode , CLTV_FAR_FAR_AWAY , DISABLE_GOSSIP_TICKS , MIN_CLTV_EXPIRY_DELTA , PendingAddHTLCInfo , PendingHTLCInfo , PendingHTLCRouting , PaymentId , RecipientOnionFields } ;
20
20
use crate :: ln:: onion_utils;
21
21
use 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 } ;
23
23
use crate :: types:: features:: { InitFeatures , Bolt11InvoiceFeatures } ;
24
24
use crate :: ln:: functional_test_utils:: test_default_channel_config;
25
25
use crate :: ln:: msgs;
@@ -40,9 +40,11 @@ use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
40
40
41
41
use crate :: io;
42
42
use 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 ;
45
46
use crate :: ln:: functional_test_utils:: * ;
47
+ use crate :: ln:: onion_utils:: { construct_trampoline_onion_keys, construct_trampoline_onion_packet} ;
46
48
47
49
fn 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 > )
48
50
where F1 : for < ' a > FnMut ( & ' a mut msgs:: UpdateAddHTLC ) ,
@@ -1001,6 +1003,85 @@ fn test_trampoline_onion_payload_serialization() {
1001
1003
assert_eq ! ( carol_payload_hex, "2e020405f5e10004030c35000e2102edabbd16b41c8371b92ef2f04c1185b4f03b6dcd52ba9b78d9d7c89c8f221145" ) ;
1002
1004
}
1003
1005
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
+
1004
1085
fn do_test_fail_htlc_backwards_with_reason ( failure_code : FailureCode ) {
1005
1086
1006
1087
let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
0 commit comments