X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=1d3e264a3fcbf263eec75e3b85e8d0b65c81e024;hb=4353d4a11c12c148fbf3e95dd2e2f824f60433df;hp=174aecd3ba036f46dc9acdc95d2b287ef536d812;hpb=3f2efcdfa73ee703093107f908cc7eeb0aa467e8;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 174aecd3..1d3e264a 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -7,7 +7,6 @@ // You may not use this file except in accordance with one or both of these // licenses. -use bitcoin::blockdata::block::BlockHeader; use bitcoin::blockdata::script::{Script,Builder}; use bitcoin::blockdata::transaction::{TxIn, TxOut, Transaction, SigHashType}; use bitcoin::blockdata::opcodes; @@ -16,16 +15,18 @@ use bitcoin::consensus::encode; use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::hashes::sha256d::Hash as Sha256d; use bitcoin::hash_types::{Txid, BlockHash, WPubkeyHash}; use bitcoin::secp256k1::key::{PublicKey,SecretKey}; use bitcoin::secp256k1::{Secp256k1,Signature}; use bitcoin::secp256k1; +use ln::{PaymentPreimage, PaymentHash}; use ln::features::{ChannelFeatures, InitFeatures}; use ln::msgs; use ln::msgs::{DecodeError, OptionalField, DataLossProtect}; -use ln::channelmanager::{PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT}; +use ln::channelmanager::{BestBlock, PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT}; use ln::chan_utils::{CounterpartyCommitmentSecrets, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript, ChannelPublicKeys, CommitmentTransaction, HolderCommitmentTransaction, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, MAX_HTLCS, get_commitment_transaction_number_obscure_factor}; use ln::chan_utils; use chain::chaininterface::{FeeEstimator,ConfirmationTarget}; @@ -39,9 +40,9 @@ use util::errors::APIError; use util::config::{UserConfig,ChannelConfig}; use util::scid_utils::scid_from_parts; -use std; -use std::{cmp,mem,fmt}; -use std::ops::Deref; +use prelude::*; +use core::{cmp,mem,fmt}; +use core::ops::Deref; #[cfg(any(test, feature = "fuzztarget"))] use std::sync::Mutex; use bitcoin::hashes::hex::ToHex; @@ -248,18 +249,21 @@ const MULTI_STATE_FLAGS: u32 = BOTH_SIDES_SHUTDOWN_MASK | ChannelState::PeerDisc 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. -#[derive(PartialEq)] -enum UpdateStatus { - /// Status has been gossiped. - Fresh, - /// Status has been changed. - DisabledMarked, - /// Status has been marked to be gossiped at next flush +/// The "channel disabled" bit in channel_update must be set based on whether we are connected to +/// our counterparty or not. However, we don't want to announce updates right away to avoid +/// spamming the network with updates if the connection is flapping. Instead, we "stage" updates to +/// our channel_update message and track the current state here. +/// See implementation at [`super::channelmanager::ChannelManager::timer_tick_occurred`]. +#[derive(Clone, Copy, PartialEq)] +pub(super) enum ChannelUpdateStatus { + /// We've announced the channel as enabled and are connected to our peer. + Enabled, + /// Our channel is no longer live, but we haven't announced the channel as disabled yet. DisabledStaged, + /// Our channel is live again, but we haven't announced the channel as enabled yet. + EnabledStaged, + /// We've announced the channel as disabled. + Disabled, } /// An enum indicating whether the local or remote side offered a given HTLC. @@ -284,7 +288,7 @@ impl HTLCCandidate { } /// Information needed for constructing an invoice route hint for this channel. -#[derive(Clone)] +#[derive(Clone, Debug, PartialEq)] pub struct CounterpartyForwardingInfo { /// Base routing fee in millisatoshis. pub fee_base_msat: u32, @@ -376,13 +380,10 @@ pub(super) struct Channel { last_sent_closing_fee: Option<(u32, u64, Signature)>, // (feerate, fee, holder_sig) - /// The hash of the block in which the funding transaction reached our CONF_TARGET. We use this - /// to detect unconfirmation after a serialize-unserialize roundtrip where we may not see a full - /// series of block_connected/block_disconnected calls. Obviously this is not a guarantee as we - /// could miss the funding_tx_confirmed_in block as well, but it serves as a useful fallback. + /// The hash of the block in which the funding transaction was included. funding_tx_confirmed_in: Option, + funding_tx_confirmation_height: u32, short_channel_id: Option, - funding_tx_confirmations: u64, counterparty_dust_limit_satoshis: u64, #[cfg(test)] @@ -419,7 +420,11 @@ pub(super) struct Channel { commitment_secrets: CounterpartyCommitmentSecrets, - network_sync: UpdateStatus, + channel_update_status: ChannelUpdateStatus, + + /// Our counterparty's channel_announcement signatures provided in announcement_signatures. + /// This can be used to rebroadcast the channel_announcement message later. + announcement_sigs: Option<(Signature, Signature)>, // We save these values so we can make sure `next_local_commit_tx_fee_msat` and // `next_remote_commit_tx_fee_msat` properly predict what the next commitment transaction fee will @@ -429,6 +434,15 @@ pub(super) struct Channel { next_local_commitment_tx_fee_info_cached: Mutex>, #[cfg(any(test, feature = "fuzztarget"))] next_remote_commitment_tx_fee_info_cached: Mutex>, + + /// lnd has a long-standing bug where, upon reconnection, if the channel is not yet confirmed + /// they will not send a channel_reestablish until the channel locks in. Then, they will send a + /// funding_locked *before* sending the channel_reestablish (which is clearly a violation of + /// the BOLT specs). We copy c-lightning's workaround here and simply store the funding_locked + /// message until we receive a channel_reestablish. + /// + /// See-also + pub workaround_lnd_bug_4006: Option, } #[cfg(any(test, feature = "fuzztarget"))] @@ -441,12 +455,7 @@ struct CommitmentTxInfoCached { } pub const OUR_MAX_HTLCS: u16 = 50; //TODO -/// Confirmation count threshold at which we close a channel. Ideally we'd keep the channel around -/// on ice until the funding transaction gets more confirmations, but the LN protocol doesn't -/// really allow for this, so instead we're stuck closing it out at that point. -const UNCONF_THRESHOLD: u32 = 6; const SPENDING_INPUT_FOR_A_OUTPUT_WEIGHT: u64 = 79; // prevout: 36, nSequence: 4, script len: 1, witness lengths: (3+1)/4, sig: 73/4, if-selector: 1, redeemScript: (6 ops + 2*33 pubkeys + 1*2 delay)/4 -const B_OUTPUT_PLUS_SPENDING_INPUT_WEIGHT: u64 = 104; // prevout: 40, nSequence: 4, script len: 1, witness lengths: 3/4, sig: 73/4, pubkey: 33/4, output: 31 (TODO: Wrong? Useless?) #[cfg(not(test))] const COMMITMENT_TX_BASE_WEIGHT: u64 = 724; @@ -461,6 +470,22 @@ pub const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172; /// it's 2^24. pub const MAX_FUNDING_SATOSHIS: u64 = 1 << 24; +/// Maximum counterparty `dust_limit_satoshis` allowed. 2 * standard dust threshold on p2wsh output +/// Scales up on Bitcoin Core's proceeding policy with dust outputs. A typical p2wsh output is 43 +/// bytes to which Core's `GetDustThreshold()` sums up a minimal spend of 67 bytes (even if +/// a p2wsh witnessScript might be *effectively* smaller), `dustRelayFee` is set to 3000sat/kb, thus +/// 110 * 3000 / 1000 = 330. Per-protocol rules, all time-sensitive outputs are p2wsh, a value of +/// 330 sats is the lower bound desired to ensure good propagation of transactions. We give a bit +/// of margin to our counterparty and pick up 660 satoshis as an accepted `dust_limit_satoshis` +/// upper bound to avoid negotiation conflicts with other implementations. +pub const MAX_DUST_LIMIT_SATOSHIS: u64 = 2 * 330; + +/// A typical p2wsh output is 43 bytes to which Core's `GetDustThreshold()` sums up a minimal +/// spend of 67 bytes (even if a p2wsh witnessScript might be *effectively* smaller), `dustRelayFee` +/// is set to 3000sat/kb, thus 110 * 3000 / 1000 = 330. Per-protocol rules, all time-sensitive outputs +/// are p2wsh, a value of 330 sats is the lower bound desired to ensure good propagation of transactions. +pub const MIN_DUST_LIMIT_SATOSHIS: u64 = 330; + /// Used to return a simple Error back to ChannelManager. Will get converted to a /// msgs::ErrorAction::SendErrorMessage or msgs::ErrorAction::IgnoreError as appropriate with our /// channel_id in ChannelManager. @@ -504,10 +529,6 @@ impl Channel { cmp::min(channel_value_satoshis, cmp::max(q, 1000)) //TODO } - fn derive_holder_dust_limit_satoshis(at_open_background_feerate: u32) -> u64 { - cmp::max(at_open_background_feerate as u64 * B_OUTPUT_PLUS_SPENDING_INPUT_WEIGHT / 1000, 546) //TODO - } - // Constructors: pub fn new_outbound(fee_estimator: &F, keys_provider: &K, counterparty_node_id: PublicKey, channel_value_satoshis: u64, push_msat: u64, user_id: u64, config: &UserConfig) -> Result, APIError> where K::Target: KeysInterface, @@ -527,9 +548,9 @@ impl Channel { if holder_selected_contest_delay < BREAKDOWN_TIMEOUT { return Err(APIError::APIMisuseError {err: format!("Configured with an unreasonable our_to_self_delay ({}) putting user funds at risks", holder_selected_contest_delay)}); } - let background_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background); - if Channel::::get_holder_selected_channel_reserve_satoshis(channel_value_satoshis) < Channel::::derive_holder_dust_limit_satoshis(background_feerate) { - return Err(APIError::FeeRateTooHigh{err: format!("Not enough reserve above dust limit can be found at current fee rate({})", background_feerate), feerate: background_feerate}); + let holder_selected_channel_reserve_satoshis = Channel::::get_holder_selected_channel_reserve_satoshis(channel_value_satoshis); + if holder_selected_channel_reserve_satoshis < MIN_DUST_LIMIT_SATOSHIS { + return Err(APIError::APIMisuseError { err: format!("Holder selected channel reserve below implemention limit dust_limit_satoshis {}", holder_selected_channel_reserve_satoshis) }); } let feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal); @@ -581,12 +602,12 @@ impl Channel { last_sent_closing_fee: None, funding_tx_confirmed_in: None, + funding_tx_confirmation_height: 0, short_channel_id: None, - funding_tx_confirmations: 0, feerate_per_kw: feerate, counterparty_dust_limit_satoshis: 0, - holder_dust_limit_satoshis: Channel::::derive_holder_dust_limit_satoshis(background_feerate), + holder_dust_limit_satoshis: MIN_DUST_LIMIT_SATOSHIS, counterparty_max_htlc_value_in_flight_msat: 0, counterparty_selected_channel_reserve_satoshis: 0, counterparty_htlc_minimum_msat: 0, @@ -613,12 +634,16 @@ impl Channel { commitment_secrets: CounterpartyCommitmentSecrets::new(), - network_sync: UpdateStatus::Fresh, + channel_update_status: ChannelUpdateStatus::Enabled, + + announcement_sigs: None, #[cfg(any(test, feature = "fuzztarget"))] next_local_commitment_tx_fee_info_cached: Mutex::new(None), #[cfg(any(test, feature = "fuzztarget"))] next_remote_commitment_tx_fee_info_cached: Mutex::new(None), + + workaround_lnd_bug_4006: None, }) } @@ -707,11 +732,11 @@ impl Channel { if msg.max_accepted_htlcs < config.peer_channel_config_limits.min_max_accepted_htlcs { return Err(ChannelError::Close(format!("max_accepted_htlcs ({}) is less than the user specified limit ({})", msg.max_accepted_htlcs, config.peer_channel_config_limits.min_max_accepted_htlcs))); } - if msg.dust_limit_satoshis < config.peer_channel_config_limits.min_dust_limit_satoshis { - return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is less than the user specified limit ({})", msg.dust_limit_satoshis, config.peer_channel_config_limits.min_dust_limit_satoshis))); + if msg.dust_limit_satoshis < MIN_DUST_LIMIT_SATOSHIS { + return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is less than the implementation limit ({})", msg.dust_limit_satoshis, MIN_DUST_LIMIT_SATOSHIS))); } - if msg.dust_limit_satoshis > config.peer_channel_config_limits.max_dust_limit_satoshis { - return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is greater than the user specified limit ({})", msg.dust_limit_satoshis, config.peer_channel_config_limits.max_dust_limit_satoshis))); + if msg.dust_limit_satoshis > MAX_DUST_LIMIT_SATOSHIS { + return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is greater than the implementation limit ({})", msg.dust_limit_satoshis, MAX_DUST_LIMIT_SATOSHIS))); } // Convert things into internal flags and prep our state: @@ -727,13 +752,12 @@ impl Channel { let background_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background); - let holder_dust_limit_satoshis = Channel::::derive_holder_dust_limit_satoshis(background_feerate); let holder_selected_channel_reserve_satoshis = Channel::::get_holder_selected_channel_reserve_satoshis(msg.funding_satoshis); - if holder_selected_channel_reserve_satoshis < holder_dust_limit_satoshis { - return Err(ChannelError::Close(format!("Suitable channel reserve not found. remote_channel_reserve was ({}). dust_limit_satoshis is ({}).", holder_selected_channel_reserve_satoshis, holder_dust_limit_satoshis))); + if holder_selected_channel_reserve_satoshis < MIN_DUST_LIMIT_SATOSHIS { + return Err(ChannelError::Close(format!("Suitable channel reserve not found. remote_channel_reserve was ({}). dust_limit_satoshis is ({}).", holder_selected_channel_reserve_satoshis, MIN_DUST_LIMIT_SATOSHIS))); } - if msg.channel_reserve_satoshis < holder_dust_limit_satoshis { - return Err(ChannelError::Close(format!("channel_reserve_satoshis ({}) is smaller than our dust limit ({})", msg.channel_reserve_satoshis, holder_dust_limit_satoshis))); + if msg.channel_reserve_satoshis < MIN_DUST_LIMIT_SATOSHIS { + return Err(ChannelError::Close(format!("channel_reserve_satoshis ({}) is smaller than our dust limit ({})", msg.channel_reserve_satoshis, MIN_DUST_LIMIT_SATOSHIS))); } if holder_selected_channel_reserve_satoshis < msg.dust_limit_satoshis { return Err(ChannelError::Close(format!("Dust limit ({}) too high for the channel reserve we require the remote to keep ({})", msg.dust_limit_satoshis, holder_selected_channel_reserve_satoshis))); @@ -819,13 +843,13 @@ impl Channel { last_sent_closing_fee: None, funding_tx_confirmed_in: None, + funding_tx_confirmation_height: 0, short_channel_id: None, - funding_tx_confirmations: 0, feerate_per_kw: msg.feerate_per_kw, channel_value_satoshis: msg.funding_satoshis, counterparty_dust_limit_satoshis: msg.dust_limit_satoshis, - holder_dust_limit_satoshis, + holder_dust_limit_satoshis: MIN_DUST_LIMIT_SATOSHIS, counterparty_max_htlc_value_in_flight_msat: cmp::min(msg.max_htlc_value_in_flight_msat, msg.funding_satoshis * 1000), counterparty_selected_channel_reserve_satoshis: msg.channel_reserve_satoshis, counterparty_htlc_minimum_msat: msg.htlc_minimum_msat, @@ -855,12 +879,16 @@ impl Channel { commitment_secrets: CounterpartyCommitmentSecrets::new(), - network_sync: UpdateStatus::Fresh, + channel_update_status: ChannelUpdateStatus::Enabled, + + announcement_sigs: None, #[cfg(any(test, feature = "fuzztarget"))] next_local_commitment_tx_fee_info_cached: Mutex::new(None), #[cfg(any(test, feature = "fuzztarget"))] next_remote_commitment_tx_fee_info_cached: Mutex::new(None), + + workaround_lnd_bug_4006: None, }; Ok(chan) @@ -894,7 +922,10 @@ impl Channel { let mut local_htlc_total_msat = 0; let mut value_to_self_msat_offset = 0; - log_trace!(logger, "Building commitment transaction number {} (really {} xor {}) for {}, generated by {} with fee {}...", commitment_number, (INITIAL_COMMITMENT_NUMBER - commitment_number), get_commitment_transaction_number_obscure_factor(&self.get_holder_pubkeys().payment_point, &self.get_counterparty_pubkeys().payment_point, self.is_outbound()), if local { "us" } else { "remote" }, if generated_by_local { "us" } else { "remote" }, feerate_per_kw); + log_trace!(logger, "Building commitment transaction number {} (really {} xor {}) for channel {} for {}, generated by {} with fee {}...", + commitment_number, (INITIAL_COMMITMENT_NUMBER - commitment_number), + get_commitment_transaction_number_obscure_factor(&self.get_holder_pubkeys().payment_point, &self.get_counterparty_pubkeys().payment_point, self.is_outbound()), + log_bytes!(self.channel_id), if local { "us" } else { "remote" }, if generated_by_local { "us" } else { "remote" }, feerate_per_kw); macro_rules! get_htlc_in_commitment { ($htlc: expr, $offered: expr) => { @@ -1214,7 +1245,7 @@ impl Channel { // on-chain ChannelsMonitors during block rescan. Ideally we'd figure out a way to drop // these, but for now we just have to treat them as normal. - let mut pending_idx = std::usize::MAX; + let mut pending_idx = core::usize::MAX; for (idx, htlc) in self.pending_inbound_htlcs.iter().enumerate() { if htlc.htlc_id == htlc_id_arg { assert_eq!(htlc.payment_hash, payment_hash_calc); @@ -1237,7 +1268,7 @@ impl Channel { break; } } - if pending_idx == std::usize::MAX { + if pending_idx == core::usize::MAX { return Err(ChannelError::Ignore("Unable to find a pending HTLC which matched the given HTLC ID".to_owned())); } @@ -1276,7 +1307,7 @@ impl Channel { _ => {} } } - log_trace!(logger, "Adding HTLC claim to holding_cell! Current state: {}", self.channel_state); + log_trace!(logger, "Adding HTLC claim to holding_cell in channel {}! Current state: {}", log_bytes!(self.channel_id()), self.channel_state); self.holding_cell_htlc_updates.push(HTLCUpdateAwaitingACK::ClaimHTLC { payment_preimage: payment_preimage_arg, htlc_id: htlc_id_arg, }); @@ -1290,7 +1321,7 @@ impl Channel { debug_assert!(false, "Have an inbound HTLC we tried to claim before it was fully committed to"); return Ok((None, Some(monitor_update))); } - log_trace!(logger, "Upgrading HTLC {} to LocalRemoved with a Fulfill!", log_bytes!(htlc.payment_hash.0)); + log_trace!(logger, "Upgrading HTLC {} to LocalRemoved with a Fulfill in channel {}!", log_bytes!(htlc.payment_hash.0), log_bytes!(self.channel_id)); htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::Fulfill(payment_preimage_arg.clone())); } @@ -1326,7 +1357,7 @@ impl Channel { /// /// 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> { + pub fn get_update_fail_htlc(&mut self, htlc_id_arg: u64, err_packet: msgs::OnionErrorPacket, logger: &L) -> Result, ChannelError> where L::Target: Logger { 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"); } @@ -1336,7 +1367,7 @@ impl Channel { // on-chain ChannelsMonitors during block rescan. Ideally we'd figure out a way to drop // these, but for now we just have to treat them as normal. - let mut pending_idx = std::usize::MAX; + let mut pending_idx = core::usize::MAX; for (idx, htlc) in self.pending_inbound_htlcs.iter().enumerate() { if htlc.htlc_id == htlc_id_arg { match htlc.state { @@ -1353,7 +1384,7 @@ impl Channel { pending_idx = idx; } } - if pending_idx == std::usize::MAX { + if pending_idx == core::usize::MAX { return Err(ChannelError::Ignore("Unable to find a pending HTLC which matched the given HTLC ID".to_owned())); } @@ -1376,6 +1407,7 @@ impl Channel { _ => {} } } + log_trace!(logger, "Placing failure for HTLC ID {} in holding cell in channel {}.", htlc_id_arg, log_bytes!(self.channel_id())); self.holding_cell_htlc_updates.push(HTLCUpdateAwaitingACK::FailHTLC { htlc_id: htlc_id_arg, err_packet, @@ -1383,6 +1415,7 @@ impl Channel { return Ok(None); } + log_trace!(logger, "Failing HTLC ID {} back with a update_fail_htlc message in channel {}.", htlc_id_arg, log_bytes!(self.channel_id())); { let htlc = &mut self.pending_inbound_htlcs[pending_idx]; htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailRelay(err_packet.clone())); @@ -1411,9 +1444,6 @@ impl Channel { if msg.channel_reserve_satoshis > self.channel_value_satoshis { return Err(ChannelError::Close(format!("Bogus channel_reserve_satoshis ({}). Must not be greater than ({})", msg.channel_reserve_satoshis, self.channel_value_satoshis))); } - if msg.dust_limit_satoshis > msg.channel_reserve_satoshis { - return Err(ChannelError::Close(format!("Bogus channel_reserve ({}) and dust_limit ({})", msg.channel_reserve_satoshis, msg.dust_limit_satoshis))); - } if msg.channel_reserve_satoshis < self.holder_dust_limit_satoshis { return Err(ChannelError::Close(format!("Peer never wants payout outputs? channel_reserve_satoshis was ({}). dust_limit is ({})", msg.channel_reserve_satoshis, self.holder_dust_limit_satoshis))); } @@ -1449,11 +1479,11 @@ impl Channel { if msg.max_accepted_htlcs < config.peer_channel_config_limits.min_max_accepted_htlcs { return Err(ChannelError::Close(format!("max_accepted_htlcs ({}) is less than the user specified limit ({})", msg.max_accepted_htlcs, config.peer_channel_config_limits.min_max_accepted_htlcs))); } - if msg.dust_limit_satoshis < config.peer_channel_config_limits.min_dust_limit_satoshis { - return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is less than the user specified limit ({})", msg.dust_limit_satoshis, config.peer_channel_config_limits.min_dust_limit_satoshis))); + if msg.dust_limit_satoshis < MIN_DUST_LIMIT_SATOSHIS { + return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is less than the implementation limit ({})", msg.dust_limit_satoshis, MIN_DUST_LIMIT_SATOSHIS))); } - if msg.dust_limit_satoshis > config.peer_channel_config_limits.max_dust_limit_satoshis { - return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is greater than the user specified limit ({})", msg.dust_limit_satoshis, config.peer_channel_config_limits.max_dust_limit_satoshis))); + if msg.dust_limit_satoshis > MAX_DUST_LIMIT_SATOSHIS { + return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is greater than the implementation limit ({})", msg.dust_limit_satoshis, MAX_DUST_LIMIT_SATOSHIS))); } if msg.minimum_depth > config.peer_channel_config_limits.max_minimum_depth { return Err(ChannelError::Close(format!("We consider the minimum depth to be unreasonably large. Expected minimum: ({}). Actual: ({})", config.peer_channel_config_limits.max_minimum_depth, msg.minimum_depth))); @@ -1517,7 +1547,10 @@ impl Channel { let initial_commitment_bitcoin_tx = trusted_tx.built_transaction(); let sighash = initial_commitment_bitcoin_tx.get_sighash_all(&funding_script, self.channel_value_satoshis); // They sign the holder commitment transaction... - log_trace!(logger, "Checking funding_created tx signature {} by key {} against tx {} (sighash {}) with redeemscript {}", log_bytes!(sig.serialize_compact()[..]), log_bytes!(self.counterparty_funding_pubkey().serialize()), encode::serialize_hex(&initial_commitment_bitcoin_tx.transaction), log_bytes!(sighash[..]), encode::serialize_hex(&funding_script)); + log_trace!(logger, "Checking funding_created tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} for channel {}.", + log_bytes!(sig.serialize_compact()[..]), log_bytes!(self.counterparty_funding_pubkey().serialize()), + encode::serialize_hex(&initial_commitment_bitcoin_tx.transaction), log_bytes!(sighash[..]), + encode::serialize_hex(&funding_script), log_bytes!(self.channel_id())); secp_check!(self.secp_ctx.verify(&sighash, &sig, self.counterparty_funding_pubkey()), "Invalid funding_created signature from peer".to_owned()); } @@ -1526,7 +1559,8 @@ impl Channel { let counterparty_trusted_tx = counterparty_initial_commitment_tx.trust(); let counterparty_initial_bitcoin_tx = counterparty_trusted_tx.built_transaction(); - log_trace!(logger, "Initial counterparty ID {} tx {}", counterparty_initial_bitcoin_tx.txid, encode::serialize_hex(&counterparty_initial_bitcoin_tx.transaction)); + log_trace!(logger, "Initial counterparty tx for channel {} is: txid {} tx {}", + log_bytes!(self.channel_id()), counterparty_initial_bitcoin_tx.txid, encode::serialize_hex(&counterparty_initial_bitcoin_tx.transaction)); let counterparty_signature = self.holder_signer.sign_counterparty_commitment(&counterparty_initial_commitment_tx, &self.secp_ctx) .map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed".to_owned()))?.0; @@ -1539,7 +1573,7 @@ impl Channel { &self.get_counterparty_pubkeys().funding_pubkey } - pub fn funding_created(&mut self, msg: &msgs::FundingCreated, last_block_hash: BlockHash, logger: &L) -> Result<(msgs::FundingSigned, ChannelMonitor), ChannelError> where L::Target: Logger { + pub fn funding_created(&mut self, msg: &msgs::FundingCreated, best_block: BestBlock, logger: &L) -> Result<(msgs::FundingSigned, ChannelMonitor), ChannelError> where L::Target: Logger { if self.is_outbound() { return Err(ChannelError::Close("Received funding_created for an outbound channel?".to_owned())); } @@ -1593,7 +1627,7 @@ impl Channel { &self.channel_transaction_parameters, funding_redeemscript.clone(), self.channel_value_satoshis, obscure_factor, - holder_commitment_tx, last_block_hash); + holder_commitment_tx, best_block); channel_monitor.provide_latest_counterparty_commitment_tx(counterparty_initial_commitment_txid, Vec::new(), self.cur_counterparty_commitment_transaction_number, self.counterparty_cur_commitment_point.unwrap(), logger); @@ -1602,6 +1636,8 @@ impl Channel { self.cur_counterparty_commitment_transaction_number -= 1; self.cur_holder_commitment_transaction_number -= 1; + log_info!(logger, "Generated funding_signed for peer for channel {}", log_bytes!(self.channel_id())); + Ok((msgs::FundingSigned { channel_id: self.channel_id, signature @@ -1610,7 +1646,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<(ChannelMonitor, Transaction), ChannelError> where L::Target: Logger { + pub fn funding_signed(&mut self, msg: &msgs::FundingSigned, best_block: BestBlock, 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())); } @@ -1630,7 +1666,8 @@ impl Channel { let counterparty_trusted_tx = counterparty_initial_commitment_tx.trust(); let counterparty_initial_bitcoin_tx = counterparty_trusted_tx.built_transaction(); - log_trace!(logger, "Initial counterparty ID {} tx {}", counterparty_initial_bitcoin_tx.txid, encode::serialize_hex(&counterparty_initial_bitcoin_tx.transaction)); + log_trace!(logger, "Initial counterparty tx for channel {} is: txid {} tx {}", + log_bytes!(self.channel_id()), counterparty_initial_bitcoin_tx.txid, encode::serialize_hex(&counterparty_initial_bitcoin_tx.transaction)); let holder_signer = self.build_holder_transaction_keys(self.cur_holder_commitment_transaction_number)?; let initial_commitment_tx = self.build_commitment_transaction(self.cur_holder_commitment_transaction_number, &holder_signer, true, false, self.feerate_per_kw, logger).0; @@ -1663,7 +1700,7 @@ impl Channel { &self.channel_transaction_parameters, funding_redeemscript.clone(), self.channel_value_satoshis, obscure_factor, - holder_commitment_tx, last_block_hash); + holder_commitment_tx, best_block); channel_monitor.provide_latest_counterparty_commitment_tx(counterparty_initial_bitcoin_tx.txid, Vec::new(), self.cur_counterparty_commitment_transaction_number, self.counterparty_cur_commitment_point.unwrap(), logger); @@ -1672,12 +1709,15 @@ impl Channel { self.cur_holder_commitment_transaction_number -= 1; self.cur_counterparty_commitment_transaction_number -= 1; + log_info!(logger, "Received funding_signed from peer for channel {}", log_bytes!(self.channel_id())); + Ok((channel_monitor, self.funding_transaction.as_ref().cloned().unwrap())) } - pub fn funding_locked(&mut self, msg: &msgs::FundingLocked) -> Result<(), ChannelError> { + pub fn funding_locked(&mut self, msg: &msgs::FundingLocked, logger: &L) -> Result<(), ChannelError> where L::Target: Logger { if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { - return Err(ChannelError::Close("Peer sent funding_locked when we needed a channel_reestablish".to_owned())); + self.workaround_lnd_bug_4006 = Some(msg.clone()); + return Err(ChannelError::Ignore("Peer sent funding_locked when we needed a channel_reestablish. The peer is likely lnd, see https://github.com/lightningnetwork/lnd/issues/4006".to_owned())); } let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS); @@ -1705,6 +1745,9 @@ impl Channel { self.counterparty_prev_commitment_point = self.counterparty_cur_commitment_point; self.counterparty_cur_commitment_point = Some(msg.next_per_commitment_point); + + log_info!(logger, "Received funding_locked from peer for channel {}", log_bytes!(self.channel_id())); + Ok(()) } @@ -2014,7 +2057,7 @@ impl Channel { if pending_remote_value_msat - msg.amount_msat - chan_reserve_msat < remote_fee_cost_incl_stuck_buffer_msat { // Note that if the pending_forward_status is not updated here, then it's because we're already failing // the HTLC, i.e. its status is already set to failing. - log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation"); + log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation in channel {}. Rebalancing is required.", log_bytes!(self.channel_id())); pending_forward_status = create_pending_htlc_status(self, pending_forward_status, 0x1000|7); } } else { @@ -2146,7 +2189,10 @@ impl Channel { let bitcoin_tx = trusted_tx.built_transaction(); let sighash = bitcoin_tx.get_sighash_all(&funding_script, self.channel_value_satoshis); - log_trace!(logger, "Checking commitment tx signature {} by key {} against tx {} (sighash {}) with redeemscript {}", log_bytes!(msg.signature.serialize_compact()[..]), log_bytes!(self.counterparty_funding_pubkey().serialize()), encode::serialize_hex(&bitcoin_tx.transaction), log_bytes!(sighash[..]), encode::serialize_hex(&funding_script)); + log_trace!(logger, "Checking commitment tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} in channel {}", + log_bytes!(msg.signature.serialize_compact()[..]), + log_bytes!(self.counterparty_funding_pubkey().serialize()), encode::serialize_hex(&bitcoin_tx.transaction), + log_bytes!(sighash[..]), encode::serialize_hex(&funding_script), log_bytes!(self.channel_id())); if let Err(_) = self.secp_ctx.verify(&sighash, &msg.signature, &self.counterparty_funding_pubkey()) { return Err((None, ChannelError::Close("Invalid commitment tx signature from peer".to_owned()))); } @@ -2193,7 +2239,9 @@ impl Channel { let htlc_tx = self.build_htlc_transaction(&commitment_txid, &htlc, true, &keys, feerate_per_kw); let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &keys); let htlc_sighash = hash_to_message!(&bip143::SigHashCache::new(&htlc_tx).signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, SigHashType::All)[..]); - log_trace!(logger, "Checking HTLC tx signature {} by key {} against tx {} (sighash {}) with redeemscript {}", log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(keys.countersignatory_htlc_key.serialize()), encode::serialize_hex(&htlc_tx), log_bytes!(htlc_sighash[..]), encode::serialize_hex(&htlc_redeemscript)); + log_trace!(logger, "Checking HTLC tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} in channel {}.", + log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(keys.countersignatory_htlc_key.serialize()), + encode::serialize_hex(&htlc_tx), log_bytes!(htlc_sighash[..]), encode::serialize_hex(&htlc_redeemscript), log_bytes!(self.channel_id())); if let Err(_) = self.secp_ctx.verify(&htlc_sighash, &msg.htlc_signatures[idx], &keys.countersignatory_htlc_key) { return Err((None, ChannelError::Close("Invalid HTLC tx signature from peer".to_owned()))); } @@ -2243,6 +2291,8 @@ impl Channel { Some(forward_info.clone()) } else { None }; if let Some(forward_info) = new_forward { + log_trace!(logger, "Updating HTLC {} to AwaitingRemoteRevokeToAnnounce due to commitment_signed in channel {}.", + log_bytes!(htlc.payment_hash.0), log_bytes!(self.channel_id)); htlc.state = InboundHTLCState::AwaitingRemoteRevokeToAnnounce(forward_info); need_commitment = true; } @@ -2251,6 +2301,8 @@ impl Channel { if let Some(fail_reason) = if let &mut OutboundHTLCState::RemoteRemoved(ref mut fail_reason) = &mut htlc.state { Some(fail_reason.take()) } else { None } { + log_trace!(logger, "Updating HTLC {} to AwaitingRemoteRevokeToRemove due to commitment_signed in channel {}.", + log_bytes!(htlc.payment_hash.0), log_bytes!(self.channel_id)); htlc.state = OutboundHTLCState::AwaitingRemoteRevokeToRemove(fail_reason); need_commitment = true; } @@ -2276,6 +2328,8 @@ impl Channel { self.latest_monitor_update_id = monitor_update.update_id; monitor_update.updates.append(&mut additional_update.updates); } + log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updated HTLC state but awaiting a monitor update resolution to reply.", + log_bytes!(self.channel_id)); // TODO: Call maybe_propose_first_closing_signed on restoration (or call it here and // re-send the message on restoration) return Err((Some(monitor_update), ChannelError::Ignore("Previous monitor update failure prevented generation of RAA".to_owned()))); @@ -2295,6 +2349,9 @@ impl Channel { (None, self.maybe_propose_first_closing_signed(fee_estimator)) } else { (None, None) }; + log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updating HTLC state and responding with{} a revoke_and_ack.", + log_bytes!(self.channel_id()), if commitment_signed.is_some() { " our own commitment_signed and" } else { "" }); + Ok((msgs::RevokeAndACK { channel_id: self.channel_id, per_commitment_secret, @@ -2302,12 +2359,23 @@ impl Channel { }, commitment_signed, closing_signed, monitor_update)) } + /// Public version of the below, checking relevant preconditions first. + /// If we're not in a state where freeing the holding cell makes sense, this is a no-op and + /// returns `(None, Vec::new())`. + pub fn maybe_free_holding_cell_htlcs(&mut self, logger: &L) -> Result<(Option<(msgs::CommitmentUpdate, ChannelMonitorUpdate)>, Vec<(HTLCSource, PaymentHash)>), ChannelError> where L::Target: Logger { + if self.channel_state >= ChannelState::ChannelFunded as u32 && + (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32 | ChannelState::PeerDisconnected as u32 | ChannelState::MonitorUpdateFailed as u32)) == 0 { + self.free_holding_cell_htlcs(logger) + } else { Ok((None, Vec::new())) } + } + /// Used to fulfill holding_cell_htlcs when we get a remote ack (or implicitly get it by them /// fulfilling or failing the last pending HTLC) fn free_holding_cell_htlcs(&mut self, logger: &L) -> Result<(Option<(msgs::CommitmentUpdate, ChannelMonitorUpdate)>, Vec<(HTLCSource, PaymentHash)>), ChannelError> where L::Target: Logger { assert_eq!(self.channel_state & ChannelState::MonitorUpdateFailed as u32, 0); if self.holding_cell_htlc_updates.len() != 0 || self.holding_cell_update_fee.is_some() { - log_trace!(logger, "Freeing holding cell with {} HTLC updates{}", self.holding_cell_htlc_updates.len(), if self.holding_cell_update_fee.is_some() { " and a fee update" } else { "" }); + log_trace!(logger, "Freeing holding cell with {} HTLC updates{} in channel {}", self.holding_cell_htlc_updates.len(), + if self.holding_cell_update_fee.is_some() { " and a fee update" } else { "" }, log_bytes!(self.channel_id())); let mut monitor_update = ChannelMonitorUpdate { update_id: self.latest_monitor_update_id + 1, // We don't increment this yet! @@ -2333,7 +2401,8 @@ impl Channel { Err(e) => { match e { ChannelError::Ignore(ref msg) => { - log_info!(logger, "Failed to send HTLC with payment_hash {} due to {}", log_bytes!(payment_hash.0), msg); + log_info!(logger, "Failed to send HTLC with payment_hash {} due to {} in channel {}", + log_bytes!(payment_hash.0), msg, log_bytes!(self.channel_id())); // If we fail to send here, then this HTLC should // be failed backwards. Failing to send here // indicates that this HTLC may keep being put back @@ -2366,7 +2435,7 @@ impl Channel { } }, &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, ref err_packet } => { - match self.get_update_fail_htlc(htlc_id, err_packet.clone()) { + match self.get_update_fail_htlc(htlc_id, err_packet.clone(), logger) { Ok(update_fail_msg_option) => update_fail_htlcs.push(update_fail_msg_option.unwrap()), Err(e) => { if let ChannelError::Ignore(_) = e {} @@ -2397,6 +2466,10 @@ impl Channel { self.latest_monitor_update_id = monitor_update.update_id; monitor_update.updates.append(&mut additional_update.updates); + log_debug!(logger, "Freeing holding cell in channel {} resulted in {}{} HTLCs added, {} HTLCs fulfilled, and {} HTLCs failed.", + log_bytes!(self.channel_id()), if update_fee.is_some() { "a fee update, " } else { "" }, + update_add_htlcs.len(), update_fulfill_htlcs.len(), update_fail_htlcs.len()); + Ok((Some((msgs::CommitmentUpdate { update_add_htlcs, update_fulfill_htlcs, @@ -2472,7 +2545,7 @@ impl Channel { self.counterparty_cur_commitment_point = Some(msg.next_per_commitment_point); self.cur_counterparty_commitment_transaction_number -= 1; - log_trace!(logger, "Updating HTLCs on receipt of RAA..."); + log_trace!(logger, "Updating HTLCs on receipt of RAA in channel {}...", log_bytes!(self.channel_id())); let mut to_forward_infos = Vec::new(); let mut revoked_htlcs = Vec::new(); let mut update_fail_htlcs = Vec::new(); @@ -2509,10 +2582,8 @@ impl Channel { }); for htlc in pending_inbound_htlcs.iter_mut() { let swap = if let &InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_) = &htlc.state { - log_trace!(logger, " ...promoting inbound AwaitingRemoteRevokeToAnnounce {} to Committed", log_bytes!(htlc.payment_hash.0)); true } else if let &InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) = &htlc.state { - log_trace!(logger, " ...promoting inbound AwaitingAnnouncedRemoteRevoke {} to Committed", log_bytes!(htlc.payment_hash.0)); true } else { false }; if swap { @@ -2520,11 +2591,13 @@ impl Channel { mem::swap(&mut state, &mut htlc.state); if let InboundHTLCState::AwaitingRemoteRevokeToAnnounce(forward_info) = state { + log_trace!(logger, " ...promoting inbound AwaitingRemoteRevokeToAnnounce {} to AwaitingAnnouncedRemoteRevoke", log_bytes!(htlc.payment_hash.0)); htlc.state = InboundHTLCState::AwaitingAnnouncedRemoteRevoke(forward_info); require_commitment = true; } else if let InboundHTLCState::AwaitingAnnouncedRemoteRevoke(forward_info) = state { match forward_info { PendingHTLCStatus::Fail(fail_msg) => { + log_trace!(logger, " ...promoting inbound AwaitingAnnouncedRemoteRevoke {} to LocalRemoved due to PendingHTLCStatus indicating failure", log_bytes!(htlc.payment_hash.0)); require_commitment = true; match fail_msg { HTLCFailureMsg::Relay(msg) => { @@ -2538,6 +2611,7 @@ impl Channel { } }, PendingHTLCStatus::Forward(forward_info) => { + log_trace!(logger, " ...promoting inbound AwaitingAnnouncedRemoteRevoke {} to Committed", log_bytes!(htlc.payment_hash.0)); to_forward_infos.push((forward_info, htlc.htlc_id)); htlc.state = InboundHTLCState::Committed; } @@ -2595,6 +2669,7 @@ impl Channel { } self.monitor_pending_forwards.append(&mut to_forward_infos); self.monitor_pending_failures.append(&mut revoked_htlcs); + log_debug!(logger, "Received a valid revoke_and_ack for channel {} but awaiting a monitor update resolution to reply.", log_bytes!(self.channel_id())); return Ok((None, Vec::new(), Vec::new(), None, monitor_update, Vec::new())) } @@ -2625,6 +2700,8 @@ impl Channel { self.latest_monitor_update_id = monitor_update.update_id; monitor_update.updates.append(&mut additional_update.updates); + log_debug!(logger, "Received a valid revoke_and_ack for channel {}. Responding with a commitment update with {} HTLCs failed.", + log_bytes!(self.channel_id()), update_fail_htlcs.len() + update_fail_malformed_htlcs.len()); Ok((Some(msgs::CommitmentUpdate { update_add_htlcs: Vec::new(), update_fulfill_htlcs: Vec::new(), @@ -2634,6 +2711,7 @@ impl Channel { commitment_signed }), to_forward_infos, revoked_htlcs, None, monitor_update, htlcs_to_fail)) } else { + log_debug!(logger, "Received a valid revoke_and_ack for channel {} with no reply necessary.", log_bytes!(self.channel_id())); Ok((None, to_forward_infos, revoked_htlcs, self.maybe_propose_first_closing_signed(fee_estimator), monitor_update, htlcs_to_fail)) } } @@ -2679,19 +2757,16 @@ impl Channel { } } - /// Removes any uncommitted HTLCs, to be used on peer disconnection, including any pending - /// HTLCs that we intended to add but haven't as we were waiting on a remote revoke. - /// Returns the set of PendingHTLCStatuses from remote uncommitted HTLCs (which we're - /// implicitly dropping) and the payment_hashes of HTLCs we tried to add but are dropping. + /// Removes any uncommitted inbound HTLCs and resets the state of uncommitted outbound HTLC + /// updates, to be used on peer disconnection. After this, update_*_htlc messages need to be + /// resent. /// No further message handling calls may be made until a channel_reestablish dance has /// completed. - pub fn remove_uncommitted_htlcs_and_mark_paused(&mut self, logger: &L) -> Vec<(HTLCSource, PaymentHash)> where L::Target: Logger { - let mut outbound_drops = Vec::new(); - + pub fn remove_uncommitted_htlcs_and_mark_paused(&mut self, logger: &L) where L::Target: Logger { assert_eq!(self.channel_state & ChannelState::ShutdownComplete as u32, 0); if self.channel_state < ChannelState::FundingSent as u32 { self.channel_state = ChannelState::ShutdownComplete as u32; - return outbound_drops; + return; } // Upon reconnect we have to start the closing_signed dance over, but shutdown messages // will be retransmitted. @@ -2734,23 +2809,8 @@ impl Channel { } } - self.holding_cell_htlc_updates.retain(|htlc_update| { - match htlc_update { - // Note that currently on channel reestablish we assert that there are - // no holding cell HTLC update_adds, so if in the future we stop - // dropping added HTLCs here and failing them backwards, then there will - // need to be corresponding changes made in the Channel's re-establish - // logic. - &HTLCUpdateAwaitingACK::AddHTLC { ref payment_hash, ref source, .. } => { - outbound_drops.push((source.clone(), payment_hash.clone())); - false - }, - &HTLCUpdateAwaitingACK::ClaimHTLC {..} | &HTLCUpdateAwaitingACK::FailHTLC {..} => true, - } - }); self.channel_state |= ChannelState::PeerDisconnected as u32; - log_debug!(logger, "Peer disconnection resulted in {} remote-announced HTLC drops and {} waiting-to-locally-announced HTLC drops on channel {}", outbound_drops.len(), inbound_drop_count, log_bytes!(self.channel_id())); - outbound_drops + log_trace!(logger, "Peer disconnection resulted in {} remote-announced HTLC drops on channel {}", inbound_drop_count, log_bytes!(self.channel_id())); } /// Indicates that a ChannelMonitor update failed to be stored by the client and further @@ -2817,10 +2877,9 @@ impl Channel { self.monitor_pending_revoke_and_ack = false; 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 funding_broadcastable.is_some() { "a funding broadcastable, " } else { "" }, - if commitment_update.is_some() { "a" } else { "no" }, - if raa.is_some() { "an" } else { "no" }, + log_debug!(logger, "Restored monitor updating in channel {} resulting in {}{} commitment update and {} RAA, with {} first", + log_bytes!(self.channel_id()), 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, funding_broadcastable, funding_locked) } @@ -2898,8 +2957,8 @@ impl Channel { } } - log_trace!(logger, "Regenerated latest commitment update with {} update_adds, {} update_fulfills, {} update_fails, and {} update_fail_malformeds", - update_add_htlcs.len(), update_fulfill_htlcs.len(), update_fail_htlcs.len(), update_fail_malformed_htlcs.len()); + log_trace!(logger, "Regenerated latest commitment update in channel {} with {} update_adds, {} update_fulfills, {} update_fails, and {} update_fail_malformeds", + log_bytes!(self.channel_id()), update_add_htlcs.len(), update_fulfill_htlcs.len(), update_fail_htlcs.len(), update_fail_malformed_htlcs.len()); msgs::CommitmentUpdate { update_add_htlcs, update_fulfill_htlcs, update_fail_htlcs, update_fail_malformed_htlcs, update_fee: None, @@ -2909,7 +2968,7 @@ impl Channel { /// May panic if some calls other than message-handling calls (which will all Err immediately) /// have been called between remove_uncommitted_htlcs_and_mark_paused and this call. - pub fn channel_reestablish(&mut self, msg: &msgs::ChannelReestablish, logger: &L) -> Result<(Option, Option, Option, Option, RAACommitmentOrder, Option), ChannelError> where L::Target: Logger { + pub fn channel_reestablish(&mut self, msg: &msgs::ChannelReestablish, logger: &L) -> Result<(Option, Option, Option, Option, RAACommitmentOrder, Vec<(HTLCSource, PaymentHash)>, Option), ChannelError> where L::Target: Logger { if self.channel_state & (ChannelState::PeerDisconnected as u32) == 0 { // While BOLT 2 doesn't indicate explicitly we should error this channel here, it // almost certainly indicates we are going to end up out-of-sync in some way, so we @@ -2960,7 +3019,7 @@ impl Channel { return Err(ChannelError::Close("Peer claimed they saw a revoke_and_ack but we haven't sent funding_locked yet".to_owned())); } // Short circuit the whole handler as there is nothing we can resend them - return Ok((None, None, None, None, RAACommitmentOrder::CommitmentFirst, shutdown_msg)); + return Ok((None, None, None, None, RAACommitmentOrder::CommitmentFirst, Vec::new(), shutdown_msg)); } // We have OurFundingLocked set! @@ -2968,7 +3027,7 @@ impl Channel { return Ok((Some(msgs::FundingLocked { channel_id: self.channel_id(), next_per_commitment_point, - }), None, None, None, RAACommitmentOrder::CommitmentFirst, shutdown_msg)); + }), None, None, None, RAACommitmentOrder::CommitmentFirst, Vec::new(), shutdown_msg)); } let required_revoke = if msg.next_remote_commitment_number + 1 == INITIAL_COMMITMENT_NUMBER - self.cur_holder_commitment_transaction_number { @@ -3009,14 +3068,6 @@ impl Channel { } if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32 | ChannelState::MonitorUpdateFailed as u32)) == 0 { - // Note that if in the future we no longer drop holding cell update_adds on peer - // disconnect, this logic will need to be updated. - for htlc_update in self.holding_cell_htlc_updates.iter() { - if let &HTLCUpdateAwaitingACK::AddHTLC { .. } = htlc_update { - debug_assert!(false, "There shouldn't be any add-HTLCs in the holding cell now because they should have been dropped on peer disconnect. Panic here because said HTLCs won't be handled correctly."); - } - } - // We're up-to-date and not waiting on a remote revoke (if we are our // channel_reestablish should result in them sending a revoke_and_ack), but we may // have received some updates while we were disconnected. Free the holding cell @@ -3025,20 +3076,14 @@ impl Channel { Err(ChannelError::Close(msg)) => return Err(ChannelError::Close(msg)), Err(ChannelError::Ignore(_)) | Err(ChannelError::CloseDelayBroadcast(_)) => panic!("Got non-channel-failing result from free_holding_cell_htlcs"), Ok((Some((commitment_update, monitor_update)), htlcs_to_fail)) => { - // If in the future we no longer drop holding cell update_adds on peer - // disconnect, we may be handed some HTLCs to fail backwards here. - assert!(htlcs_to_fail.is_empty()); - return Ok((resend_funding_locked, required_revoke, Some(commitment_update), Some(monitor_update), self.resend_order.clone(), shutdown_msg)); + return Ok((resend_funding_locked, required_revoke, Some(commitment_update), Some(monitor_update), self.resend_order.clone(), htlcs_to_fail, shutdown_msg)); }, Ok((None, htlcs_to_fail)) => { - // If in the future we no longer drop holding cell update_adds on peer - // disconnect, we may be handed some HTLCs to fail backwards here. - assert!(htlcs_to_fail.is_empty()); - return Ok((resend_funding_locked, required_revoke, None, None, self.resend_order.clone(), shutdown_msg)); + return Ok((resend_funding_locked, required_revoke, None, None, self.resend_order.clone(), htlcs_to_fail, shutdown_msg)); }, } } else { - return Ok((resend_funding_locked, required_revoke, None, None, self.resend_order.clone(), shutdown_msg)); + return Ok((resend_funding_locked, required_revoke, None, None, self.resend_order.clone(), Vec::new(), shutdown_msg)); } } else if msg.next_local_commitment_number == next_counterparty_commitment_number - 1 { if required_revoke.is_some() { @@ -3049,10 +3094,10 @@ impl Channel { if self.channel_state & (ChannelState::MonitorUpdateFailed as u32) != 0 { self.monitor_pending_commitment_signed = true; - return Ok((resend_funding_locked, None, None, None, self.resend_order.clone(), shutdown_msg)); + return Ok((resend_funding_locked, None, None, None, self.resend_order.clone(), Vec::new(), shutdown_msg)); } - return Ok((resend_funding_locked, required_revoke, Some(self.get_last_commitment_update(logger)), None, self.resend_order.clone(), shutdown_msg)); + return Ok((resend_funding_locked, required_revoke, Some(self.get_last_commitment_update(logger)), None, self.resend_order.clone(), Vec::new(), shutdown_msg)); } else { return Err(ChannelError::Close("Peer attempted to reestablish channel with a very old remote commitment transaction".to_owned())); } @@ -3468,7 +3513,7 @@ impl Channel { /// is_usable() and considers things like the channel being temporarily disabled. /// Allowed in any state (including after shutdown) pub fn is_live(&self) -> bool { - self.is_usable() && (self.channel_state & (ChannelState::PeerDisconnected as u32 | ChannelState::MonitorUpdateFailed as u32) == 0) + self.is_usable() && (self.channel_state & (ChannelState::PeerDisconnected as u32) == 0) } /// Returns true if this channel has been marked as awaiting a monitor update to move forward. @@ -3492,46 +3537,149 @@ impl Channel { } else { false } } - pub fn to_disabled_staged(&mut self) { - self.network_sync = UpdateStatus::DisabledStaged; + pub fn channel_update_status(&self) -> ChannelUpdateStatus { + self.channel_update_status } - pub fn to_disabled_marked(&mut self) { - self.network_sync = UpdateStatus::DisabledMarked; + pub fn set_channel_update_status(&mut self, status: ChannelUpdateStatus) { + self.channel_update_status = status; } - pub fn to_fresh(&mut self) { - self.network_sync = UpdateStatus::Fresh; - } + fn check_get_funding_locked(&mut self, height: u32) -> Option { + if self.funding_tx_confirmation_height == 0 { + return None; + } - pub fn is_disabled_staged(&self) -> bool { - self.network_sync == UpdateStatus::DisabledStaged + let funding_tx_confirmations = height as i64 - self.funding_tx_confirmation_height as i64 + 1; + if funding_tx_confirmations <= 0 { + self.funding_tx_confirmation_height = 0; + } + + if funding_tx_confirmations < self.minimum_depth as i64 { + return None; + } + + let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS); + let need_commitment_update = if non_shutdown_state == ChannelState::FundingSent as u32 { + self.channel_state |= ChannelState::OurFundingLocked as u32; + 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.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 ignore. + false + } else if self.channel_state < ChannelState::ChannelFunded as u32 { + panic!("Started confirming a channel in a state pre-FundingSent?: {}", self.channel_state); + } else { + // We got a reorg but not enough to trigger a force close, just ignore. + false + }; + + if need_commitment_update { + if self.channel_state & (ChannelState::MonitorUpdateFailed as u32) == 0 { + let next_per_commitment_point = self.holder_signer.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx); + return Some(msgs::FundingLocked { + channel_id: self.channel_id, + next_per_commitment_point, + }); + } else { + self.monitor_pending_funding_locked = true; + } + } + None } - pub fn is_disabled_marked(&self) -> bool { - self.network_sync == UpdateStatus::DisabledMarked + /// When a transaction is confirmed, we check whether it is or spends the funding transaction + /// In the first case, we store the confirmation height and calculating the short channel id. + /// In the second, we simply return an Err indicating we need to be force-closed now. + pub fn transactions_confirmed(&mut self, block_hash: &BlockHash, height: u32, txdata: &TransactionData, logger: &L) + -> Result, msgs::ErrorMessage> where L::Target: Logger { + let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS); + for &(index_in_block, tx) in txdata.iter() { + if let Some(funding_txo) = self.get_funding_txo() { + // If we haven't yet sent a funding_locked, but are in FundingSent (ignoring + // whether they've sent a funding_locked or not), check if we should send one. + if non_shutdown_state & !(ChannelState::TheirFundingLocked as u32) == ChannelState::FundingSent as u32 { + if tx.txid() == funding_txo.txid { + let txo_idx = funding_txo.index as usize; + if txo_idx >= tx.output.len() || tx.output[txo_idx].script_pubkey != self.get_funding_redeemscript().to_v0_p2wsh() || + tx.output[txo_idx].value != self.channel_value_satoshis { + if self.is_outbound() { + // If we generated the funding transaction and it doesn't match what it + // should, the client is really broken and we should just panic and + // tell them off. That said, because hash collisions happen with high + // probability in fuzztarget mode, if we're fuzzing we just close the + // channel and move on. + #[cfg(not(feature = "fuzztarget"))] + panic!("Client called ChannelManager::funding_transaction_generated with bogus transaction!"); + } + self.update_time_counter += 1; + return Err(msgs::ErrorMessage { + channel_id: self.channel_id(), + data: "funding tx had wrong script/value or output index".to_owned() + }); + } else { + if self.is_outbound() { + for input in tx.input.iter() { + if input.witness.is_empty() { + // We generated a malleable funding transaction, implying we've + // just exposed ourselves to funds loss to our counterparty. + #[cfg(not(feature = "fuzztarget"))] + panic!("Client called ChannelManager::funding_transaction_generated with bogus transaction!"); + } + } + } + self.funding_tx_confirmation_height = height; + self.funding_tx_confirmed_in = Some(*block_hash); + self.short_channel_id = match scid_from_parts(height as u64, index_in_block as u64, txo_idx as u64) { + Ok(scid) => Some(scid), + Err(_) => panic!("Block was bogus - either height was > 16 million, had > 16 million transactions, or had > 65k outputs"), + } + } + } + // If we allow 1-conf funding, we may need to check for funding_locked here and + // send it immediately instead of waiting for a best_block_updated call (which + // may have already happened for this block). + if let Some(funding_locked) = self.check_get_funding_locked(height) { + log_info!(logger, "Sending a funding_locked to our peer for channel {}", log_bytes!(self.channel_id)); + return Ok(Some(funding_locked)); + } + } + for inp in tx.input.iter() { + if inp.previous_output == funding_txo.into_bitcoin_outpoint() { + log_info!(logger, "Detected channel-closing tx {} spending {}:{}, closing channel {}", tx.txid(), inp.previous_output.txid, inp.previous_output.vout, log_bytes!(self.channel_id())); + return Err(msgs::ErrorMessage { + channel_id: self.channel_id(), + data: "Commitment or closing transaction was confirmed on chain.".to_owned() + }); + } + } + } + } + Ok(None) } - /// When we receive a new block, we (a) check whether the block contains the funding - /// transaction (which would start us counting blocks until we send the funding_signed), and - /// (b) check the height of the block against outbound holding cell HTLCs in case we need to - /// give up on them prematurely and time them out. Everything else (e.g. commitment - /// transaction broadcasts, channel closure detection, HTLC transaction broadcasting, etc) is + /// When a new block is connected, we check the height of the block against outbound holding + /// cell HTLCs in case we need to give up on them prematurely and time them out. Everything + /// else (e.g. commitment transaction broadcasts, HTLC transaction broadcasting, etc) is /// handled by the ChannelMonitor. /// /// If we return Err, the channel may have been closed, at which point the standard /// requirements apply - no calls may be made except those explicitly stated to be allowed /// post-shutdown. - /// Only returns an ErrorAction of DisconnectPeer, if Err. /// /// May return some HTLCs (and their payment_hash) which have timed out and should be failed /// back. - pub fn block_connected(&mut self, header: &BlockHeader, txdata: &TransactionData, height: u32) -> Result<(Option, Vec<(HTLCSource, PaymentHash)>), msgs::ErrorMessage> { + pub fn best_block_updated(&mut self, height: u32, highest_header_time: u32, logger: &L) + -> Result<(Option, Vec<(HTLCSource, PaymentHash)>), msgs::ErrorMessage> where L::Target: Logger { let mut timed_out_htlcs = Vec::new(); + let unforwarded_htlc_cltv_limit = height + HTLC_FAIL_BACK_BUFFER; self.holding_cell_htlc_updates.retain(|htlc_update| { match htlc_update { &HTLCUpdateAwaitingACK::AddHTLC { ref payment_hash, ref source, ref cltv_expiry, .. } => { - if *cltv_expiry <= height + HTLC_FAIL_BACK_BUFFER { + if *cltv_expiry <= unforwarded_htlc_cltv_limit { timed_out_htlcs.push((source.clone(), payment_hash.clone())); false } else { true } @@ -3540,112 +3688,63 @@ impl Channel { } }); - if self.funding_tx_confirmations > 0 { - self.funding_tx_confirmations += 1; + self.update_time_counter = cmp::max(self.update_time_counter, highest_header_time); + + if let Some(funding_locked) = self.check_get_funding_locked(height) { + log_info!(logger, "Sending a funding_locked to our peer for channel {}", log_bytes!(self.channel_id)); + return Ok((Some(funding_locked), timed_out_htlcs)); } let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS); - if non_shutdown_state & !(ChannelState::TheirFundingLocked as u32) == ChannelState::FundingSent as u32 { - for &(index_in_block, tx) in txdata.iter() { - let funding_txo = self.get_funding_txo().unwrap(); - if tx.txid() == funding_txo.txid { - let txo_idx = funding_txo.index as usize; - if txo_idx >= tx.output.len() || tx.output[txo_idx].script_pubkey != self.get_funding_redeemscript().to_v0_p2wsh() || - tx.output[txo_idx].value != self.channel_value_satoshis { - if self.is_outbound() { - // If we generated the funding transaction and it doesn't match what it - // should, the client is really broken and we should just panic and - // tell them off. That said, because hash collisions happen with high - // probability in fuzztarget mode, if we're fuzzing we just close the - // channel and move on. - #[cfg(not(feature = "fuzztarget"))] - panic!("Client called ChannelManager::funding_transaction_generated with bogus transaction!"); - } - self.channel_state = ChannelState::ShutdownComplete as u32; - self.update_time_counter += 1; - return Err(msgs::ErrorMessage { - channel_id: self.channel_id(), - data: "funding tx had wrong script/value".to_owned() - }); - } else { - if self.is_outbound() { - for input in tx.input.iter() { - if input.witness.is_empty() { - // We generated a malleable funding transaction, implying we've - // just exposed ourselves to funds loss to our counterparty. - #[cfg(not(feature = "fuzztarget"))] - panic!("Client called ChannelManager::funding_transaction_generated with bogus transaction!"); - } - } - } - self.funding_tx_confirmations = 1; - self.short_channel_id = match scid_from_parts(height as u64, index_in_block as u64, txo_idx as u64) { - Ok(scid) => Some(scid), - Err(_) => panic!("Block was bogus - either height was > 16 million, had > 16 million transactions, or had > 65k outputs"), - } - } - } + if non_shutdown_state >= ChannelState::ChannelFunded as u32 || + (non_shutdown_state & ChannelState::OurFundingLocked as u32) == ChannelState::OurFundingLocked as u32 { + let mut funding_tx_confirmations = height as i64 - self.funding_tx_confirmation_height as i64 + 1; + if self.funding_tx_confirmation_height == 0 { + // Note that check_get_funding_locked may reset funding_tx_confirmation_height to + // zero if it has been reorged out, however in either case, our state flags + // indicate we've already sent a funding_locked + funding_tx_confirmations = 0; } - } - self.update_time_counter = cmp::max(self.update_time_counter, header.time); - if self.funding_tx_confirmations > 0 { - if self.funding_tx_confirmations == self.minimum_depth as u64 { - let need_commitment_update = if non_shutdown_state == ChannelState::FundingSent as u32 { - self.channel_state |= ChannelState::OurFundingLocked as u32; - 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.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 - // funding_tx_confirmed_in and return. - false - } else if self.channel_state < ChannelState::ChannelFunded as u32 { - panic!("Started confirming a channel in a state pre-FundingSent?: {}", self.channel_state); - } else { - // We got a reorg but not enough to trigger a force close, just update - // funding_tx_confirmed_in and return. - false - }; - self.funding_tx_confirmed_in = Some(header.block_hash()); - - //TODO: Note that this must be a duplicate of the previous commitment point they sent us, - //as otherwise we will have a commitment transaction that they can't revoke (well, kinda, - //they can by sending two revoke_and_acks back-to-back, but not really). This appears to be - //a protocol oversight, but I assume I'm just missing something. - if need_commitment_update { - if self.channel_state & (ChannelState::MonitorUpdateFailed as u32) == 0 { - let next_per_commitment_point = self.holder_signer.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx); - return Ok((Some(msgs::FundingLocked { - channel_id: self.channel_id, - next_per_commitment_point, - }), timed_out_htlcs)); - } else { - self.monitor_pending_funding_locked = true; - return Ok((None, timed_out_htlcs)); - } - } + // If we've sent funding_locked (or have both sent and received funding_locked), and + // the funding transaction's confirmation count has dipped below minimum_depth / 2, + // close the channel and hope we can get the latest state on chain (because presumably + // the funding transaction is at least still in the mempool of most nodes). + if funding_tx_confirmations < self.minimum_depth as i64 / 2 { + return Err(msgs::ErrorMessage { + channel_id: self.channel_id(), + data: format!("Funding transaction was un-confirmed. Locked at {} confs, now have {} confs.", self.minimum_depth, funding_tx_confirmations), + }); } } + Ok((None, timed_out_htlcs)) } - /// Called by channelmanager based on chain blocks being disconnected. - /// Returns true if we need to close the channel now due to funding transaction - /// unconfirmation/reorg. - pub fn block_disconnected(&mut self, header: &BlockHeader) -> bool { - if self.funding_tx_confirmations > 0 { - self.funding_tx_confirmations -= 1; - if self.funding_tx_confirmations == UNCONF_THRESHOLD as u64 { - return true; + /// Indicates the funding transaction is no longer confirmed in the main chain. This may + /// force-close the channel, but may also indicate a harmless reorganization of a block or two + /// before the channel has reached funding_locked and we can just wait for more blocks. + pub fn funding_transaction_unconfirmed(&mut self, logger: &L) -> Result<(), msgs::ErrorMessage> where L::Target: Logger { + if self.funding_tx_confirmation_height != 0 { + // We handle the funding disconnection by calling best_block_updated with a height one + // below where our funding was connected, implying a reorg back to conf_height - 1. + let reorg_height = self.funding_tx_confirmation_height - 1; + // We use the time field to bump the current time we set on channel updates if its + // larger. If we don't know that time has moved forward, we can just set it to the last + // time we saw and it will be ignored. + let best_time = self.update_time_counter; + match self.best_block_updated(reorg_height, best_time, logger) { + Ok((funding_locked, timed_out_htlcs)) => { + assert!(funding_locked.is_none(), "We can't generate a funding with 0 confirmations?"); + assert!(timed_out_htlcs.is_empty(), "We can't have accepted HTLCs with a timeout before our funding confirmation?"); + Ok(()) + }, + Err(e) => Err(e) } + } else { + // We never learned about the funding confirmation anyway, just ignore + Ok(()) } - if Some(header.block_hash()) == self.funding_tx_confirmed_in { - self.funding_tx_confirmations = self.minimum_depth as u64 - 1; - } - false } // Methods to get unprompted messages to send to the remote end (or where we already returned @@ -3786,6 +3885,8 @@ impl Channel { /// closing). /// Note that the "channel must be funded" requirement is stricter than BOLT 7 requires - see /// https://github.com/lightningnetwork/lightning-rfc/issues/468 + /// + /// This will only return ChannelError::Ignore upon failure. pub fn get_channel_announcement(&self, node_id: PublicKey, chain_hash: BlockHash) -> Result<(msgs::UnsignedChannelAnnouncement, Signature), ChannelError> { if !self.config.announced_channel { return Err(ChannelError::Ignore("Channel is not available for public announcements".to_owned())); @@ -3816,6 +3917,63 @@ impl Channel { Ok((msg, sig)) } + /// Signs the given channel announcement, returning a ChannelError::Ignore if no keys are + /// available. + fn sign_channel_announcement(&self, our_node_secret: &SecretKey, our_node_id: PublicKey, msghash: secp256k1::Message, announcement: msgs::UnsignedChannelAnnouncement, our_bitcoin_sig: Signature) -> Result { + if let Some((their_node_sig, their_bitcoin_sig)) = self.announcement_sigs { + let were_node_one = announcement.node_id_1 == our_node_id; + + let our_node_sig = self.secp_ctx.sign(&msghash, our_node_secret); + Ok(msgs::ChannelAnnouncement { + node_signature_1: if were_node_one { our_node_sig } else { their_node_sig }, + node_signature_2: if were_node_one { their_node_sig } else { our_node_sig }, + bitcoin_signature_1: if were_node_one { our_bitcoin_sig } else { their_bitcoin_sig }, + bitcoin_signature_2: if were_node_one { their_bitcoin_sig } else { our_bitcoin_sig }, + contents: announcement, + }) + } else { + Err(ChannelError::Ignore("Attempted to sign channel announcement before we'd received announcement_signatures".to_string())) + } + } + + /// Processes an incoming announcement_signatures message, providing a fully-signed + /// channel_announcement message which we can broadcast and storing our counterparty's + /// signatures for later reconstruction/rebroadcast of the channel_announcement. + pub fn announcement_signatures(&mut self, our_node_secret: &SecretKey, our_node_id: PublicKey, chain_hash: BlockHash, msg: &msgs::AnnouncementSignatures) -> Result { + let (announcement, our_bitcoin_sig) = self.get_channel_announcement(our_node_id.clone(), chain_hash)?; + + let msghash = hash_to_message!(&Sha256d::hash(&announcement.encode()[..])[..]); + + if self.secp_ctx.verify(&msghash, &msg.node_signature, &self.get_counterparty_node_id()).is_err() { + return Err(ChannelError::Close(format!( + "Bad announcement_signatures. Failed to verify node_signature. UnsignedChannelAnnouncement used for verification is {:?}. their_node_key is {:?}", + &announcement, self.get_counterparty_node_id()))); + } + if self.secp_ctx.verify(&msghash, &msg.bitcoin_signature, self.counterparty_funding_pubkey()).is_err() { + return Err(ChannelError::Close(format!( + "Bad announcement_signatures. Failed to verify bitcoin_signature. UnsignedChannelAnnouncement used for verification is {:?}. their_bitcoin_key is ({:?})", + &announcement, self.counterparty_funding_pubkey()))); + } + + self.announcement_sigs = Some((msg.node_signature, msg.bitcoin_signature)); + + self.sign_channel_announcement(our_node_secret, our_node_id, msghash, announcement, our_bitcoin_sig) + } + + /// Gets a signed channel_announcement for this channel, if we previously received an + /// announcement_signatures from our counterparty. + pub fn get_signed_channel_announcement(&self, our_node_secret: &SecretKey, our_node_id: PublicKey, chain_hash: BlockHash) -> Option { + let (announcement, our_bitcoin_sig) = match self.get_channel_announcement(our_node_id.clone(), chain_hash) { + Ok(res) => res, + Err(_) => return None, + }; + let msghash = hash_to_message!(&Sha256d::hash(&announcement.encode()[..])[..]); + match self.sign_channel_announcement(our_node_secret, our_node_id, msghash, announcement, our_bitcoin_sig) { + Ok(res) => Some(res), + Err(_) => None, + } + } + /// May panic if called on a channel that wasn't immediately-previously /// self.remove_uncommitted_htlcs_and_mark_paused()'d pub fn get_channel_reestablish(&self, logger: &L) -> msgs::ChannelReestablish where L::Target: Logger { @@ -3831,13 +3989,13 @@ impl Channel { let dummy_pubkey = PublicKey::from_slice(&pk).unwrap(); let data_loss_protect = if self.cur_counterparty_commitment_transaction_number + 1 < INITIAL_COMMITMENT_NUMBER { let remote_last_secret = self.commitment_secrets.get_secret(self.cur_counterparty_commitment_transaction_number + 2).unwrap(); - log_trace!(logger, "Enough info to generate a Data Loss Protect with per_commitment_secret {}", log_bytes!(remote_last_secret)); + log_trace!(logger, "Enough info to generate a Data Loss Protect with per_commitment_secret {} for channel {}", log_bytes!(remote_last_secret), log_bytes!(self.channel_id())); OptionalField::Present(DataLossProtect { your_last_per_commitment_secret: remote_last_secret, my_current_per_commitment_point: dummy_pubkey }) } else { - log_info!(logger, "Sending a data_loss_protect with no previous remote per_commitment_secret"); + log_info!(logger, "Sending a data_loss_protect with no previous remote per_commitment_secret for channel {}", log_bytes!(self.channel_id())); OptionalField::Present(DataLossProtect { your_last_per_commitment_secret: [0;32], my_current_per_commitment_point: dummy_pubkey, @@ -3872,10 +4030,18 @@ impl Channel { /// Adds a pending outbound HTLC to this channel, note that you probably want /// send_htlc_and_commit instead cause you'll want both messages at once. - /// This returns an option instead of a pure UpdateAddHTLC as we may be in a state where we are - /// waiting on the remote peer to send us a revoke_and_ack during which time we cannot add new - /// HTLCs on the wire or we wouldn't be able to determine what they actually ACK'ed. - /// You MUST call send_commitment prior to any other calls on this Channel + /// + /// This returns an optional UpdateAddHTLC as we may be in a state where we cannot add HTLCs on + /// the wire: + /// * In cases where we're waiting on the remote peer to send us a revoke_and_ack, we + /// wouldn't be able to determine what they actually ACK'ed if we have two sets of updates + /// awaiting ACK. + /// * In cases where we're marked MonitorUpdateFailed, we cannot commit to a new state as we + /// may not yet have sent the previous commitment update messages and will need to regenerate + /// them. + /// + /// You MUST call send_commitment prior to calling any other methods on this Channel! + /// /// If an Err is returned, it's a ChannelError::Ignore! pub fn send_htlc(&mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32, source: HTLCSource, onion_routing_packet: msgs::OnionPacket) -> Result, ChannelError> { if (self.channel_state & (ChannelState::ChannelFunded as u32 | BOTH_SIDES_SHUTDOWN_MASK)) != (ChannelState::ChannelFunded as u32) { @@ -3894,14 +4060,14 @@ impl Channel { return Err(ChannelError::Ignore(format!("Cannot send less than their minimum HTLC value ({})", self.counterparty_htlc_minimum_msat))); } - if (self.channel_state & (ChannelState::PeerDisconnected as u32 | ChannelState::MonitorUpdateFailed as u32)) != 0 { + if (self.channel_state & (ChannelState::PeerDisconnected as u32)) != 0 { // Note that this should never really happen, if we're !is_live() on receipt of an // incoming HTLC for relay will result in us rejecting the HTLC and we won't allow // the user to send directly into a !is_live() channel. However, if we // disconnected during the time the previous hop was doing the commitment dance we may // end up getting here after the forwarding delay. In any case, returning an // IgnoreError will get ChannelManager to do the right thing and fail backwards now. - return Err(ChannelError::Ignore("Cannot send an HTLC while disconnected/frozen for channel monitor update".to_owned())); + return Err(ChannelError::Ignore("Cannot send an HTLC while disconnected from channel counterparty".to_owned())); } let (outbound_htlc_count, htlc_outbound_value_msat) = self.get_outbound_pending_htlc_stats(); @@ -3946,7 +4112,7 @@ impl Channel { } // Now update local state: - if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == (ChannelState::AwaitingRemoteRevoke as u32) { + if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32 | ChannelState::MonitorUpdateFailed as u32)) != 0 { self.holding_cell_htlc_updates.push(HTLCUpdateAwaitingACK::AddHTLC { amount_msat, payment_hash, @@ -4104,18 +4270,17 @@ impl Channel { signature = res.0; htlc_signatures = res.1; - log_trace!(logger, "Signed remote commitment tx {} (txid {}) with redeemscript {} -> {}", + log_trace!(logger, "Signed remote commitment tx {} (txid {}) with redeemscript {} -> {} in channel {}", encode::serialize_hex(&counterparty_commitment_tx.0.trust().built_transaction().transaction), - &counterparty_commitment_txid, - encode::serialize_hex(&self.get_funding_redeemscript()), - log_bytes!(signature.serialize_compact()[..])); + &counterparty_commitment_txid, encode::serialize_hex(&self.get_funding_redeemscript()), + log_bytes!(signature.serialize_compact()[..]), log_bytes!(self.channel_id())); for (ref htlc_sig, ref htlc) in htlc_signatures.iter().zip(htlcs) { - log_trace!(logger, "Signed remote HTLC tx {} with redeemscript {} with pubkey {} -> {}", + log_trace!(logger, "Signed remote HTLC tx {} with redeemscript {} with pubkey {} -> {} in channel {}", encode::serialize_hex(&chan_utils::build_htlc_transaction(&counterparty_commitment_txid, feerate_per_kw, self.get_holder_selected_contest_delay(), htlc, &counterparty_keys.broadcaster_delayed_payment_key, &counterparty_keys.revocation_key)), encode::serialize_hex(&chan_utils::get_htlc_redeemscript(&htlc, &counterparty_keys)), log_bytes!(counterparty_keys.broadcaster_htlc_key.serialize()), - log_bytes!(htlc_sig.serialize_compact()[..])); + log_bytes!(htlc_sig.serialize_compact()[..]), log_bytes!(self.channel_id())); } } @@ -4277,33 +4442,32 @@ fn is_unsupported_shutdown_script(their_features: &InitFeatures, script: &Script const SERIALIZATION_VERSION: u8 = 1; const MIN_SERIALIZATION_VERSION: u8 = 1; -impl Writeable for InboundHTLCRemovalReason { +impl_writeable_tlv_based_enum!(InboundHTLCRemovalReason,; + (0, FailRelay), + (1, FailMalformed), + (2, Fulfill), +); + +impl Writeable for ChannelUpdateStatus { fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { + // We only care about writing out the current state as it was announced, ie only either + // Enabled or Disabled. In the case of DisabledStaged, we most recently announced the + // channel as enabled, so we write 0. For EnabledStaged, we similarly write a 1. match self { - &InboundHTLCRemovalReason::FailRelay(ref error_packet) => { - 0u8.write(writer)?; - error_packet.write(writer)?; - }, - &InboundHTLCRemovalReason::FailMalformed((ref onion_hash, ref err_code)) => { - 1u8.write(writer)?; - onion_hash.write(writer)?; - err_code.write(writer)?; - }, - &InboundHTLCRemovalReason::Fulfill(ref payment_preimage) => { - 2u8.write(writer)?; - payment_preimage.write(writer)?; - }, + ChannelUpdateStatus::Enabled => 0u8.write(writer)?, + ChannelUpdateStatus::DisabledStaged => 0u8.write(writer)?, + ChannelUpdateStatus::EnabledStaged => 1u8.write(writer)?, + ChannelUpdateStatus::Disabled => 1u8.write(writer)?, } Ok(()) } } -impl Readable for InboundHTLCRemovalReason { +impl Readable for ChannelUpdateStatus { fn read(reader: &mut R) -> Result { Ok(match ::read(reader)? { - 0 => InboundHTLCRemovalReason::FailRelay(Readable::read(reader)?), - 1 => InboundHTLCRemovalReason::FailMalformed((Readable::read(reader)?, Readable::read(reader)?)), - 2 => InboundHTLCRemovalReason::Fulfill(Readable::read(reader)?), + 0 => ChannelUpdateStatus::Enabled, + 1 => ChannelUpdateStatus::Disabled, _ => return Err(DecodeError::InvalidValue), }) } @@ -4312,10 +4476,9 @@ impl Readable for InboundHTLCRemovalReason { impl Writeable for Channel { fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { // Note that we write out as if remove_uncommitted_htlcs_and_mark_paused had just been - // called but include holding cell updates (and obviously we don't modify self). + // called. - writer.write_all(&[SERIALIZATION_VERSION; 1])?; - writer.write_all(&[MIN_SERIALIZATION_VERSION; 1])?; + write_ver_prefix!(writer, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION); self.user_id.write(writer)?; self.config.write(writer)?; @@ -4328,8 +4491,8 @@ impl Writeable for Channel { let mut key_data = VecWriter(Vec::new()); self.holder_signer.write(&mut key_data)?; - assert!(key_data.0.len() < std::usize::MAX); - assert!(key_data.0.len() < std::u32::MAX as usize); + assert!(key_data.0.len() < core::usize::MAX); + assert!(key_data.0.len() < core::u32::MAX as usize); (key_data.0.len() as u32).write(writer)?; writer.write_all(&key_data.0[..])?; @@ -4390,9 +4553,10 @@ impl Writeable for Channel { &OutboundHTLCState::Committed => { 1u8.write(writer)?; }, - &OutboundHTLCState::RemoteRemoved(ref fail_reason) => { - 2u8.write(writer)?; - fail_reason.write(writer)?; + &OutboundHTLCState::RemoteRemoved(_) => { + // Treat this as a Committed because we haven't received the CS - they'll + // resend the claim/fail on reconnect as we all (hopefully) the missing CS. + 1u8.write(writer)?; }, &OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref fail_reason) => { 3u8.write(writer)?; @@ -4470,8 +4634,8 @@ impl Writeable for Channel { } self.funding_tx_confirmed_in.write(writer)?; + self.funding_tx_confirmation_height.write(writer)?; self.short_channel_id.write(writer)?; - self.funding_tx_confirmations.write(writer)?; self.counterparty_dust_limit_satoshis.write(writer)?; self.holder_dust_limit_satoshis.write(writer)?; @@ -4502,6 +4666,11 @@ impl Writeable for Channel { self.counterparty_shutdown_scriptpubkey.write(writer)?; self.commitment_secrets.write(writer)?; + + self.channel_update_status.write(writer)?; + + write_tlv_fields!(writer, {(0, self.announcement_sigs, option)}); + Ok(()) } } @@ -4510,11 +4679,7 @@ const MAX_ALLOC_SIZE: usize = 64*1024; impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel where K::Target: KeysInterface { fn read(reader: &mut R, keys_source: &'a K) -> Result { - let _ver: u8 = Readable::read(reader)?; - let min_ver: u8 = Readable::read(reader)?; - if min_ver > SERIALIZATION_VERSION { - return Err(DecodeError::UnknownVersion); - } + let _ver = read_ver_prefix!(reader, SERIALIZATION_VERSION); let user_id = Readable::read(reader)?; let config: ChannelConfig = Readable::read(reader)?; @@ -4641,8 +4806,8 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel }; let funding_tx_confirmed_in = Readable::read(reader)?; + let funding_tx_confirmation_height = Readable::read(reader)?; let short_channel_id = Readable::read(reader)?; - let funding_tx_confirmations = Readable::read(reader)?; let counterparty_dust_limit_satoshis = Readable::read(reader)?; let holder_dust_limit_satoshis = Readable::read(reader)?; @@ -4674,6 +4839,11 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel let counterparty_shutdown_scriptpubkey = Readable::read(reader)?; let commitment_secrets = Readable::read(reader)?; + let channel_update_status = Readable::read(reader)?; + + let mut announcement_sigs = None; + read_tlv_fields!(reader, {(0, announcement_sigs, option)}); + let mut secp_ctx = Secp256k1::new(); secp_ctx.seeded_randomize(&keys_source.get_secure_random_bytes()); @@ -4723,8 +4893,8 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel last_sent_closing_fee, funding_tx_confirmed_in, + funding_tx_confirmation_height, short_channel_id, - funding_tx_confirmations, counterparty_dust_limit_satoshis, holder_dust_limit_satoshis, @@ -4748,12 +4918,16 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel commitment_secrets, - network_sync: UpdateStatus::Fresh, + channel_update_status, + + announcement_sigs, #[cfg(any(test, feature = "fuzztarget"))] next_local_commitment_tx_fee_info_cached: Mutex::new(None), #[cfg(any(test, feature = "fuzztarget"))] next_remote_commitment_tx_fee_info_cached: Mutex::new(None), + + workaround_lnd_bug_4006: None, }) } } @@ -4769,15 +4943,16 @@ mod tests { use bitcoin::network::constants::Network; 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::{PaymentPreimage, PaymentHash}; + use ln::channelmanager::{BestBlock, HTLCSource}; + 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; @@ -4786,10 +4961,12 @@ mod tests { use bitcoin::secp256k1::{Secp256k1, Message, Signature, All}; use bitcoin::secp256k1::ffi::Signature as FFISignature; use bitcoin::secp256k1::key::{SecretKey,PublicKey}; + use bitcoin::secp256k1::recovery::RecoverableSignature; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::Hash; use bitcoin::hash_types::{Txid, WPubkeyHash}; use std::sync::Arc; + use prelude::*; struct TestFeeEstimator { fee_est: u32 @@ -4831,6 +5008,7 @@ mod tests { } fn get_secure_random_bytes(&self) -> [u8; 32] { [0; 32] } fn read_chan_signer(&self, _data: &[u8]) -> Result { panic!(); } + fn sign_invoice(&self, _invoice_preimage: Vec) -> Result { panic!(); } } fn public_from_secret_hex(secp_ctx: &Secp256k1, hex: &str) -> PublicKey { @@ -4880,7 +5058,6 @@ mod tests { // Create Node B's channel by receiving Node A's open_channel message // Make sure A's dust limit is as we expect. let open_channel_msg = node_a_chan.get_open_channel(genesis_block(network).header.block_hash()); - assert_eq!(open_channel_msg.dust_limit_satoshis, 1560); let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); let node_b_chan = Channel::::new_from_req(&&feeest, &&keys_provider, node_b_node_id, InitFeatures::known(), &open_channel_msg, 7, &config).unwrap(); @@ -4888,6 +5065,7 @@ mod tests { let mut accept_channel_msg = node_b_chan.get_accept_channel(); accept_channel_msg.dust_limit_satoshis = 546; node_a_chan.accept_channel(&accept_channel_msg, &config, InitFeatures::known()).unwrap(); + node_a_chan.holder_dust_limit_satoshis = 1560; // Put some inbound and outbound HTLCs in A's channel. let htlc_amount_msat = 11_092_000; // put an amount below A's effective dust limit but above B's. @@ -4982,8 +5160,8 @@ mod tests { let secp_ctx = Secp256k1::new(); let seed = [42; 32]; let network = Network::Testnet; - let chain_hash = genesis_block(network).header.block_hash(); - let last_block_hash = chain_hash; + let best_block = BestBlock::from_genesis(network); + let chain_hash = best_block.block_hash(); let keys_provider = test_utils::TestKeysInterface::new(&seed, network); // Go through the flow of opening a channel between two nodes. @@ -5009,10 +5187,10 @@ mod tests { }]}; let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 }; 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(); + let (funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&logger).unwrap(); // Node B --> Node A: funding signed - let _ = node_a_chan.funding_signed(&funding_signed_msg, last_block_hash, &&logger); + let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&logger); // Now disconnect the two nodes and check that the commitment point in // Node B's channel_reestablish message is sane.