- let remote_hash_commitment_number_len = byte_utils::slice_to_be64(read_bytes!(8));
- if remote_hash_commitment_number_len > data.len() as u64 / 32 { return None; }
- let mut remote_hash_commitment_number = HashMap::with_capacity(remote_hash_commitment_number_len as usize);
- for _ in 0..remote_hash_commitment_number_len {
- let mut txid = [0; 32];
- txid[..].copy_from_slice(read_bytes!(32));
- let commitment_number = byte_utils::slice_to_be48(read_bytes!(6));
- if let Some(_) = remote_hash_commitment_number.insert(txid, commitment_number) {
- return None;
- }
- }
-
- macro_rules! read_local_tx {
- () => {
- {
- let tx_len = byte_utils::slice_to_be64(read_bytes!(8));
- let tx_ser = read_bytes!(tx_len);
- let tx: Transaction = unwrap_obj!(serialize::deserialize(tx_ser));
- if serialize::serialize(&tx).unwrap() != tx_ser {
- // We check that the tx re-serializes to the same form to ensure there is
- // no extra data, and as rust-bitcoin doesn't handle the 0-input ambiguity
- // all that well.
- return None;
- }
-
- let revocation_key = unwrap_obj!(PublicKey::from_slice(&secp_ctx, read_bytes!(33)));
- let a_htlc_key = unwrap_obj!(PublicKey::from_slice(&secp_ctx, read_bytes!(33)));
- let b_htlc_key = unwrap_obj!(PublicKey::from_slice(&secp_ctx, read_bytes!(33)));
- let delayed_payment_key = unwrap_obj!(PublicKey::from_slice(&secp_ctx, read_bytes!(33)));
- let feerate_per_kw = byte_utils::slice_to_be64(read_bytes!(8));
-
- let htlc_outputs_len = byte_utils::slice_to_be64(read_bytes!(8));
- if htlc_outputs_len > data.len() as u64 / 128 { return None; }
- let mut htlc_outputs = Vec::with_capacity(htlc_outputs_len as usize);
- for _ in 0..htlc_outputs_len {
- htlc_outputs.push((read_htlc_in_commitment!(),
- unwrap_obj!(Signature::from_compact(&secp_ctx, read_bytes!(64))),
- unwrap_obj!(Signature::from_compact(&secp_ctx, read_bytes!(64)))));
- }
-
- LocalSignedTx {
- txid: tx.txid(),
- tx, revocation_key, a_htlc_key, b_htlc_key, delayed_payment_key, feerate_per_kw, htlc_outputs
- }
- }
- }
- }
-
- let prev_local_signed_commitment_tx = match read_bytes!(1)[0] {
- 0 => None,
- 1 => {
- Some(read_local_tx!())
- },
- _ => return None,
- };
-
- let current_local_signed_commitment_tx = match read_bytes!(1)[0] {
- 0 => None,
- 1 => {
- Some(read_local_tx!())
- },
- _ => return None,
- };
-
- let payment_preimages_len = byte_utils::slice_to_be64(read_bytes!(8));
- if payment_preimages_len > data.len() as u64 / 32 { return None; }
- let mut payment_preimages = HashMap::with_capacity(payment_preimages_len as usize);
- let mut sha = Sha256::new();
- for _ in 0..payment_preimages_len {
- let mut preimage = [0; 32];
- preimage[..].copy_from_slice(read_bytes!(32));
- sha.reset();
- sha.input(&preimage);
- let mut hash = [0; 32];
- sha.result(&mut hash);
- if let Some(_) = payment_preimages.insert(hash, preimage) {
- return None;
- }
- }
-
- let destination_script_len = byte_utils::slice_to_be64(read_bytes!(8));
- let destination_script = Script::from(read_bytes!(destination_script_len).to_vec());
-
- Some(ChannelMonitor {
- funding_txo,
- commitment_transaction_number_obscure_factor,
-
- key_storage,
- delayed_payment_base_key,
- their_htlc_base_key,
- their_cur_revocation_points,
-
- our_to_self_delay,
- their_to_self_delay,
-
- old_secrets,
- remote_claimable_outpoints,
- remote_commitment_txn_on_chain: Mutex::new(remote_commitment_txn_on_chain),
- remote_hash_commitment_number,
-
- prev_local_signed_commitment_tx,
- current_local_signed_commitment_tx,
-
- payment_preimages,
-
- destination_script,
- secp_ctx,
- })
- }
-
- //TODO: Functions to serialize/deserialize (with different forms depending on which information
- //we want to leave out (eg funding_txo, etc).
-
- /// Can only fail if idx is < get_min_seen_secret
- pub fn get_secret(&self, idx: u64) -> Result<[u8; 32], HandleError> {
- for i in 0..self.old_secrets.len() {
- if (idx & (!((1 << i) - 1))) == self.old_secrets[i].1 {
- return Ok(ChannelMonitor::derive_secret(self.old_secrets[i].0, i as u8, idx))
- }
- }
- assert!(idx < self.get_min_seen_secret());
- Err(HandleError{err: "idx too low", action: None})
- }
-
- pub fn get_min_seen_secret(&self) -> u64 {
- //TODO This can be optimized?
- let mut min = 1 << 48;
- for &(_, idx) in self.old_secrets.iter() {
- if idx < min {
- min = idx;
- }
- }
- min
- }
-
- /// Attempts to claim a remote commitment transaction's outputs using the revocation key and
- /// data in remote_claimable_outpoints. Will directly claim any HTLC outputs which expire at a
- /// height > height + CLTV_SHARED_CLAIM_BUFFER. In any case, will install monitoring for
- /// HTLC-Success/HTLC-Timeout transactions, and claim them using the revocation key (if
- /// applicable) as well.
- fn check_spend_remote_transaction(&self, tx: &Transaction, height: u32) -> Vec<Transaction> {
- // Most secp and related errors trying to create keys means we have no hope of constructing
- // a spend transaction...so we return no transactions to broadcast
- let mut txn_to_broadcast = Vec::new();
- macro_rules! ignore_error {
- ( $thing : expr ) => {
- match $thing {
- Ok(a) => a,
- Err(_) => return txn_to_broadcast
- }
- };
- }
-
- let commitment_txid = tx.txid(); //TODO: This is gonna be a performance bottleneck for watchtowers!
- let per_commitment_option = self.remote_claimable_outpoints.get(&commitment_txid);
-
- let commitment_number = 0xffffffffffff - ((((tx.input[0].sequence as u64 & 0xffffff) << 3*8) | (tx.lock_time as u64 & 0xffffff)) ^ self.commitment_transaction_number_obscure_factor);
- if commitment_number >= self.get_min_seen_secret() {
- let secret = self.get_secret(commitment_number).unwrap();
- let per_commitment_key = ignore_error!(SecretKey::from_slice(&self.secp_ctx, &secret));
- let (revocation_pubkey, b_htlc_key) = match self.key_storage {
- KeyStorage::PrivMode { ref revocation_base_key, ref htlc_base_key } => {
- let per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key);
- (ignore_error!(chan_utils::derive_public_revocation_key(&self.secp_ctx, &per_commitment_point, &PublicKey::from_secret_key(&self.secp_ctx, &revocation_base_key))),
- ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &per_commitment_point, &PublicKey::from_secret_key(&self.secp_ctx, &htlc_base_key))))
- },
- KeyStorage::SigsMode { ref revocation_base_key, ref htlc_base_key, .. } => {
- let per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key);
- (ignore_error!(chan_utils::derive_public_revocation_key(&self.secp_ctx, &per_commitment_point, &revocation_base_key)),
- ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &per_commitment_point, &htlc_base_key)))
- },
- };
- let delayed_key = ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key), &self.delayed_payment_base_key));
- let a_htlc_key = match self.their_htlc_base_key {
- None => return txn_to_broadcast,
- Some(their_htlc_base_key) => ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key), &their_htlc_base_key)),
- };
-
- let revokeable_redeemscript = chan_utils::get_revokeable_redeemscript(&revocation_pubkey, self.our_to_self_delay, &delayed_key);
- let revokeable_p2wsh = revokeable_redeemscript.to_v0_p2wsh();
-
- let mut total_value = 0;
- let mut values = Vec::new();
- let mut inputs = Vec::new();
- let mut htlc_idxs = Vec::new();
-
- for (idx, outp) in tx.output.iter().enumerate() {
- if outp.script_pubkey == revokeable_p2wsh {
- inputs.push(TxIn {
- previous_output: BitcoinOutPoint {
- txid: commitment_txid,
- vout: idx as u32,
- },
- script_sig: Script::new(),
- sequence: 0xfffffffd,
- witness: Vec::new(),
- });
- htlc_idxs.push(None);
- values.push(outp.value);
- total_value += outp.value;
- break; // There can only be one of these
- }