diff --git a/src/fiber/channel.rs b/src/fiber/channel.rs index ff93f1815..f4d0a1240 100644 --- a/src/fiber/channel.rs +++ b/src/fiber/channel.rs @@ -1083,7 +1083,11 @@ where state.update_state(ChannelState::SigningCommitment(flags)); state.maybe_transition_to_tx_signatures(flags, &self.network)?; } - CommitmentSignedFlags::ChannelReady() => {} + CommitmentSignedFlags::ChannelReady() => { + // we are in ChannelReady state for TLC operations, after sending commitment_signed message, + // set the flag of waiting_tlc_ack to true, so that we don't handle TLC operations until we receive the ack. + state.waiting_tlc_ack = true; + } CommitmentSignedFlags::PendingShutdown(_) => { state.maybe_transition_to_shutdown(&self.network)?; } @@ -1097,6 +1101,7 @@ where command: AddTlcCommand, ) -> Result { debug!("handle add tlc command : {:?}", &command); + state.check_ack_status_for_tlc()?; state.check_for_tlc_update(Some(command.amount))?; state.check_tlc_expiry(command.expiry)?; let tlc = state.create_outbounding_tlc(command); @@ -1138,6 +1143,7 @@ where state: &mut ChannelActorState, command: RemoveTlcCommand, ) -> ProcessingChannelResult { + state.check_ack_status_for_tlc()?; state.check_for_tlc_update(None)?; let tlc = state.remove_tlc_with_reason(TLCId::Received(command.id), &command.reason)?; let msg = FiberMessageWithPeerId::new( @@ -2002,6 +2008,10 @@ pub struct ChannelActorState { // An inbound channel is one where the counterparty is the funder of the channel. pub is_acceptor: bool, + // we are expecting ACK for the commitment_signed message, + // when we are in this state, we won't process any AddTlc and RemoveTlc commands. + pub waiting_tlc_ack: bool, + // TODO: consider transaction fee while building the commitment transaction. // The invariant here is that the sum of `to_local_amount` and `to_remote_amount` @@ -2173,6 +2183,8 @@ pub enum ProcessingChannelError { RepeatedProcessing(String), #[error("Invalid parameter: {0}")] InvalidParameter(String), + #[error("Unable to handle TLC command in waiting TLC ACK state")] + WaitingTlcAck, #[error("Capacity error: {0}")] CapacityError(#[from] CapacityError), #[error("Failed to spawn actor: {0}")] @@ -2777,6 +2789,7 @@ impl ChannelActorState { funding_tx: None, funding_tx_confirmed_at: None, is_acceptor: true, + waiting_tlc_ack: false, funding_udt_type_script, to_local_amount: local_value, to_remote_amount: remote_value, @@ -2840,6 +2853,7 @@ impl ChannelActorState { funding_tx_confirmed_at: None, funding_udt_type_script, is_acceptor: false, + waiting_tlc_ack: false, to_local_amount, to_remote_amount: 0, commitment_fee_rate, @@ -4119,6 +4133,12 @@ impl ChannelActorState { Ok(()) } + fn check_ack_status_for_tlc(&self) -> ProcessingChannelResult { + if self.waiting_tlc_ack { + return Err(ProcessingChannelError::WaitingTlcAck); + } + Ok(()) + } fn check_for_tlc_update(&self, add_tlc_amount: Option) -> ProcessingChannelResult { match self.state { ChannelState::ChannelReady() => {} @@ -4915,6 +4935,7 @@ impl ChannelActorState { self.update_state_on_raa_msg(true); self.append_remote_commitment_point(next_per_commitment_point); + self.waiting_tlc_ack = false; emit_service_event( network,