Skip to content

Commit a1bbef7

Browse files
Make BlindedMessagePath creation infallible
The LDK codebase in general is comfortable panicking if the entropy source provided to it is dysfunctional. Up until now we made an exception for blinded path creation, where we would handle an error that could occur on mul_tweak that could only occur if the session_priv provided was not actually random. In comparable cases in onion_utils, we would panic instead. In upcoming commits, we will be including blinded paths in outbound revoke_and_ack messages as part of implementing async payments, where it is difficult to handle failing back an HTLC if blinded path creation fails. Thus we now have an incentive to make the blinded path creation methods infallible, so do so here.
1 parent b3f8ccf commit a1bbef7

File tree

6 files changed

+55
-84
lines changed

6 files changed

+55
-84
lines changed

lightning/src/blinded_path/message.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ impl BlindedMessagePath {
5757
pub fn one_hop<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
5858
recipient_node_id: PublicKey, local_node_receive_key: ReceiveAuthKey,
5959
context: MessageContext, entropy_source: ES, secp_ctx: &Secp256k1<T>,
60-
) -> Result<Self, ()>
60+
) -> Self
6161
where
6262
ES::Target: EntropySource,
6363
{
@@ -73,7 +73,7 @@ impl BlindedMessagePath {
7373
intermediate_nodes: &[MessageForwardNode], recipient_node_id: PublicKey,
7474
local_node_receive_key: ReceiveAuthKey, context: MessageContext, entropy_source: ES,
7575
secp_ctx: &Secp256k1<T>,
76-
) -> Result<Self, ()>
76+
) -> Self
7777
where
7878
ES::Target: EntropySource,
7979
{
@@ -96,7 +96,7 @@ impl BlindedMessagePath {
9696
intermediate_nodes: &[MessageForwardNode], recipient_node_id: PublicKey,
9797
dummy_hop_count: usize, local_node_receive_key: ReceiveAuthKey, context: MessageContext,
9898
entropy_source: ES, secp_ctx: &Secp256k1<T>,
99-
) -> Result<Self, ()>
99+
) -> Self
100100
where
101101
ES::Target: EntropySource,
102102
{
@@ -107,7 +107,7 @@ impl BlindedMessagePath {
107107
let blinding_secret =
108108
SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted");
109109

110-
Ok(Self(BlindedPath {
110+
Self(BlindedPath {
111111
introduction_node,
112112
blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret),
113113
blinded_hops: blinded_hops(
@@ -118,9 +118,8 @@ impl BlindedMessagePath {
118118
context,
119119
&blinding_secret,
120120
local_node_receive_key,
121-
)
122-
.map_err(|_| ())?,
123-
}))
121+
),
122+
})
124123
}
125124

126125
/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
@@ -669,7 +668,7 @@ pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
669668
secp_ctx: &Secp256k1<T>, intermediate_nodes: &[MessageForwardNode],
670669
recipient_node_id: PublicKey, dummy_hop_count: usize, context: MessageContext,
671670
session_priv: &SecretKey, local_node_receive_key: ReceiveAuthKey,
672-
) -> Result<Vec<BlindedHop>, secp256k1::Error> {
671+
) -> Vec<BlindedHop> {
673672
let dummy_count = cmp::min(dummy_hop_count, MAX_DUMMY_HOPS_COUNT);
674673
let pks = intermediate_nodes
675674
.iter()

lightning/src/blinded_path/payment.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,7 @@ impl BlindedPaymentPath {
151151
payee_node_id,
152152
payee_tlvs,
153153
&blinding_secret,
154-
)
155-
.map_err(|_| ())?,
154+
),
156155
},
157156
payinfo: blinded_payinfo,
158157
})
@@ -663,7 +662,7 @@ pub(crate) const PAYMENT_PADDING_ROUND_OFF: usize = 30;
663662
pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
664663
secp_ctx: &Secp256k1<T>, intermediate_nodes: &[PaymentForwardNode], payee_node_id: PublicKey,
665664
payee_tlvs: ReceiveTlvs, session_priv: &SecretKey,
666-
) -> Result<Vec<BlindedHop>, secp256k1::Error> {
665+
) -> Vec<BlindedHop> {
667666
let pks = intermediate_nodes
668667
.iter()
669668
.map(|node| (node.node_id, None))

lightning/src/blinded_path/utils.rs

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,8 @@ macro_rules! build_keys_helper {
5151
hmac.input(encrypted_data_ss.as_ref());
5252
Hmac::from_engine(hmac).to_byte_array()
5353
};
54-
pk.mul_tweak(
55-
$secp_ctx,
56-
&Scalar::from_be_bytes(hop_pk_blinding_factor).unwrap(),
57-
)?
54+
pk.mul_tweak($secp_ctx, &Scalar::from_be_bytes(hop_pk_blinding_factor).unwrap())
55+
.expect("RNG is busted")
5856
};
5957
let onion_packet_ss = SharedSecret::new(&blinded_hop_pk, &onion_packet_pubkey_priv);
6058

