@@ -53,7 +53,7 @@ use crate::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringFeeParame
53
53
use crate::ln::onion_payment::{check_incoming_htlc_cltv, create_recv_pending_htlc_info, create_fwd_pending_htlc_info, decode_incoming_update_add_htlc_onion, InboundOnionErr, NextPacketDetails};
54
54
use crate::ln::msgs;
55
55
use crate::ln::onion_utils;
56
- use crate::ln::onion_utils::HTLCFailReason;
56
+ use crate::ln::onion_utils::{ HTLCFailReason, INVALID_ONION_BLINDING} ;
57
57
use crate::ln::msgs::{ChannelMessageHandler, DecodeError, LightningError};
58
58
#[cfg(test)]
59
59
use crate::ln::outbound_payment;
@@ -119,6 +119,8 @@ pub enum PendingHTLCRouting {
119
119
/// The SCID from the onion that we should forward to. This could be a real SCID or a fake one
120
120
/// generated using `get_fake_scid` from the scid_utils::fake_scid module.
121
121
short_channel_id: u64, // This should be NonZero<u64> eventually when we bump MSRV
122
+ /// Set if this HTLC is being forwarded within a blinded path.
123
+ blinded: Option<BlindedForward>,
122
124
},
123
125
/// An HTLC paid to an invoice (supposedly) generated by us.
124
126
/// At this point, we have not checked that the invoice being paid was actually generated by us,
@@ -155,6 +157,28 @@ pub enum PendingHTLCRouting {
155
157
},
156
158
}
157
159
160
+ /// Information used to forward or fail this HTLC that is being forwarded within a blinded path.
161
+ #[derive(Clone, Copy, Hash, PartialEq, Eq)]
162
+ pub struct BlindedForward {
163
+ /// The `blinding_point` that was set in the inbound [`msgs::UpdateAddHTLC`], or in the inbound
164
+ /// onion payload if we're the introduction node. Useful for calculating the next hop's
165
+ /// [`msgs::UpdateAddHTLC::blinding_point`].
166
+ pub inbound_blinding_point: PublicKey,
167
+ // Another field will be added here when we support forwarding as a non-intro node.
168
+ }
169
+
170
+ impl PendingHTLCRouting {
171
+ // Used to override the onion failure code and data if the HTLC is blinded.
172
+ fn blinded_failure(&self) -> Option<BlindedFailure> {
173
+ // TODO: needs update when we support receiving to multi-hop blinded paths
174
+ if let Self::Forward { blinded: Some(_), .. } = self {
175
+ Some(BlindedFailure::FromIntroductionNode)
176
+ } else {
177
+ None
178
+ }
179
+ }
180
+ }
181
+
158
182
/// Full details of an incoming HTLC, including routing info.
159
183
#[derive(Clone)] // See Channel::revoke_and_ack for why, tl;dr: Rust bug
160
184
pub struct PendingHTLCInfo {
@@ -213,6 +237,13 @@ pub(super) enum HTLCForwardInfo {
213
237
},
214
238
}
215
239
240
+ // Used for failing blinded HTLCs backwards correctly.
241
+ #[derive(Clone, Debug, Hash, PartialEq, Eq)]
242
+ enum BlindedFailure {
243
+ FromIntroductionNode,
244
+ // Another variant will be added here for non-intro nodes.
245
+ }
246
+
216
247
/// Tracks the inbound corresponding to an outbound HTLC
217
248
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
218
249
pub(crate) struct HTLCPreviousHopData {
@@ -222,6 +253,7 @@ pub(crate) struct HTLCPreviousHopData {
222
253
htlc_id: u64,
223
254
incoming_packet_shared_secret: [u8; 32],
224
255
phantom_shared_secret: Option<[u8; 32]>,
256
+ blinded_failure: Option<BlindedFailure>,
225
257
226
258
// This field is consumed by `claim_funds_from_hop()` when updating a force-closed backwards
227
259
// channel with a preimage provided by the forward channel.
@@ -2945,14 +2977,24 @@ where
2945
2977
msg, &self.node_signer, &self.logger, &self.secp_ctx
2946
2978
)?;
2947
2979
2980
+ let is_blinded = match next_hop {
2981
+ onion_utils::Hop::Forward {
2982
+ next_hop_data: msgs::InboundOnionPayload::BlindedForward { .. }, ..
2983
+ } => true,
2984
+ _ => false, // TODO: update this when we support receiving to multi-hop blinded paths
2985
+ };
2986
+
2948
2987
macro_rules! return_err {
2949
2988
($msg: expr, $err_code: expr, $data: expr) => {
2950
2989
{
2951
2990
log_info!(self.logger, "Failed to accept/forward incoming HTLC: {}", $msg);
2991
+ let (err_code, err_data) = if is_blinded {
2992
+ (INVALID_ONION_BLINDING, &[0; 32][..])
2993
+ } else { ($err_code, $data) };
2952
2994
return Err(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC {
2953
2995
channel_id: msg.channel_id,
2954
2996
htlc_id: msg.htlc_id,
2955
- reason: HTLCFailReason::reason($ err_code, $data .to_vec())
2997
+ reason: HTLCFailReason::reason(err_code, err_data .to_vec())
2956
2998
.get_encrypted_failure_packet(&shared_secret, &None),
2957
2999
}));
2958
3000
}
@@ -4013,8 +4055,10 @@ where
4013
4055
})?;
4014
4056
4015
4057
let routing = match payment.forward_info.routing {
4016
- PendingHTLCRouting::Forward { onion_packet, .. } => {
4017
- PendingHTLCRouting::Forward { onion_packet, short_channel_id: next_hop_scid }
4058
+ PendingHTLCRouting::Forward { onion_packet, blinded, .. } => {
4059
+ PendingHTLCRouting::Forward {
4060
+ onion_packet, blinded, short_channel_id: next_hop_scid
4061
+ }
4018
4062
},
4019
4063
_ => unreachable!() // Only `PendingHTLCRouting::Forward`s are intercepted
4020
4064
};
@@ -4058,6 +4102,7 @@ where
4058
4102
htlc_id: payment.prev_htlc_id,
4059
4103
incoming_packet_shared_secret: payment.forward_info.incoming_shared_secret,
4060
4104
phantom_shared_secret: None,
4105
+ blinded_failure: payment.forward_info.routing.blinded_failure(),
4061
4106
});
4062
4107
4063
4108
let failure_reason = HTLCFailReason::from_failure_code(0x4000 | 10);
@@ -4106,6 +4151,7 @@ where
4106
4151
htlc_id: prev_htlc_id,
4107
4152
incoming_packet_shared_secret: incoming_shared_secret,
4108
4153
phantom_shared_secret: $phantom_ss,
4154
+ blinded_failure: routing.blinded_failure(),
4109
4155
});
4110
4156
4111
4157
let reason = if $next_hop_unknown {
@@ -4135,7 +4181,7 @@ where
4135
4181
}
4136
4182
}
4137
4183
}
4138
- if let PendingHTLCRouting::Forward { onion_packet, .. } = routing {
4184
+ if let PendingHTLCRouting::Forward { ref onion_packet, .. } = routing {
4139
4185
let phantom_pubkey_res = self.node_signer.get_node_id(Recipient::PhantomNode);
4140
4186
if phantom_pubkey_res.is_ok() && fake_scid::is_valid_phantom(&self.fake_scid_rand_bytes, short_chan_id, &self.chain_hash) {
4141
4187
let phantom_shared_secret = self.node_signer.ecdh(Recipient::PhantomNode, &onion_packet.public_key.unwrap(), None).unwrap().secret_bytes();
@@ -4210,7 +4256,9 @@ where
4210
4256
prev_short_channel_id, prev_htlc_id, prev_funding_outpoint, prev_user_channel_id,
4211
4257
forward_info: PendingHTLCInfo {
4212
4258
incoming_shared_secret, payment_hash, outgoing_amt_msat, outgoing_cltv_value,
4213
- routing: PendingHTLCRouting::Forward { onion_packet, .. }, skimmed_fee_msat, ..
4259
+ routing: PendingHTLCRouting::Forward {
4260
+ onion_packet, blinded, ..
4261
+ }, skimmed_fee_msat, ..
4214
4262
},
4215
4263
}) => {
4216
4264
log_trace!(self.logger, "Adding HTLC from short id {} with payment_hash {} to channel with short id {} after delay", prev_short_channel_id, &payment_hash, short_chan_id);
@@ -4222,10 +4270,19 @@ where
4222
4270
incoming_packet_shared_secret: incoming_shared_secret,
4223
4271
// Phantom payments are only PendingHTLCRouting::Receive.
4224
4272
phantom_shared_secret: None,
4273
+ blinded_failure: blinded.map(|_| BlindedFailure::FromIntroductionNode),
4274
+ });
4275
+ let next_blinding_point = blinded.and_then(|b| {
4276
+ let encrypted_tlvs_ss = self.node_signer.ecdh(
4277
+ Recipient::Node, &b.inbound_blinding_point, None
4278
+ ).unwrap().secret_bytes();
4279
+ onion_utils::next_hop_pubkey(
4280
+ &self.secp_ctx, b.inbound_blinding_point, &encrypted_tlvs_ss
4281
+ ).ok()
4225
4282
});
4226
4283
if let Err(e) = chan.queue_add_htlc(outgoing_amt_msat,
4227
4284
payment_hash, outgoing_cltv_value, htlc_source.clone(),
4228
- onion_packet, skimmed_fee_msat, &self.fee_estimator,
4285
+ onion_packet, skimmed_fee_msat, next_blinding_point, &self.fee_estimator,
4229
4286
&self.logger)
4230
4287
{
4231
4288
if let ChannelError::Ignore(msg) = e {
@@ -4276,6 +4333,7 @@ where
4276
4333
skimmed_fee_msat, ..
4277
4334
}
4278
4335
}) => {
4336
+ let blinded_failure = routing.blinded_failure();
4279
4337
let (cltv_expiry, onion_payload, payment_data, phantom_shared_secret, mut onion_fields) = match routing {
4280
4338
PendingHTLCRouting::Receive { payment_data, payment_metadata, incoming_cltv_expiry, phantom_shared_secret, custom_tlvs } => {
4281
4339
let _legacy_hop_data = Some(payment_data.clone());
@@ -4305,6 +4363,7 @@ where
4305
4363
htlc_id: prev_htlc_id,
4306
4364
incoming_packet_shared_secret: incoming_shared_secret,
4307
4365
phantom_shared_secret,
4366
+ blinded_failure,
4308
4367
},
4309
4368
// We differentiate the received value from the sender intended value
4310
4369
// if possible so that we don't prematurely mark MPP payments complete
@@ -4335,6 +4394,7 @@ where
4335
4394
htlc_id: $htlc.prev_hop.htlc_id,
4336
4395
incoming_packet_shared_secret: $htlc.prev_hop.incoming_packet_shared_secret,
4337
4396
phantom_shared_secret,
4397
+ blinded_failure: None,
4338
4398
}), payment_hash,
4339
4399
HTLCFailReason::reason(0x4000 | 15, htlc_msat_height_data),
4340
4400
HTLCDestination::FailedPayment { payment_hash: $payment_hash },
@@ -5098,9 +5158,23 @@ where
5098
5158
&self.pending_events, &self.logger)
5099
5159
{ self.push_pending_forwards_ev(); }
5100
5160
},
5101
- HTLCSource::PreviousHopData(HTLCPreviousHopData { ref short_channel_id, ref htlc_id, ref incoming_packet_shared_secret, ref phantom_shared_secret, ref outpoint, .. }) => {
5102
- log_trace!(self.logger, "Failing HTLC with payment_hash {} backwards from us with {:?}", &payment_hash, onion_error);
5103
- let err_packet = onion_error.get_encrypted_failure_packet(incoming_packet_shared_secret, phantom_shared_secret);
5161
+ HTLCSource::PreviousHopData(HTLCPreviousHopData {
5162
+ ref short_channel_id, ref htlc_id, ref incoming_packet_shared_secret,
5163
+ ref phantom_shared_secret, ref outpoint, ref blinded_failure, ..
5164
+ }) => {
5165
+ log_trace!(self.logger, "Failing {}HTLC with payment_hash {} backwards from us: {:?}",
5166
+ if blinded_failure.is_some() { "blinded " } else { "" }, &payment_hash, onion_error);
5167
+ let err_packet = match blinded_failure {
5168
+ Some(BlindedFailure::FromIntroductionNode) => {
5169
+ let blinded_onion_error = HTLCFailReason::reason(INVALID_ONION_BLINDING, vec![0; 32]);
5170
+ blinded_onion_error.get_encrypted_failure_packet(
5171
+ incoming_packet_shared_secret, phantom_shared_secret
5172
+ )
5173
+ },
5174
+ None => {
5175
+ onion_error.get_encrypted_failure_packet(incoming_packet_shared_secret, phantom_shared_secret)
5176
+ }
5177
+ };
5104
5178
5105
5179
let mut push_forward_ev = false;
5106
5180
let mut forward_htlcs = self.forward_htlcs.lock().unwrap();
@@ -6381,8 +6455,12 @@ where
6381
6455
// but if we've sent a shutdown and they haven't acknowledged it yet, we just
6382
6456
// want to reject the new HTLC and fail it backwards instead of forwarding.
6383
6457
match pending_forward_info {
6384
- PendingHTLCStatus::Forward(PendingHTLCInfo { ref incoming_shared_secret, .. }) => {
6385
- let reason = if (error_code & 0x1000) != 0 {
6458
+ PendingHTLCStatus::Forward(PendingHTLCInfo {
6459
+ ref incoming_shared_secret, ref routing, ..
6460
+ }) => {
6461
+ let reason = if routing.blinded_failure().is_some() {
6462
+ HTLCFailReason::reason(INVALID_ONION_BLINDING, vec![0; 32])
6463
+ } else if (error_code & 0x1000) != 0 {
6386
6464
let (real_code, error_data) = self.get_htlc_inbound_temp_fail_err_and_data(error_code, chan);
6387
6465
HTLCFailReason::reason(real_code, error_data)
6388
6466
} else {
@@ -6584,6 +6662,7 @@ where
6584
6662
htlc_id: prev_htlc_id,
6585
6663
incoming_packet_shared_secret: forward_info.incoming_shared_secret,
6586
6664
phantom_shared_secret: None,
6665
+ blinded_failure: forward_info.routing.blinded_failure(),
6587
6666
});
6588
6667
6589
6668
failed_intercept_forwards.push((htlc_source, forward_info.payment_hash,
@@ -8180,6 +8259,7 @@ where
8180
8259
incoming_packet_shared_secret: htlc.forward_info.incoming_shared_secret,
8181
8260
phantom_shared_secret: None,
8182
8261
outpoint: htlc.prev_funding_outpoint,
8262
+ blinded_failure: htlc.forward_info.routing.blinded_failure(),
8183
8263
});
8184
8264
8185
8265
let requested_forward_scid /* intercept scid */ = match htlc.forward_info.routing {
@@ -9143,9 +9223,14 @@ impl_writeable_tlv_based!(PhantomRouteHints, {
9143
9223
(6, real_node_pubkey, required),
9144
9224
});
9145
9225
9226
+ impl_writeable_tlv_based!(BlindedForward, {
9227
+ (0, inbound_blinding_point, required),
9228
+ });
9229
+
9146
9230
impl_writeable_tlv_based_enum!(PendingHTLCRouting,
9147
9231
(0, Forward) => {
9148
9232
(0, onion_packet, required),
9233
+ (1, blinded, option),
9149
9234
(2, short_channel_id, required),
9150
9235
},
9151
9236
(1, Receive) => {
@@ -9247,10 +9332,15 @@ impl_writeable_tlv_based_enum!(PendingHTLCStatus, ;
9247
9332
(1, Fail),
9248
9333
);
9249
9334
9335
+ impl_writeable_tlv_based_enum!(BlindedFailure,
9336
+ (0, FromIntroductionNode) => {}, ;
9337
+ );
9338
+
9250
9339
impl_writeable_tlv_based!(HTLCPreviousHopData, {
9251
9340
(0, short_channel_id, required),
9252
9341
(1, phantom_shared_secret, option),
9253
9342
(2, outpoint, required),
9343
+ (3, blinded_failure, option),
9254
9344
(4, htlc_id, required),
9255
9345
(6, incoming_packet_shared_secret, required),
9256
9346
(7, user_channel_id, option),
0 commit comments