X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=45f7aa73b9b6a4c2d1167d79d42a681dbd2591e3;hb=306e9a5acf7553b966030cc0ba177d2743675ea5;hp=2f447c86155ffc78853f1516b2e44e120adb8b0f;hpb=57e813f971ef391036e6d88742c269b6676f376e;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 2f447c86..45f7aa73 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -26,9 +26,10 @@ use ln::{PaymentPreimage, PaymentHash}; use ln::features::{ChannelFeatures, InitFeatures}; use ln::msgs; use ln::msgs::{DecodeError, OptionalField, DataLossProtect}; -use ln::channelmanager::{BestBlock, PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT}; +use ln::channelmanager::{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::BestBlock; use chain::chaininterface::{FeeEstimator,ConfirmationTarget}; use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, HTLC_FAIL_BACK_BUFFER}; use chain::transaction::{OutPoint, TransactionData}; @@ -114,8 +115,8 @@ enum InboundHTLCState { /// commitment transaction without it as otherwise we'll have to force-close the channel to /// claim it before the timeout (obviously doesn't apply to revoked HTLCs that we can't claim /// anyway). That said, ChannelMonitor does this for us (see - /// ChannelMonitor::would_broadcast_at_height) so we actually remove the HTLC from our own - /// local state before then, once we're sure that the next commitment_signed and + /// ChannelMonitor::should_broadcast_holder_commitment_txn) so we actually remove the HTLC from + /// our own local state before then, once we're sure that the next commitment_signed and /// ChannelMonitor::provide_latest_local_commitment_tx will not include this HTLC. LocalRemoved(InboundHTLCRemovalReason), } @@ -396,7 +397,7 @@ pub(super) struct Channel { counterparty_max_htlc_value_in_flight_msat: u64, //get_holder_max_htlc_value_in_flight_msat(): u64, /// minimum channel reserve for self to maintain - set by them. - counterparty_selected_channel_reserve_satoshis: u64, + counterparty_selected_channel_reserve_satoshis: Option, // get_holder_selected_channel_reserve_satoshis(channel_value_sats: u64): u64 counterparty_htlc_minimum_msat: u64, holder_htlc_minimum_msat: u64, @@ -405,7 +406,7 @@ pub(super) struct Channel { #[cfg(not(test))] counterparty_max_accepted_htlcs: u16, //implied by OUR_MAX_HTLCS: max_accepted_htlcs: u16, - minimum_depth: u32, + minimum_depth: Option, counterparty_forwarding_info: Option, @@ -455,7 +456,6 @@ struct CommitmentTxInfoCached { } pub const OUR_MAX_HTLCS: u16 = 50; //TODO -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 #[cfg(not(test))] const COMMITMENT_TX_BASE_WEIGHT: u64 = 724; @@ -609,11 +609,11 @@ impl Channel { counterparty_dust_limit_satoshis: 0, holder_dust_limit_satoshis: MIN_DUST_LIMIT_SATOSHIS, counterparty_max_htlc_value_in_flight_msat: 0, - counterparty_selected_channel_reserve_satoshis: 0, + counterparty_selected_channel_reserve_satoshis: None, // Filled in in accept_channel counterparty_htlc_minimum_msat: 0, holder_htlc_minimum_msat: if config.own_channel_config.our_htlc_minimum_msat == 0 { 1 } else { config.own_channel_config.our_htlc_minimum_msat }, counterparty_max_accepted_htlcs: 0, - minimum_depth: 0, // Filled in in accept_channel + minimum_depth: None, // Filled in in accept_channel counterparty_forwarding_info: None, @@ -851,11 +851,11 @@ impl Channel { counterparty_dust_limit_satoshis: msg.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_selected_channel_reserve_satoshis: Some(msg.channel_reserve_satoshis), counterparty_htlc_minimum_msat: msg.htlc_minimum_msat, holder_htlc_minimum_msat: if config.own_channel_config.our_htlc_minimum_msat == 0 { 1 } else { config.own_channel_config.our_htlc_minimum_msat }, counterparty_max_accepted_htlcs: msg.max_accepted_htlcs, - minimum_depth: config.own_channel_config.minimum_depth, + minimum_depth: Some(config.own_channel_config.minimum_depth), counterparty_forwarding_info: None, @@ -1036,7 +1036,7 @@ impl Channel { } else { self.counterparty_max_commitment_tx_output.lock().unwrap() }; - debug_assert!(broadcaster_max_commitment_tx_output.0 <= value_to_self_msat as u64 || value_to_self_msat / 1000 >= self.counterparty_selected_channel_reserve_satoshis as i64); + debug_assert!(broadcaster_max_commitment_tx_output.0 <= value_to_self_msat as u64 || value_to_self_msat / 1000 >= self.counterparty_selected_channel_reserve_satoshis.unwrap() as i64); broadcaster_max_commitment_tx_output.0 = cmp::max(broadcaster_max_commitment_tx_output.0, value_to_self_msat as u64); debug_assert!(broadcaster_max_commitment_tx_output.1 <= value_to_remote_msat as u64 || value_to_remote_msat / 1000 >= Channel::::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis) as i64); broadcaster_max_commitment_tx_output.1 = cmp::max(broadcaster_max_commitment_tx_output.1, value_to_remote_msat as u64); @@ -1216,13 +1216,6 @@ impl Channel { make_funding_redeemscript(&self.get_holder_pubkeys().funding_pubkey, self.counterparty_funding_pubkey()) } - /// Builds the htlc-success or htlc-timeout transaction which spends a given HTLC output - /// @local is used only to convert relevant internal structures which refer to remote vs local - /// to decide value of outputs and direction of HTLCs. - fn build_htlc_transaction(&self, prev_hash: &Txid, htlc: &HTLCOutputInCommitment, local: bool, keys: &TxCreationKeys, feerate_per_kw: u32) -> Transaction { - chan_utils::build_htlc_transaction(prev_hash, feerate_per_kw, if local { self.get_counterparty_selected_contest_delay() } else { self.get_holder_selected_contest_delay() }, htlc, &keys.broadcaster_delayed_payment_key, &keys.revocation_key) - } - /// Per HTLC, only one get_update_fail_htlc or get_update_fulfill_htlc call may be made. /// In such cases we debug_assert!(false) and return a ChannelError::Ignore. Thus, will always /// return Ok(_) if debug assertions are turned on or preconditions are met. @@ -1488,6 +1481,12 @@ impl Channel { 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))); } + if msg.minimum_depth == 0 { + // Note that if this changes we should update the serialization minimum version to + // indicate to older clients that they don't understand some features of the current + // channel. + return Err(ChannelError::Close("Minimum confirmation depth must be at least 1".to_owned())); + } let counterparty_shutdown_scriptpubkey = if their_features.supports_upfront_shutdown_script() { match &msg.shutdown_scriptpubkey { @@ -1511,10 +1510,10 @@ impl Channel { self.counterparty_dust_limit_satoshis = msg.dust_limit_satoshis; self.counterparty_max_htlc_value_in_flight_msat = cmp::min(msg.max_htlc_value_in_flight_msat, self.channel_value_satoshis * 1000); - self.counterparty_selected_channel_reserve_satoshis = msg.channel_reserve_satoshis; + self.counterparty_selected_channel_reserve_satoshis = Some(msg.channel_reserve_satoshis); self.counterparty_htlc_minimum_msat = msg.htlc_minimum_msat; self.counterparty_max_accepted_htlcs = msg.max_accepted_htlcs; - self.minimum_depth = msg.minimum_depth; + self.minimum_depth = Some(msg.minimum_depth); let counterparty_pubkeys = ChannelPublicKeys { funding_pubkey: msg.funding_pubkey, @@ -1785,8 +1784,22 @@ impl Channel { /// corner case properly. pub fn get_inbound_outbound_available_balance_msat(&self) -> (u64, u64) { // Note that we have to handle overflow due to the above case. - (cmp::max(self.channel_value_satoshis as i64 * 1000 - self.value_to_self_msat as i64 - self.get_inbound_pending_htlc_stats().1 as i64, 0) as u64, - cmp::max(self.value_to_self_msat as i64 - self.get_outbound_pending_htlc_stats().1 as i64, 0) as u64) + ( + cmp::max(self.channel_value_satoshis as i64 * 1000 + - self.value_to_self_msat as i64 + - self.get_inbound_pending_htlc_stats().1 as i64 + - Self::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis) as i64 * 1000, + 0) as u64, + cmp::max(self.value_to_self_msat as i64 + - self.get_outbound_pending_htlc_stats().1 as i64 + - self.counterparty_selected_channel_reserve_satoshis.unwrap_or(0) as i64 * 1000, + 0) as u64 + ) + } + + pub fn get_holder_counterparty_selected_channel_reserve_satoshis(&self) -> (u64, Option) { + (Self::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis), + self.counterparty_selected_channel_reserve_satoshis) } // Get the fee cost of a commitment tx with a given number of HTLC outputs. @@ -2064,7 +2077,7 @@ impl Channel { // Check that they won't violate our local required channel reserve by adding this HTLC. let htlc_candidate = HTLCCandidate::new(msg.amount_msat, HTLCInitiator::RemoteOffered); let local_commit_tx_fee_msat = self.next_local_commit_tx_fee_msat(htlc_candidate, None); - if self.value_to_self_msat < self.counterparty_selected_channel_reserve_satoshis * 1000 + local_commit_tx_fee_msat { + if self.value_to_self_msat < self.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 + local_commit_tx_fee_msat { return Err(ChannelError::Close("Cannot accept HTLC that would put our balance under counterparty-announced channel reserve value".to_owned())); } } @@ -2236,7 +2249,10 @@ impl Channel { let mut htlcs_and_sigs = Vec::with_capacity(htlcs_cloned.len()); for (idx, (htlc, source)) in htlcs_cloned.drain(..).enumerate() { if let Some(_) = htlc.transaction_output_index { - let htlc_tx = self.build_htlc_transaction(&commitment_txid, &htlc, true, &keys, feerate_per_kw); + let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, feerate_per_kw, + self.get_counterparty_selected_contest_delay().unwrap(), &htlc, + &keys.broadcaster_delayed_payment_key, &keys.revocation_key); + 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 {} in channel {}.", @@ -3336,6 +3352,10 @@ impl Channel { self.channel_id } + pub fn minimum_depth(&self) -> Option { + self.minimum_depth + } + /// Gets the "user_id" value passed into the construction of this channel. It has no special /// meaning and exists only to allow users to have a persistent identifier of a channel. pub fn get_user_id(&self) -> u64 { @@ -3363,8 +3383,9 @@ impl Channel { &self.channel_transaction_parameters.holder_pubkeys } - fn get_counterparty_selected_contest_delay(&self) -> u16 { - self.channel_transaction_parameters.counterparty_parameters.as_ref().unwrap().selected_contest_delay + pub fn get_counterparty_selected_contest_delay(&self) -> Option { + self.channel_transaction_parameters.counterparty_parameters + .as_ref().map(|params| params.selected_contest_delay) } fn get_counterparty_pubkeys(&self) -> &ChannelPublicKeys { @@ -3404,7 +3425,7 @@ impl Channel { } pub fn get_fee_proportional_millionths(&self) -> u32 { - self.config.fee_proportional_millionths + self.config.forwarding_fee_proportional_millionths } pub fn get_cltv_expiry_delta(&self) -> u16 { @@ -3438,7 +3459,7 @@ impl Channel { ChannelValueStat { value_to_self_msat: self.value_to_self_msat, channel_value_msat: self.channel_value_satoshis * 1000, - channel_reserve_msat: self.counterparty_selected_channel_reserve_satoshis * 1000, + channel_reserve_msat: self.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000, pending_outbound_htlcs_amount_msat: self.pending_outbound_htlcs.iter().map(|ref h| h.amount_msat).sum::(), pending_inbound_htlcs_amount_msat: self.pending_inbound_htlcs.iter().map(|ref h| h.amount_msat).sum::(), holding_cell_outbound_amount_msat: { @@ -3477,24 +3498,8 @@ impl Channel { /// Gets the fee we'd want to charge for adding an HTLC output to this Channel /// Allowed in any state (including after shutdown) - pub fn get_holder_fee_base_msat(&self, fee_estimator: &F) -> u32 - where F::Target: FeeEstimator - { - // For lack of a better metric, we calculate what it would cost to consolidate the new HTLC - // output value back into a transaction with the regular channel output: - - // the fee cost of the HTLC-Success/HTLC-Timeout transaction: - let mut res = self.feerate_per_kw as u64 * cmp::max(HTLC_TIMEOUT_TX_WEIGHT, HTLC_SUCCESS_TX_WEIGHT) / 1000; - - if self.is_outbound() { - // + the marginal fee increase cost to us in the commitment transaction: - res += self.feerate_per_kw as u64 * COMMITMENT_TX_WEIGHT_PER_HTLC / 1000; - } - - // + the marginal cost of an input which spends the HTLC-Success/HTLC-Timeout output: - res += fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal) as u64 * SPENDING_INPUT_FOR_A_OUTPUT_WEIGHT / 1000; - - res as u32 + pub fn get_outbound_forwarding_fee_base_msat(&self) -> u32 { + self.config.forwarding_fee_base_msat } /// Returns true if we've ever received a message from the remote end for this Channel @@ -3513,7 +3518,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. @@ -3555,7 +3560,7 @@ impl Channel { self.funding_tx_confirmation_height = 0; } - if funding_tx_confirmations < self.minimum_depth as i64 { + if funding_tx_confirmations < self.minimum_depth.unwrap_or(0) as i64 { return None; } @@ -3710,10 +3715,10 @@ impl Channel { // 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 { + if funding_tx_confirmations < self.minimum_depth.unwrap() 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), + data: format!("Funding transaction was un-confirmed. Locked at {} confs, now have {} confs.", self.minimum_depth.unwrap(), funding_tx_confirmations), }); } } @@ -3808,7 +3813,7 @@ impl Channel { max_htlc_value_in_flight_msat: Channel::::get_holder_max_htlc_value_in_flight_msat(self.channel_value_satoshis), channel_reserve_satoshis: Channel::::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis), htlc_minimum_msat: self.holder_htlc_minimum_msat, - minimum_depth: self.minimum_depth, + minimum_depth: self.minimum_depth.unwrap(), to_self_delay: self.get_holder_selected_contest_delay(), max_accepted_htlcs: OUR_MAX_HTLCS, funding_pubkey: keys.funding_pubkey, @@ -4030,10 +4035,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) { @@ -4052,14 +4065,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(); @@ -4074,7 +4087,7 @@ impl Channel { if !self.is_outbound() { // Check that we won't violate the remote channel reserve by adding this HTLC. let counterparty_balance_msat = self.channel_value_satoshis * 1000 - self.value_to_self_msat; - let holder_selected_chan_reserve_msat = Channel::::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis); + let holder_selected_chan_reserve_msat = Channel::::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis) * 1000; let htlc_candidate = HTLCCandidate::new(amount_msat, HTLCInitiator::LocalOffered); let counterparty_commit_tx_fee_msat = self.next_remote_commit_tx_fee_msat(htlc_candidate, None); if counterparty_balance_msat < holder_selected_chan_reserve_msat + counterparty_commit_tx_fee_msat { @@ -4098,13 +4111,13 @@ impl Channel { // Check self.counterparty_selected_channel_reserve_satoshis (the amount we must keep as // reserve for the remote to have something to claim if we misbehave) - let chan_reserve_msat = self.counterparty_selected_channel_reserve_satoshis * 1000; + let chan_reserve_msat = self.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000; if pending_value_to_self_msat - amount_msat - commit_tx_fee_msat < chan_reserve_msat { return Err(ChannelError::Ignore(format!("Cannot send value that would put our balance under counterparty-announced channel reserve value ({})", chan_reserve_msat))); } // 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, @@ -4303,8 +4316,7 @@ impl Channel { } pub fn channel_update(&mut self, msg: &msgs::ChannelUpdate) -> Result<(), ChannelError> { - let usable_channel_value_msat = (self.channel_value_satoshis - self.counterparty_selected_channel_reserve_satoshis) * 1000; - if msg.contents.htlc_minimum_msat >= usable_channel_value_msat { + if msg.contents.htlc_minimum_msat >= self.channel_value_satoshis * 1000 { return Err(ChannelError::Close("Minimum htlc value is greater than channel value".to_string())); } self.counterparty_forwarding_info = Some(CounterpartyForwardingInfo { @@ -4431,7 +4443,7 @@ fn is_unsupported_shutdown_script(their_features: &InitFeatures, script: &Script return !script.is_p2pkh() && !script.is_p2sh() && !script.is_v0_p2wpkh() && !script.is_v0_p2wsh() } -const SERIALIZATION_VERSION: u8 = 1; +const SERIALIZATION_VERSION: u8 = 2; const MIN_SERIALIZATION_VERSION: u8 = 1; impl_writeable_tlv_based_enum!(InboundHTLCRemovalReason,; @@ -4473,7 +4485,13 @@ impl Writeable for Channel { write_ver_prefix!(writer, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION); self.user_id.write(writer)?; - self.config.write(writer)?; + + // Write out the old serialization for the config object. This is read by version-1 + // deserializers, but we will read the version in the TLV at the end instead. + self.config.forwarding_fee_proportional_millionths.write(writer)?; + self.config.cltv_expiry_delta.write(writer)?; + self.config.announced_channel.write(writer)?; + self.config.commit_upfront_shutdown_pubkey.write(writer)?; self.channel_id.write(writer)?; (self.channel_state | ChannelState::PeerDisconnected as u32).write(writer)?; @@ -4632,11 +4650,16 @@ impl Writeable for Channel { self.counterparty_dust_limit_satoshis.write(writer)?; self.holder_dust_limit_satoshis.write(writer)?; self.counterparty_max_htlc_value_in_flight_msat.write(writer)?; - self.counterparty_selected_channel_reserve_satoshis.write(writer)?; + + // Note that this field is ignored by 0.0.99+ as the TLV Optional variant is used instead. + self.counterparty_selected_channel_reserve_satoshis.unwrap_or(0).write(writer)?; + self.counterparty_htlc_minimum_msat.write(writer)?; self.holder_htlc_minimum_msat.write(writer)?; self.counterparty_max_accepted_htlcs.write(writer)?; - self.minimum_depth.write(writer)?; + + // Note that this field is ignored by 0.0.99+ as the TLV Optional variant is used instead. + self.minimum_depth.unwrap_or(0).write(writer)?; match &self.counterparty_forwarding_info { Some(info) => { @@ -4661,7 +4684,18 @@ impl Writeable for Channel { self.channel_update_status.write(writer)?; - write_tlv_fields!(writer, {(0, self.announcement_sigs, option)}); + write_tlv_fields!(writer, { + (0, self.announcement_sigs, option), + // minimum_depth and counterparty_selected_channel_reserve_satoshis used to have a + // default value instead of being Option<>al. Thus, to maintain compatibility we write + // them twice, once with their original default values above, and once as an option + // here. On the read side, old versions will simply ignore the odd-type entries here, + // and new versions map the default values to None and allow the TLV entries here to + // override that. + (1, self.minimum_depth, option), + (3, self.counterparty_selected_channel_reserve_satoshis, option), + (5, self.config, required), + }); Ok(()) } @@ -4671,10 +4705,21 @@ 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 = read_ver_prefix!(reader, SERIALIZATION_VERSION); + let ver = read_ver_prefix!(reader, SERIALIZATION_VERSION); let user_id = Readable::read(reader)?; - let config: ChannelConfig = Readable::read(reader)?; + + let mut config = Some(ChannelConfig::default()); + if ver == 1 { + // Read the old serialization of the ChannelConfig from version 0.0.98. + config.as_mut().unwrap().forwarding_fee_proportional_millionths = Readable::read(reader)?; + config.as_mut().unwrap().cltv_expiry_delta = Readable::read(reader)?; + config.as_mut().unwrap().announced_channel = Readable::read(reader)?; + config.as_mut().unwrap().commit_upfront_shutdown_pubkey = Readable::read(reader)?; + } else { + // Read the 8 bytes of backwards-compatibility ChannelConfig data. + let mut _val: u64 = Readable::read(reader)?; + } let channel_id = Readable::read(reader)?; let channel_state = Readable::read(reader)?; @@ -4804,11 +4849,26 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel let counterparty_dust_limit_satoshis = Readable::read(reader)?; let holder_dust_limit_satoshis = Readable::read(reader)?; let counterparty_max_htlc_value_in_flight_msat = Readable::read(reader)?; - let counterparty_selected_channel_reserve_satoshis = Readable::read(reader)?; + let mut counterparty_selected_channel_reserve_satoshis = None; + if ver == 1 { + // Read the old serialization from version 0.0.98. + counterparty_selected_channel_reserve_satoshis = Some(Readable::read(reader)?); + } else { + // Read the 8 bytes of backwards-compatibility data. + let _dummy: u64 = Readable::read(reader)?; + } let counterparty_htlc_minimum_msat = Readable::read(reader)?; let holder_htlc_minimum_msat = Readable::read(reader)?; let counterparty_max_accepted_htlcs = Readable::read(reader)?; - let minimum_depth = Readable::read(reader)?; + + let mut minimum_depth = None; + if ver == 1 { + // Read the old serialization from version 0.0.98. + minimum_depth = Some(Readable::read(reader)?); + } else { + // Read the 4 bytes of backwards-compatibility data. + let _dummy: u32 = Readable::read(reader)?; + } let counterparty_forwarding_info = match ::read(reader)? { 0 => None, @@ -4834,7 +4894,12 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel let channel_update_status = Readable::read(reader)?; let mut announcement_sigs = None; - read_tlv_fields!(reader, {(0, announcement_sigs, option)}); + read_tlv_fields!(reader, { + (0, announcement_sigs, option), + (1, minimum_depth, option), + (3, counterparty_selected_channel_reserve_satoshis, option), + (5, config, option), // Note that if none is provided we will *not* overwrite the existing one. + }); let mut secp_ctx = Secp256k1::new(); secp_ctx.seeded_randomize(&keys_source.get_secure_random_bytes()); @@ -4842,7 +4907,7 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel Ok(Channel { user_id, - config, + config: config.unwrap(), channel_id, channel_state, secp_ctx, @@ -4936,13 +5001,14 @@ mod tests { use bitcoin::hashes::hex::FromHex; use hex; use ln::{PaymentPreimage, PaymentHash}; - use ln::channelmanager::{BestBlock, HTLCSource}; + use ln::channelmanager::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::BestBlock; use chain::chaininterface::{FeeEstimator,ConfirmationTarget}; use chain::keysinterface::{InMemorySigner, KeysInterface, BaseSign}; use chain::transaction::OutPoint; @@ -5289,6 +5355,7 @@ mod tests { config.channel_options.announced_channel = false; let mut chan = Channel::::new_outbound(&&feeest, &&keys_provider, counterparty_node_id, 10_000_000, 100000, 42, &config).unwrap(); // Nothing uses their network key in this test chan.holder_dust_limit_satoshis = 546; + chan.counterparty_selected_channel_reserve_satoshis = Some(0); // Filled in in accept_channel let funding_info = OutPoint{ txid: Txid::from_hex("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be").unwrap(), index: 0 }; @@ -5376,7 +5443,9 @@ mod tests { let remote_signature = Signature::from_der(&hex::decode($counterparty_htlc_sig_hex).unwrap()[..]).unwrap(); let ref htlc = htlcs[$htlc_idx]; - let htlc_tx = chan.build_htlc_transaction(&unsigned_tx.txid, &htlc, true, &keys, chan.feerate_per_kw); + let htlc_tx = chan_utils::build_htlc_transaction(&unsigned_tx.txid, chan.feerate_per_kw, + chan.get_counterparty_selected_contest_delay().unwrap(), + &htlc, &keys.broadcaster_delayed_payment_key, &keys.revocation_key); let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &keys); let htlc_sighash = Message::from_slice(&bip143::SigHashCache::new(&htlc_tx).signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, SigHashType::All)[..]).unwrap(); secp_ctx.verify(&htlc_sighash, &remote_signature, &keys.countersignatory_htlc_key).unwrap();