@@ -84,9 +82,9 @@ macro_rules! build_keys_helper {
8482
Sha256::from_engine(sha).to_byte_array()
8583
};
8684

87-
msg_blinding_point_priv = msg_blinding_point_priv.mul_tweak(
88-
&Scalar::from_be_bytes(msg_blinding_point_blinding_factor).unwrap(),
89-
)?;
85+
msg_blinding_point_priv = msg_blinding_point_priv
86+
.mul_tweak(&Scalar::from_be_bytes(msg_blinding_point_blinding_factor).unwrap())
87+
.expect("RNG is busted");
9088
msg_blinding_point =
9189
PublicKey::from_secret_key($secp_ctx, &msg_blinding_point_priv);
9290

@@ -96,9 +94,9 @@ macro_rules! build_keys_helper {
9694
sha.input(onion_packet_ss.as_ref());
9795
Sha256::from_engine(sha).to_byte_array()
9896
};
99-
onion_packet_pubkey_priv = onion_packet_pubkey_priv.mul_tweak(
100-
&Scalar::from_be_bytes(onion_packet_pubkey_blinding_factor).unwrap(),
101-
)?;
97+
onion_packet_pubkey_priv = onion_packet_pubkey_priv
98+
.mul_tweak(&Scalar::from_be_bytes(onion_packet_pubkey_blinding_factor).unwrap())
99+
.expect("RNG is busted");
102100
onion_packet_pubkey =
103101
PublicKey::from_secret_key($secp_ctx, &onion_packet_pubkey_priv);
104102
};
@@ -109,8 +107,7 @@ macro_rules! build_keys_helper {
109107
pub(crate) fn construct_keys_for_onion_message<'a, T, I, F>(
110108
secp_ctx: &Secp256k1<T>, unblinded_path: I, destination: Destination, session_priv: &SecretKey,
111109
mut callback: F,
112-
) -> Result<(), secp256k1::Error>
113-
where
110+
) where
114111
T: secp256k1::Signing + secp256k1::Verification,
115112
I: Iterator<Item = PublicKey>,
116113
F: FnMut(SharedSecret, PublicKey, [u8; 32], Option<PublicKey>, Option<Vec<u8>>),
@@ -134,13 +131,11 @@ where
134131
}
135132
},
136133
}
137-
Ok(())
138134
}
139135

140136
fn construct_keys_for_blinded_path<'a, T, I, F, H>(
141137
secp_ctx: &Secp256k1<T>, unblinded_path: I, session_priv: &SecretKey, mut callback: F,
142-
) -> Result<(), secp256k1::Error>
143-
where
138+
) where
144139
T: secp256k1::Signing + secp256k1::Verification,
145140
H: Borrow<PublicKey>,
146141
I: Iterator<Item = H>,
@@ -151,7 +146,6 @@ where
151146
for pk in unblinded_path {
152147
build_keys_in_loop!(pk, false, None);
153148
}
154-
Ok(())
155149
}
156150

