Skip to content

Commit 17375b0

Browse files
committed
Fix channel_reestablish exchanging in case of lost messages
This uses the new storage in HTLC state enums to reproduce the various updates in a CommitmentUpdate group which is obviously required to re-send a commitment_update after pending unreceived updates were dropped. Does not yet handle dropped update_fee updates properly.
1 parent b4dcbfa commit 17375b0

File tree

1 file changed

+85
-27
lines changed

1 file changed

+85
-27
lines changed

src/ln/channel.rs

Lines changed: 85 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2079,40 +2079,49 @@ impl Channel {
20792079

20802080
if msg.next_local_commitment_number == 0 || msg.next_local_commitment_number >= INITIAL_COMMITMENT_NUMBER ||
20812081
msg.next_remote_commitment_number == 0 || msg.next_remote_commitment_number >= INITIAL_COMMITMENT_NUMBER {
2082-
return Err(ChannelError::Close("Peer send garbage channel_reestablish"));
2082+
return Err(ChannelError::Close("Peer sent a garbage channel_reestablish"));
20832083
}
20842084

20852085
// Go ahead and unmark PeerDisconnected as various calls we may make check for it (and all
20862086
// remaining cases either succeed or ErrorMessage-fail).
20872087
self.channel_state &= !(ChannelState::PeerDisconnected as u32);
20882088

2089-
let mut required_revoke = None;
2090-
if msg.next_remote_commitment_number == INITIAL_COMMITMENT_NUMBER - self.cur_local_commitment_transaction_number {
2089+
let required_revoke = if msg.next_remote_commitment_number == INITIAL_COMMITMENT_NUMBER - self.cur_local_commitment_transaction_number {
20912090
// Remote isn't waiting on any RevokeAndACK from us!
20922091
// Note that if we need to repeat our FundingLocked we'll do that in the next if block.
2092+
None
20932093
} else if msg.next_remote_commitment_number == (INITIAL_COMMITMENT_NUMBER - 1) - self.cur_local_commitment_transaction_number {
20942094
let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &self.build_local_commitment_secret(self.cur_local_commitment_transaction_number));
20952095
let per_commitment_secret = chan_utils::build_commitment_secret(self.local_keys.commitment_seed, self.cur_local_commitment_transaction_number + 2);
2096-
required_revoke = Some(msgs::RevokeAndACK {
2096+
Some(msgs::RevokeAndACK {
20972097
channel_id: self.channel_id,
20982098
per_commitment_secret,
20992099
next_per_commitment_point,
2100-
});
2100+
})
21012101
} else {
21022102
return Err(ChannelError::Close("Peer attempted to reestablish channel with a very old local commitment transaction"));
2103-
}
2103+
};
21042104

2105-
if msg.next_local_commitment_number == INITIAL_COMMITMENT_NUMBER - self.cur_remote_commitment_transaction_number {
2106-
if msg.next_remote_commitment_number == INITIAL_COMMITMENT_NUMBER - self.cur_local_commitment_transaction_number {
2107-
log_debug!(self, "Reconnected channel {} with no lost commitment txn", log_bytes!(self.channel_id()));
2108-
if msg.next_local_commitment_number == 1 && msg.next_remote_commitment_number == 1 {
2109-
let next_per_commitment_secret = self.build_local_commitment_secret(self.cur_local_commitment_transaction_number);
2110-
let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &next_per_commitment_secret);
2111-
return Ok((Some(msgs::FundingLocked {
2112-
channel_id: self.channel_id(),
2113-
next_per_commitment_point: next_per_commitment_point,
2114-
}), None, None, None));
2115-
}
2105+
// We increment cur_remote_commitment_transaction_number only upon receipt of
2106+
// revoke_and_ack, not on sending commitment_signed, so we add one if have
2107+
// AwaitingRemoteRevoke set, which indicates we sent a commitment_signed but haven't gotten
2108+
// the corresponding revoke_and_ack back yet.
2109+
let our_next_remote_commitment_number = INITIAL_COMMITMENT_NUMBER - self.cur_remote_commitment_transaction_number + if (self.channel_state & ChannelState::AwaitingRemoteRevoke as u32) != 0 { 1 } else { 0 };
2110+
2111+
let resend_funding_locked = if msg.next_local_commitment_number == 1 && INITIAL_COMMITMENT_NUMBER - self.cur_local_commitment_transaction_number == 1 {
2112+
let next_per_commitment_secret = self.build_local_commitment_secret(self.cur_local_commitment_transaction_number);
2113+
let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &next_per_commitment_secret);
2114+
Some(msgs::FundingLocked {
2115+
channel_id: self.channel_id(),
2116+
next_per_commitment_point: next_per_commitment_point,
2117+
})
2118+
} else { None };
2119+
2120+
if msg.next_local_commitment_number == our_next_remote_commitment_number {
2121+
if required_revoke.is_some() {
2122+
log_debug!(self, "Reconnected channel {} with only lost outbound RAA", log_bytes!(self.channel_id()));
2123+
} else {
2124+
log_debug!(self, "Reconnected channel {} with no loss", log_bytes!(self.channel_id()));
21162125
}
21172126

21182127
if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == 0 {
@@ -2130,20 +2139,69 @@ impl Channel {
21302139
panic!("Got non-channel-failing result from free_holding_cell_htlcs");
21312140
}
21322141
},
2133-
Ok(Some((commitment_update, channel_monitor))) => return Ok((None, required_revoke, Some(commitment_update), Some(channel_monitor))),
2134-
Ok(None) => return Ok((None, required_revoke, None, None)),
2142+
Ok(Some((commitment_update, channel_monitor))) => return Ok((resend_funding_locked, required_revoke, Some(commitment_update), Some(channel_monitor))),
2143+
Ok(None) => return Ok((resend_funding_locked, required_revoke, None, None)),
21352144
}
21362145
} else {
2137-
return Ok((None, required_revoke, None, None));
2146+
return Ok((resend_funding_locked, required_revoke, None, None));
21382147
}
2139-
} else if msg.next_local_commitment_number == (INITIAL_COMMITMENT_NUMBER - 1) - self.cur_remote_commitment_transaction_number {
2140-
return Ok((None, required_revoke,
2148+
} else if msg.next_local_commitment_number == our_next_remote_commitment_number - 1 {
2149+
if required_revoke.is_some() {
2150+
log_debug!(self, "Reconnected channel {} with lost outbound RAA and lost remote commitment tx", log_bytes!(self.channel_id()));
2151+
} else {
2152+
log_debug!(self, "Reconnected channel {} with only lost remote commitment tx", log_bytes!(self.channel_id()));
2153+
}
2154+
let mut update_add_htlcs = Vec::new();
2155+
let mut update_fulfill_htlcs = Vec::new();
2156+
let mut update_fail_htlcs = Vec::new();
2157+
let mut update_fail_malformed_htlcs = Vec::new();
2158+
2159+
for htlc in self.pending_outbound_htlcs.iter() {
2160+
if let &OutboundHTLCState::LocalAnnounced(ref onion_packet) = &htlc.state {
2161+
update_add_htlcs.push(msgs::UpdateAddHTLC {
2162+
channel_id: self.channel_id(),
2163+
htlc_id: htlc.htlc_id,
2164+
amount_msat: htlc.amount_msat,
2165+
payment_hash: htlc.payment_hash,
2166+
cltv_expiry: htlc.cltv_expiry,
2167+
onion_routing_packet: (**onion_packet).clone(),
2168+
});
2169+
}
2170+
}
2171+
2172+
for htlc in self.pending_inbound_htlcs.iter() {
2173+
if let &InboundHTLCState::LocalRemoved(ref reason) = &htlc.state {
2174+
match reason {
2175+
&InboundHTLCRemovalReason::FailRelay(ref err_packet) => {
2176+
update_fail_htlcs.push(msgs::UpdateFailHTLC {
2177+
channel_id: self.channel_id(),
2178+
htlc_id: htlc.htlc_id,
2179+
reason: err_packet.clone()
2180+
});
2181+
},
2182+
&InboundHTLCRemovalReason::FailMalformed((ref sha256_of_onion, ref failure_code)) => {
2183+
update_fail_malformed_htlcs.push(msgs::UpdateFailMalformedHTLC {
2184+
channel_id: self.channel_id(),
2185+
htlc_id: htlc.htlc_id,
2186+
sha256_of_onion: sha256_of_onion.clone(),
2187+
failure_code: failure_code.clone(),
2188+
});
2189+
},
2190+
&InboundHTLCRemovalReason::Fulfill(ref payment_preimage) => {
2191+
update_fulfill_htlcs.push(msgs::UpdateFulfillHTLC {
2192+
channel_id: self.channel_id(),
2193+
htlc_id: htlc.htlc_id,
2194+
payment_preimage: payment_preimage.clone(),
2195+
});
2196+
},
2197+
}
2198+
}
2199+
}
2200+
2201+
return Ok((resend_funding_locked, required_revoke,
21412202
Some(msgs::CommitmentUpdate {
2142-
update_add_htlcs: Vec::new(),
2143-
update_fulfill_htlcs: Vec::new(),
2144-
update_fail_htlcs: Vec::new(),
2145-
update_fail_malformed_htlcs: Vec::new(),
2146-
update_fee: None,
2203+
update_add_htlcs, update_fulfill_htlcs, update_fail_htlcs, update_fail_malformed_htlcs,
2204+
update_fee: None, //TODO: We need to support re-generating any update_fees in the last commitment_signed!
21472205
commitment_signed: self.send_commitment_no_state_update().expect("It looks like we failed to re-generate a commitment_signed we had previously sent?").0,
21482206
}), None));
21492207
} else {

0 commit comments

Comments
 (0)