Skip to content

Commit 215308f

Browse files
committed
Clarify roles in failing HTLCs, implement most of it
1 parent ac3bf5b commit 215308f

File tree

5 files changed

+236
-113
lines changed

5 files changed

+236
-113
lines changed

src/ln/channel.rs

Lines changed: 49 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,36 @@ impl Channel {
791791
})
792792
}
793793

794+
pub fn get_update_fail_htlc(&mut self, payment_hash: &[u8; 32], err_packet: msgs::OnionErrorPacket) -> Result<msgs::UpdateFailHTLC, HandleError> {
795+
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
796+
return Err(HandleError{err: "Was asked to fail an HTLC when channel was not in an operational state", msg: None});
797+
}
798+
799+
let mut htlc_id = 0;
800+
let mut htlc_amount_msat = 0;
801+
self.pending_htlcs.retain(|ref htlc| {
802+
if !htlc.outbound && htlc.payment_hash == *payment_hash {
803+
if htlc_id != 0 {
804+
panic!("Duplicate HTLC payment_hash, you probably re-used payment preimages, NEVER DO THIS!");
805+
}
806+
htlc_id = htlc.htlc_id;
807+
htlc_amount_msat += htlc.amount_msat;
808+
false
809+
} else { true }
810+
});
811+
if htlc_amount_msat == 0 {
812+
return Err(HandleError{err: "Unable to find a pending HTLC which matched the given payment preimage", msg: None});
813+
}
814+
815+
self.value_to_self_msat += htlc_amount_msat;
816+
817+
Ok(msgs::UpdateFailHTLC {
818+
channel_id: self.channel_id(),
819+
htlc_id,
820+
reason: err_packet
821+
})
822+
}
823+
794824
// Message handlers:
795825

796826
pub fn accept_channel(&mut self, msg: &msgs::AcceptChannel) -> Result<(), HandleError> {
@@ -1010,7 +1040,7 @@ impl Channel {
10101040
}
10111041

10121042
/// Removes an outbound HTLC which has been commitment_signed by the remote end
1013-
fn remove_htlc(&mut self, htlc_id: u64, check_preimage: Option<[u8; 32]>) -> Result<HTLCOutput, HandleError> {
1043+
fn remove_outbound_htlc(&mut self, htlc_id: u64, check_preimage: Option<[u8; 32]>) -> Result<HTLCOutput, HandleError> {
10141044
let mut found_idx = None;
10151045
for (idx, ref htlc) in self.pending_htlcs.iter().enumerate() {
10161046
if htlc.outbound && htlc.htlc_id == htlc_id {
@@ -1026,7 +1056,7 @@ impl Channel {
10261056
}
10271057
}
10281058
match found_idx {
1029-
None => Err(HandleError{err: "Remote tried to fulfill an HTLC we couldn't find", msg: None}),
1059+
None => Err(HandleError{err: "Remote tried to fulfill/fail an HTLC we couldn't find", msg: None}),
10301060
Some(idx) => {
10311061
Ok(self.pending_htlcs.swap_remove(idx))
10321062
}
@@ -1096,9 +1126,7 @@ impl Channel {
10961126
let mut payment_hash = [0; 32];
10971127
sha.result(&mut payment_hash);
10981128

1099-
//TODO: Tell channel_monitor about the payment_preimage
1100-
1101-
match self.remove_htlc(msg.htlc_id, Some(payment_hash)) {
1129+
match self.remove_outbound_htlc(msg.htlc_id, Some(payment_hash)) {
11021130
Err(e) => return Err(e),
11031131
Ok(htlc) => {
11041132
//TODO: Double-check that we didn't exceed some limits (or value_to_self went
@@ -1110,43 +1138,42 @@ impl Channel {
11101138
self.check_and_free_holding_cell_htlcs()
11111139
}
11121140

1113-
1114-
pub fn update_fail_htlc(&mut self, msg: &msgs::UpdateFailHTLC) -> Result<Option<(Vec<msgs::UpdateAddHTLC>, msgs::CommitmentSigned)>, HandleError> {
1141+
pub fn update_fail_htlc(&mut self, msg: &msgs::UpdateFailHTLC) -> Result<([u8; 32], Option<(Vec<msgs::UpdateAddHTLC>, msgs::CommitmentSigned)>), HandleError> {
11151142
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
11161143
return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", msg: None});
11171144
}
11181145

1119-
//TODO: Lots of checks here (and implementation after the remove?)
1120-
1121-
match self.remove_htlc(msg.htlc_id, None) {
1146+
let payment_hash = match self.remove_outbound_htlc(msg.htlc_id, None) {
11221147
Err(e) => return Err(e),
1123-
Ok(_htlc) => {
1148+
Ok(htlc) => {
11241149
//TODO: Double-check that we didn't exceed some limits (or value_to_self went
11251150
//negative here?)
1126-
////TODO: Something?
1151+
self.value_to_self_msat -= htlc.amount_msat;
1152+
htlc.payment_hash
11271153
}
1128-
}
1154+
};
11291155

1130-
self.check_and_free_holding_cell_htlcs()
1156+
let holding_cell_freedom = self.check_and_free_holding_cell_htlcs()?;
1157+
Ok((payment_hash, holding_cell_freedom))
11311158
}
11321159

1133-
pub fn update_fail_malformed_htlc(&mut self, msg: &msgs::UpdateFailMalformedHTLC) -> Result<Option<(Vec<msgs::UpdateAddHTLC>, msgs::CommitmentSigned)>, HandleError> {
1160+
pub fn update_fail_malformed_htlc(&mut self, msg: &msgs::UpdateFailMalformedHTLC) -> Result<([u8; 32], Option<(Vec<msgs::UpdateAddHTLC>, msgs::CommitmentSigned)>), HandleError> {
11341161
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
11351162
return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", msg: None});
11361163
}
11371164

1138-
//TODO: Lots of checks here (and implementation after the remove?)
1139-
1140-
match self.remove_htlc(msg.htlc_id, None) {
1165+
let payment_hash = match self.remove_outbound_htlc(msg.htlc_id, None) {
11411166
Err(e) => return Err(e),
1142-
Ok(_htlc) => {
1167+
Ok(htlc) => {
11431168
//TODO: Double-check that we didn't exceed some limits (or value_to_self went
11441169
//negative here?)
1145-
////TODO: Something?
1170+
self.value_to_self_msat -= htlc.amount_msat;
1171+
htlc.payment_hash
11461172
}
1147-
}
1173+
};
11481174

1149-
self.check_and_free_holding_cell_htlcs()
1175+
let holding_cell_freedom = self.check_and_free_holding_cell_htlcs()?;
1176+
Ok((payment_hash, holding_cell_freedom))
11501177
}
11511178

11521179
pub fn commitment_signed(&mut self, msg: &msgs::CommitmentSigned) -> Result<(msgs::RevokeAndACK, Vec<PendingForwardHTLCInfo>), HandleError> {

0 commit comments

Comments
 (0)