Skip to content

Commit e4ff468

Browse files
committedMay 3, 2023
convert to attributable errors
1 parent c182567 commit e4ff468

File tree

6 files changed

+386
-52
lines changed

6 files changed

+386
-52
lines changed
 

‎lightning-invoice/src/lib.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -519,12 +519,15 @@ impl InvoiceBuilder<tb::False, tb::False, tb::False, tb::False, tb::False, tb::F
519519
/// Construct new, empty `InvoiceBuilder`. All necessary fields have to be filled first before
520520
/// `InvoiceBuilder::build(self)` becomes available.
521521
pub fn new(currency: Currency) -> Self {
522+
let mut features = InvoiceFeatures::empty();
523+
features.set_attributable_errors_optional();
524+
522525
InvoiceBuilder {
523526
currency,
524527
amount: None,
525528
si_prefix: None,
526529
timestamp: None,
527-
tagged_fields: Vec::new(),
530+
tagged_fields: vec![TaggedField::Features(features)],
528531
error: None,
529532

530533
phantom_d: core::marker::PhantomData,

‎lightning/src/ln/channelmanager.rs

+58-11
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ use crate::routing::router::{BlindedTail, DefaultRouter, InFlightHtlcs, Path, Pa
4949
use crate::routing::scoring::ProbabilisticScorer;
5050
use crate::ln::msgs;
5151
use crate::ln::onion_utils;
52-
use crate::ln::onion_utils::HTLCFailReason;
52+
use crate::ln::onion_utils::{HTLCFailReason,FailureStructure};
5353
use crate::ln::msgs::{ChannelMessageHandler, DecodeError, LightningError, MAX_VALUE_MSAT};
5454
#[cfg(test)]
5555
use crate::ln::outbound_payment;
@@ -128,6 +128,7 @@ pub(super) struct PendingHTLCInfo {
128128
/// may overshoot this in either case)
129129
pub(super) outgoing_amt_msat: u64,
130130
pub(super) outgoing_cltv_value: u32,
131+
pub(super) structure: Option<FailureStructure>,
131132
}
132133

133134
#[derive(Clone)] // See Channel::revoke_and_ack for why, tl;dr: Rust bug
@@ -167,7 +168,7 @@ pub(super) enum HTLCForwardInfo {
167168
}
168169

169170
/// Tracks the inbound corresponding to an outbound HTLC
170-
#[derive(Clone, Hash, PartialEq, Eq)]
171+
#[derive(Clone, Hash, PartialEq, Eq, Debug)]
171172
pub(crate) struct HTLCPreviousHopData {
172173
// Note that this may be an outbound SCID alias for the associated channel.
173174
short_channel_id: u64,
@@ -178,6 +179,8 @@ pub(crate) struct HTLCPreviousHopData {
178179
// This field is consumed by `claim_funds_from_hop()` when updating a force-closed backwards
179180
// channel with a preimage provided by the forward channel.
180181
outpoint: OutPoint,
182+
183+
structure: Option<FailureStructure>,
181184
}
182185

183186
enum OnionPayload {
@@ -278,7 +281,7 @@ impl_writeable_tlv_based_enum!(SentHTLCId,
278281

279282
/// Tracks the inbound corresponding to an outbound HTLC
280283
#[allow(clippy::derive_hash_xor_eq)] // Our Hash is faithful to the data, we just don't have SecretKey::hash
281-
#[derive(Clone, PartialEq, Eq)]
284+
#[derive(Clone, PartialEq, Eq, Debug)]
282285
pub(crate) enum HTLCSource {
283286
PreviousHopData(HTLCPreviousHopData),
284287
OutboundRoute {
@@ -2327,13 +2330,15 @@ where
23272330
}
23282331
},
23292332
};
2333+
23302334
Ok(PendingHTLCInfo {
23312335
routing,
23322336
payment_hash,
23332337
incoming_shared_secret: shared_secret,
23342338
incoming_amt_msat: Some(amt_msat),
23352339
outgoing_amt_msat: hop_data.amt_to_forward,
23362340
outgoing_cltv_value: hop_data.outgoing_cltv_value,
2341+
structure: hop_data.structure,
23372342
})
23382343
}
23392344

@@ -2373,11 +2378,15 @@ where
23732378
($msg: expr, $err_code: expr, $data: expr) => {
23742379
{
23752380
log_info!(self.logger, "Failed to accept/forward incoming HTLC: {}", $msg);
2381+
let no_structure = FailureStructure { // TODO: Return legacy failure.
2382+
max_hops: 3,
2383+
payload_len: 8,
2384+
};
23762385
return PendingHTLCStatus::Fail(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC {
23772386
channel_id: msg.channel_id,
23782387
htlc_id: msg.htlc_id,
23792388
reason: HTLCFailReason::reason($err_code, $data.to_vec())
2380-
.get_encrypted_failure_packet(&shared_secret, &None),
2389+
.get_encrypted_failure_packet(&shared_secret, &None, &no_structure),
23812390
}));
23822391
}
23832392
}
@@ -2433,6 +2442,7 @@ where
24332442
incoming_amt_msat: Some(msg.amount_msat),
24342443
outgoing_amt_msat: next_hop_data.amt_to_forward,
24352444
outgoing_cltv_value: next_hop_data.outgoing_cltv_value,
2445+
structure: next_hop_data.structure,
24362446
})
24372447
}
24382448
};
@@ -3219,6 +3229,7 @@ where
32193229
htlc_id: payment.prev_htlc_id,
32203230
incoming_packet_shared_secret: payment.forward_info.incoming_shared_secret,
32213231
phantom_shared_secret: None,
3232+
structure: payment.forward_info.structure,
32223233
});
32233234