157151
struct PublicKeyWithTlvs<W: Writeable> {
@@ -168,7 +162,7 @@ impl<W: Writeable> Borrow<PublicKey> for PublicKeyWithTlvs<W> {
168162

169163
pub(crate) fn construct_blinded_hops<'a, T, I, W>(
170164
secp_ctx: &Secp256k1<T>, unblinded_path: I, session_priv: &SecretKey,
171-
) -> Result<Vec<BlindedHop>, secp256k1::Error>
165+
) -> Vec<BlindedHop>
172166
where
173167
T: secp256k1::Signing + secp256k1::Verification,
174168
I: Iterator<Item = ((PublicKey, Option<ReceiveAuthKey>), W)>,
@@ -194,8 +188,8 @@ where
194188
),
195189
});
196190
},
197-
)?;
198-
Ok(blinded_hops)
191+
);
192+
blinded_hops
199193
}
200194

201195
/// Encrypt TLV payload to be used as a [`crate::blinded_path::BlindedHop::encrypted_payload`].

lightning/src/ln/blinded_payment_tests.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1552,7 +1552,7 @@ fn route_blinding_spec_test_vector() {
15521552
];
15531553
let mut dave_eve_blinded_hops = blinded_path::utils::construct_blinded_hops(
15541554
&secp_ctx, path.into_iter(), &dave_eve_session_priv,
1555-
).unwrap();
1555+
);
15561556

15571557
// Concatenate an additional Bob -> Carol blinded path to the Eve -> Dave blinded path.
15581558
let bob_carol_session_priv = secret_from_hex("0202020202020202020202020202020202020202020202020202020202020202");
@@ -1563,7 +1563,7 @@ fn route_blinding_spec_test_vector() {
15631563
];
15641564
let bob_carol_blinded_hops = blinded_path::utils::construct_blinded_hops(
15651565
&secp_ctx, path.into_iter(), &bob_carol_session_priv,
1566-
).unwrap();
1566+
);
15671567

