- *current_remote_commitment_txid = Some(new_txid);
- }
- self.remote_claimable_outpoints.insert(new_txid, htlc_outputs);
- self.current_remote_commitment_number = commitment_number;
- //TODO: Merge this into the other per-remote-transaction output storage stuff
- match self.their_cur_revocation_points {
- Some(old_points) => {
- if old_points.0 == commitment_number + 1 {
- self.their_cur_revocation_points = Some((old_points.0, old_points.1, Some(their_revocation_point)));
- } else if old_points.0 == commitment_number + 2 {
- if let Some(old_second_point) = old_points.2 {
- self.their_cur_revocation_points = Some((old_points.0 - 1, old_second_point, Some(their_revocation_point)));
- } else {
- self.their_cur_revocation_points = Some((commitment_number, their_revocation_point, None));
- }
- } else {
- self.their_cur_revocation_points = Some((commitment_number, their_revocation_point, None));
- }
- },
- None => {
- self.their_cur_revocation_points = Some((commitment_number, their_revocation_point, None));
- }
- }
- }
-
- pub(super) fn provide_rescue_remote_commitment_tx_info(&mut self, their_revocation_point: PublicKey) {
- match self.key_storage {
- Storage::Local { ref payment_base_key, .. } => {
- if let Ok(payment_key) = chan_utils::derive_public_key(&self.secp_ctx, &their_revocation_point, &PublicKey::from_secret_key(&self.secp_ctx, &payment_base_key)) {
- let to_remote_script = Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0)
- .push_slice(&Hash160::hash(&payment_key.serialize())[..])
- .into_script();
- if let Ok(to_remote_key) = chan_utils::derive_private_key(&self.secp_ctx, &their_revocation_point, &payment_base_key) {
- self.to_remote_rescue = Some((to_remote_script, to_remote_key));
- }
- }
- },
- Storage::Watchtower { .. } => {}
- }
- }
-
- /// Informs this monitor of the latest local (ie broadcastable) commitment transaction. The
- /// monitor watches for timeouts and may broadcast it if we approach such a timeout. Thus, it
- /// 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<Signature>, Option<HTLCSource>)>) {
- assert!(self.their_to_self_delay.is_some());
- 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(),
- tx: commitment_tx,
- revocation_key: local_keys.revocation_key,
- a_htlc_key: local_keys.a_htlc_key,
- b_htlc_key: local_keys.b_htlc_key,
- delayed_payment_key: local_keys.a_delayed_payment_key,
- per_commitment_point: local_keys.per_commitment_point,
- feerate_per_kw,
- htlc_outputs,
- });
- }
-
- /// Provides a payment_hash->payment_preimage mapping. Will be automatically pruned when all
- /// commitment_tx_infos which contain the payment hash have been revoked.
- pub(super) fn provide_payment_preimage(&mut self, payment_hash: &PaymentHash, payment_preimage: &PaymentPreimage) {
- self.payment_preimages.insert(payment_hash.clone(), payment_preimage.clone());
- }
-
- /// Combines this ChannelMonitor with the information contained in the other ChannelMonitor.
- /// After a successful call this ChannelMonitor is up-to-date and is safe to use to monitor the
- /// chain for new blocks/transactions.
- pub fn insert_combine(&mut self, mut other: ChannelMonitor) -> Result<(), MonitorUpdateError> {
- match self.key_storage {
- Storage::Local { ref funding_info, .. } => {
- if funding_info.is_none() { return Err(MonitorUpdateError("Try to combine a Local monitor without funding_info")); }
- let our_funding_info = funding_info;
- if let Storage::Local { ref funding_info, .. } = other.key_storage {
- if funding_info.is_none() { return Err(MonitorUpdateError("Try to combine a Local monitor without funding_info")); }
- // We should be able to compare the entire funding_txo, but in fuzztarget it's trivially
- // easy to collide the funding_txo hash and have a different scriptPubKey.
- if funding_info.as_ref().unwrap().0 != our_funding_info.as_ref().unwrap().0 {
- return Err(MonitorUpdateError("Funding transaction outputs are not identical!"));
- }
- } else {
- return Err(MonitorUpdateError("Try to combine a Local monitor with a Watchtower one !"));
- }
- },
- Storage::Watchtower { .. } => {
- if let Storage::Watchtower { .. } = other.key_storage {
- unimplemented!();
- } else {
- return Err(MonitorUpdateError("Try to combine a Watchtower monitor with a Local one !"));
- }
- },
- }
- let other_min_secret = other.get_min_seen_secret();
- let our_min_secret = self.get_min_seen_secret();
- if our_min_secret > other_min_secret {
- self.provide_secret(other_min_secret, other.get_secret(other_min_secret).unwrap())?;
- }
- if let Some(ref local_tx) = self.current_local_signed_commitment_tx {
- if let Some(ref other_local_tx) = other.current_local_signed_commitment_tx {
- let our_commitment_number = 0xffffffffffff - ((((local_tx.tx.without_valid_witness().input[0].sequence as u64 & 0xffffff) << 3*8) | (local_tx.tx.without_valid_witness().lock_time as u64 & 0xffffff)) ^ self.commitment_transaction_number_obscure_factor);
- let other_commitment_number = 0xffffffffffff - ((((other_local_tx.tx.without_valid_witness().input[0].sequence as u64 & 0xffffff) << 3*8) | (other_local_tx.tx.without_valid_witness().lock_time as u64 & 0xffffff)) ^ other.commitment_transaction_number_obscure_factor);
- if our_commitment_number >= other_commitment_number {
- self.key_storage = other.key_storage;
- }
- }
- }
- // TODO: We should use current_remote_commitment_number and the commitment number out of
- // local transactions to decide how to merge
- if our_min_secret >= other_min_secret {
- self.their_cur_revocation_points = other.their_cur_revocation_points;
- for (txid, htlcs) in other.remote_claimable_outpoints.drain() {
- self.remote_claimable_outpoints.insert(txid, htlcs);
- }
- if let Some(local_tx) = other.prev_local_signed_commitment_tx {
- self.prev_local_signed_commitment_tx = Some(local_tx);
- }
- if let Some(local_tx) = other.current_local_signed_commitment_tx {
- self.current_local_signed_commitment_tx = Some(local_tx);
- }
- self.payment_preimages = other.payment_preimages;
- self.to_remote_rescue = other.to_remote_rescue;
- }
-
- self.current_remote_commitment_number = cmp::min(self.current_remote_commitment_number, other.current_remote_commitment_number);
- Ok(())
- }
-
- /// Allows this monitor to scan only for transactions which are applicable. Note that this is
- /// optional, without it this monitor cannot be used in an SPV client, but you may wish to
- /// avoid this (or call unset_funding_info) on a monitor you wish to send to a watchtower as it
- /// provides slightly better privacy.
- /// It's the responsibility of the caller to register outpoint and script with passing the former
- /// value as key to add_update_monitor.
- pub(super) fn set_funding_info(&mut self, new_funding_info: (OutPoint, Script)) {
- match self.key_storage {
- Storage::Local { ref mut funding_info, .. } => {
- *funding_info = Some(new_funding_info);
- },
- Storage::Watchtower { .. } => {
- panic!("Channel somehow ended up with its internal ChannelMonitor being in Watchtower mode?");
- }
- }
- }
-
- /// We log these base keys at channel opening to being able to rebuild redeemscript in case of leaked revoked commit tx
- /// Panics if commitment_transaction_number_obscure_factor doesn't fit in 48 bits
- pub(super) fn set_basic_channel_info(&mut self, their_htlc_base_key: &PublicKey, their_delayed_payment_base_key: &PublicKey, their_to_self_delay: u16, funding_redeemscript: Script, channel_value_satoshis: u64, commitment_transaction_number_obscure_factor: u64) {
- self.their_htlc_base_key = Some(their_htlc_base_key.clone());
- self.their_delayed_payment_base_key = Some(their_delayed_payment_base_key.clone());
- self.their_to_self_delay = Some(their_to_self_delay);
- self.funding_redeemscript = Some(funding_redeemscript);
- self.channel_value_satoshis = Some(channel_value_satoshis);
- assert!(commitment_transaction_number_obscure_factor < (1 << 48));
- self.commitment_transaction_number_obscure_factor = commitment_transaction_number_obscure_factor;
- }
-
- pub(super) fn unset_funding_info(&mut self) {
- match self.key_storage {
- Storage::Local { ref mut funding_info, .. } => {
- *funding_info = None;
- },
- Storage::Watchtower { .. } => {
- panic!("Channel somehow ended up with its internal ChannelMonitor being in Watchtower mode?");
- },
- }
- }
-
- /// Gets the funding transaction outpoint of the channel this ChannelMonitor is monitoring for.
- pub fn get_funding_txo(&self) -> Option<OutPoint> {
- match self.key_storage {
- Storage::Local { ref funding_info, .. } => {
- match funding_info {
- &Some((outpoint, _)) => Some(outpoint),
- &None => None
- }
- },
- Storage::Watchtower { .. } => {
- return None;
- }
- }
- }
-
- /// Gets the sets of all outpoints which this ChannelMonitor expects to hear about spends of.
- /// Generally useful when deserializing as during normal operation the return values of
- /// block_connected are sufficient to ensure all relevant outpoints are being monitored (note
- /// that the get_funding_txo outpoint and transaction must also be monitored for!).
- pub fn get_monitored_outpoints(&self) -> Vec<(Sha256dHash, u32, &Script)> {
- let mut res = Vec::with_capacity(self.remote_commitment_txn_on_chain.len() * 2);
- for (ref txid, &(_, ref outputs)) in self.remote_commitment_txn_on_chain.iter() {
- for (idx, output) in outputs.iter().enumerate() {
- res.push(((*txid).clone(), idx as u32, output));
- }
- }
- res
- }
-
- /// Serializes into a vec, with various modes for the exposed pub fns
- fn write<W: Writer>(&self, writer: &mut W, for_local_storage: bool) -> Result<(), ::std::io::Error> {
- //TODO: We still write out all the serialization here manually instead of using the fancy
- //serialization framework we have, we should migrate things over to it.
- writer.write_all(&[SERIALIZATION_VERSION; 1])?;
- writer.write_all(&[MIN_SERIALIZATION_VERSION; 1])?;
-
- // Set in initial Channel-object creation, so should always be set by now:
- U48(self.commitment_transaction_number_obscure_factor).write(writer)?;
-
- macro_rules! write_option {
- ($thing: expr) => {
- match $thing {
- &Some(ref t) => {
- 1u8.write(writer)?;
- t.write(writer)?;
- },
- &None => 0u8.write(writer)?,
- }
- }
- }
-
- match self.key_storage {
- Storage::Local { ref funding_key, ref revocation_base_key, ref htlc_base_key, ref delayed_payment_base_key, ref payment_base_key, ref shutdown_pubkey, ref funding_info, ref current_remote_commitment_txid, ref prev_remote_commitment_txid } => {
- writer.write_all(&[0; 1])?;
- writer.write_all(&funding_key[..])?;
- writer.write_all(&revocation_base_key[..])?;
- writer.write_all(&htlc_base_key[..])?;
- writer.write_all(&delayed_payment_base_key[..])?;
- writer.write_all(&payment_base_key[..])?;
- writer.write_all(&shutdown_pubkey.serialize())?;
- match funding_info {
- &Some((ref outpoint, ref script)) => {
- writer.write_all(&outpoint.txid[..])?;
- writer.write_all(&byte_utils::be16_to_array(outpoint.index))?;
- script.write(writer)?;
- },
- &None => {
- debug_assert!(false, "Try to serialize a useless Local monitor !");
- },
- }
- current_remote_commitment_txid.write(writer)?;
- prev_remote_commitment_txid.write(writer)?;
- },
- Storage::Watchtower { .. } => unimplemented!(),
- }
-
- writer.write_all(&self.their_htlc_base_key.as_ref().unwrap().serialize())?;
- writer.write_all(&self.their_delayed_payment_base_key.as_ref().unwrap().serialize())?;
- self.funding_redeemscript.as_ref().unwrap().write(writer)?;
- self.channel_value_satoshis.unwrap().write(writer)?;
-
- match self.their_cur_revocation_points {
- Some((idx, pubkey, second_option)) => {
- writer.write_all(&byte_utils::be48_to_array(idx))?;
- writer.write_all(&pubkey.serialize())?;
- match second_option {
- Some(second_pubkey) => {
- writer.write_all(&second_pubkey.serialize())?;
- },
- None => {
- writer.write_all(&[0; 33])?;
- },
- }
- },
- None => {
- writer.write_all(&byte_utils::be48_to_array(0))?;
- },
- }
-
- writer.write_all(&byte_utils::be16_to_array(self.our_to_self_delay))?;
- writer.write_all(&byte_utils::be16_to_array(self.their_to_self_delay.unwrap()))?;
-
- for &(ref secret, ref idx) in self.old_secrets.iter() {
- writer.write_all(secret)?;
- writer.write_all(&byte_utils::be64_to_array(*idx))?;
- }
-
- macro_rules! serialize_htlc_in_commitment {
- ($htlc_output: expr) => {
- writer.write_all(&[$htlc_output.offered as u8; 1])?;
- writer.write_all(&byte_utils::be64_to_array($htlc_output.amount_msat))?;
- writer.write_all(&byte_utils::be32_to_array($htlc_output.cltv_expiry))?;
- writer.write_all(&$htlc_output.payment_hash.0[..])?;
- $htlc_output.transaction_output_index.write(writer)?;
- }
- }
-
- writer.write_all(&byte_utils::be64_to_array(self.remote_claimable_outpoints.len() as u64))?;
- for (ref txid, ref htlc_infos) in self.remote_claimable_outpoints.iter() {
- writer.write_all(&txid[..])?;
- writer.write_all(&byte_utils::be64_to_array(htlc_infos.len() as u64))?;
- for &(ref htlc_output, ref htlc_source) in htlc_infos.iter() {
- serialize_htlc_in_commitment!(htlc_output);
- write_option!(htlc_source);
- }
- }
-
- writer.write_all(&byte_utils::be64_to_array(self.remote_commitment_txn_on_chain.len() as u64))?;
- for (ref txid, &(commitment_number, ref txouts)) in self.remote_commitment_txn_on_chain.iter() {
- writer.write_all(&txid[..])?;
- writer.write_all(&byte_utils::be48_to_array(commitment_number))?;
- (txouts.len() as u64).write(writer)?;
- for script in txouts.iter() {
- script.write(writer)?;
- }
- }
-
- if for_local_storage {
- writer.write_all(&byte_utils::be64_to_array(self.remote_hash_commitment_number.len() as u64))?;
- for (ref payment_hash, commitment_number) in self.remote_hash_commitment_number.iter() {
- writer.write_all(&payment_hash.0[..])?;
- writer.write_all(&byte_utils::be48_to_array(*commitment_number))?;
- }
- } else {
- writer.write_all(&byte_utils::be64_to_array(0))?;
- }
-
- macro_rules! serialize_local_tx {
- ($local_tx: expr) => {
- $local_tx.tx.write(writer)?;
- writer.write_all(&$local_tx.revocation_key.serialize())?;
- writer.write_all(&$local_tx.a_htlc_key.serialize())?;
- writer.write_all(&$local_tx.b_htlc_key.serialize())?;
- writer.write_all(&$local_tx.delayed_payment_key.serialize())?;
- writer.write_all(&$local_tx.per_commitment_point.serialize())?;
-
- writer.write_all(&byte_utils::be64_to_array($local_tx.feerate_per_kw))?;
- writer.write_all(&byte_utils::be64_to_array($local_tx.htlc_outputs.len() as u64))?;
- for &(ref htlc_output, ref sig, ref htlc_source) in $local_tx.htlc_outputs.iter() {
- serialize_htlc_in_commitment!(htlc_output);
- if let &Some(ref their_sig) = sig {
- 1u8.write(writer)?;
- writer.write_all(&their_sig.serialize_compact())?;