X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=57ccab1adf2f39a6b9aaa6cd1873e87cc1ffce2c;hb=82d40eefb2e6887c6667d1672bfe1e078936dad8;hp=64f7e4f0b682d78db36cecd00d3cdaa0251cf387;hpb=4f06d7a83c04d3f99131175aec9a30ec0c55df5d;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 64f7e4f0..57ccab1a 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -295,7 +295,7 @@ pub(super) struct Channel { holding_cell_update_fee: Option, next_local_htlc_id: u64, next_remote_htlc_id: u64, - channel_update_count: u32, + update_time_counter: u32, feerate_per_kw: u64, #[cfg(debug_assertions)] @@ -433,10 +433,6 @@ impl Channel { cmp::max(at_open_background_feerate * B_OUTPUT_PLUS_SPENDING_INPUT_WEIGHT / 1000, 546) //TODO } - fn derive_our_htlc_minimum_msat(_at_open_channel_feerate_per_kw: u64) -> u64 { - 1000 // TODO - } - // Constructors: pub fn new_outbound(fee_estimator: &F, keys_provider: &K, their_node_id: PublicKey, channel_value_satoshis: u64, push_msat: u64, user_id: u64, logger: Arc, config: &UserConfig) -> Result, APIError> where K::Target: KeysInterface, @@ -490,7 +486,7 @@ impl Channel { holding_cell_update_fee: None, next_local_htlc_id: 0, next_remote_htlc_id: 0, - channel_update_count: 1, + update_time_counter: 1, resend_order: RAACommitmentOrder::CommitmentFirst, @@ -519,7 +515,7 @@ impl Channel { their_max_htlc_value_in_flight_msat: 0, their_channel_reserve_satoshis: 0, their_htlc_minimum_msat: 0, - our_htlc_minimum_msat: Channel::::derive_our_htlc_minimum_msat(feerate), + our_htlc_minimum_msat: if config.own_channel_config.our_htlc_minimum_msat == 0 { 1 } else { config.own_channel_config.our_htlc_minimum_msat }, their_to_self_delay: 0, our_to_self_delay: config.own_channel_config.our_to_self_delay, their_max_accepted_htlcs: 0, @@ -714,7 +710,7 @@ impl Channel { holding_cell_update_fee: None, next_local_htlc_id: 0, next_remote_htlc_id: 0, - channel_update_count: 1, + update_time_counter: 1, resend_order: RAACommitmentOrder::CommitmentFirst, @@ -744,7 +740,7 @@ impl Channel { their_max_htlc_value_in_flight_msat: cmp::min(msg.max_htlc_value_in_flight_msat, msg.funding_satoshis * 1000), their_channel_reserve_satoshis: msg.channel_reserve_satoshis, their_htlc_minimum_msat: msg.htlc_minimum_msat, - our_htlc_minimum_msat: Channel::::derive_our_htlc_minimum_msat(msg.feerate_per_kw as u64), + our_htlc_minimum_msat: if config.own_channel_config.our_htlc_minimum_msat == 0 { 1 } else { config.own_channel_config.our_htlc_minimum_msat }, their_to_self_delay: msg.to_self_delay, our_to_self_delay: config.own_channel_config.our_to_self_delay, their_max_accepted_htlcs: msg.max_accepted_htlcs, @@ -1142,8 +1138,11 @@ impl Channel { } /// Per HTLC, only one get_update_fail_htlc or get_update_fulfill_htlc call may be made. - /// In such cases we debug_assert!(false) and return an IgnoreError. Thus, will always return - /// Ok(_) if debug assertions are turned on and preconditions are met. + /// In such cases we debug_assert!(false) and return a ChannelError::Ignore. Thus, will always + /// return Ok(_) if debug assertions are turned on or preconditions are met. + /// + /// Note that it is still possible to hit these assertions in case we find a preimage on-chain + /// but then have a reorg which settles on an HTLC-failure on chain. fn get_update_fulfill_htlc(&mut self, htlc_id_arg: u64, payment_preimage_arg: PaymentPreimage) -> Result<(Option, Option), ChannelError> { // Either ChannelFunded got set (which means it won't be unset) or there is no way any // caller thought we could have something claimed (cause we wouldn't have accepted in an @@ -1171,6 +1170,7 @@ impl Channel { } else { log_warn!(self, "Have preimage and want to fulfill HTLC with payment hash {} we already failed against channel {}", log_bytes!(htlc.payment_hash.0), log_bytes!(self.channel_id())); } + debug_assert!(false, "Tried to fulfill an HTLC that was already fail/fulfilled"); return Ok((None, None)); }, _ => { @@ -1204,6 +1204,9 @@ impl Channel { match pending_update { &HTLCUpdateAwaitingACK::ClaimHTLC { htlc_id, .. } => { if htlc_id_arg == htlc_id { + // Make sure we don't leave latest_monitor_update_id incremented here: + self.latest_monitor_update_id -= 1; + debug_assert!(false, "Tried to fulfill an HTLC that was already fulfilled"); return Ok((None, None)); } }, @@ -1212,6 +1215,7 @@ impl Channel { log_warn!(self, "Have preimage and want to fulfill HTLC with pending failure against channel {}", log_bytes!(self.channel_id())); // TODO: We may actually be able to switch to a fulfill here, though its // rare enough it may not be worth the complexity burden. + debug_assert!(false, "Tried to fulfill an HTLC that was already failed"); return Ok((None, Some(monitor_update))); } }, @@ -1263,8 +1267,11 @@ impl Channel { } /// Per HTLC, only one get_update_fail_htlc or get_update_fulfill_htlc call may be made. - /// In such cases we debug_assert!(false) and return an IgnoreError. Thus, will always return - /// Ok(_) if debug assertions are turned on and preconditions are met. + /// In such cases we debug_assert!(false) and return a ChannelError::Ignore. Thus, will always + /// return Ok(_) if debug assertions are turned on or preconditions are met. + /// + /// Note that it is still possible to hit these assertions in case we find a preimage on-chain + /// but then have a reorg which settles on an HTLC-failure on chain. pub fn get_update_fail_htlc(&mut self, htlc_id_arg: u64, err_packet: msgs::OnionErrorPacket) -> Result, ChannelError> { if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) { panic!("Was asked to fail an HTLC when channel was not in an operational state"); @@ -1281,6 +1288,7 @@ impl Channel { match htlc.state { InboundHTLCState::Committed => {}, InboundHTLCState::LocalRemoved(_) => { + debug_assert!(false, "Tried to fail an HTLC that was already fail/fulfilled"); return Ok(None); }, _ => { @@ -1301,11 +1309,13 @@ impl Channel { match pending_update { &HTLCUpdateAwaitingACK::ClaimHTLC { htlc_id, .. } => { if htlc_id_arg == htlc_id { + debug_assert!(false, "Tried to fail an HTLC that was already fulfilled"); return Err(ChannelError::Ignore("Unable to find a pending HTLC which matched the given HTLC ID")); } }, &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } => { if htlc_id_arg == htlc_id { + debug_assert!(false, "Tried to fail an HTLC that was already failed"); return Err(ChannelError::Ignore("Unable to find a pending HTLC which matched the given HTLC ID")); } }, @@ -1586,7 +1596,7 @@ impl Channel { self.channel_state |= ChannelState::TheirFundingLocked as u32; } else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::OurFundingLocked as u32) { self.channel_state = ChannelState::ChannelFunded as u32 | (self.channel_state & MULTI_STATE_FLAGS); - self.channel_update_count += 1; + self.update_time_counter += 1; } else if (self.channel_state & (ChannelState::ChannelFunded as u32) != 0 && // Note that funding_signed/funding_created will have decremented both by 1! self.cur_local_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 1 && @@ -1656,6 +1666,9 @@ impl Channel { if msg.amount_msat > self.channel_value_satoshis * 1000 { return Err(ChannelError::Close("Remote side tried to send more than the total value of the channel")); } + if msg.amount_msat == 0 { + return Err(ChannelError::Close("Remote side tried to send a 0-msat HTLC")); + } if msg.amount_msat < self.our_htlc_minimum_msat { return Err(ChannelError::Close("Remote side tried to send less than our minimum HTLC value")); } @@ -2480,7 +2493,7 @@ impl Channel { } Channel::::check_remote_fee(fee_estimator, msg.feerate_per_kw)?; self.pending_update_fee = Some(msg.feerate_per_kw as u64); - self.channel_update_count += 1; + self.update_time_counter += 1; Ok(()) } @@ -2763,7 +2776,7 @@ impl Channel { // From here on out, we may not fail! self.channel_state |= ChannelState::RemoteShutdownSent as u32; - self.channel_update_count += 1; + self.update_time_counter += 1; // We can't send our shutdown until we've committed all of our pending HTLCs, but the // remote side is unlikely to accept any new HTLCs, so we go ahead and "free" any holding @@ -2793,7 +2806,7 @@ impl Channel { }; self.channel_state |= ChannelState::LocalShutdownSent as u32; - self.channel_update_count += 1; + self.update_time_counter += 1; Ok((our_shutdown, self.maybe_propose_first_closing_signed(fee_estimator), dropped_outbound_htlcs)) } @@ -2860,7 +2873,7 @@ impl Channel { if last_fee == msg.fee_satoshis { self.build_signed_closing_transaction(&mut closing_tx, &msg.signature, &our_sig); self.channel_state = ChannelState::ShutdownComplete as u32; - self.channel_update_count += 1; + self.update_time_counter += 1; return Ok((None, Some(closing_tx))); } } @@ -2910,7 +2923,7 @@ impl Channel { self.build_signed_closing_transaction(&mut closing_tx, &msg.signature, &our_sig); self.channel_state = ChannelState::ShutdownComplete as u32; - self.channel_update_count += 1; + self.update_time_counter += 1; Ok((Some(msgs::ClosingSigned { channel_id: self.channel_id, @@ -3022,8 +3035,8 @@ impl Channel { } /// Allowed in any state (including after shutdown) - pub fn get_channel_update_count(&self) -> u32 { - self.channel_update_count + pub fn get_update_time_counter(&self) -> u32 { + self.update_time_counter } pub fn get_latest_monitor_update_id(&self) -> u64 { @@ -3149,7 +3162,7 @@ impl Channel { panic!("Client called ChannelManager::funding_transaction_generated with bogus transaction!"); } self.channel_state = ChannelState::ShutdownComplete as u32; - self.channel_update_count += 1; + self.update_time_counter += 1; return Err(msgs::ErrorMessage { channel_id: self.channel_id(), data: "funding tx had wrong script/value".to_owned() @@ -3175,6 +3188,7 @@ impl Channel { } if header.bitcoin_hash() != self.last_block_connected { self.last_block_connected = header.bitcoin_hash(); + self.update_time_counter = cmp::max(self.update_time_counter, header.time); if let Some(channel_monitor) = self.channel_monitor.as_mut() { channel_monitor.last_block_hash = self.last_block_connected; } @@ -3185,7 +3199,7 @@ impl Channel { true } else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::TheirFundingLocked as u32) { self.channel_state = ChannelState::ChannelFunded as u32 | (self.channel_state & MULTI_STATE_FLAGS); - self.channel_update_count += 1; + self.update_time_counter += 1; true } else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::OurFundingLocked as u32) { // We got a reorg but not enough to trigger a force close, just update @@ -3492,6 +3506,11 @@ impl Channel { if amount_msat > self.channel_value_satoshis * 1000 { return Err(ChannelError::Ignore("Cannot send more than the total value of the channel")); } + + if amount_msat == 0 { + return Err(ChannelError::Ignore("Cannot send 0-msat HTLC")); + } + if amount_msat < self.their_htlc_minimum_msat { return Err(ChannelError::Ignore("Cannot send less than their minimum HTLC value")); } @@ -3728,7 +3747,7 @@ impl Channel { } else { self.channel_state |= ChannelState::LocalShutdownSent as u32; } - self.channel_update_count += 1; + self.update_time_counter += 1; // Go ahead and drop holding cell updates as we'd rather fail payments than wait to send // our shutdown until we've committed all of the pending changes. @@ -3777,7 +3796,7 @@ impl Channel { } self.channel_state = ChannelState::ShutdownComplete as u32; - self.channel_update_count += 1; + self.update_time_counter += 1; if self.channel_monitor.is_some() { (self.channel_monitor.as_mut().unwrap().get_latest_local_commitment_txn(), dropped_outbound_htlcs) } else { @@ -3964,7 +3983,7 @@ impl Writeable for Channel { self.next_local_htlc_id.write(writer)?; (self.next_remote_htlc_id - dropped_inbound_htlcs).write(writer)?; - self.channel_update_count.write(writer)?; + self.update_time_counter.write(writer)?; self.feerate_per_kw.write(writer)?; match self.last_sent_closing_fee { @@ -4124,7 +4143,7 @@ impl ReadableArgs> for Channel::read(reader)? { @@ -4203,7 +4222,7 @@ impl ReadableArgs> for Channel ReadableArgs> for Channel = Arc::new(test_utils::TestLogger::new()); + let secp_ctx = Secp256k1::new(); + let mut seed = [0; 32]; + let mut rng = thread_rng(); + rng.fill_bytes(&mut seed); + let network = Network::Testnet; + let keys_provider = test_utils::TestKeysInterface::new(&seed, network, logger.clone() as Arc); + + // Go through the flow of opening a channel between two nodes. + + // Create Node A's channel + let node_a_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); + let config = UserConfig::default(); + let mut node_a_chan = Channel::::new_outbound(&&feeest, &&keys_provider, node_a_node_id, 10000000, 100000, 42, Arc::clone(&logger), &config).unwrap(); + + // Create Node B's channel by receiving Node A's open_channel message + let open_channel_msg = node_a_chan.get_open_channel(genesis_block(network).header.bitcoin_hash(), &&feeest); + let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); + let mut node_b_chan = Channel::::new_from_req(&&feeest, &&keys_provider, node_b_node_id, InitFeatures::supported(), &open_channel_msg, 7, logger, &config).unwrap(); + + // Node B --> Node A: accept channel + let accept_channel_msg = node_b_chan.get_accept_channel(); + node_a_chan.accept_channel(&accept_channel_msg, &config, InitFeatures::supported()).unwrap(); + + // Node A --> Node B: funding created + let output_script = node_a_chan.get_funding_redeemscript(); + let tx = Transaction { version: 1, lock_time: 0, input: Vec::new(), output: vec![TxOut { + value: 10000000, script_pubkey: output_script.clone(), + }]}; + let funding_outpoint = OutPoint::new(tx.txid(), 0); + let (funding_created_msg, _) = node_a_chan.get_outbound_funding_created(funding_outpoint).unwrap(); + let (funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg).unwrap(); + + // Node B --> Node A: funding signed + let _ = node_a_chan.funding_signed(&funding_signed_msg); + + // Now disconnect the two nodes and check that the commitment point in + // Node B's channel_reestablish message is sane. + node_b_chan.remove_uncommitted_htlcs_and_mark_paused(); + let expected_commitment_point = PublicKey::from_secret_key(&secp_ctx, &node_b_chan.build_local_commitment_secret(node_b_chan.cur_local_commitment_transaction_number + 1)); + let msg = node_b_chan.get_channel_reestablish(); + match msg.data_loss_protect { + OptionalField::Present(DataLossProtect { my_current_per_commitment_point, .. }) => { + assert_eq!(expected_commitment_point, my_current_per_commitment_point); + }, + _ => panic!() + } + + // Check that the commitment point in Node A's channel_reestablish message + // is sane. + node_a_chan.remove_uncommitted_htlcs_and_mark_paused(); + let expected_commitment_point = PublicKey::from_secret_key(&secp_ctx, &node_a_chan.build_local_commitment_secret(node_a_chan.cur_local_commitment_transaction_number + 1)); + let msg = node_a_chan.get_channel_reestablish(); + match msg.data_loss_protect { + OptionalField::Present(DataLossProtect { my_current_per_commitment_point, .. }) => { + assert_eq!(expected_commitment_point, my_current_per_commitment_point); + }, + _ => panic!() + } + } + #[test] fn outbound_commitment_test() { // Test vectors from BOLT 3 Appendix C: