Skip to content

Commit 3c34395

Browse files
committed
Enforce compile-time check for flag getters and setters
This ensures that we cannot define or use flag getters/setters on `ChannelState` variants in which said flag is not valid.
1 parent e82dba5 commit 3c34395

File tree

1 file changed

+63
-40
lines changed

1 file changed

+63
-40
lines changed

lightning/src/ln/channel.rs

Lines changed: 63 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ enum HTLCUpdateAwaitingACK {
267267
}
268268

269269
macro_rules! define_state_flags {
270-
($flag_type_doc: expr, $flag_type: ident, [$(($flag_doc: expr, $flag: ident, $value: expr)),+], $extra_flags: expr) => {
270+
($flag_type_doc: expr, $flag_type: ident, [$(($flag_doc: expr, $flag: ident, $value: expr, $get: ident, $set: ident, $clear: ident)),+], $extra_flags: expr) => {
271271
#[doc = $flag_type_doc]
272272
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq)]
273273
struct $flag_type(u32);
@@ -296,15 +296,18 @@ macro_rules! define_state_flags {
296296

297297
#[allow(unused)]
298298
fn is_empty(&self) -> bool { self.0 == 0 }
299-
300299
#[allow(unused)]
301300
fn is_set(&self, flag: Self) -> bool { *self & flag == flag }
301+
#[allow(unused)]
302+
fn set(&mut self, flag: Self) { *self |= flag }
303+
#[allow(unused)]
304+
fn clear(&mut self, flag: Self) { self.0 &= !flag.0 }
302305
}
303306

304-
impl core::ops::Not for $flag_type {
305-
type Output = Self;
306-
fn not(self) -> Self::Output { Self(!self.0) }
307-
}
307+
$(
308+
define_state_flags!($flag_type, Self::$flag, $get, $set, $clear);
309+
)*
310+
308311
impl core::ops::BitOr for $flag_type {
309312
type Output = Self;
310313
fn bitor(self, rhs: Self) -> Self::Output { Self(self.0 | rhs.0) }
@@ -323,8 +326,28 @@ macro_rules! define_state_flags {
323326
($flag_type_doc: expr, $flag_type: ident, $flags: tt) => {
324327
define_state_flags!($flag_type_doc, $flag_type, $flags, 0);
325328
};
329+
($flag_type: ident, $flag: expr, $get: ident, $set: ident, $clear: ident) => {
330+
impl $flag_type {
331+
#[allow(unused)]
332+
fn $get(&self) -> bool { self.is_set($flag_type::new() | $flag) }
333+
#[allow(unused)]
334+
fn $set(&mut self) { self.set($flag_type::new() | $flag) }
335+
#[allow(unused)]
336+
fn $clear(&mut self) { self.clear($flag_type::new() | $flag) }
337+
}
338+
};
326339
($flag_type_doc: expr, FUNDED_STATE, $flag_type: ident, $flags: tt) => {
327340
define_state_flags!($flag_type_doc, $flag_type, $flags, FundedStateFlags::ALL.0);
341+
342+
define_state_flags!($flag_type, FundedStateFlags::PEER_DISCONNECTED,
343+
is_peer_disconnected, set_peer_disconnected, clear_peer_disconnected);
344+
define_state_flags!($flag_type, FundedStateFlags::MONITOR_UPDATE_IN_PROGRESS,
345+
is_monitor_update_in_progress, set_monitor_update_in_progress, clear_monitor_update_in_progress);
346+
define_state_flags!($flag_type, FundedStateFlags::REMOTE_SHUTDOWN_SENT,
347+
is_remote_shutdown_sent, set_remote_shutdown_sent, clear_remote_shutdown_sent);
348+
define_state_flags!($flag_type, FundedStateFlags::LOCAL_SHUTDOWN_SENT,
349+
is_local_shutdown_sent, set_local_shutdown_sent, clear_local_shutdown_sent);
350+
328351
impl core::ops::BitOr<FundedStateFlags> for $flag_type {
329352
type Output = Self;
330353
fn bitor(self, rhs: FundedStateFlags) -> Self::Output { Self(self.0 | rhs.0) }
@@ -371,25 +394,29 @@ define_state_flags!(
371394
"Flags that apply to all [`ChannelState`] variants in which the channel is funded.",
372395
FundedStateFlags, [
373396
("Indicates the remote side is considered \"disconnected\" and no updates are allowed \
374-
until after we've done a `channel_reestablish` dance.", PEER_DISCONNECTED, state_flags::PEER_DISCONNECTED),
397+
until after we've done a `channel_reestablish` dance.", PEER_DISCONNECTED, state_flags::PEER_DISCONNECTED,
398+
is_peer_disconnected, set_peer_disconnected, clear_peer_disconnected),
375399
("Indicates the user has told us a `ChannelMonitor` update is pending async persistence \
376400
somewhere and we should pause sending any outbound messages until they've managed to \
377-
complete it.", MONITOR_UPDATE_IN_PROGRESS, state_flags::MONITOR_UPDATE_IN_PROGRESS),
401+
complete it.", MONITOR_UPDATE_IN_PROGRESS, state_flags::MONITOR_UPDATE_IN_PROGRESS,
402+
is_monitor_update_in_progress, set_monitor_update_in_progress, clear_monitor_update_in_progress),
378403
("Indicates we received a `shutdown` message from the remote end. If set, they may not add \
379404
any new HTLCs to the channel, and we are expected to respond with our own `shutdown` \
380-
message when possible.", REMOTE_SHUTDOWN_SENT, state_flags::REMOTE_SHUTDOWN_SENT),
405+
message when possible.", REMOTE_SHUTDOWN_SENT, state_flags::REMOTE_SHUTDOWN_SENT,
406+
is_remote_shutdown_sent, set_remote_shutdown_sent, clear_remote_shutdown_sent),
381407
("Indicates we sent a `shutdown` message. At this point, we may not add any new HTLCs to \
382-
the channel.", LOCAL_SHUTDOWN_SENT, state_flags::LOCAL_SHUTDOWN_SENT)
408+
the channel.", LOCAL_SHUTDOWN_SENT, state_flags::LOCAL_SHUTDOWN_SENT,
409+
is_local_shutdown_sent, set_local_shutdown_sent, clear_local_shutdown_sent)
383410
]
384411
);
385412

386413
define_state_flags!(
387414
"Flags that only apply to [`ChannelState::NegotiatingFunding`].",
388415
NegotiatingFundingFlags, [
389416
("Indicates we have (or are prepared to) send our `open_channel`/`accept_channel` message.",
390-
OUR_INIT_SENT, state_flags::OUR_INIT_SENT),
417+
OUR_INIT_SENT, state_flags::OUR_INIT_SENT, is_our_init_sent, set_our_init_sent, clear_our_init_sent),
391418
("Indicates we have received their `open_channel`/`accept_channel` message.",
392-
THEIR_INIT_SENT, state_flags::THEIR_INIT_SENT)
419+
THEIR_INIT_SENT, state_flags::THEIR_INIT_SENT, is_their_init_sent, set_their_init_sent, clear_their_init_sent)
393420
]
394421
);
395422

@@ -398,13 +425,16 @@ define_state_flags!(
398425
FUNDED_STATE, AwaitingChannelReadyFlags, [
399426
("Indicates they sent us a `channel_ready` message. Once both `THEIR_CHANNEL_READY` and \
400427
`OUR_CHANNEL_READY` are set, our state moves on to `ChannelReady`.",
401-
THEIR_CHANNEL_READY, state_flags::THEIR_CHANNEL_READY),
428+
THEIR_CHANNEL_READY, state_flags::THEIR_CHANNEL_READY,
429+
is_their_channel_ready, set_their_channel_ready, clear_their_channel_ready),
402430
("Indicates we sent them a `channel_ready` message. Once both `THEIR_CHANNEL_READY` and \
403431
`OUR_CHANNEL_READY` are set, our state moves on to `ChannelReady`.",
404-
OUR_CHANNEL_READY, state_flags::OUR_CHANNEL_READY),
432+
OUR_CHANNEL_READY, state_flags::OUR_CHANNEL_READY,
433+
is_our_channel_ready, set_our_channel_ready, clear_our_channel_ready),
405434
("Indicates the channel was funded in a batch and the broadcast of the funding transaction \
406435
is being held until all channels in the batch have received `funding_signed` and have \
407-
their monitors persisted.", WAITING_FOR_BATCH, state_flags::WAITING_FOR_BATCH)
436+
their monitors persisted.", WAITING_FOR_BATCH, state_flags::WAITING_FOR_BATCH,
437+
is_waiting_for_batch, set_waiting_for_batch, clear_waiting_for_batch)
408438
]
409439
);
410440

@@ -415,7 +445,8 @@ define_state_flags!(
415445
`revoke_and_ack` message. During this period, we can't generate new `commitment_signed` \
416446
messages as we'd be unable to determine which HTLCs they included in their `revoke_and_ack` \
417447
implicit ACK, so instead we have to hold them away temporarily to be sent later.",
418-
AWAITING_REMOTE_REVOKE, state_flags::AWAITING_REMOTE_REVOKE)
448+
AWAITING_REMOTE_REVOKE, state_flags::AWAITING_REMOTE_REVOKE,
449+
is_awaiting_remote_revoke, set_awaiting_remote_revoke, clear_awaiting_remote_revoke)
419450
]
420451
);
421452

