Skip to content

Commit fbd8e91

Browse files
committed
Attributable failures
1 parent 894c91e commit fbd8e91

File tree

8 files changed

+590
-99
lines changed

8 files changed

+590
-99
lines changed

lightning/src/ln/channel.rs

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ use crate::ln::chan_utils::{
4949
ClosingTransaction, commit_tx_fee_sat,
5050
};
5151
use crate::ln::chan_utils;
52-
use crate::ln::onion_utils::{HTLCFailReason};
52+
use crate::ln::onion_utils::{HTLCFailReason, ATTRIBUTION_DATA_LEN};
5353
use crate::chain::BestBlock;
5454
use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, LowerBoundedFeeEstimator, fee_for_weight};
5555
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, LATENCY_GRACE_PERIOD_BLOCKS};
@@ -4722,7 +4722,7 @@ trait FailHTLCContents {
47224722
impl FailHTLCContents for msgs::OnionErrorPacket {
47234723
type Message = msgs::UpdateFailHTLC;
47244724
fn to_message(self, htlc_id: u64, channel_id: ChannelId) -> Self::Message {
4725-
msgs::UpdateFailHTLC { htlc_id, channel_id, reason: self.data }
4725+
msgs::UpdateFailHTLC { htlc_id, channel_id, reason: self.data, attribution_data: self.attribution_data }
47264726
}
47274727
fn to_inbound_htlc_state(self) -> InboundHTLCState {
47284728
InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailRelay(self))
@@ -6750,6 +6750,7 @@ impl<SP: Deref> FundedChannel<SP> where
67506750
channel_id: self.context.channel_id(),
67516751
htlc_id: htlc.htlc_id,
67526752
reason: err_packet.data.clone(),
6753+
attribution_data: err_packet.attribution_data,
67536754
});
67546755
},
67556756
&InboundHTLCRemovalReason::FailMalformed((ref sha256_of_onion, ref failure_code)) => {
@@ -10008,6 +10009,7 @@ impl<SP: Deref> Writeable for FundedChannel<SP> where SP::Target: SignerProvider
1000810009
dropped_inbound_htlcs += 1;
1000910010
}
1001010011
}
10012+
let mut removed_htlc_failure_attribution_data: Vec<&Option<[u8; ATTRIBUTION_DATA_LEN]>> = Vec::new();
1001110013
(self.context.pending_inbound_htlcs.len() as u64 - dropped_inbound_htlcs).write(writer)?;
1001210014
for htlc in self.context.pending_inbound_htlcs.iter() {
1001310015
if let &InboundHTLCState::RemoteAnnounced(_) = &htlc.state {
@@ -10033,9 +10035,10 @@ impl<SP: Deref> Writeable for FundedChannel<SP> where SP::Target: SignerProvider
1003310035
&InboundHTLCState::LocalRemoved(ref removal_reason) => {
1003410036
4u8.write(writer)?;
1003510037
match removal_reason {
10036-
InboundHTLCRemovalReason::FailRelay(msgs::OnionErrorPacket { data }) => {
10038+
InboundHTLCRemovalReason::FailRelay(msgs::OnionErrorPacket { data, attribution_data }) => {
1003710039
0u8.write(writer)?;
1003810040
data.write(writer)?;
10041+
removed_htlc_failure_attribution_data.push(&attribution_data);
1003910042
},
1004010043
InboundHTLCRemovalReason::FailMalformed((hash, code)) => {
1004110044
1u8.write(writer)?;
@@ -10097,10 +10100,11 @@ impl<SP: Deref> Writeable for FundedChannel<SP> where SP::Target: SignerProvider
1009710100

1009810101
let mut holding_cell_skimmed_fees: Vec<Option<u64>> = Vec::new();
1009910102
let mut holding_cell_blinding_points: Vec<Option<PublicKey>> = Vec::new();
10103+
let mut holding_cell_failure_attribution_data: Vec<(u32, [u8; ATTRIBUTION_DATA_LEN])> = Vec::new();
1010010104
// Vec of (htlc_id, failure_code, sha256_of_onion)
1010110105
let mut malformed_htlcs: Vec<(u64, u16, [u8; 32])> = Vec::new();
1010210106
(self.context.holding_cell_htlc_updates.len() as u64).write(writer)?;
10103-
for update in self.context.holding_cell_htlc_updates.iter() {
10107+
for (i, update) in self.context.holding_cell_htlc_updates.iter().enumerate() {
1010410108
match update {
1010510109
&HTLCUpdateAwaitingACK::AddHTLC {
1010610110
ref amount_msat, ref cltv_expiry, ref payment_hash, ref source, ref onion_routing_packet,
@@ -10125,6 +10129,13 @@ impl<SP: Deref> Writeable for FundedChannel<SP> where SP::Target: SignerProvider
1012510129
2u8.write(writer)?;
1012610130
htlc_id.write(writer)?;
1012710131
err_packet.data.write(writer)?;
10132+
10133+
// Store the attribution data for later writing. Include the holding cell htlc update index because
10134+
// FailMalformedHTLC is stored with the same type 2 and we wouldn't be able to distinguish the two
10135+
// when reading back in.
10136+
if let Some(attribution_data ) = err_packet.attribution_data {
10137+
holding_cell_failure_attribution_data.push((i as u32, attribution_data));
10138+
}
1012810139
}
1012910140
&HTLCUpdateAwaitingACK::FailMalformedHTLC {
1013010141
htlc_id, failure_code, sha256_of_onion
@@ -10308,6 +10319,8 @@ impl<SP: Deref> Writeable for FundedChannel<SP> where SP::Target: SignerProvider
1030810319
(49, self.context.local_initiated_shutdown, option), // Added in 0.0.122
1030910320
(51, is_manual_broadcast, option), // Added in 0.0.124
1031010321
(53, funding_tx_broadcast_safe_event_emitted, option), // Added in 0.0.124
10322+
(55, removed_htlc_failure_attribution_data, optional_vec), // Added in 0.2
10323+
(57, holding_cell_failure_attribution_data, optional_vec), // Added in 0.2
1031110324
});
1031210325

1031310326
Ok(())
@@ -10385,6 +10398,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1038510398
let reason = match <u8 as Readable>::read(reader)? {
1038610399
0 => InboundHTLCRemovalReason::FailRelay(msgs::OnionErrorPacket {
1038710400
data: Readable::read(reader)?,
10401+
attribution_data: None,
1038810402
}),
1038910403
1 => InboundHTLCRemovalReason::FailMalformed(Readable::read(reader)?),
1039010404
2 => InboundHTLCRemovalReason::Fulfill(Readable::read(reader)?),
@@ -10449,6 +10463,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1044910463
htlc_id: Readable::read(reader)?,
1045010464
err_packet: OnionErrorPacket {
1045110465
data: Readable::read(reader)?,
10466+
attribution_data: None,
1045210467
},
1045310468
},
1045410469
_ => return Err(DecodeError::InvalidValue),
@@ -10592,6 +10607,9 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1059210607
let mut pending_outbound_blinding_points_opt: Option<Vec<Option<PublicKey>>> = None;
1059310608
let mut holding_cell_blinding_points_opt: Option<Vec<Option<PublicKey>>> = None;
1059410609

10610+
let mut removed_htlc_failure_attribution_data: Option<Vec<Option<[u8; ATTRIBUTION_DATA_LEN]>>> = None;
10611+
let mut holding_cell_failure_attribution_data: Option<Vec<(u32, [u8; ATTRIBUTION_DATA_LEN])>> = None;
10612+
1059510613
let mut malformed_htlcs: Option<Vec<(u64, u16, [u8; 32])>> = None;
1059610614
let mut monitor_pending_update_adds: Option<Vec<msgs::UpdateAddHTLC>> = None;
1059710615

@@ -10634,6 +10652,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1063410652
(49, local_initiated_shutdown, option),
1063510653
(51, is_manual_broadcast, option),
1063610654
(53, funding_tx_broadcast_safe_event_emitted, option),
10655+
(55, removed_htlc_failure_attribution_data, optional_vec),
10656+
(57, holding_cell_failure_attribution_data, optional_vec),
1063710657
});
1063810658

1063910659
let holder_signer = signer_provider.derive_channel_signer(channel_keys_id);
@@ -10715,6 +10735,38 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1071510735
if iter.next().is_some() { return Err(DecodeError::InvalidValue) }
1071610736
}
1071710737

10738+
if let Some(attribution_datas) = removed_htlc_failure_attribution_data {
10739+
let mut removed_htlc_relay_failures =
10740+
pending_inbound_htlcs.iter_mut().filter_map(|status|
10741+
if let InboundHTLCState::LocalRemoved(ref mut reason) = &mut status.state {
10742+
if let InboundHTLCRemovalReason::FailRelay(ref mut packet) = reason {
10743+
Some(&mut packet.attribution_data)
10744+
} else {
10745+
None
10746+
}
10747+
} else {
10748+
None
10749+
}
10750+
);
10751+
10752+
for attribution_data in attribution_datas {
10753+
*removed_htlc_relay_failures.next().ok_or(DecodeError::InvalidValue)? = attribution_data;
10754+
}
10755+
if removed_htlc_relay_failures.next().is_some() { return Err(DecodeError::InvalidValue); }
10756+
}
10757+
10758+
if let Some(attribution_datas) = holding_cell_failure_attribution_data {
10759+
for (i, attribution_data) in attribution_datas {
10760+
let update = holding_cell_htlc_updates.get_mut(i as usize).ok_or(DecodeError::InvalidValue)?;
10761+
10762+
if let HTLCUpdateAwaitingACK::FailHTLC { htlc_id: _, ref mut err_packet } = update {
10763+
err_packet.attribution_data = Some(attribution_data);
10764+
} else {
10765+
return Err(DecodeError::InvalidValue);
10766+
}
10767+
}
10768+
}
10769+
1071810770
if let Some(malformed_htlcs) = malformed_htlcs {
1071910771
for (malformed_htlc_id, failure_code, sha256_of_onion) in malformed_htlcs {
1072010772
let htlc_idx = holding_cell_htlc_updates.iter().position(|htlc| {
@@ -10912,7 +10964,7 @@ mod tests {
1091210964
use bitcoin::transaction::{Transaction, TxOut, Version};
1091310965
use bitcoin::opcodes;
1091410966
use bitcoin::network::Network;
10915-
use crate::ln::onion_utils::INVALID_ONION_BLINDING;
10967+
use crate::ln::onion_utils::{ATTRIBUTION_DATA_LEN, INVALID_ONION_BLINDING};
1091610968
use crate::types::payment::{PaymentHash, PaymentPreimage};
1091710969
use crate::ln::channel_keys::{RevocationKey, RevocationBasepoint};
1091810970
use crate::ln::channelmanager::{self, HTLCSource, PaymentId};
@@ -11548,7 +11600,7 @@ mod tests {
1154811600
htlc_id: 0,
1154911601
};
1155011602
let dummy_holding_cell_failed_htlc = |htlc_id| HTLCUpdateAwaitingACK::FailHTLC {
11551-
htlc_id, err_packet: msgs::OnionErrorPacket { data: vec![42] }
11603+
htlc_id, err_packet: msgs::OnionErrorPacket { data: vec![42], attribution_data: Some([1; ATTRIBUTION_DATA_LEN]) }
1155211604
};
1155311605
let dummy_holding_cell_malformed_htlc = |htlc_id| HTLCUpdateAwaitingACK::FailMalformedHTLC {
1155411606
htlc_id, failure_code: INVALID_ONION_BLINDING, sha256_of_onion: [0; 32],

lightning/src/ln/channelmanager.rs

Lines changed: 92 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ use crate::routing::gossip::NodeId;
5959
use crate::routing::router::{BlindedTail, InFlightHtlcs, Path, Payee, PaymentParameters, RouteParameters, RouteParametersConfig, Router, FixedRouter, Route};
6060
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, InboundHTLCErr, NextPacketDetails};
6161
use crate::ln::msgs;
62-
use crate::ln::onion_utils;
62+
use crate::ln::onion_utils::{self, ATTRIBUTION_DATA_LEN};
6363
use crate::ln::onion_utils::{HTLCFailReason, INVALID_ONION_BLINDING};
6464
use crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, CommitmentUpdate, DecodeError, LightningError, MessageSendEvent};
6565
#[cfg(test)]
@@ -4433,6 +4433,7 @@ where
44334433
channel_id: msg.channel_id,
44344434
htlc_id: msg.htlc_id,
44354435
reason: failure.data.clone(),
4436+
attribution_data: failure.attribution_data,
44364437
})
44374438
}
44384439

@@ -4458,10 +4459,12 @@ where
44584459
}
44594460
let failure = HTLCFailReason::reason($err_code, $data.to_vec())
44604461
.get_encrypted_failure_packet(&shared_secret, &None);
4462+
44614463
return PendingHTLCStatus::Fail(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC {
44624464
channel_id: msg.channel_id,
44634465
htlc_id: msg.htlc_id,
44644466
reason: failure.data,
4467+
attribution_data: failure.attribution_data,
44654468
}));
44664469
}
44674470
}
@@ -12852,11 +12855,15 @@ impl_writeable_tlv_based!(PendingHTLCInfo, {
1285212855
impl Writeable for HTLCFailureMsg {
1285312856
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
1285412857
match self {
12855-
HTLCFailureMsg::Relay(msgs::UpdateFailHTLC { channel_id, htlc_id, reason }) => {
12858+
HTLCFailureMsg::Relay(msgs::UpdateFailHTLC { channel_id, htlc_id, reason, attribution_data }) => {
1285612859
0u8.write(writer)?;
1285712860
channel_id.write(writer)?;
1285812861
htlc_id.write(writer)?;
1285912862
reason.write(writer)?;
12863+
12864+
// This code will only ever be hit for legacy data that is re-serialized. It isn't necessary to try
12865+
// writing out attribution data, because it can never be present.
12866+
debug_assert!(attribution_data.is_none());
1286012867
},
1286112868
HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC {
1286212869
channel_id, htlc_id, sha256_of_onion, failure_code
@@ -12881,6 +12888,7 @@ impl Readable for HTLCFailureMsg {
1288112888
channel_id: Readable::read(reader)?,
1288212889
htlc_id: Readable::read(reader)?,
1288312890
reason: Readable::read(reader)?,
12891+
attribution_data: None,
1288412892
}))
1288512893
},
1288612894
1 => {
@@ -13111,6 +13119,7 @@ impl Writeable for HTLCForwardInfo {
1311113119
write_tlv_fields!(w, {
1311213120
(0, htlc_id, required),
1311313121
(2, err_packet.data, required),
13122+
(5, err_packet.attribution_data, option),
1311413123
});
1311513124
},
1311613125
Self::FailMalformedHTLC { htlc_id, failure_code, sha256_of_onion } => {
@@ -13141,8 +13150,12 @@ impl Readable for HTLCForwardInfo {
1314113150
(1, malformed_htlc_failure_code, option),
1314213151
(2, err_packet, required),
1314313152
(3, sha256_of_onion, option),
13153+
(5, attribution_data, option),
1314413154
});
1314513155
if let Some(failure_code) = malformed_htlc_failure_code {
13156+
if attribution_data.is_some() {
13157+
return Err(DecodeError::InvalidValue);
13158+
}
1314613159
Self::FailMalformedHTLC {
1314713160
htlc_id: _init_tlv_based_struct_field!(htlc_id, required),
1314813161
failure_code,
@@ -13153,6 +13166,7 @@ impl Readable for HTLCForwardInfo {
1315313166
htlc_id: _init_tlv_based_struct_field!(htlc_id, required),
1315413167
err_packet: crate::ln::msgs::OnionErrorPacket {
1315513168
data: _init_tlv_based_struct_field!(err_packet, required),
13169+
attribution_data: _init_tlv_based_struct_field!(attribution_data, option),
1315613170
},
1315713171
}
1315813172
}
@@ -14852,6 +14866,7 @@ mod tests {
1485214866
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
1485314867
use core::sync::atomic::Ordering;
1485414868
use crate::events::{Event, HTLCDestination, ClosureReason};
14869+
use crate::ln::onion_utils::ATTRIBUTION_DATA_LEN;
1485514870
use crate::ln::types::ChannelId;
1485614871
use crate::types::payment::{PaymentPreimage, PaymentHash, PaymentSecret};
1485714872
use crate::ln::channelmanager::{RAACommitmentOrder, create_recv_pending_htlc_info, inbound_payment, ChannelConfigOverrides, HTLCForwardInfo, InterceptId, PaymentId, RecipientOnionFields};
@@ -15325,6 +15340,80 @@ mod tests {
1532515340
nodes[1].logger.assert_log_contains("lightning::ln::channelmanager", "Payment preimage didn't match payment hash", 1);
1532615341
}
1532715342

15343+
#[test]
15344+
fn test_htlc_localremoved_persistence() {
15345+
let chanmon_cfgs: Vec<TestChanMonCfg> = create_chanmon_cfgs(2);
15346+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
15347+
15348+
let persister;
15349+
let chain_monitor;
15350+
let deserialized_chanmgr;
15351+
15352+
// Send a keysend payment that fails because of a preimage mismatch.
15353+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
15354+
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
15355+
15356+
let payer_pubkey = nodes[0].node.get_our_node_id();
15357+
let payee_pubkey = nodes[1].node.get_our_node_id();
15358+
15359+
let _chan = create_chan_between_nodes(&nodes[0], &nodes[1]);
15360+
let route_params = RouteParameters::from_payment_params_and_value(
15361+
PaymentParameters::for_keysend(payee_pubkey, 40, false), 10_000);
15362+
let network_graph = nodes[0].network_graph;
15363+
let first_hops = nodes[0].node.list_usable_channels();
15364+
let scorer = test_utils::TestScorer::new();
15365+
let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
15366+
let route = find_route(
15367+
&payer_pubkey, &route_params, &network_graph, Some(&first_hops.iter().collect::<Vec<_>>()),
15368+
nodes[0].logger, &scorer, &Default::default(), &random_seed_bytes
15369+
).unwrap();
15370+
15371+
let test_preimage = PaymentPreimage([42; 32]);
15372+
let mismatch_payment_hash = PaymentHash([43; 32]);
15373+
let session_privs = nodes[0].node.test_add_new_pending_payment(mismatch_payment_hash,
15374+
RecipientOnionFields::spontaneous_empty(), PaymentId(mismatch_payment_hash.0), &route).unwrap();
15375+
nodes[0].node.test_send_payment_internal(&route, mismatch_payment_hash,
15376+
RecipientOnionFields::spontaneous_empty(), Some(test_preimage), PaymentId(mismatch_payment_hash.0), None, session_privs).unwrap();
15377+
check_added_monitors!(nodes[0], 1);
15378+
15379+
let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
15380+
nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
15381+
commitment_signed_dance!(nodes[1], nodes[0], &updates.commitment_signed, false);
15382+
expect_pending_htlcs_forwardable!(nodes[1]);
15383+
expect_htlc_handling_failed_destinations!(nodes[1].node.get_and_clear_pending_events(), &[HTLCDestination::FailedPayment { payment_hash: mismatch_payment_hash }]);
15384+
check_added_monitors(&nodes[1], 1);
15385+
15386+
// Save the update_fail_htlc message for later comparison.
15387+
let msgs = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
15388+
let htlc_fail_msg = msgs.update_fail_htlcs[0].clone();
15389+
15390+
// Reload node.
15391+
nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id());
15392+
nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id());
15393+
15394+
let monitor_encoded = get_monitor!(nodes[1], _chan.3).encode();
15395+
reload_node!(nodes[1], nodes[1].node.encode(), &[&monitor_encoded], persister, chain_monitor, deserialized_chanmgr);
15396+
15397+
nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init {
15398+
features: nodes[1].node.init_features(), networks: None, remote_network_address: None
15399+
}, true).unwrap();
15400+
let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
15401+
assert_eq!(reestablish_1.len(), 1);
15402+
nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init {
15403+
features: nodes[0].node.init_features(), networks: None, remote_network_address: None
15404+
}, false).unwrap();
15405+
let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
15406+
assert_eq!(reestablish_2.len(), 1);
15407+
nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &reestablish_2[0]);
15408+
handle_chan_reestablish_msgs!(nodes[0], nodes[1]);
15409+
nodes[1].node.handle_channel_reestablish(nodes[0].node.get_our_node_id(), &reestablish_1[0]);
15410+
15411+
// Assert that same failure message is resent after reload.
15412+
let msgs = handle_chan_reestablish_msgs!(nodes[1], nodes[0]);
15413+
let htlc_fail_msg_after_reload = msgs.2.unwrap().update_fail_htlcs[0].clone();
15414+
assert_eq!(htlc_fail_msg, htlc_fail_msg_after_reload);
15415+
}
15416+
1532815417
#[test]
1532915418
fn test_multi_hop_missing_secret() {
1533015419
let chanmon_cfgs = create_chanmon_cfgs(4);
@@ -16283,7 +16372,7 @@ mod tests {
1628316372
let mut nodes = create_network(1, &node_cfg, &chanmgrs);
1628416373

1628516374
let dummy_failed_htlc = |htlc_id| {
16286-
HTLCForwardInfo::FailHTLC { htlc_id, err_packet: msgs::OnionErrorPacket { data: vec![42] } }
16375+
HTLCForwardInfo::FailHTLC { htlc_id, err_packet: msgs::OnionErrorPacket { data: vec![42], attribution_data: Some([0; ATTRIBUTION_DATA_LEN]) } }
1628716376
};
1628816377
let dummy_malformed_htlc = |htlc_id| {
1628916378
HTLCForwardInfo::FailMalformedHTLC { htlc_id, failure_code: 0x4000, sha256_of_onion: [0; 32] }

lightning/src/ln/functional_tests.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crate::chain::chaininterface::LowerBoundedFeeEstimator;
1717
use crate::chain::channelmonitor;
1818
use crate::chain::channelmonitor::{Balance, ChannelMonitorUpdateStep, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY, COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE};
1919
use crate::chain::transaction::OutPoint;
20+
use crate::ln::onion_utils::ATTRIBUTION_DATA_LEN;
2021
use crate::sign::{ecdsa::EcdsaChannelSigner, EntropySource, OutputSpender, SignerProvider};
2122
use crate::events::bump_transaction::WalletSource;
2223
use crate::events::{Event, FundingInfo, PathFailure, PaymentPurpose, ClosureReason, HTLCDestination, PaymentFailureReason};
@@ -7058,6 +7059,7 @@ pub fn test_update_fulfill_htlc_bolt2_update_fail_htlc_before_commitment() {
70587059
channel_id: chan.2,
70597060
htlc_id: 0,
70607061
reason: Vec::new(),
7062+
attribution_data: Some([0; ATTRIBUTION_DATA_LEN])
70617063
};
70627064

70637065
nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &update_msg);

0 commit comments

Comments
 (0)