X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fln%2Fchannel.rs;h=f890f03968903b137b99e34db09f6f4e4f4890ee;hb=335012640a809821cd5a0afd35cb1e7463e1002d;hp=47c05de2ab989ab69c00a8f219efb63adebb527a;hpb=dfc04ad0b4a70649c07625aa80c8bb8587718cc2;p=rust-lightning diff --git a/src/ln/channel.rs b/src/ln/channel.rs index 47c05de2..f890f039 100644 --- a/src/ln/channel.rs +++ b/src/ln/channel.rs @@ -16,7 +16,7 @@ use crypto::hkdf::{hkdf_extract,hkdf_expand}; use ln::msgs; use ln::msgs::{ErrorAction, HandleError, MsgEncodable}; use ln::channelmonitor::ChannelMonitor; -use ln::channelmanager::{PendingHTLCStatus, PendingForwardHTLCInfo, HTLCFailReason}; +use ln::channelmanager::{PendingHTLCStatus, PendingForwardHTLCInfo, HTLCFailReason, HTLCFailureMsg}; use ln::chan_utils::{TxCreationKeys,HTLCOutputInCommitment,HTLC_SUCCESS_TX_WEIGHT,HTLC_TIMEOUT_TX_WEIGHT}; use ln::chan_utils; use chain::chaininterface::{FeeEstimator,ConfirmationTarget}; @@ -373,6 +373,8 @@ impl Channel { } fn derive_minimum_depth(_channel_value_satoshis_msat: u64, _value_to_self_msat: u64) -> u32 { + // Note that in order to comply with BOLT 7 announcement_signatures requirements this must + // be at least 6. const CONF_TARGET: u32 = 12; //TODO: Should be much higher CONF_TARGET } @@ -1018,10 +1020,13 @@ impl Channel { for (idx, htlc) in self.pending_htlcs.iter().enumerate() { if !htlc.outbound && htlc.payment_hash == payment_hash_calc && htlc.state != HTLCState::LocalRemoved && htlc.state != HTLCState::LocalRemovedAwaitingCommitment { - if pending_idx != std::usize::MAX { - panic!("Duplicate HTLC payment_hash, ChannelManager should have prevented this!"); + if let Some(PendingHTLCStatus::Fail(_)) = htlc.pending_forward_state { + } else { + if pending_idx != std::usize::MAX { + panic!("Duplicate HTLC payment_hash, ChannelManager should have prevented this!"); + } + pending_idx = idx; } - pending_idx = idx; } } if pending_idx == std::usize::MAX { @@ -1640,6 +1645,7 @@ impl Channel { update_add_htlcs, update_fulfill_htlcs, update_fail_htlcs, + update_fail_malformed_htlcs: Vec::new(), commitment_signed, }, monitor_update))) }, @@ -1677,7 +1683,8 @@ impl Channel { let mut to_forward_infos = Vec::new(); let mut revoked_htlcs = Vec::new(); - let mut failed_htlcs = Vec::new(); + let mut update_fail_htlcs = Vec::new(); + let mut update_fail_malformed_htlcs = Vec::new(); let mut require_commitment = false; let mut value_to_self_msat_diff: i64 = 0; // We really shouldnt have two passes here, but retain gives a non-mutable ref (Rust bug) @@ -1705,7 +1712,10 @@ impl Channel { PendingHTLCStatus::Fail(fail_msg) => { htlc.state = HTLCState::LocalRemoved; require_commitment = true; - failed_htlcs.push(fail_msg); + match fail_msg { + HTLCFailureMsg::Relay(msg) => update_fail_htlcs.push(msg), + HTLCFailureMsg::Malformed(msg) => update_fail_malformed_htlcs.push(msg), + } }, PendingHTLCStatus::Forward(forward_info) => { to_forward_infos.push(forward_info); @@ -1724,10 +1734,14 @@ impl Channel { match self.free_holding_cell_htlcs()? { Some(mut commitment_update) => { - commitment_update.0.update_fail_htlcs.reserve(failed_htlcs.len()); - for fail_msg in failed_htlcs.drain(..) { + commitment_update.0.update_fail_htlcs.reserve(update_fail_htlcs.len()); + for fail_msg in update_fail_htlcs.drain(..) { commitment_update.0.update_fail_htlcs.push(fail_msg); } + commitment_update.0.update_fail_malformed_htlcs.reserve(update_fail_malformed_htlcs.len()); + for fail_msg in update_fail_malformed_htlcs.drain(..) { + commitment_update.0.update_fail_malformed_htlcs.push(fail_msg); + } Ok((Some(commitment_update.0), to_forward_infos, revoked_htlcs, commitment_update.1)) }, None => { @@ -1736,7 +1750,8 @@ impl Channel { Ok((Some(msgs::CommitmentUpdate { update_add_htlcs: Vec::new(), update_fulfill_htlcs: Vec::new(), - update_fail_htlcs: failed_htlcs, + update_fail_htlcs, + update_fail_malformed_htlcs, commitment_signed }), to_forward_infos, revoked_htlcs, monitor_update)) } else { @@ -2260,18 +2275,22 @@ impl Channel { /// Gets an UnsignedChannelAnnouncement, as well as a signature covering it using our /// bitcoin_key, if available, for this channel. The channel must be publicly announceable and - /// available for use (have exchanged FundingLocked messages in both directions. Should be used + /// available for use (have exchanged FundingLocked messages in both directions). Should be used /// for both loose and in response to an AnnouncementSignatures message from the remote peer. - /// Note that you can get an announcement for a channel which is closing, though you should - /// likely not announce such a thing. In case its already been announced, a channel_update - /// message can mark the channel disabled. + /// Will only fail if we're not in a state where channel_announcement may be sent (including + /// closing). + /// Note that the "channel must be funded" requirement is stricter than BOLT 7 requires - see + /// https://github.com/lightningnetwork/lightning-rfc/issues/468 pub fn get_channel_announcement(&self, our_node_id: PublicKey, chain_hash: Sha256dHash) -> Result<(msgs::UnsignedChannelAnnouncement, Signature), HandleError> { if !self.announce_publicly { return Err(HandleError{err: "Channel is not available for public announcements", action: None}); } - if self.channel_state & (ChannelState::ChannelFunded as u32) != (ChannelState::ChannelFunded as u32) { + if self.channel_state & (ChannelState::ChannelFunded as u32) == 0 { return Err(HandleError{err: "Cannot get a ChannelAnnouncement until the channel funding has been locked", action: None}); } + if (self.channel_state & (ChannelState::LocalShutdownSent as u32 | ChannelState::ShutdownComplete as u32)) != 0 { + return Err(HandleError{err: "Cannot get a ChannelAnnouncement once the channel is closing", action: None}); + } let were_node_one = our_node_id.serialize()[..] < self.their_node_id.serialize()[..]; let our_bitcoin_key = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.funding_key); @@ -2284,6 +2303,7 @@ impl Channel { node_id_2: if were_node_one { self.get_their_node_id() } else { our_node_id }, bitcoin_key_1: if were_node_one { our_bitcoin_key } else { self.their_funding_pubkey.unwrap() }, bitcoin_key_2: if were_node_one { self.their_funding_pubkey.unwrap() } else { our_bitcoin_key }, + excess_data: Vec::new(), }; let msghash = Message::from_slice(&Sha256dHash::from_data(&msg.encode()[..])[..]).unwrap();