X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=f80377b7d4a9247fd7e30dea1ee4930eda270ea9;hb=69ee4860848d5992b238eca3343141004d9d1572;hp=f46d76042df91601e4bc278425906e40bf075e37;hpb=c09104f46ef5b44a1efb38669b95d21fa77d37ec;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index f46d7604..f80377b7 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -41,11 +41,12 @@ use util::errors::APIError; use util::config::{UserConfig,ChannelConfig}; use util::scid_utils::scid_from_parts; +use io; use prelude::*; use core::{cmp,mem,fmt}; use core::ops::Deref; -#[cfg(any(test, feature = "fuzztarget"))] -use std::sync::Mutex; +#[cfg(any(test, feature = "fuzztarget", debug_assertions))] +use sync::Mutex; use bitcoin::hashes::hex::ToHex; use bitcoin::blockdata::opcodes::all::OP_PUSHBYTES_0; @@ -306,6 +307,7 @@ pub struct CounterpartyForwardingInfo { enum UpdateFulfillFetch { NewClaim { monitor_update: ChannelMonitorUpdate, + htlc_value_msat: u64, msg: Option, }, DuplicateClaim {}, @@ -319,6 +321,8 @@ pub enum UpdateFulfillCommitFetch { NewClaim { /// The ChannelMonitorUpdate which places the new payment preimage in the channel monitor monitor_update: ChannelMonitorUpdate, + /// The value of the HTLC which was claimed, in msat. + htlc_value_msat: u64, /// The update_fulfill message and commitment_signed message (if the claim was not placed /// in the holding cell). msgs: Option<(msgs::UpdateFulfillHTLC, msgs::CommitmentSigned)>, @@ -336,6 +340,9 @@ pub enum UpdateFulfillCommitFetch { // Holder designates channel data owned for the benefice of the user client. // Counterparty designates channel data owned by the another channel participant entity. pub(super) struct Channel { + #[cfg(any(test, feature = "_test_utils"))] + pub(crate) config: ChannelConfig, + #[cfg(not(any(test, feature = "_test_utils")))] config: ChannelConfig, user_id: u64, @@ -401,10 +408,10 @@ pub(super) struct Channel { #[cfg(debug_assertions)] /// Max to_local and to_remote outputs in a locally-generated commitment transaction - holder_max_commitment_tx_output: ::std::sync::Mutex<(u64, u64)>, + holder_max_commitment_tx_output: Mutex<(u64, u64)>, #[cfg(debug_assertions)] /// Max to_local and to_remote outputs in a remote-generated commitment transaction - counterparty_max_commitment_tx_output: ::std::sync::Mutex<(u64, u64)>, + counterparty_max_commitment_tx_output: Mutex<(u64, u64)>, last_sent_closing_fee: Option<(u32, u64, Signature)>, // (feerate, fee, holder_sig) @@ -492,7 +499,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; @@ -632,9 +638,9 @@ impl Channel { monitor_pending_failures: Vec::new(), #[cfg(debug_assertions)] - holder_max_commitment_tx_output: ::std::sync::Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)), + holder_max_commitment_tx_output: Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)), #[cfg(debug_assertions)] - counterparty_max_commitment_tx_output: ::std::sync::Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)), + counterparty_max_commitment_tx_output: Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)), last_sent_closing_fee: None, @@ -876,9 +882,9 @@ impl Channel { monitor_pending_failures: Vec::new(), #[cfg(debug_assertions)] - holder_max_commitment_tx_output: ::std::sync::Mutex::new((msg.push_msat, msg.funding_satoshis * 1000 - msg.push_msat)), + holder_max_commitment_tx_output: Mutex::new((msg.push_msat, msg.funding_satoshis * 1000 - msg.push_msat)), #[cfg(debug_assertions)] - counterparty_max_commitment_tx_output: ::std::sync::Mutex::new((msg.push_msat, msg.funding_satoshis * 1000 - msg.push_msat)), + counterparty_max_commitment_tx_output: Mutex::new((msg.push_msat, msg.funding_satoshis * 1000 - msg.push_msat)), last_sent_closing_fee: None, @@ -1276,6 +1282,7 @@ impl Channel { // these, but for now we just have to treat them as normal. let mut pending_idx = core::usize::MAX; + let mut htlc_value_msat = 0; 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); @@ -1295,6 +1302,7 @@ impl Channel { } } pending_idx = idx; + htlc_value_msat = htlc.amount_msat; break; } } @@ -1336,7 +1344,7 @@ impl Channel { // TODO: We may actually be able to switch to a fulfill here, though its // rare enough it may not be worth the complexity burden. debug_assert!(false, "Tried to fulfill an HTLC that was already failed"); - return UpdateFulfillFetch::NewClaim { monitor_update, msg: None }; + return UpdateFulfillFetch::NewClaim { monitor_update, htlc_value_msat, msg: None }; } }, _ => {} @@ -1348,7 +1356,7 @@ impl Channel { }); #[cfg(any(test, feature = "fuzztarget"))] self.historical_inbound_htlc_fulfills.insert(htlc_id_arg); - return UpdateFulfillFetch::NewClaim { monitor_update, msg: None }; + return UpdateFulfillFetch::NewClaim { monitor_update, htlc_value_msat, msg: None }; } #[cfg(any(test, feature = "fuzztarget"))] self.historical_inbound_htlc_fulfills.insert(htlc_id_arg); @@ -1358,7 +1366,7 @@ impl Channel { if let InboundHTLCState::Committed = htlc.state { } else { debug_assert!(false, "Have an inbound HTLC we tried to claim before it was fully committed to"); - return UpdateFulfillFetch::NewClaim { monitor_update, msg: None }; + return UpdateFulfillFetch::NewClaim { monitor_update, htlc_value_msat, msg: None }; } 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())); @@ -1366,6 +1374,7 @@ impl Channel { UpdateFulfillFetch::NewClaim { monitor_update, + htlc_value_msat, msg: Some(msgs::UpdateFulfillHTLC { channel_id: self.channel_id(), htlc_id: htlc_id_arg, @@ -1374,17 +1383,21 @@ impl Channel { } } - pub fn get_update_fulfill_htlc_and_commit(&mut self, htlc_id: u64, payment_preimage: PaymentPreimage, logger: &L) -> Result where L::Target: Logger { + pub fn get_update_fulfill_htlc_and_commit(&mut self, htlc_id: u64, payment_preimage: PaymentPreimage, logger: &L) -> Result where L::Target: Logger { match self.get_update_fulfill_htlc(htlc_id, payment_preimage, logger) { - UpdateFulfillFetch::NewClaim { mut monitor_update, msg: Some(update_fulfill_htlc) } => { - let (commitment, mut additional_update) = self.send_commitment_no_status_check(logger)?; + UpdateFulfillFetch::NewClaim { mut monitor_update, htlc_value_msat, msg: Some(update_fulfill_htlc) } => { + let (commitment, mut additional_update) = match self.send_commitment_no_status_check(logger) { + Err(e) => return Err((e, monitor_update)), + Ok(res) => res + }; // send_commitment_no_status_check may bump latest_monitor_id but we want them to be // strictly increasing by one, so decrement it here. self.latest_monitor_update_id = monitor_update.update_id; monitor_update.updates.append(&mut additional_update.updates); - Ok(UpdateFulfillCommitFetch::NewClaim { monitor_update, msgs: Some((update_fulfill_htlc, commitment)) }) + Ok(UpdateFulfillCommitFetch::NewClaim { monitor_update, htlc_value_msat, msgs: Some((update_fulfill_htlc, commitment)) }) }, - UpdateFulfillFetch::NewClaim { monitor_update, msg: None } => Ok(UpdateFulfillCommitFetch::NewClaim { monitor_update, msgs: None }), + UpdateFulfillFetch::NewClaim { monitor_update, htlc_value_msat, msg: None } => + Ok(UpdateFulfillCommitFetch::NewClaim { monitor_update, htlc_value_msat, msgs: None }), UpdateFulfillFetch::DuplicateClaim {} => Ok(UpdateFulfillCommitFetch::DuplicateClaim {}), } } @@ -2161,7 +2174,7 @@ impl Channel { /// Marks an outbound HTLC which we have received update_fail/fulfill/malformed #[inline] - fn mark_outbound_htlc_removed(&mut self, htlc_id: u64, check_preimage: Option, fail_reason: Option) -> Result<&HTLCSource, ChannelError> { + fn mark_outbound_htlc_removed(&mut self, htlc_id: u64, check_preimage: Option, fail_reason: Option) -> Result<&OutboundHTLCOutput, ChannelError> { for htlc in self.pending_outbound_htlcs.iter_mut() { if htlc.htlc_id == htlc_id { match check_preimage { @@ -2180,13 +2193,13 @@ impl Channel { OutboundHTLCState::AwaitingRemoteRevokeToRemove(_) | OutboundHTLCState::AwaitingRemovedRemoteRevoke(_) | OutboundHTLCState::RemoteRemoved(_) => return Err(ChannelError::Close(format!("Remote tried to fulfill/fail HTLC ({}) that they'd already fulfilled/failed", htlc_id))), } - return Ok(&htlc.source); + return Ok(htlc); } } Err(ChannelError::Close("Remote tried to fulfill/fail an HTLC we couldn't find".to_owned())) } - pub fn update_fulfill_htlc(&mut self, msg: &msgs::UpdateFulfillHTLC) -> Result { + pub fn update_fulfill_htlc(&mut self, msg: &msgs::UpdateFulfillHTLC) -> Result<(HTLCSource, u64), ChannelError> { if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) { return Err(ChannelError::Close("Got fulfill HTLC message when channel was not in an operational state".to_owned())); } @@ -2195,7 +2208,7 @@ impl Channel { } let payment_hash = PaymentHash(Sha256::hash(&msg.payment_preimage.0[..]).into_inner()); - self.mark_outbound_htlc_removed(msg.htlc_id, Some(payment_hash), None).map(|source| source.clone()) + self.mark_outbound_htlc_removed(msg.htlc_id, Some(payment_hash), None).map(|htlc| (htlc.source.clone(), htlc.amount_msat)) } pub fn update_fail_htlc(&mut self, msg: &msgs::UpdateFailHTLC, fail_reason: HTLCFailReason) -> Result<(), ChannelError> { @@ -2494,7 +2507,7 @@ impl Channel { // in it hitting the holding cell again and we cannot change the state of a // holding cell HTLC from fulfill to anything else. let (update_fulfill_msg_option, mut additional_monitor_update) = - if let UpdateFulfillFetch::NewClaim { msg, monitor_update } = self.get_update_fulfill_htlc(htlc_id, *payment_preimage, logger) { + if let UpdateFulfillFetch::NewClaim { msg, monitor_update, .. } = self.get_update_fulfill_htlc(htlc_id, *payment_preimage, logger) { (msg, monitor_update) } else { unreachable!() }; update_fulfill_htlcs.push(update_fulfill_msg_option.unwrap()); @@ -3482,7 +3495,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 { @@ -3555,24 +3568,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 @@ -4160,7 +4157,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 { @@ -4516,7 +4513,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,; @@ -4526,7 +4523,7 @@ impl_writeable_tlv_based_enum!(InboundHTLCRemovalReason,; ); impl Writeable for ChannelUpdateStatus { - fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { + fn write(&self, writer: &mut W) -> Result<(), 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. @@ -4541,7 +4538,7 @@ impl Writeable for ChannelUpdateStatus { } impl Readable for ChannelUpdateStatus { - fn read(reader: &mut R) -> Result { + fn read(reader: &mut R) -> Result { Ok(match ::read(reader)? { 0 => ChannelUpdateStatus::Enabled, 1 => ChannelUpdateStatus::Disabled, @@ -4551,14 +4548,20 @@ impl Readable for ChannelUpdateStatus { } impl Writeable for Channel { - fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { + fn write(&self, writer: &mut W) -> Result<(), io::Error> { // Note that we write out as if remove_uncommitted_htlcs_and_mark_paused had just been // called. 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)?; @@ -4717,10 +4720,15 @@ 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)?; + + // 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)?; + + // 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 { @@ -4763,6 +4771,7 @@ impl Writeable for Channel { // override that. (1, self.minimum_depth, option), (3, self.counterparty_selected_channel_reserve_satoshis, option), + (5, self.config, required), }); Ok(()) @@ -4772,11 +4781,22 @@ impl Writeable for Channel { 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); + fn read(reader: &mut R, keys_source: &'a K) -> Result { + 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)?; @@ -4906,20 +4926,25 @@ 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 mut counterparty_selected_channel_reserve_satoshis = Some(Readable::read(reader)?); - if counterparty_selected_channel_reserve_satoshis == Some(0) { - // Versions up to 0.0.98 had counterparty_selected_channel_reserve_satoshis as a - // non-option, writing 0 for what we now consider None. - counterparty_selected_channel_reserve_satoshis = None; + 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 mut minimum_depth = Some(Readable::read(reader)?); - if minimum_depth == Some(0) { - // Versions up to 0.0.98 had minimum_depth as a non-option, writing 0 for what we now - // consider None. - minimum_depth = None; + + 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)? { @@ -4960,6 +4985,7 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel (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(); @@ -4968,7 +4994,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, @@ -5004,9 +5030,9 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel feerate_per_kw, #[cfg(debug_assertions)] - holder_max_commitment_tx_output: ::std::sync::Mutex::new((0, 0)), + holder_max_commitment_tx_output: Mutex::new((0, 0)), #[cfg(debug_assertions)] - counterparty_max_commitment_tx_output: ::std::sync::Mutex::new((0, 0)), + counterparty_max_commitment_tx_output: Mutex::new((0, 0)), last_sent_closing_fee, @@ -5087,7 +5113,7 @@ mod tests { use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::Hash; use bitcoin::hash_types::{Txid, WPubkeyHash}; - use std::sync::Arc; + use sync::Arc; use prelude::*; struct TestFeeEstimator {