Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Channel phase refactor, wrap channel phase, store wrapped phase in map #3418

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 44 additions & 10 deletions lightning/src/ln/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1139,6 +1139,7 @@ impl<'a, SP: Deref> ChannelPhase<SP> where
SP::Target: SignerProvider,
<SP::Target as SignerProvider>::EcdsaSigner: ChannelSigner,
{
#[inline]
pub fn context(&'a self) -> &'a ChannelContext<SP> {
match self {
ChannelPhase::Funded(chan) => &chan.context,
Expand All @@ -1149,6 +1150,7 @@ impl<'a, SP: Deref> ChannelPhase<SP> where
}
}

#[inline]
pub fn context_mut(&'a mut self) -> &'a mut ChannelContext<SP> {
match self {
ChannelPhase::Funded(ref mut chan) => &mut chan.context,
Expand All @@ -1162,40 +1164,72 @@ impl<'a, SP: Deref> ChannelPhase<SP> where

/// A top-level channel struct, containing a channel phase
pub(super) struct ChannelWrapper<SP: Deref> where SP::Target: SignerProvider {
phase: ChannelPhase<SP>,
/// The inner channel phase
/// Option is used to facilitate in-place replacement (see e.g. move_v2_to_funded),
/// but it is never None, ensured in new() and set_phase()
phase: Option<ChannelPhase<SP>>,
Comment on lines +1167 to +1170
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See other comment about moving ChannelContext here. Seems we shouldn't need to use an Option.

}

impl<'a, SP: Deref> ChannelWrapper<SP> where SP::Target: SignerProvider {
pub fn new(phase: ChannelPhase<SP>) -> Self {
Self { phase }
Self {
phase: Some(phase),
}
}

#[inline]
pub fn phase(&self) -> &ChannelPhase<SP> {
&self.phase
self.phase.as_ref().unwrap()
}

#[inline]
pub fn phase_mut(&mut self) -> &mut ChannelPhase<SP> {
&mut self.phase
self.phase.as_mut().unwrap()
}

pub fn phase_take(self) -> ChannelPhase<SP> {
self.phase
match self.phase {
Some(phase) => phase,
None => panic!("None phase"),
}
}

pub fn get_funded_channel(&self) -> Option<&Channel<SP>> {
optout21 marked this conversation as resolved.
Show resolved Hide resolved
if let ChannelPhase::Funded(chan) = &self.phase {
if let ChannelPhase::Funded(chan) = &self.phase.as_ref().unwrap() {
Some(chan)
} else {
None
}
}

/// Change the internal phase
#[inline]
pub fn set_phase(&mut self, new_phase: ChannelPhase<SP>) {
self.phase = Some(new_phase);
}

pub fn move_v2_to_funded(&mut self, signing_session: InteractiveTxSigningSession) -> Result<(), ChannelError> {
// We need a borrow to the phase field, but self is only a mut ref
let phase_inline = self.phase.take().unwrap();
let new_phase = match phase_inline {
ChannelPhase::UnfundedOutboundV2(chan) =>
ChannelPhase::Funded(chan.into_funded_channel(signing_session)?),
ChannelPhase::UnfundedInboundV2(chan) =>
ChannelPhase::Funded(chan.into_funded_channel(signing_session)?),
_ => phase_inline,
};
self.set_phase(new_phase);
Ok(())
}

#[inline]
pub fn context(&'a self) -> &'a ChannelContext<SP> {
self.phase.context()
self.phase().context()
}

#[inline]
pub fn context_mut(&'a mut self) -> &'a mut ChannelContext<SP> {
self.phase.context_mut()
self.phase_mut().context_mut()
}
}

Expand Down Expand Up @@ -8888,7 +8922,7 @@ impl<SP: Deref> OutboundV2Channel<SP> where SP::Target: SignerProvider {
}
}

pub fn into_channel(self, signing_session: InteractiveTxSigningSession) -> Result<Channel<SP>, ChannelError>{
pub fn into_funded_channel(self, signing_session: InteractiveTxSigningSession) -> Result<Channel<SP>, ChannelError>{
let channel = Channel {
context: self.context,
interactive_tx_signing_session: Some(signing_session),
Expand Down Expand Up @@ -9082,7 +9116,7 @@ impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
self.generate_accept_channel_v2_message()
}

pub fn into_channel(self, signing_session: InteractiveTxSigningSession) -> Result<Channel<SP>, ChannelError>{
pub fn into_funded_channel(self, signing_session: InteractiveTxSigningSession) -> Result<Channel<SP>, ChannelError>{
let channel = Channel {
context: self.context,
interactive_tx_signing_session: Some(signing_session),
Expand Down
21 changes: 10 additions & 11 deletions lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5037,6 +5037,7 @@ where
}
}
} else {
// put it back
peer_state.channel_by_id.insert(temporary_channel_id, ChannelWrapper::new(phase));
return Err(APIError::APIMisuseError {
err: format!(
Expand Down Expand Up @@ -8368,18 +8369,16 @@ where
"Got a tx_complete message with no interactive transaction construction expected or in-progress"
.into())),
}.map_err(|err| MsgHandleErrInternal::send_err_msg_no_close(format!("{}", err), msg.channel_id))?;
let (channel_id, channel) = chan_entry.remove_entry();
let channel = match channel.phase_take() {
ChannelPhase::UnfundedOutboundV2(chan) => chan.into_channel(signing_session),
ChannelPhase::UnfundedInboundV2(chan) => chan.into_channel(signing_session),
_ => {

// change the channel phase inline
match chan_entry.get_mut().move_v2_to_funded(signing_session) {
Ok(_) => {},
Err(err) => {
debug_assert!(false); // It cannot be another variant as we are in the `Ok` branch of the above match.
Err(ChannelError::Warn(
"Got a tx_complete message with no interactive transaction construction expected or in-progress"
.into()))
},
}.map_err(|err| MsgHandleErrInternal::send_err_msg_no_close(format!("{}", err), msg.channel_id))?;
peer_state.channel_by_id.insert(channel_id, ChannelWrapper::new(ChannelPhase::Funded(channel)));
return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got a tx_complete message, could not transition to funding, {}", err), msg.channel_id))?;
}
}

if let Some(funding_ready_for_sig_event) = funding_ready_for_sig_event_opt {
let mut pending_events = self.pending_events.lock().unwrap();
pending_events.push_back((funding_ready_for_sig_event, None));
Expand Down
Loading