15681568
let mut blinded_hops = bob_carol_blinded_hops;
15691569
blinded_hops.append(&mut dave_eve_blinded_hops);
@@ -2030,7 +2030,7 @@ fn do_test_trampoline_single_hop_receive(success: bool) {
20302030
let path = [((carol_node_id, None), WithoutLength(&carol_unblinded_tlvs))];
20312031
blinded_path::utils::construct_blinded_hops(
20322032
&secp_ctx, path.into_iter(), &carol_alice_trampoline_session_priv,
2033-
).unwrap()
2033+
)
20342034
} else {
20352035
let payee_tlvs = blinded_path::payment::TrampolineForwardTlvs {
20362036
next_trampoline: alice_node_id,
@@ -2051,7 +2051,7 @@ fn do_test_trampoline_single_hop_receive(success: bool) {
20512051
let path = [((carol_node_id, None), WithoutLength(&carol_unblinded_tlvs))];
20522052
blinded_path::utils::construct_blinded_hops(
20532053
&secp_ctx, path.into_iter(), &carol_alice_trampoline_session_priv,
2054-
).unwrap()
2054+
)
20552055
};
20562056

20572057
let route = Route {
@@ -2255,7 +2255,7 @@ fn test_trampoline_unblinded_receive() {
22552255
let carol_blinding_point = PublicKey::from_secret_key(&secp_ctx, &carol_alice_trampoline_session_priv);
22562256
let carol_blinded_hops = blinded_path::utils::construct_blinded_hops(
22572257
&secp_ctx, path.into_iter(), &carol_alice_trampoline_session_priv,
2258-
).unwrap();
2258+
);
22592259

22602260
let route = Route {
22612261
paths: vec![Path {

lightning/src/onion_message/functional_tests.rs

Lines changed: 18 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -437,8 +437,7 @@ fn one_blinded_hop() {
437437
let entropy = &*nodes[1].entropy_source;
438438
let receive_key = nodes[1].messenger.node_signer.get_receive_auth_key();
439439
let blinded_path =
440-
BlindedMessagePath::new(&[], nodes[1].node_id, receive_key, context, entropy, &secp_ctx)
441-
.unwrap();
440+
BlindedMessagePath::new(&[], nodes[1].node_id, receive_key, context, entropy, &secp_ctx);
442441
let destination = Destination::BlindedPath(blinded_path);
443442
let instructions = MessageSendInstructions::WithoutReplyPath { destination };
444443
nodes[0].messenger.send_onion_message(test_msg, instructions).unwrap();
@@ -463,8 +462,7 @@ fn blinded_path_with_dummy_hops() {
463462
context,
464463
entropy,
465464
&secp_ctx,
466-
)
467-
.unwrap();
465+
);
468466
// Ensure that dummy hops are added to the blinded path.
469467
assert_eq!(blinded_path.blinded_hops().len(), 6);
470468
let destination = Destination::BlindedPath(blinded_path);
@@ -492,8 +490,7 @@ fn two_unblinded_two_blinded() {
492490
context,
493491
entropy,
494492
&secp_ctx,
495-
)
496-
.unwrap();
493+
);
497494
let path = OnionMessagePath {
498495
intermediate_nodes: vec![nodes[1].node_id, nodes[2].node_id],
499496
destination: Destination::BlindedPath(blinded_path),
@@ -525,8 +522,7 @@ fn three_blinded_hops() {
525522
context,
526523
entropy,
527524
&secp_ctx,
528-
)
529-
.unwrap();
525+
);
530526
let destination = Destination::BlindedPath(blinded_path);
531527
let instructions = MessageSendInstructions::WithoutReplyPath { destination };
532528

@@ -553,8 +549,7 @@ fn async_response_over_one_blinded_hop() {
553549
let entropy = &*nodes[1].entropy_source;
554550
let receive_key = nodes[1].messenger.node_signer.get_receive_auth_key();
555551
let reply_path =
556-
BlindedMessagePath::new(&[], nodes[1].node_id, receive_key, context, entropy, &secp_ctx)
557-
.unwrap();
552+
BlindedMessagePath::new(&[], nodes[1].node_id, receive_key, context, entropy, &secp_ctx);
558553

559554
// 4. Create a responder using the reply path for Alice.
560555
let responder = Some(Responder::new(reply_path));
@@ -595,8 +590,7 @@ fn async_response_with_reply_path_succeeds() {
595590
let entropy = &*bob.entropy_source;
596591
let receive_key = bob.messenger.node_signer.get_receive_auth_key();
597592
let reply_path =
598-
BlindedMessagePath::new(&[], bob.node_id, receive_key, context, entropy, &secp_ctx)
599-
.unwrap();
593+
BlindedMessagePath::new(&[], bob.node_id, receive_key, context, entropy, &secp_ctx);
600594

601595
// Alice asynchronously responds to Bob, expecting a response back from him.
602596
let responder = Responder::new(reply_path);
@@ -638,8 +632,7 @@ fn async_response_with_reply_path_fails() {
638632
let entropy = &*bob.entropy_source;
639633
let receive_key = bob.messenger.node_signer.get_receive_auth_key();
640634
let reply_path =
641-
BlindedMessagePath::new(&[], bob.node_id, receive_key, context, entropy, &secp_ctx)
642-
.unwrap();
635+
BlindedMessagePath::new(&[], bob.node_id, receive_key, context, entropy, &secp_ctx);
643636

644637
// Alice tries to asynchronously respond to Bob, but fails because the nodes are unannounced and
645638
// disconnected. Thus, a reply path could no be created for the response.
@@ -697,8 +690,7 @@ fn test_blinded_path_padding_for_full_length_path() {
697690
context,
698691
entropy,
699692
&secp_ctx,
700-
)
701-
.unwrap();
693+
);
702694

703695
assert!(is_padded(&blinded_path.blinded_hops(), MESSAGE_PADDING_ROUND_OFF));
704696

@@ -734,8 +726,7 @@ fn test_blinded_path_no_padding_for_compact_path() {
734726
context,
735727
entropy,
736728
&secp_ctx,
737-
)
738-
.unwrap();
729+
);
739730

740731
assert!(!is_padded(&blinded_path.blinded_hops(), MESSAGE_PADDING_ROUND_OFF));
741732
}
@@ -762,8 +753,7 @@ fn we_are_intro_node() {
762753
context,
763754
entropy,
764755
&secp_ctx,
765-
)
766-
.unwrap();
756+
);
767757
let destination = Destination::BlindedPath(blinded_path);
768758
let instructions = MessageSendInstructions::WithoutReplyPath { destination };
769759

@@ -784,8 +774,7 @@ fn we_are_intro_node() {
784774
context,
785775
entropy,
786776
&secp_ctx,
787-
)
788-
.unwrap();
777+
);
789778
let destination = Destination::BlindedPath(blinded_path);
790779
let instructions = MessageSendInstructions::WithoutReplyPath { destination };
791780

@@ -814,8 +803,7 @@ fn invalid_blinded_path_error() {
814803
context,
815804
entropy,
816805
&secp_ctx,
817-
)
818-
.unwrap();
806+
);
819807
blinded_path.clear_blinded_hops();
820808
let destination = Destination::BlindedPath(blinded_path);
821809
let instructions = MessageSendInstructions::WithoutReplyPath { destination };
@@ -850,8 +838,7 @@ fn reply_path() {
850838
context,
851839
entropy,
852840
&secp_ctx,
853-
)
854-
.unwrap();
841+
);
855842
nodes[0]
856843
.messenger
857844
.send_onion_message_using_path(path, test_msg.clone(), Some(reply_path))
@@ -878,8 +865,7 @@ fn reply_path() {
878865
context,
879866
entropy,
880867
&secp_ctx,
881-
)
882-
.unwrap();
868+
);
883869
let destination = Destination::BlindedPath(blinded_path);
884870
let intermediate_nodes = [
885871
MessageForwardNode { node_id: nodes[2].node_id, short_channel_id: None },
@@ -895,8 +881,7 @@ fn reply_path() {
895881
context,
896882
entropy,
897883
&secp_ctx,
898-
)
899-
.unwrap();
884+
);
900885
let instructions = MessageSendInstructions::WithSpecifiedReplyPath { destination, reply_path };
901886