32243235
let failure_reason = HTLCFailReason::from_failure_code(0x4000 | 10);
@@ -3253,7 +3264,8 @@ where
32533264
prev_short_channel_id, prev_htlc_id, prev_funding_outpoint, prev_user_channel_id,
32543265
forward_info: PendingHTLCInfo {
32553266
routing, incoming_shared_secret, payment_hash, outgoing_amt_msat,
3256-
outgoing_cltv_value, incoming_amt_msat: _
3267+
outgoing_cltv_value, incoming_amt_msat: _,
3268+
structure,
32573269
}
32583270
}) => {
32593271
macro_rules! failure_handler {
@@ -3266,6 +3278,7 @@ where
32663278
htlc_id: prev_htlc_id,
32673279
incoming_packet_shared_secret: incoming_shared_secret,
32683280
phantom_shared_secret: $phantom_ss,
3281+
structure,
32693282
});
32703283

32713284
let reason = if $next_hop_unknown {
@@ -3367,6 +3380,7 @@ where
33673380
forward_info: PendingHTLCInfo {
33683381
incoming_shared_secret, payment_hash, outgoing_amt_msat, outgoing_cltv_value,
33693382
routing: PendingHTLCRouting::Forward { onion_packet, .. }, incoming_amt_msat: _,
3383+
structure,
33703384
},
33713385
}) => {
33723386
log_trace!(self.logger, "Adding HTLC from short id {} with payment_hash {} to channel with short id {} after delay", prev_short_channel_id, log_bytes!(payment_hash.0), short_chan_id);
@@ -3377,6 +3391,7 @@ where
33773391
incoming_packet_shared_secret: incoming_shared_secret,
33783392
// Phantom payments are only PendingHTLCRouting::Receive.
33793393
phantom_shared_secret: None,
3394+
structure,
33803395
});
33813396
if let Err(e) = chan.get_mut().queue_add_htlc(outgoing_amt_msat,
33823397
payment_hash, outgoing_cltv_value, htlc_source.clone(),
@@ -3424,7 +3439,8 @@ where
34243439
HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo {
34253440
prev_short_channel_id, prev_htlc_id, prev_funding_outpoint, prev_user_channel_id,
34263441
forward_info: PendingHTLCInfo {
3427-
routing, incoming_shared_secret, payment_hash, incoming_amt_msat, outgoing_amt_msat, ..
3442+
routing, incoming_shared_secret, payment_hash, incoming_amt_msat, outgoing_amt_msat,
3443+
structure, ..
34283444
}
34293445
}) => {
34303446
let (cltv_expiry, onion_payload, payment_data, phantom_shared_secret, mut onion_fields) = match routing {
@@ -3451,6 +3467,7 @@ where
34513467
htlc_id: prev_htlc_id,
34523468
incoming_packet_shared_secret: incoming_shared_secret,
34533469
phantom_shared_secret,
3470+
structure: structure,
34543471
},
34553472
// We differentiate the received value from the sender intended value
34563473
// if possible so that we don't prematurely mark MPP payments complete
@@ -3479,6 +3496,7 @@ where
34793496
htlc_id: $htlc.prev_hop.htlc_id,
34803497
incoming_packet_shared_secret: $htlc.prev_hop.incoming_packet_shared_secret,
34813498
phantom_shared_secret,
3499+
structure: $htlc.prev_hop.structure,
34823500
}), payment_hash,
34833501
HTLCFailReason::reason(0x4000 | 15, htlc_msat_height_data),
34843502
HTLCDestination::FailedPayment { payment_hash: $payment_hash },
@@ -3676,6 +3694,7 @@ where
36763694
HTLCForwardInfo::FailHTLC { .. } => {
36773695
panic!("Got pending fail of our own HTLC");
36783696
}
3697+
_ => panic!("Unsupported forward info"),
36793698
}
36803699
}
36813700
}
@@ -4099,9 +4118,11 @@ where
40994118
&self.pending_events, &self.logger)
41004119
{ self.push_pending_forwards_ev(); }
41014120
},
4102-
HTLCSource::PreviousHopData(HTLCPreviousHopData { ref short_channel_id, ref htlc_id, ref incoming_packet_shared_secret, ref phantom_shared_secret, ref outpoint }) => {
4121+
HTLCSource::PreviousHopData(HTLCPreviousHopData { ref short_channel_id, ref htlc_id, ref incoming_packet_shared_secret, ref phantom_shared_secret, ref outpoint, structure: Some(structure) }) => {
41034122
log_trace!(self.logger, "Failing HTLC with payment_hash {} backwards from us with {:?}", log_bytes!(payment_hash.0), onion_error);
4104-
let err_packet = onion_error.get_encrypted_failure_packet(incoming_packet_shared_secret, phantom_shared_secret);
4123+
let err_packet = onion_error.get_encrypted_failure_packet(incoming_packet_shared_secret, phantom_shared_secret, structure);
4124+
4125+
log_trace!(self.logger, "Failure packet length: {}", err_packet.data.len());
41054126

41064127
let mut push_forward_ev = false;
41074128
let mut forward_htlcs = self.forward_htlcs.lock().unwrap();
@@ -4124,6 +4145,7 @@ where
41244145
failed_next_destination: destination,
41254146
});
41264147
},
4148+
_ => panic!("Unhandled htlc source type {:?}", source),
41274149
}
41284150
}
41294151

