Skip to content

Commit b9c7393

Browse files
committed
Clarify roles in failing HTLCs, impl it, support rebalances
1 parent ac3bf5b commit b9c7393

File tree

6 files changed

+558
-192
lines changed

6 files changed

+558
-192
lines changed

src/ln/channel.rs

Lines changed: 50 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -782,15 +782,47 @@ impl Channel {
782782
return Err(HandleError{err: "Unable to find a pending HTLC which matched the given payment preimage", msg: None});
783783
}
784784

785+
//TODO: This is racy af, they may have pending messages in flight to us that will not have
786+
//received this yet!
785787
self.value_to_self_msat += htlc_amount_msat;
786-
787788
Ok(msgs::UpdateFulfillHTLC {
788789
channel_id: self.channel_id(),
789790
htlc_id: htlc_id,
790791
payment_preimage: payment_preimage,
791792
})
792793
}
793794

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

796828
pub fn accept_channel(&mut self, msg: &msgs::AcceptChannel) -> Result<(), HandleError> {
@@ -1010,7 +1042,7 @@ impl Channel {
10101042
}
10111043

10121044
/// 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> {
1045+
fn remove_outbound_htlc(&mut self, htlc_id: u64, check_preimage: Option<[u8; 32]>) -> Result<HTLCOutput, HandleError> {
10141046
let mut found_idx = None;
10151047
for (idx, ref htlc) in self.pending_htlcs.iter().enumerate() {
10161048
if htlc.outbound && htlc.htlc_id == htlc_id {
@@ -1026,7 +1058,7 @@ impl Channel {
10261058
}
10271059
}
10281060
match found_idx {
1029-
None => Err(HandleError{err: "Remote tried to fulfill an HTLC we couldn't find", msg: None}),
1061+
None => Err(HandleError{err: "Remote tried to fulfill/fail an HTLC we couldn't find", msg: None}),
10301062
Some(idx) => {
10311063
Ok(self.pending_htlcs.swap_remove(idx))
10321064
}
@@ -1096,9 +1128,7 @@ impl Channel {
10961128
let mut payment_hash = [0; 32];
10971129
sha.result(&mut payment_hash);
10981130

1099-
//TODO: Tell channel_monitor about the payment_preimage
1100-
1101-
match self.remove_htlc(msg.htlc_id, Some(payment_hash)) {
1131+
match self.remove_outbound_htlc(msg.htlc_id, Some(payment_hash)) {
11021132
Err(e) => return Err(e),
11031133
Ok(htlc) => {
11041134
//TODO: Double-check that we didn't exceed some limits (or value_to_self went
@@ -1110,43 +1140,40 @@ impl Channel {
11101140
self.check_and_free_holding_cell_htlcs()
11111141
}
11121142

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

1119-
//TODO: Lots of checks here (and implementation after the remove?)
1120-
1121-
match self.remove_htlc(msg.htlc_id, None) {
1148+
let payment_hash = match self.remove_outbound_htlc(msg.htlc_id, None) {
11221149
Err(e) => return Err(e),
1123-
Ok(_htlc) => {
1150+
Ok(htlc) => {
11241151
//TODO: Double-check that we didn't exceed some limits (or value_to_self went
11251152
//negative here?)
1126-
////TODO: Something?
1153+
htlc.payment_hash
11271154
}
1128-
}
1155+
};
11291156

1130-
self.check_and_free_holding_cell_htlcs()
1157+
let holding_cell_freedom = self.check_and_free_holding_cell_htlcs()?;
1158+
Ok((payment_hash, holding_cell_freedom))
11311159
}
11321160

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

1138-
//TODO: Lots of checks here (and implementation after the remove?)
1139-
1140-
match self.remove_htlc(msg.htlc_id, None) {
1166+
let payment_hash = match self.remove_outbound_htlc(msg.htlc_id, None) {
11411167
Err(e) => return Err(e),
1142-
Ok(_htlc) => {
1168+
Ok(htlc) => {
11431169
//TODO: Double-check that we didn't exceed some limits (or value_to_self went
11441170
//negative here?)
1145-
////TODO: Something?
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)