+macro_rules! define_state_flags {
+ ($flag_type_doc: expr, $flag_type: ident, [$(($flag_doc: expr, $flag: ident, $value: expr)),+], $extra_flags: expr) => {
+ #[doc = $flag_type_doc]
+ #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq)]
+ struct $flag_type(u32);
+
+ impl $flag_type {
+ $(
+ #[doc = $flag_doc]
+ const $flag: $flag_type = $flag_type($value);
+ )*
+
+ /// All flags that apply to the specified [`ChannelState`] variant.
+ #[allow(unused)]
+ const ALL: $flag_type = Self($(Self::$flag.0 | )* $extra_flags);
+
+ #[allow(unused)]
+ fn new() -> Self { Self(0) }
+
+ #[allow(unused)]
+ fn from_u32(flags: u32) -> Result<Self, ()> {
+ if flags & !Self::ALL.0 != 0 {
+ Err(())
+ } else {
+ Ok($flag_type(flags))
+ }
+ }
+
+ #[allow(unused)]
+ fn is_empty(&self) -> bool { self.0 == 0 }
+
+ #[allow(unused)]
+ fn is_set(&self, flag: Self) -> bool { *self & flag == flag }
+ }
+
+ impl core::ops::Not for $flag_type {
+ type Output = Self;
+ fn not(self) -> Self::Output { Self(!self.0) }
+ }
+ impl core::ops::BitOr for $flag_type {
+ type Output = Self;
+ fn bitor(self, rhs: Self) -> Self::Output { Self(self.0 | rhs.0) }
+ }
+ impl core::ops::BitOrAssign for $flag_type {
+ fn bitor_assign(&mut self, rhs: Self) { self.0 |= rhs.0; }
+ }
+ impl core::ops::BitAnd for $flag_type {
+ type Output = Self;
+ fn bitand(self, rhs: Self) -> Self::Output { Self(self.0 & rhs.0) }
+ }
+ impl core::ops::BitAndAssign for $flag_type {
+ fn bitand_assign(&mut self, rhs: Self) { self.0 &= rhs.0; }
+ }
+ };
+ ($flag_type_doc: expr, $flag_type: ident, $flags: tt) => {
+ define_state_flags!($flag_type_doc, $flag_type, $flags, 0);
+ };
+ ($flag_type_doc: expr, FUNDED_STATE, $flag_type: ident, $flags: tt) => {
+ define_state_flags!($flag_type_doc, $flag_type, $flags, FundedStateFlags::ALL.0);
+ impl core::ops::BitOr<FundedStateFlags> for $flag_type {
+ type Output = Self;
+ fn bitor(self, rhs: FundedStateFlags) -> Self::Output { Self(self.0 | rhs.0) }
+ }
+ impl core::ops::BitOrAssign<FundedStateFlags> for $flag_type {
+ fn bitor_assign(&mut self, rhs: FundedStateFlags) { self.0 |= rhs.0; }
+ }
+ impl core::ops::BitAnd<FundedStateFlags> for $flag_type {
+ type Output = Self;
+ fn bitand(self, rhs: FundedStateFlags) -> Self::Output { Self(self.0 & rhs.0) }
+ }
+ impl core::ops::BitAndAssign<FundedStateFlags> for $flag_type {
+ fn bitand_assign(&mut self, rhs: FundedStateFlags) { self.0 &= rhs.0; }
+ }
+ impl PartialEq<FundedStateFlags> for $flag_type {
+ fn eq(&self, other: &FundedStateFlags) -> bool { self.0 == other.0 }
+ }
+ impl From<FundedStateFlags> for $flag_type {
+ fn from(flags: FundedStateFlags) -> Self { Self(flags.0) }
+ }
+ };
+}
+
+/// We declare all the states/flags here together to help determine which bits are still available
+/// to choose.
+mod state_flags {
+ pub const OUR_INIT_SENT: u32 = 1 << 0;
+ pub const THEIR_INIT_SENT: u32 = 1 << 1;
+ pub const FUNDING_CREATED: u32 = 1 << 2;
+ pub const FUNDING_SENT: u32 = 1 << 3;
+ pub const THEIR_CHANNEL_READY: u32 = 1 << 4;
+ pub const OUR_CHANNEL_READY: u32 = 1 << 5;
+ pub const CHANNEL_READY: u32 = 1 << 6;
+ pub const PEER_DISCONNECTED: u32 = 1 << 7;
+ pub const MONITOR_UPDATE_IN_PROGRESS: u32 = 1 << 8;
+ pub const AWAITING_REMOTE_REVOKE: u32 = 1 << 9;
+ pub const REMOTE_SHUTDOWN_SENT: u32 = 1 << 10;
+ pub const LOCAL_SHUTDOWN_SENT: u32 = 1 << 11;
+ pub const SHUTDOWN_COMPLETE: u32 = 1 << 12;
+ pub const WAITING_FOR_BATCH: u32 = 1 << 13;
+}
+
+define_state_flags!(
+ "Flags that apply to all [`ChannelState`] variants in which the channel is funded.",
+ FundedStateFlags, [
+ ("Indicates the remote side is considered \"disconnected\" and no updates are allowed \
+ until after we've done a `channel_reestablish` dance.", PEER_DISCONNECTED, state_flags::PEER_DISCONNECTED),
+ ("Indicates the user has told us a `ChannelMonitor` update is pending async persistence \
+ somewhere and we should pause sending any outbound messages until they've managed to \
+ complete it.", MONITOR_UPDATE_IN_PROGRESS, state_flags::MONITOR_UPDATE_IN_PROGRESS),
+ ("Indicates we received a `shutdown` message from the remote end. If set, they may not add \
+ any new HTLCs to the channel, and we are expected to respond with our own `shutdown` \
+ message when possible.", REMOTE_SHUTDOWN_SENT, state_flags::REMOTE_SHUTDOWN_SENT),
+ ("Indicates we sent a `shutdown` message. At this point, we may not add any new HTLCs to \
+ the channel.", LOCAL_SHUTDOWN_SENT, state_flags::LOCAL_SHUTDOWN_SENT)
+ ]
+);
+
+define_state_flags!(
+ "Flags that only apply to [`ChannelState::NegotiatingFunding`].",
+ NegotiatingFundingFlags, [
+ ("Indicates we have (or are prepared to) send our `open_channel`/`accept_channel` message.",
+ OUR_INIT_SENT, state_flags::OUR_INIT_SENT),
+ ("Indicates we have received their `open_channel`/`accept_channel` message.",
+ THEIR_INIT_SENT, state_flags::THEIR_INIT_SENT)
+ ]
+);
+
+define_state_flags!(
+ "Flags that only apply to [`ChannelState::FundingSent`].",
+ FUNDED_STATE, FundingSentFlags, [
+ ("Indicates they sent us a `channel_ready` message. Once both `THEIR_CHANNEL_READY` and \
+ `OUR_CHANNEL_READY` are set, our state moves on to `ChannelReady`.",
+ THEIR_CHANNEL_READY, state_flags::THEIR_CHANNEL_READY),
+ ("Indicates we sent them a `channel_ready` message. Once both `THEIR_CHANNEL_READY` and \
+ `OUR_CHANNEL_READY` are set, our state moves on to `ChannelReady`.",
+ OUR_CHANNEL_READY, state_flags::OUR_CHANNEL_READY),
+ ("Indicates the channel was funded in a batch and the broadcast of the funding transaction \
+ is being held until all channels in the batch have received `funding_signed` and have \
+ their monitors persisted.", WAITING_FOR_BATCH, state_flags::WAITING_FOR_BATCH)
+ ]
+);
+
+define_state_flags!(
+ "Flags that only apply to [`ChannelState::ChannelReady`].",
+ FUNDED_STATE, ChannelReadyFlags, [
+ ("Indicates that we have sent a `commitment_signed` but are awaiting the responding \
+ `revoke_and_ack` message. During this period, we can't generate new `commitment_signed` \
+ messages as we'd be unable to determine which HTLCs they included in their `revoke_and_ack` \
+ implicit ACK, so instead we have to hold them away temporarily to be sent later.",
+ AWAITING_REMOTE_REVOKE, state_flags::AWAITING_REMOTE_REVOKE)
+ ]
+);
+
+#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq)]