@@ -441,12 +472,12 @@ enum ChannelState {
441472
}
442473

443474
macro_rules! impl_state_flag {
444-
($get: ident, $set: ident, $clear: ident, $state_flag: expr, [$($state: ident),+]) => {
475+
($get: ident, $set: ident, $clear: ident, [$($state: ident),+]) => {
445476
#[allow(unused)]
446477
fn $get(&self) -> bool {
447478
match self {
448479
$(
449-
ChannelState::$state(flags) => flags.is_set($state_flag.into()),
480+
ChannelState::$state(flags) => flags.$get(),
450481
)*
451482
_ => false,
452483
}
@@ -455,7 +486,7 @@ macro_rules! impl_state_flag {
455486
fn $set(&mut self) {
456487
match self {
457488
$(
458-
ChannelState::$state(flags) => *flags |= $state_flag,
489+
ChannelState::$state(flags) => flags.$set(),
459490
)*
460491
_ => debug_assert!(false, "Attempted to set flag on unexpected ChannelState"),
461492
}
@@ -464,17 +495,17 @@ macro_rules! impl_state_flag {
464495
fn $clear(&mut self) {
465496
match self {
466497
$(
467-
ChannelState::$state(flags) => *flags &= !($state_flag),
498+
ChannelState::$state(flags) => flags.$clear(),
468499
)*
469500
_ => debug_assert!(false, "Attempted to clear flag on unexpected ChannelState"),
470501
}
471502
}
472503
};
473-
($get: ident, $set: ident, $clear: ident, $state_flag: expr, FUNDED_STATES) => {
474-
impl_state_flag!($get, $set, $clear, $state_flag, [AwaitingChannelReady, ChannelReady]);
504+
($get: ident, $set: ident, $clear: ident, FUNDED_STATES) => {
505+
impl_state_flag!($get, $set, $clear, [AwaitingChannelReady, ChannelReady]);
475506
};
476-
($get: ident, $set: ident, $clear: ident, $state_flag: expr, $state: ident) => {
477-
impl_state_flag!($get, $set, $clear, $state_flag, [$state]);
507+
($get: ident, $set: ident, $clear: ident, $state: ident) => {
508+
impl_state_flag!($get, $set, $clear, [$state]);
478509
};
479510
}
480511

@@ -538,22 +569,14 @@ impl ChannelState {
538569
}
539570
}
540571

541-
impl_state_flag!(is_peer_disconnected, set_peer_disconnected, clear_peer_disconnected,
542-
FundedStateFlags::PEER_DISCONNECTED, FUNDED_STATES);
543-
impl_state_flag!(is_monitor_update_in_progress, set_monitor_update_in_progress, clear_monitor_update_in_progress,
544-
FundedStateFlags::MONITOR_UPDATE_IN_PROGRESS, FUNDED_STATES);
545-
impl_state_flag!(is_local_shutdown_sent, set_local_shutdown_sent, clear_local_shutdown_sent,
546-
FundedStateFlags::LOCAL_SHUTDOWN_SENT, FUNDED_STATES);
547-
impl_state_flag!(is_remote_shutdown_sent, set_remote_shutdown_sent, clear_remote_shutdown_sent,
548-
FundedStateFlags::REMOTE_SHUTDOWN_SENT, FUNDED_STATES);
549-
impl_state_flag!(is_our_channel_ready, set_our_channel_ready, clear_our_channel_ready,
550-
AwaitingChannelReadyFlags::OUR_CHANNEL_READY, AwaitingChannelReady);
551-
impl_state_flag!(is_their_channel_ready, set_their_channel_ready, clear_their_channel_ready,
552-
AwaitingChannelReadyFlags::THEIR_CHANNEL_READY, AwaitingChannelReady);
553-
impl_state_flag!(is_waiting_for_batch, set_waiting_for_batch, clear_waiting_for_batch,
554-
AwaitingChannelReadyFlags::WAITING_FOR_BATCH, AwaitingChannelReady);
555-
impl_state_flag!(is_awaiting_remote_revoke, set_awaiting_remote_revoke, clear_awaiting_remote_revoke,
556-
ChannelReadyFlags::AWAITING_REMOTE_REVOKE, ChannelReady);
572+
impl_state_flag!(is_peer_disconnected, set_peer_disconnected, clear_peer_disconnected, FUNDED_STATES);
573+
impl_state_flag!(is_monitor_update_in_progress, set_monitor_update_in_progress, clear_monitor_update_in_progress, FUNDED_STATES);
574+
impl_state_flag!(is_local_shutdown_sent, set_local_shutdown_sent, clear_local_shutdown_sent, FUNDED_STATES);
575+
impl_state_flag!(is_remote_shutdown_sent, set_remote_shutdown_sent, clear_remote_shutdown_sent, FUNDED_STATES);
576+
impl_state_flag!(is_our_channel_ready, set_our_channel_ready, clear_our_channel_ready, AwaitingChannelReady);
577+
impl_state_flag!(is_their_channel_ready, set_their_channel_ready, clear_their_channel_ready, AwaitingChannelReady);
578+
impl_state_flag!(is_waiting_for_batch, set_waiting_for_batch, clear_waiting_for_batch, AwaitingChannelReady);
579+
impl_state_flag!(is_awaiting_remote_revoke, set_awaiting_remote_revoke, clear_awaiting_remote_revoke, ChannelReady);
557580
}
558581

559582
pub const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1;

0 commit comments

Comments
 (0)