From 8c69bb11b8e6c53f69e9a27f6657d69bee1b7e5e Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 6 Feb 2020 13:53:56 -0500 Subject: [PATCH] Update Channel::funding_signed to use ChannelMonitorUpdate This is the first of several steps to update ChannelMonitor updates to use the new ChannelMonitorUpdate objects, demonstrating how the new flow works in Channel. --- lightning/src/ln/chan_utils.rs | 12 +++++- lightning/src/ln/channel.rs | 22 +++++++---- lightning/src/ln/channelmanager.rs | 4 +- lightning/src/ln/channelmonitor.rs | 61 ++++++++++++++++++++++++++---- 4 files changed, 80 insertions(+), 19 deletions(-) diff --git a/lightning/src/ln/chan_utils.rs b/lightning/src/ln/chan_utils.rs index cccbac88..3fd489fa 100644 --- a/lightning/src/ln/chan_utils.rs +++ b/lightning/src/ln/chan_utils.rs @@ -246,7 +246,7 @@ pub(super) fn derive_public_revocation_key(secp_ctx: /// The set of public keys which are used in the creation of one commitment transaction. /// These are derived from the channel base keys and per-commitment data. -#[derive(PartialEq)] +#[derive(PartialEq, Clone)] pub struct TxCreationKeys { /// The per-commitment public key which was used to derive the other keys. pub per_commitment_point: PublicKey, @@ -262,6 +262,8 @@ pub struct TxCreationKeys { /// B's Payment Key pub(crate) b_payment_key: PublicKey, } +impl_writeable!(TxCreationKeys, 33*6, + { per_commitment_point, revocation_key, a_htlc_key, b_htlc_key, a_delayed_payment_key, b_payment_key }); /// One counterparty's public keys which do not change over the life of a channel. #[derive(Clone, PartialEq)] @@ -344,6 +346,14 @@ pub struct HTLCOutputInCommitment { pub transaction_output_index: Option, } +impl_writeable!(HTLCOutputInCommitment, 1 + 8 + 4 + 32 + 5, { + offered, + amount_msat, + cltv_expiry, + payment_hash, + transaction_output_index +}); + #[inline] pub(super) fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommitment, a_htlc_key: &PublicKey, b_htlc_key: &PublicKey, revocation_key: &PublicKey) -> Script { let payment_hash160 = Ripemd160::hash(&htlc.payment_hash.0[..]).into_inner(); diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index a3f89de9..dece3649 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -18,7 +18,7 @@ use secp256k1; use ln::features::{ChannelFeatures, InitFeatures}; use ln::msgs; use ln::msgs::{DecodeError, OptionalField, DataLossProtect}; -use ln::channelmonitor::ChannelMonitor; +use ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep}; use ln::channelmanager::{PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT, MAX_LOCAL_BREAKDOWN_TIMEOUT}; use ln::chan_utils::{CounterpartyCommitmentSecrets, LocalCommitmentTransaction, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript, ChannelPublicKeys}; use ln::chan_utils; @@ -1487,7 +1487,7 @@ impl Channel { // Now that we're past error-generating stuff, update our local state: self.channel_monitor.provide_latest_remote_commitment_tx_info(&remote_initial_commitment_tx, Vec::new(), self.cur_remote_commitment_transaction_number, self.their_cur_commitment_point.unwrap()); - self.channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx, local_keys, self.feerate_per_kw, Vec::new()); + self.channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx, local_keys, self.feerate_per_kw, Vec::new()).unwrap(); self.channel_state = ChannelState::FundingSent as u32; self.channel_id = funding_txo.to_channel_id(); self.cur_remote_commitment_transaction_number -= 1; @@ -1501,7 +1501,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) -> Result, ChannelError> { + pub fn funding_signed(&mut self, msg: &msgs::FundingSigned) -> Result> { if !self.channel_outbound { return Err(ChannelError::Close("Received funding_signed for an inbound channel?")); } @@ -1525,14 +1525,20 @@ impl Channel { // They sign the "local" commitment transaction, allowing us to broadcast the tx if we wish. secp_check!(self.secp_ctx.verify(&local_sighash, &msg.signature, their_funding_pubkey), "Invalid funding_signed signature from peer"); - self.channel_monitor.provide_latest_local_commitment_tx_info( - LocalCommitmentTransaction::new_missing_local_sig(local_initial_commitment_tx, &msg.signature, &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), their_funding_pubkey), - local_keys, self.feerate_per_kw, Vec::new()); + self.latest_monitor_update_id += 1; + let monitor_update = ChannelMonitorUpdate { + update_id: self.latest_monitor_update_id, + updates: vec![ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo { + commitment_tx: LocalCommitmentTransaction::new_missing_local_sig(local_initial_commitment_tx, &msg.signature, &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), their_funding_pubkey), + local_keys, feerate_per_kw: self.feerate_per_kw, htlc_outputs: Vec::new(), + }] + }; + self.channel_monitor.update_monitor(monitor_update.clone()).unwrap(); self.channel_state = ChannelState::FundingSent as u32 | (self.channel_state & (ChannelState::MonitorUpdateFailed as u32)); self.cur_local_commitment_transaction_number -= 1; if self.channel_state & (ChannelState::MonitorUpdateFailed as u32) == 0 { - Ok(self.channel_monitor.clone()) + Ok(monitor_update) } else { Err(ChannelError::Ignore("Previous monitor update failure prevented funding_signed from allowing funding broadcast")) } @@ -1827,7 +1833,7 @@ impl Channel { self.channel_monitor.provide_latest_local_commitment_tx_info( LocalCommitmentTransaction::new_missing_local_sig(local_commitment_tx.0, &msg.signature, &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), &their_funding_pubkey), - local_keys, self.feerate_per_kw, htlcs_and_sigs); + local_keys, self.feerate_per_kw, htlcs_and_sigs).unwrap(); for htlc in self.pending_inbound_htlcs.iter_mut() { let new_forward = if let &InboundHTLCState::RemoteAnnounced(ref forward_info) = &htlc.state { diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index ab80ccae..311cf2e4 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -2105,8 +2105,8 @@ impl ChannelManager, Option)>, + }, } impl Writeable for ChannelMonitorUpdateStep { - fn write(&self, _w: &mut W) -> Result<(), ::std::io::Error> { + fn write(&self, w: &mut W) -> Result<(), ::std::io::Error> { + match self { + &ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo { ref commitment_tx, ref local_keys, ref feerate_per_kw, ref htlc_outputs } => { + 0u8.write(w)?; + commitment_tx.write(w)?; + local_keys.write(w)?; + feerate_per_kw.write(w)?; + (htlc_outputs.len() as u64).write(w)?; + for &(ref output, ref signature, ref source) in htlc_outputs.iter() { + output.write(w)?; + signature.write(w)?; + source.write(w)?; + } + } + } Ok(()) } } impl Readable for ChannelMonitorUpdateStep { - fn read(_r: &mut R) -> Result { - unimplemented!() // We don't have any enum variants to read (and never provide Monitor Updates) + fn read(r: &mut R) -> Result { + match Readable::read(r)? { + 0u8 => { + Ok(ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo { + commitment_tx: Readable::read(r)?, + local_keys: Readable::read(r)?, + feerate_per_kw: Readable::read(r)?, + htlc_outputs: { + let len: u64 = Readable::read(r)?; + let mut res = Vec::new(); + for _ in 0..len { + res.push((Readable::read(r)?, Readable::read(r)?, Readable::read(r)?)); + } + res + }, + }) + }, + _ => Err(DecodeError::InvalidValue), + } } } @@ -1307,8 +1347,10 @@ impl ChannelMonitor { /// is important that any clones of this channel monitor (including remote clones) by kept /// up-to-date as our local commitment transaction is updated. /// Panics if set_their_to_self_delay has never been called. - pub(super) fn provide_latest_local_commitment_tx_info(&mut self, commitment_tx: LocalCommitmentTransaction, local_keys: chan_utils::TxCreationKeys, feerate_per_kw: u64, htlc_outputs: Vec<(HTLCOutputInCommitment, Option, Option)>) { - assert!(self.their_to_self_delay.is_some()); + pub(super) fn provide_latest_local_commitment_tx_info(&mut self, commitment_tx: LocalCommitmentTransaction, local_keys: chan_utils::TxCreationKeys, feerate_per_kw: u64, htlc_outputs: Vec<(HTLCOutputInCommitment, Option, Option)>) -> Result<(), MonitorUpdateError> { + if self.their_to_self_delay.is_none() { + return Err(MonitorUpdateError("Got a local commitment tx info update before we'd set basic information about the channel")); + } self.prev_local_signed_commitment_tx = self.current_local_signed_commitment_tx.take(); self.current_local_signed_commitment_tx = Some(LocalSignedTx { txid: commitment_tx.txid(), @@ -1321,6 +1363,7 @@ impl ChannelMonitor { feerate_per_kw, htlc_outputs, }); + Ok(()) } /// Provides a payment_hash->payment_preimage mapping. Will be automatically pruned when all @@ -1339,6 +1382,8 @@ impl ChannelMonitor { } for update in updates.updates.drain(..) { match update { + ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo { commitment_tx, local_keys, feerate_per_kw, htlc_outputs } => + self.provide_latest_local_commitment_tx_info(commitment_tx, local_keys, feerate_per_kw, htlc_outputs)?, } } self.latest_update_id = updates.update_id; @@ -3514,7 +3559,7 @@ mod tests { let mut monitor = ChannelMonitor::new(keys, &SecretKey::from_slice(&[41; 32]).unwrap(), &SecretKey::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[43; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()), 0, Script::new(), logger.clone()); monitor.their_to_self_delay = Some(10); - monitor.provide_latest_local_commitment_tx_info(LocalCommitmentTransaction::dummy(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..10])); + monitor.provide_latest_local_commitment_tx_info(LocalCommitmentTransaction::dummy(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..10])).unwrap(); monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[5..15]), 281474976710655, dummy_key); monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[15..20]), 281474976710654, dummy_key); monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[17..20]), 281474976710653, dummy_key); @@ -3540,7 +3585,7 @@ mod tests { // Now update local commitment tx info, pruning only element 18 as we still care about the // previous commitment tx's preimages too - monitor.provide_latest_local_commitment_tx_info(LocalCommitmentTransaction::dummy(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..5])); + monitor.provide_latest_local_commitment_tx_info(LocalCommitmentTransaction::dummy(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..5])).unwrap(); secret[0..32].clone_from_slice(&hex::decode("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap()); monitor.provide_secret(281474976710653, secret.clone()).unwrap(); assert_eq!(monitor.payment_preimages.len(), 12); @@ -3548,7 +3593,7 @@ mod tests { test_preimages_exist!(&preimages[18..20], monitor); // But if we do it again, we'll prune 5-10 - monitor.provide_latest_local_commitment_tx_info(LocalCommitmentTransaction::dummy(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..3])); + monitor.provide_latest_local_commitment_tx_info(LocalCommitmentTransaction::dummy(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..3])).unwrap(); secret[0..32].clone_from_slice(&hex::decode("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap()); monitor.provide_secret(281474976710652, secret.clone()).unwrap(); assert_eq!(monitor.payment_preimages.len(), 5); -- 2.30.2