X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=fd1bf4f30a4da75094508d373a657052aec52b41;hb=9ab7a48ff1887fe4ef74877f5c35d67e15e3ceeb;hp=e77f502d1edb57230e83d3fc0aa15898e3c19cdd;hpb=12f06c3fff74e181a0f2290121943d1693d32780;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index e77f502d..fd1bf4f3 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -299,6 +299,10 @@ macro_rules! define_state_flags { #[allow(unused)] fn is_set(&self, flag: Self) -> bool { *self & flag == flag } + #[allow(unused)] + fn set(&mut self, flag: Self) { *self |= flag } + #[allow(unused)] + fn clear(&mut self, flag: Self) -> Self { self.0 &= !flag.0; *self } } impl core::ops::Not for $flag_type { @@ -323,6 +327,16 @@ macro_rules! define_state_flags { ($flag_type_doc: expr, $flag_type: ident, $flags: tt) => { define_state_flags!($flag_type_doc, $flag_type, $flags, 0); }; + ($flag_type: ident, $flag: expr, $get: ident, $set: ident, $clear: ident) => { + impl $flag_type { + #[allow(unused)] + fn $get(&self) -> bool { self.is_set($flag_type::new() | $flag) } + #[allow(unused)] + fn $set(&mut self) { self.set($flag_type::new() | $flag) } + #[allow(unused)] + fn $clear(&mut self) -> Self { self.clear($flag_type::new() | $flag) } + } + }; ($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 for $flag_type { @@ -3045,12 +3059,12 @@ impl Channel where let mut check_reconnection = false; match &self.context.channel_state { ChannelState::AwaitingChannelReady(flags) => { - let flags = *flags & !FundedStateFlags::ALL; + let flags = flags.clone().clear(FundedStateFlags::ALL.into()); debug_assert!(!flags.is_set(AwaitingChannelReadyFlags::OUR_CHANNEL_READY) || !flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH)); - if flags & !AwaitingChannelReadyFlags::WAITING_FOR_BATCH == AwaitingChannelReadyFlags::THEIR_CHANNEL_READY { + if flags.clone().clear(AwaitingChannelReadyFlags::WAITING_FOR_BATCH) == AwaitingChannelReadyFlags::THEIR_CHANNEL_READY { // If we reconnected before sending our `channel_ready` they may still resend theirs. check_reconnection = true; - } else if (flags & !AwaitingChannelReadyFlags::WAITING_FOR_BATCH).is_empty() { + } else if flags.clone().clear(AwaitingChannelReadyFlags::WAITING_FOR_BATCH).is_empty() { self.context.channel_state.set_their_channel_ready(); } else if flags == AwaitingChannelReadyFlags::OUR_CHANNEL_READY { self.context.channel_state = ChannelState::ChannelReady(self.context.channel_state.with_funded_state_flags_mask().into()); @@ -4176,8 +4190,8 @@ impl Channel where // first received the funding_signed. let mut funding_broadcastable = if self.context.is_outbound() && - matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(flags) if !flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH)) || - matches!(self.context.channel_state, ChannelState::ChannelReady(_)) + (matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(flags) if !flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH)) || + matches!(self.context.channel_state, ChannelState::ChannelReady(_))) { self.context.funding_transaction.take() } else { None }; @@ -5185,7 +5199,7 @@ impl Channel where if !self.is_awaiting_monitor_update() { return false; } if matches!( self.context.channel_state, ChannelState::AwaitingChannelReady(flags) - if (flags & !(AwaitingChannelReadyFlags::THEIR_CHANNEL_READY | FundedStateFlags::PEER_DISCONNECTED | FundedStateFlags::MONITOR_UPDATE_IN_PROGRESS | AwaitingChannelReadyFlags::WAITING_FOR_BATCH)).is_empty() + if flags.clone().clear(AwaitingChannelReadyFlags::THEIR_CHANNEL_READY | FundedStateFlags::PEER_DISCONNECTED | FundedStateFlags::MONITOR_UPDATE_IN_PROGRESS | AwaitingChannelReadyFlags::WAITING_FOR_BATCH).is_empty() ) { // If we're not a 0conf channel, we'll be waiting on a monitor update with only // AwaitingChannelReady set, though our peer could have sent their channel_ready. @@ -5271,14 +5285,14 @@ impl Channel where // Note that we don't include ChannelState::WaitingForBatch as we don't want to send // channel_ready until the entire batch is ready. - let need_commitment_update = if matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(f) if (f & !FundedStateFlags::ALL).is_empty()) { + let need_commitment_update = if matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(f) if f.clone().clear(FundedStateFlags::ALL.into()).is_empty()) { self.context.channel_state.set_our_channel_ready(); true - } else if matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(f) if f & !FundedStateFlags::ALL == AwaitingChannelReadyFlags::THEIR_CHANNEL_READY) { + } else if matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(f) if f.clone().clear(FundedStateFlags::ALL.into()) == AwaitingChannelReadyFlags::THEIR_CHANNEL_READY) { self.context.channel_state = ChannelState::ChannelReady(self.context.channel_state.with_funded_state_flags_mask().into()); self.context.update_time_counter += 1; true - } else if matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(f) if f & !FundedStateFlags::ALL == AwaitingChannelReadyFlags::OUR_CHANNEL_READY) { + } else if matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(f) if f.clone().clear(FundedStateFlags::ALL.into()) == AwaitingChannelReadyFlags::OUR_CHANNEL_READY) { // We got a reorg but not enough to trigger a force close, just ignore. false } else { @@ -7471,6 +7485,8 @@ impl Writeable for Channel where SP::Target: SignerProvider { let mut channel_state = self.context.channel_state; if matches!(channel_state, ChannelState::AwaitingChannelReady(_)|ChannelState::ChannelReady(_)) { channel_state.set_peer_disconnected(); + } else { + debug_assert!(false, "Pre-funded/shutdown channels should not be written"); } channel_state.to_u32().write(writer)?; } @@ -8891,17 +8907,34 @@ mod tests { fn blinding_point_skimmed_fee_malformed_ser() { // Ensure that channel blinding points, skimmed fees, and malformed HTLCs are (de)serialized // properly. + let logger = test_utils::TestLogger::new(); let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000}); let secp_ctx = Secp256k1::new(); let seed = [42; 32]; let network = Network::Testnet; + let best_block = BestBlock::from_network(network); let keys_provider = test_utils::TestKeysInterface::new(&seed, network); let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let config = UserConfig::default(); let features = channelmanager::provided_init_features(&config); - let outbound_chan = OutboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &features, 10000000, 100000, 42, &config, 0, 42, None).unwrap(); - let mut chan = Channel { context: outbound_chan.context }; + let mut outbound_chan = OutboundV1Channel::<&TestKeysInterface>::new( + &feeest, &&keys_provider, &&keys_provider, node_b_node_id, &features, 10000000, 100000, 42, &config, 0, 42, None + ).unwrap(); + let inbound_chan = InboundV1Channel::<&TestKeysInterface>::new( + &feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_channel_type_features(&config), + &features, &outbound_chan.get_open_channel(ChainHash::using_genesis_block(network)), 7, &config, 0, &&logger, false + ).unwrap(); + outbound_chan.accept_channel(&inbound_chan.get_accept_channel_message(), &config.channel_handshake_limits, &features).unwrap(); + let tx = Transaction { version: 1, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut { + value: 10000000, script_pubkey: outbound_chan.context.get_funding_redeemscript(), + }]}; + let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 }; + let funding_created = outbound_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap().unwrap(); + let mut chan = match inbound_chan.funding_created(&funding_created, best_block, &&keys_provider, &&logger) { + Ok((chan, _, _)) => chan, + Err((_, e)) => panic!("{}", e), + }; let dummy_htlc_source = HTLCSource::OutboundRoute { path: Path {