X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=63f730781a6b6a56e71f10586d6286f193b3a38c;hb=eee1c30ea6592463d41eefad8306223ec5548014;hp=174eed9b9185669dcc704f81d5b849d62837d641;hpb=e23c270720df2798c3e35e2ba804d98060d76d17;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 174eed9b..63f73078 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -250,7 +250,7 @@ pub const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1; /// Liveness is called to fluctuate given peer disconnecton/monitor failures/closing. /// If channel is public, network should have a liveness view announced by us on a /// best-effort, which means we may filter out some status transitions to avoid spam. -/// See further timer_chan_freshness_every_min. +/// See further timer_tick_occurred. #[derive(PartialEq)] enum UpdateStatus { /// Status has been gossiped. @@ -405,9 +405,9 @@ pub(super) struct Channel { counterparty_forwarding_info: Option, pub(crate) channel_transaction_parameters: ChannelTransactionParameters, + funding_transaction: Option, counterparty_cur_commitment_point: Option, - counterparty_prev_commitment_point: Option, counterparty_node_id: PublicKey, @@ -595,8 +595,9 @@ impl Channel { counterparty_parameters: None, funding_outpoint: None }, - counterparty_cur_commitment_point: None, + funding_transaction: None, + counterparty_cur_commitment_point: None, counterparty_prev_commitment_point: None, counterparty_node_id, @@ -836,8 +837,9 @@ impl Channel { }), funding_outpoint: None }, - counterparty_cur_commitment_point: Some(msg.first_per_commitment_point), + funding_transaction: None, + counterparty_cur_commitment_point: Some(msg.first_per_commitment_point), counterparty_prev_commitment_point: None, counterparty_node_id, @@ -1600,7 +1602,7 @@ impl Channel { /// Handles a funding_signed message from the remote end. /// If this call is successful, broadcast the funding transaction (and not before!) - pub fn funding_signed(&mut self, msg: &msgs::FundingSigned, last_block_hash: BlockHash, logger: &L) -> Result, ChannelError> where L::Target: Logger { + pub fn funding_signed(&mut self, msg: &msgs::FundingSigned, last_block_hash: BlockHash, logger: &L) -> Result<(ChannelMonitor, Transaction), ChannelError> where L::Target: Logger { if !self.is_outbound() { return Err(ChannelError::Close("Received funding_signed for an inbound channel?".to_owned())); } @@ -1662,7 +1664,7 @@ impl Channel { self.cur_holder_commitment_transaction_number -= 1; self.cur_counterparty_commitment_transaction_number -= 1; - Ok(channel_monitor) + Ok((channel_monitor, self.funding_transaction.as_ref().cloned().unwrap())) } pub fn funding_locked(&mut self, msg: &msgs::FundingLocked) -> Result<(), ChannelError> { @@ -2763,20 +2765,21 @@ impl Channel { /// Indicates that the latest ChannelMonitor update has been committed by the client /// successfully and we should restore normal operation. Returns messages which should be sent /// to the remote side. - pub fn monitor_updating_restored(&mut self, logger: &L) -> (Option, Option, RAACommitmentOrder, Vec<(PendingHTLCInfo, u64)>, Vec<(HTLCSource, PaymentHash, HTLCFailReason)>, bool, Option) where L::Target: Logger { + pub fn monitor_updating_restored(&mut self, logger: &L) -> (Option, Option, RAACommitmentOrder, Vec<(PendingHTLCInfo, u64)>, Vec<(HTLCSource, PaymentHash, HTLCFailReason)>, Option, Option) where L::Target: Logger { assert_eq!(self.channel_state & ChannelState::MonitorUpdateFailed as u32, ChannelState::MonitorUpdateFailed as u32); self.channel_state &= !(ChannelState::MonitorUpdateFailed as u32); - let needs_broadcast_safe = self.channel_state & (ChannelState::FundingSent as u32) != 0 && self.is_outbound(); + let funding_broadcastable = if self.channel_state & (ChannelState::FundingSent as u32) != 0 && self.is_outbound() { + self.funding_transaction.take() + } else { None }; - // Because we will never generate a FundingBroadcastSafe event when we're in - // MonitorUpdateFailed, if we assume the user only broadcast the funding transaction when - // they received the FundingBroadcastSafe event, we can only ever hit - // monitor_pending_funding_locked when we're an inbound channel which failed to persist the - // monitor on funding_created, and we even got the funding transaction confirmed before the - // monitor was persisted. + // We will never broadcast the funding transaction when we're in MonitorUpdateFailed (and + // we assume the user never directly broadcasts the funding transaction and waits for us to + // do it). Thus, we can only ever hit monitor_pending_funding_locked when we're an inbound + // channel which failed to persist the monitor on funding_created, and we got the funding + // transaction confirmed before the monitor was persisted. let funding_locked = if self.monitor_pending_funding_locked { - assert!(!self.is_outbound(), "Funding transaction broadcast without FundingBroadcastSafe!"); + assert!(!self.is_outbound(), "Funding transaction broadcast by the local client before it should have - LDK didn't do it!"); self.monitor_pending_funding_locked = false; let next_per_commitment_point = self.holder_signer.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx); Some(msgs::FundingLocked { @@ -2793,7 +2796,7 @@ impl Channel { if self.channel_state & (ChannelState::PeerDisconnected as u32) != 0 { self.monitor_pending_revoke_and_ack = false; self.monitor_pending_commitment_signed = false; - return (None, None, RAACommitmentOrder::RevokeAndACKFirst, forwards, failures, needs_broadcast_safe, funding_locked); + return (None, None, RAACommitmentOrder::RevokeAndACKFirst, forwards, failures, funding_broadcastable, funding_locked); } let raa = if self.monitor_pending_revoke_and_ack { @@ -2807,11 +2810,11 @@ impl Channel { self.monitor_pending_commitment_signed = false; let order = self.resend_order.clone(); log_trace!(logger, "Restored monitor updating resulting in {}{} commitment update and {} RAA, with {} first", - if needs_broadcast_safe { "a funding broadcast safe, " } else { "" }, + if funding_broadcastable.is_some() { "a funding broadcastable, " } else { "" }, if commitment_update.is_some() { "a" } else { "no" }, if raa.is_some() { "an" } else { "no" }, match order { RAACommitmentOrder::CommitmentFirst => "commitment", RAACommitmentOrder::RevokeAndACKFirst => "RAA"}); - (raa, commitment_update, order, forwards, failures, needs_broadcast_safe, funding_locked) + (raa, commitment_update, order, forwards, failures, funding_broadcastable, funding_locked) } pub fn update_fee(&mut self, fee_estimator: &F, msg: &msgs::UpdateFee) -> Result<(), ChannelError> @@ -3764,7 +3767,7 @@ impl Channel { /// Note that channel_id changes during this call! /// Do NOT broadcast the funding transaction until after a successful funding_signed call! /// If an Err is returned, it is a ChannelError::Close. - pub fn get_outbound_funding_created(&mut self, funding_txo: OutPoint, logger: &L) -> Result where L::Target: Logger { + pub fn get_outbound_funding_created(&mut self, funding_transaction: Transaction, funding_txo: OutPoint, logger: &L) -> Result where L::Target: Logger { if !self.is_outbound() { panic!("Tried to create outbound funding_created message on an inbound channel!"); } @@ -3795,6 +3798,7 @@ impl Channel { self.channel_state = ChannelState::FundingCreated as u32; self.channel_id = funding_txo.to_channel_id(); + self.funding_transaction = Some(funding_transaction); Ok(msgs::FundingCreated { temporary_channel_id, @@ -4519,8 +4523,9 @@ impl Writeable for Channel { } self.channel_transaction_parameters.write(writer)?; - self.counterparty_cur_commitment_point.write(writer)?; + self.funding_transaction.write(writer)?; + self.counterparty_cur_commitment_point.write(writer)?; self.counterparty_prev_commitment_point.write(writer)?; self.counterparty_node_id.write(writer)?; @@ -4689,6 +4694,8 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel }; let channel_parameters = Readable::read(reader)?; + let funding_transaction = Readable::read(reader)?; + let counterparty_cur_commitment_point = Readable::read(reader)?; let counterparty_prev_commitment_point = Readable::read(reader)?; @@ -4761,8 +4768,9 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel counterparty_forwarding_info, channel_transaction_parameters: channel_parameters, - counterparty_cur_commitment_point, + funding_transaction, + counterparty_cur_commitment_point, counterparty_prev_commitment_point, counterparty_node_id, @@ -4792,14 +4800,14 @@ mod tests { use bitcoin::hashes::hex::FromHex; use hex; use ln::channelmanager::{HTLCSource, PaymentPreimage, PaymentHash}; - use ln::channel::{Channel,Sign,InboundHTLCOutput,OutboundHTLCOutput,InboundHTLCState,OutboundHTLCState,HTLCOutputInCommitment,HTLCCandidate,HTLCInitiator,TxCreationKeys}; + use ln::channel::{Channel,InboundHTLCOutput,OutboundHTLCOutput,InboundHTLCState,OutboundHTLCState,HTLCOutputInCommitment,HTLCCandidate,HTLCInitiator,TxCreationKeys}; use ln::channel::MAX_FUNDING_SATOSHIS; use ln::features::InitFeatures; use ln::msgs::{ChannelUpdate, DataLossProtect, DecodeError, OptionalField, UnsignedChannelUpdate}; use ln::chan_utils; use ln::chan_utils::{ChannelPublicKeys, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT}; use chain::chaininterface::{FeeEstimator,ConfirmationTarget}; - use chain::keysinterface::{InMemorySigner, KeysInterface}; + use chain::keysinterface::{InMemorySigner, KeysInterface, BaseSign}; use chain::transaction::OutPoint; use util::config::UserConfig; use util::enforcing_trait_impls::EnforcingSigner; @@ -5030,7 +5038,7 @@ mod tests { value: 10000000, script_pubkey: output_script.clone(), }]}; let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 }; - let funding_created_msg = node_a_chan.get_outbound_funding_created(funding_outpoint, &&logger).unwrap(); + let funding_created_msg = node_a_chan.get_outbound_funding_created(tx.clone(), funding_outpoint, &&logger).unwrap(); let (funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, last_block_hash, &&logger).unwrap(); // Node B --> Node A: funding signed