@@ -5034,13 +5056,13 @@ where
50345056
// but if we've sent a shutdown and they haven't acknowledged it yet, we just
50355057
// want to reject the new HTLC and fail it backwards instead of forwarding.
50365058
match pending_forward_info {
5037-
PendingHTLCStatus::Forward(PendingHTLCInfo { ref incoming_shared_secret, .. }) => {
5059+
PendingHTLCStatus::Forward(PendingHTLCInfo { ref incoming_shared_secret, structure: Some(structure), .. }) => { // TODO: Implement legacy.
50385060
let reason = if (error_code & 0x1000) != 0 {
50395061
let (real_code, error_data) = self.get_htlc_inbound_temp_fail_err_and_data(error_code, chan);
50405062
HTLCFailReason::reason(real_code, error_data)
50415063
} else {
50425064
HTLCFailReason::from_failure_code(error_code)
5043-
}.get_encrypted_failure_packet(incoming_shared_secret, &None);
5065+
}.get_encrypted_failure_packet(incoming_shared_secret, &None, &structure);
50445066
let msg = msgs::UpdateFailHTLC {
50455067
channel_id: msg.channel_id,
50465068
htlc_id: msg.htlc_id,
@@ -5190,6 +5212,7 @@ where
51905212
htlc_id: prev_htlc_id,
51915213
incoming_packet_shared_secret: forward_info.incoming_shared_secret,
51925214
phantom_shared_secret: None,
5215+
structure: forward_info.structure,
51935216
});
51945217

51955218
failed_intercept_forwards.push((htlc_source, forward_info.payment_hash,
@@ -6273,6 +6296,7 @@ where
62736296
incoming_packet_shared_secret: htlc.forward_info.incoming_shared_secret,
62746297
phantom_shared_secret: None,
62756298
outpoint: htlc.prev_funding_outpoint,
6299+
structure: htlc.forward_info.structure.clone(),
62766300
});
62776301

62786302
let requested_forward_scid /* intercept scid */ = match htlc.forward_info.routing {
@@ -6695,6 +6719,7 @@ pub fn provided_init_features(_config: &UserConfig) -> InitFeatures {
66956719
features.set_channel_type_optional();
66966720
features.set_scid_privacy_optional();
66976721
features.set_zero_conf_optional();
6722+
features.set_attributable_errors_optional();
66986723
#[cfg(anchors)]
66996724
{ // Attributes are not allowed on if expressions on our current MSRV of 1.41.
67006725
if _config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx {
@@ -6855,13 +6880,34 @@ impl_writeable_tlv_based_enum!(PendingHTLCRouting,
68556880
},
68566881
;);
68576882

6883+
impl Writeable for FailureStructure {
6884+
fn write<W:Writer>(&self,w: &mut W) -> Result<(),io::Error>{
6885+
self.max_hops.write(w)?;
6886+
self.payload_len.write(w)?;
6887+
6888+
Ok(())
6889+
}
6890+
}
6891+
6892+
impl Readable for FailureStructure {
6893+
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
6894+
let max_hops: u8 = Readable::read(r)?;
6895+
let payload_len: u8 = Readable::read(r)?;
6896+
Ok(FailureStructure {
6897+
max_hops,
6898+
payload_len,
6899+
})
6900+
}
6901+
}
6902+
68586903
impl_writeable_tlv_based!(PendingHTLCInfo, {
68596904
(0, routing, required),
68606905
(2, incoming_shared_secret, required),
68616906
(4, payment_hash, required),
68626907
(6, outgoing_amt_msat, required),
68636908
(8, outgoing_cltv_value, required),
68646909
(9, incoming_amt_msat, option),
6910+
(11, structure, option),
68656911
});
68666912

68676913

@@ -6942,7 +6988,8 @@ impl_writeable_tlv_based!(HTLCPreviousHopData, {
69426988
(1, phantom_shared_secret, option),
69436989
(2, outpoint, required),
69446990
(4, htlc_id, required),
6945-
(6, incoming_packet_shared_secret, required)
6991+
(6, incoming_packet_shared_secret, required),
6992+
(7, structure, option)
69466993
});
69476994

69486995
impl Writeable for ClaimableHTLC {

‎lightning/src/ln/features.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ mod sealed {
136136
// Byte 2
137137
BasicMPP | Wumbo | AnchorsZeroFeeHtlcTx,
138138
// Byte 3
139-
ShutdownAnySegwit,
139+
ShutdownAnySegwit | AttributableErrors,
140140
// Byte 4
141141
OnionMessages,
142142
// Byte 5
@@ -152,7 +152,7 @@ mod sealed {
152152
// Byte 2
153153
BasicMPP | Wumbo | AnchorsZeroFeeHtlcTx,
154154
// Byte 3
155-
ShutdownAnySegwit,
155+
ShutdownAnySegwit | AttributableErrors,
156156
// Byte 4
157157
OnionMessages,
158158
// Byte 5
@@ -169,7 +169,7 @@ mod sealed {
169169
// Byte 2
170170
BasicMPP,
171171
// Byte 3
172-
,
172+
AttributableErrors,
173173
// Byte 4
174174
,
175175
// Byte 5
@@ -384,6 +384,9 @@ mod sealed {
384384
define_feature!(27, ShutdownAnySegwit, [InitContext, NodeContext],
385385
"Feature flags for `opt_shutdown_anysegwit`.", set_shutdown_any_segwit_optional,
386386
set_shutdown_any_segwit_required, supports_shutdown_anysegwit, requires_shutdown_anysegwit);
387+
define_feature!(29, AttributableErrors, [InitContext, NodeContext, InvoiceContext],
388+
"Feature flags for `option_attributable_errors`.", set_attributable_errors_optional,
389+
set_attributable_errors_required, supports_attributable_errors, requires_attributable_errors);
387390
define_feature!(39, OnionMessages, [InitContext, NodeContext],
388391
"Feature flags for `option_onion_messages`.", set_onion_messages_optional,
389392
set_onion_messages_required, supports_onion_messages, requires_onion_messages);
@@ -863,6 +866,7 @@ mod tests {
863866
init_features.set_basic_mpp_optional();
864867
init_features.set_wumbo_optional();
865868
init_features.set_shutdown_any_segwit_optional();
869+
init_features.set_attributable_errors_optional();
866870
init_features.set_onion_messages_optional();
867871
init_features.set_channel_type_optional();
868872
init_features.set_scid_privacy_optional();

0 commit comments

Comments
 (0)