902887
nodes[0].messenger.send_onion_message(test_msg, instructions).unwrap();
@@ -1000,8 +985,7 @@ fn requests_peer_connection_for_buffered_messages() {
1000985
context,
1001986
entropy,
1002987
&secp_ctx,
1003-
)
1004-
.unwrap();
988+
);
1005989
let destination = Destination::BlindedPath(blinded_path);
1006990
let instructions = MessageSendInstructions::WithoutReplyPath { destination };
1007991

@@ -1049,8 +1033,7 @@ fn drops_buffered_messages_waiting_for_peer_connection() {
10491033
context,
10501034
entropy,
10511035
&secp_ctx,
1052-
)
1053-
.unwrap();
1036+
);
10541037
let destination = Destination::BlindedPath(blinded_path);
10551038
let instructions = MessageSendInstructions::WithoutReplyPath { destination };
10561039

@@ -1114,8 +1097,7 @@ fn intercept_offline_peer_oms() {
11141097
context,
11151098
entropy,
11161099
&secp_ctx,
1117-
)
1118-
.unwrap();
1100+
);
11191101
let destination = Destination::BlindedPath(blinded_path);
11201102
let instructions = MessageSendInstructions::WithoutReplyPath { destination };
11211103

0 commit comments

Comments
 (0)