@@ -366,7 +366,7 @@ fn test_onion_failure() {
366
366
let onion_keys = onion_utils:: construct_onion_keys ( & Secp256k1 :: new ( ) , & route. paths [ 0 ] , & session_priv) . unwrap ( ) ;
367
367
let recipient_onion_fields = RecipientOnionFields :: spontaneous_empty ( ) ;
368
368
let ( mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils:: build_onion_payloads (
369
- & route. paths [ 0 ] , 40000 , & recipient_onion_fields, cur_height, & None , None ) . unwrap ( ) ;
369
+ & route. paths [ 0 ] , 40000 , & recipient_onion_fields, cur_height, & None , None , None ) . unwrap ( ) ;
370
370
let mut new_payloads = Vec :: new ( ) ;
371
371
for payload in onion_payloads. drain ( ..) {
372
372
new_payloads. push ( BogusOnionHopData :: new ( payload) ) ;
@@ -385,7 +385,7 @@ fn test_onion_failure() {
385
385
let onion_keys = onion_utils:: construct_onion_keys ( & Secp256k1 :: new ( ) , & route. paths [ 0 ] , & session_priv) . unwrap ( ) ;
386
386
let recipient_onion_fields = RecipientOnionFields :: spontaneous_empty ( ) ;
387
387
let ( mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils:: build_onion_payloads (
388
- & route. paths [ 0 ] , 40000 , & recipient_onion_fields, cur_height, & None , None ) . unwrap ( ) ;
388
+ & route. paths [ 0 ] , 40000 , & recipient_onion_fields, cur_height, & None , None , None ) . unwrap ( ) ;
389
389
let mut new_payloads = Vec :: new ( ) ;
390
390
for payload in onion_payloads. drain ( ..) {
391
391
new_payloads. push ( BogusOnionHopData :: new ( payload) ) ;
@@ -639,7 +639,7 @@ fn test_onion_failure() {
639
639
let onion_keys = onion_utils:: construct_onion_keys ( & Secp256k1 :: new ( ) , & route. paths [ 0 ] , & session_priv) . unwrap ( ) ;
640
640
let recipient_onion_fields = RecipientOnionFields :: spontaneous_empty ( ) ;
641
641
let ( onion_payloads, _, htlc_cltv) = onion_utils:: build_onion_payloads (
642
- & route. paths [ 0 ] , 40000 , & recipient_onion_fields, height, & None , None ) . unwrap ( ) ;
642
+ & route. paths [ 0 ] , 40000 , & recipient_onion_fields, height, & None , None , None ) . unwrap ( ) ;
643
643
let onion_packet = onion_utils:: construct_onion_packet ( onion_payloads, onion_keys, [ 0 ; 32 ] , & payment_hash) . unwrap ( ) ;
644
644
msg. cltv_expiry = htlc_cltv;
645
645
msg. onion_routing_packet = onion_packet;
@@ -977,7 +977,7 @@ fn test_always_create_tlv_format_onion_payloads() {
977
977
let cur_height = nodes[ 0 ] . best_block_info ( ) . 1 + 1 ;
978
978
let recipient_onion_fields = RecipientOnionFields :: spontaneous_empty ( ) ;
979
979
let ( onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils:: build_onion_payloads (
980
- & route. paths [ 0 ] , 40000 , & recipient_onion_fields, cur_height, & None , None ) . unwrap ( ) ;
980
+ & route. paths [ 0 ] , 40000 , & recipient_onion_fields, cur_height, & None , None , None ) . unwrap ( ) ;
981
981
982
982
match onion_payloads[ 0 ] {
983
983
msgs:: OutboundOnionPayload :: Forward { ..} => { } ,
@@ -1014,6 +1014,138 @@ fn test_trampoline_onion_payload_serialization() {
1014
1014
assert_eq ! ( carol_payload_hex, "2e020405f5e10004030c35000e2102edabbd16b41c8371b92ef2f04c1185b4f03b6dcd52ba9b78d9d7c89c8f221145" ) ;
1015
1015
}
1016
1016
1017
+ #[ test]
1018
+ fn test_trampoline_onion_payload_assembly_values ( ) {
1019
+ let amt_msat = 150_000_000 ;
1020
+ let cur_height = 800_000 ;
1021
+
1022
+ let path = Path {
1023
+ hops : vec ! [
1024
+ // Bob
1025
+ RouteHop {
1026
+ pubkey: PublicKey :: from_slice( & <Vec <u8 >>:: from_hex( "0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c" ) . unwrap( ) ) . unwrap( ) ,
1027
+ node_features: NodeFeatures :: empty( ) ,
1028
+ short_channel_id: 0 ,
1029
+ channel_features: ChannelFeatures :: empty( ) ,
1030
+ fee_msat: 3000 ,
1031
+ cltv_expiry_delta: 24 ,
1032
+ maybe_announced_channel: false ,
1033
+ } ,
1034
+
1035
+ // Carol
1036
+ RouteHop {
1037
+ pubkey: PublicKey :: from_slice( & <Vec <u8 >>:: from_hex( "027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007" ) . unwrap( ) ) . unwrap( ) ,
1038
+ node_features: NodeFeatures :: empty( ) ,
1039
+ short_channel_id: ( 572330 << 40 ) + ( 42 << 16 ) + 2821 ,
1040
+ channel_features: ChannelFeatures :: empty( ) ,
1041
+ fee_msat: 150_153_000 ,
1042
+ cltv_expiry_delta: 0 ,
1043
+ maybe_announced_channel: false ,
1044
+ } ,
1045
+ ] ,
1046
+ trampoline_hops : vec ! [
1047
+ // Carol's pubkey
1048
+ TrampolineHop {
1049
+ pubkey: PublicKey :: from_slice( & <Vec <u8 >>:: from_hex( "027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007" ) . unwrap( ) ) . unwrap( ) ,
1050
+ node_features: Features :: empty( ) ,
1051
+ fee_msat: 2_500 ,
1052
+ cltv_expiry_delta: 24 ,
1053
+ } ,
1054
+ // Dave's pubkey (the intro node needs to be duplicated)
1055
+ TrampolineHop {
1056
+ pubkey: PublicKey :: from_slice( & <Vec <u8 >>:: from_hex( "032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991" ) . unwrap( ) ) . unwrap( ) ,
1057
+ node_features: Features :: empty( ) ,
1058
+ fee_msat: 150_500 ,
1059
+ cltv_expiry_delta: 36 ,
1060
+ }
1061
+ ] ,
1062
+ blinded_tail : Some ( BlindedTail {
1063
+ hops : vec ! [
1064
+ // Dave's blinded node id
1065
+ BlindedHop {
1066
+ blinded_node_id: PublicKey :: from_slice( & <Vec <u8 >>:: from_hex( "0295d40514096a8be54859e7dfe947b376eaafea8afe5cb4eb2c13ff857ed0b4be" ) . unwrap( ) ) . unwrap( ) ,
1067
+ encrypted_payload: vec![ ] ,
1068
+ } ,
1069
+ // Eve's blinded node id
1070
+ BlindedHop {
1071
+ blinded_node_id: PublicKey :: from_slice( & <Vec <u8 >>:: from_hex( "020e2dbadcc2005e859819ddebbe88a834ae8a6d2b049233c07335f15cd1dc5f22" ) . unwrap( ) ) . unwrap( ) ,
1072
+ encrypted_payload: vec![ ] ,
1073
+ }
1074
+ ] ,
1075
+ blinding_point : PublicKey :: from_slice ( & <Vec < u8 > >:: from_hex ( "02988face71e92c345a068f740191fd8e53be14f0bb957ef730d3c5f76087b960e" ) . unwrap ( ) ) . unwrap ( ) ,
1076
+ excess_final_cltv_expiry_delta : 0 ,
1077
+ final_value_msat : amt_msat
1078
+ } ) ,
1079
+ } ;
1080
+ assert_eq ! ( path. fee_msat( ) , 156_000 ) ;
1081
+ assert_eq ! ( path. final_value_msat( ) , amt_msat) ;
1082
+ assert_eq ! ( path. final_cltv_expiry_delta( ) , None ) ;
1083
+
1084
+ let payment_secret = PaymentSecret ( SecretKey :: from_slice ( & <Vec < u8 > >:: from_hex ( "7494b65bc092b48a75465e43e29be807eb2cc535ce8aaba31012b8ff1ceac5da" ) . unwrap ( ) ) . unwrap ( ) . secret_bytes ( ) ) ;
1085
+ let recipient_onion_fields = RecipientOnionFields :: secret_only ( payment_secret) ;
1086
+ let ( trampoline_payloads, outer_total_msat, outer_starting_htlc_offset) = onion_utils:: build_trampoline_onion_payloads ( & path, amt_msat, & recipient_onion_fields, cur_height, & None ) . unwrap ( ) ;
1087
+ assert_eq ! ( trampoline_payloads. len( ) , 3 ) ;
1088
+ assert_eq ! ( outer_total_msat, 150_153_000 ) ;
1089
+ assert_eq ! ( outer_starting_htlc_offset, 800_060 ) ;
1090
+
1091
+ let trampoline_carol_payload = & trampoline_payloads[ 0 ] ;
1092
+ let trampoline_dave_payload = & trampoline_payloads[ 1 ] ;
1093
+ let trampoline_eve_payload = & trampoline_payloads[ 2 ] ;
1094
+ if let OutboundTrampolinePayload :: BlindedReceive { sender_intended_htlc_amt_msat, total_msat, cltv_expiry_height, .. } = trampoline_eve_payload {
1095
+ assert_eq ! ( sender_intended_htlc_amt_msat, & 150_000_000 ) ;
1096
+ assert_eq ! ( total_msat, & 150_000_000 ) ;
1097
+ assert_eq ! ( cltv_expiry_height, & 800_000 ) ;
1098
+ } else {
1099
+ panic ! ( "Eve Trampoline payload must be BlindedReceive" ) ;
1100
+ }
1101
+
1102
+ if let OutboundTrampolinePayload :: BlindedForward { .. } = trampoline_dave_payload { } else {
1103
+ panic ! ( "Dave Trampoline payload must be BlindedForward" ) ;
1104
+ }
1105
+
1106
+ if let OutboundTrampolinePayload :: Forward { amt_to_forward, outgoing_cltv_value, .. } = trampoline_carol_payload {
1107
+ assert_eq ! ( amt_to_forward, & 150_150_500 ) ;
1108
+ assert_eq ! ( outgoing_cltv_value, & 800_036 ) ;
1109
+ } else {
1110
+ panic ! ( "Carol Trampoline payload must be Forward" ) ;
1111
+ }
1112
+
1113
+ // all dummy values
1114
+ let secp_ctx = Secp256k1 :: new ( ) ;
1115
+ let session_priv = SecretKey :: from_slice ( & <Vec < u8 > >:: from_hex ( "a64feb81abd58e473df290e9e1c07dc3e56114495cadf33191f44ba5448ebe99" ) . unwrap ( ) ) . unwrap ( ) ;
1116
+ let prng_seed = onion_utils:: gen_pad_from_shared_secret ( & session_priv. secret_bytes ( ) ) ;
1117
+ let payment_hash = PaymentHash ( session_priv. secret_bytes ( ) ) ;
1118
+
1119
+ let onion_keys = construct_trampoline_onion_keys ( & secp_ctx, & path, & session_priv) . unwrap ( ) ;
1120
+ let trampoline_packet = construct_trampoline_onion_packet (
1121
+ trampoline_payloads,
1122
+ onion_keys,
1123
+ prng_seed,
1124
+ & payment_hash,
1125
+ None ,
1126
+ ) . unwrap ( ) ;
1127
+
1128
+ let ( outer_payloads, total_msat, total_htlc_offset) = onion_utils:: build_onion_payloads ( & path, outer_total_msat, & recipient_onion_fields, outer_starting_htlc_offset, & None , None , Some ( trampoline_packet) ) . unwrap ( ) ;
1129
+ assert_eq ! ( outer_payloads. len( ) , 2 ) ;
1130
+ assert_eq ! ( total_msat, 150_156_000 ) ;
1131
+ assert_eq ! ( total_htlc_offset, 800_084 ) ;
1132
+
1133
+ let outer_bob_payload = & outer_payloads[ 0 ] ;
1134
+ let outer_carol_payload = & outer_payloads[ 1 ] ;
1135
+ if let OutboundOnionPayload :: TrampolineEntrypoint { amt_to_forward, outgoing_cltv_value, .. } = outer_carol_payload {
1136
+ assert_eq ! ( amt_to_forward, & 150_153_000 ) ;
1137
+ assert_eq ! ( outgoing_cltv_value, & 800_060 ) ;
1138
+ } else {
1139
+ panic ! ( "Carol payload must be TrampolineEntrypoint" ) ;
1140
+ }
1141
+ if let OutboundOnionPayload :: Forward { amt_to_forward, outgoing_cltv_value, .. } = outer_bob_payload {
1142
+ assert_eq ! ( amt_to_forward, & 150_153_000 ) ;
1143
+ assert_eq ! ( outgoing_cltv_value, & 800_084 ) ;
1144
+ } else {
1145
+ panic ! ( "Bob payload must be Forward" ) ;
1146
+ }
1147
+ }
1148
+
1017
1149
#[ test]
1018
1150
fn test_trampoline_onion_payload_construction_vectors ( ) {
1019
1151
// As per https://github.com/lightning/bolts/blob/fa0594ac2af3531d734f1d707a146d6e13679451/bolt04/trampoline-to-blinded-path-payment-onion-test.json#L251
@@ -1378,7 +1510,7 @@ fn test_phantom_invalid_onion_payload() {
1378
1510
let recipient_onion_fields = RecipientOnionFields :: secret_only ( payment_secret) ;
1379
1511
let ( mut onion_payloads, _, _) = onion_utils:: build_onion_payloads (
1380
1512
& route. paths [ 0 ] , msgs:: MAX_VALUE_MSAT + 1 ,
1381
- & recipient_onion_fields, height + 1 , & None , None ) . unwrap ( ) ;
1513
+ & recipient_onion_fields, height + 1 , & None , None , None ) . unwrap ( ) ;
1382
1514
// We only want to construct the onion packet for the last hop, not the entire route, so
1383
1515
// remove the first hop's payload and its keys.
1384
1516
onion_keys. remove ( 0 ) ;
0 commit comments