mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-02-25 15:20:24 +01:00
Channel: add holding cell HTLC variant for blinded HTLCs.
For context, blinded HTLCs where we are not the intro node must always be failed back with malformed and invalid_onion_blinding error per BOLT 4. Prior to supporting blinded payments, the only way for an update_malformed to be returned from Channel was if an onion was actually found to be malformed during initial update_add processing. This meant that any malformed HTLCs would never live in the holding cell but instead would be returned directly upon initial RAA processing. Now, we need to be able to store these HTLCs in the holding cell because the HTLC failure necessitating an update_malformed may come long after the RAA is initially processed, and we may not be a state to send the update_malformed message at that time. Therefore, add a new holding cell HTLC variant for blinded non-intro node HTLCs, which will signal to Channel to fail with malformed and the correct error code.
This commit is contained in:
parent
e4485cffb3
commit
af4d0df1bf
1 changed files with 48 additions and 2 deletions
|
@ -259,6 +259,11 @@ enum HTLCUpdateAwaitingACK {
|
||||||
htlc_id: u64,
|
htlc_id: u64,
|
||||||
err_packet: msgs::OnionErrorPacket,
|
err_packet: msgs::OnionErrorPacket,
|
||||||
},
|
},
|
||||||
|
FailMalformedHTLC {
|
||||||
|
htlc_id: u64,
|
||||||
|
failure_code: u16,
|
||||||
|
sha256_of_onion: [u8; 32],
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! define_state_flags {
|
macro_rules! define_state_flags {
|
||||||
|
@ -2719,7 +2724,9 @@ impl<SP: Deref> Channel<SP> where
|
||||||
return UpdateFulfillFetch::DuplicateClaim {};
|
return UpdateFulfillFetch::DuplicateClaim {};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
&HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } => {
|
&HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } |
|
||||||
|
&HTLCUpdateAwaitingACK::FailMalformedHTLC { htlc_id, .. } =>
|
||||||
|
{
|
||||||
if htlc_id_arg == htlc_id {
|
if htlc_id_arg == htlc_id {
|
||||||
log_warn!(logger, "Have preimage and want to fulfill HTLC with pending failure against channel {}", &self.context.channel_id());
|
log_warn!(logger, "Have preimage and want to fulfill HTLC with pending failure against channel {}", &self.context.channel_id());
|
||||||
// TODO: We may actually be able to switch to a fulfill here, though its
|
// TODO: We may actually be able to switch to a fulfill here, though its
|
||||||
|
@ -2878,7 +2885,9 @@ impl<SP: Deref> Channel<SP> where
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
&HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } => {
|
&HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } |
|
||||||
|
&HTLCUpdateAwaitingACK::FailMalformedHTLC { htlc_id, .. } =>
|
||||||
|
{
|
||||||
if htlc_id_arg == htlc_id {
|
if htlc_id_arg == htlc_id {
|
||||||
debug_assert!(false, "Tried to fail an HTLC that was already failed");
|
debug_assert!(false, "Tried to fail an HTLC that was already failed");
|
||||||
return Err(ChannelError::Ignore("Unable to find a pending HTLC which matched the given HTLC ID".to_owned()));
|
return Err(ChannelError::Ignore("Unable to find a pending HTLC which matched the given HTLC ID".to_owned()));
|
||||||
|
@ -3563,6 +3572,9 @@ impl<SP: Deref> Channel<SP> where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
&HTLCUpdateAwaitingACK::FailMalformedHTLC { .. } => {
|
||||||
|
todo!()
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if update_add_count == 0 && update_fulfill_count == 0 && update_fail_count == 0 && self.context.holding_cell_update_fee.is_none() {
|
if update_add_count == 0 && update_fulfill_count == 0 && update_fail_count == 0 && self.context.holding_cell_update_fee.is_none() {
|
||||||
|
@ -7433,6 +7445,8 @@ impl<SP: Deref> Writeable for Channel<SP> where SP::Target: SignerProvider {
|
||||||
|
|
||||||
let mut holding_cell_skimmed_fees: Vec<Option<u64>> = Vec::new();
|
let mut holding_cell_skimmed_fees: Vec<Option<u64>> = Vec::new();
|
||||||
let mut holding_cell_blinding_points: Vec<Option<PublicKey>> = Vec::new();
|
let mut holding_cell_blinding_points: Vec<Option<PublicKey>> = Vec::new();
|
||||||
|
// Vec of (htlc_id, failure_code, sha256_of_onion)
|
||||||
|
let mut malformed_htlcs: Vec<(u64, u16, [u8; 32])> = Vec::new();
|
||||||
(self.context.holding_cell_htlc_updates.len() as u64).write(writer)?;
|
(self.context.holding_cell_htlc_updates.len() as u64).write(writer)?;
|
||||||
for update in self.context.holding_cell_htlc_updates.iter() {
|
for update in self.context.holding_cell_htlc_updates.iter() {
|
||||||
match update {
|
match update {
|
||||||
|
@ -7460,6 +7474,18 @@ impl<SP: Deref> Writeable for Channel<SP> where SP::Target: SignerProvider {
|
||||||
htlc_id.write(writer)?;
|
htlc_id.write(writer)?;
|
||||||
err_packet.write(writer)?;
|
err_packet.write(writer)?;
|
||||||
}
|
}
|
||||||
|
&HTLCUpdateAwaitingACK::FailMalformedHTLC {
|
||||||
|
htlc_id, failure_code, sha256_of_onion
|
||||||
|
} => {
|
||||||
|
// We don't want to break downgrading by adding a new variant, so write a dummy
|
||||||
|
// `::FailHTLC` variant and write the real malformed error as an optional TLV.
|
||||||
|
malformed_htlcs.push((htlc_id, failure_code, sha256_of_onion));
|
||||||
|
|
||||||
|
let dummy_err_packet = msgs::OnionErrorPacket { data: Vec::new() };
|
||||||
|
2u8.write(writer)?;
|
||||||
|
htlc_id.write(writer)?;
|
||||||
|
dummy_err_packet.write(writer)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7620,6 +7646,7 @@ impl<SP: Deref> Writeable for Channel<SP> where SP::Target: SignerProvider {
|
||||||
(38, self.context.is_batch_funding, option),
|
(38, self.context.is_batch_funding, option),
|
||||||
(39, pending_outbound_blinding_points, optional_vec),
|
(39, pending_outbound_blinding_points, optional_vec),
|
||||||
(41, holding_cell_blinding_points, optional_vec),
|
(41, holding_cell_blinding_points, optional_vec),
|
||||||
|
(43, malformed_htlcs, optional_vec), // Added in 0.0.119
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -7910,6 +7937,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
|
||||||
let mut pending_outbound_blinding_points_opt: Option<Vec<Option<PublicKey>>> = None;
|
let mut pending_outbound_blinding_points_opt: Option<Vec<Option<PublicKey>>> = None;
|
||||||
let mut holding_cell_blinding_points_opt: Option<Vec<Option<PublicKey>>> = None;
|
let mut holding_cell_blinding_points_opt: Option<Vec<Option<PublicKey>>> = None;
|
||||||
|
|
||||||
|
let mut malformed_htlcs: Option<Vec<(u64, u16, [u8; 32])>> = None;
|
||||||
|
|
||||||
read_tlv_fields!(reader, {
|
read_tlv_fields!(reader, {
|
||||||
(0, announcement_sigs, option),
|
(0, announcement_sigs, option),
|
||||||
(1, minimum_depth, option),
|
(1, minimum_depth, option),
|
||||||
|
@ -7938,6 +7967,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
|
||||||
(38, is_batch_funding, option),
|
(38, is_batch_funding, option),
|
||||||
(39, pending_outbound_blinding_points_opt, optional_vec),
|
(39, pending_outbound_blinding_points_opt, optional_vec),
|
||||||
(41, holding_cell_blinding_points_opt, optional_vec),
|
(41, holding_cell_blinding_points_opt, optional_vec),
|
||||||
|
(43, malformed_htlcs, optional_vec), // Added in 0.0.119
|
||||||
});
|
});
|
||||||
|
|
||||||
let (channel_keys_id, holder_signer) = if let Some(channel_keys_id) = channel_keys_id {
|
let (channel_keys_id, holder_signer) = if let Some(channel_keys_id) = channel_keys_id {
|
||||||
|
@ -8032,6 +8062,22 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
|
||||||
if iter.next().is_some() { return Err(DecodeError::InvalidValue) }
|
if iter.next().is_some() { return Err(DecodeError::InvalidValue) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(malformed_htlcs) = malformed_htlcs {
|
||||||
|
for (malformed_htlc_id, failure_code, sha256_of_onion) in malformed_htlcs {
|
||||||
|
let htlc_idx = holding_cell_htlc_updates.iter().position(|htlc| {
|
||||||
|
if let HTLCUpdateAwaitingACK::FailHTLC { htlc_id, err_packet } = htlc {
|
||||||
|
let matches = *htlc_id == malformed_htlc_id;
|
||||||
|
if matches { debug_assert!(err_packet.data.is_empty()) }
|
||||||
|
matches
|
||||||
|
} else { false }
|
||||||
|
}).ok_or(DecodeError::InvalidValue)?;
|
||||||
|
let malformed_htlc = HTLCUpdateAwaitingACK::FailMalformedHTLC {
|
||||||
|
htlc_id: malformed_htlc_id, failure_code, sha256_of_onion
|
||||||
|
};
|
||||||
|
let _ = core::mem::replace(&mut holding_cell_htlc_updates[htlc_idx], malformed_htlc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(Channel {
|
Ok(Channel {
|
||||||
context: ChannelContext {
|
context: ChannelContext {
|
||||||
user_id,
|
user_id,
|
||||||
|
|
Loading…
Add table
Reference in a new issue