X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fln%2Fchannelmonitor.rs;h=13cdfd2fe5d75433c5c28db097af4c12c0965de1;hb=608cf1c89db01f9cf612516a88a3f77f1f48bc52;hp=045ee36d28af6387794736659312cfc8f80a7c52;hpb=f1e400f142c3411b229b108587401c45a5f51cc8;p=rust-lightning diff --git a/src/ln/channelmonitor.rs b/src/ln/channelmonitor.rs index 045ee36d..13cdfd2f 100644 --- a/src/ln/channelmonitor.rs +++ b/src/ln/channelmonitor.rs @@ -17,11 +17,12 @@ use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint; use bitcoin::blockdata::script::{Script, Builder}; use bitcoin::blockdata::opcodes; use bitcoin::consensus::encode::{self, Decodable, Encodable}; -use bitcoin::util::hash::{Hash160, BitcoinHash,Sha256dHash}; +use bitcoin::util::hash::{BitcoinHash,Sha256dHash}; use bitcoin::util::bip143; use bitcoin_hashes::Hash; use bitcoin_hashes::sha256::Hash as Sha256; +use bitcoin_hashes::hash160::Hash as Hash160; use secp256k1::{Secp256k1,Message,Signature}; use secp256k1::key::{SecretKey,PublicKey}; @@ -567,6 +568,8 @@ impl ChannelMonitor { } let new_txid = unsigned_commitment_tx.txid(); + log_trace!(self, "Tracking new remote commitment transaction with txid {} at commitment number {} with {} HTLC outputs", new_txid, commitment_number, htlc_outputs.len()); + log_trace!(self, "New potential remote commitment transaction: {}", encode::serialize_hex(unsigned_commitment_tx)); if let Storage::Local { ref mut current_remote_commitment_txid, ref mut prev_remote_commitment_txid, .. } = self.key_storage { *prev_remote_commitment_txid = current_remote_commitment_txid.take(); *current_remote_commitment_txid = Some(new_txid); @@ -986,9 +989,6 @@ impl ChannelMonitor { self.write(writer, false) } - //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(super) fn get_secret(&self, idx: u64) -> Option<[u8; 32]> { for i in 0..self.old_secrets.len() { @@ -1077,7 +1077,7 @@ impl ChannelMonitor { let local_payment_p2wpkh = if let Some(payment_key) = local_payment_key { // Note that the Network here is ignored as we immediately drop the address for the // script_pubkey version. - let payment_hash160 = Hash160::from_data(&PublicKey::from_secret_key(&self.secp_ctx, &payment_key).serialize()); + let payment_hash160 = Hash160::hash(&PublicKey::from_secret_key(&self.secp_ctx, &payment_key).serialize()); Some(Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0).push_slice(&payment_hash160[..]).into_script()) } else { None }; @@ -1245,6 +1245,44 @@ impl ChannelMonitor { watch_outputs.append(&mut tx.output.clone()); self.remote_commitment_txn_on_chain.insert(commitment_txid, (commitment_number, tx.output.iter().map(|output| { output.script_pubkey.clone() }).collect())); + log_trace!(self, "Got broadcast of non-revoked remote commitment transaction {}", commitment_txid); + + // TODO: We really should only fail backwards after our revocation claims have been + // confirmed, but we also need to do more other tracking of in-flight pre-confirm + // on-chain claims, so we can do that at the same time. + macro_rules! check_htlc_fails { + ($txid: expr, $commitment_tx: expr, $id: tt) => { + if let Some(&(_, ref latest_outpoints)) = self.remote_claimable_outpoints.get(&$txid) { + $id: for &(ref payment_hash, ref source, _) in latest_outpoints.iter() { + // Check if the HTLC is present in the commitment transaction that was + // broadcast, but not if it was below the dust limit, which we should + // fail backwards immediately as there is no way for us to learn the + // payment_preimage. + // Note that if the dust limit were allowed to change between + // commitment transactions we'd want to be check whether *any* + // broadcastable commitment transaction has the HTLC in it, but it + // cannot currently change after channel initialization, so we don't + // need to here. + for &(_, ref broadcast_source, ref output_idx) in per_commitment_data.1.iter() { + if output_idx.is_some() && source == broadcast_source { + continue $id; + } + } + log_trace!(self, "Failing HTLC with payment_hash {} from {} remote commitment tx due to broadcast of remote commitment transaction", log_bytes!(payment_hash.0), $commitment_tx); + htlc_updated.push(((*source).clone(), None, payment_hash.clone())); + } + } + } + } + if let Storage::Local { ref current_remote_commitment_txid, ref prev_remote_commitment_txid, .. } = self.key_storage { + if let &Some(ref txid) = current_remote_commitment_txid { + check_htlc_fails!(txid, "current", 'current_loop); + } + if let &Some(ref txid) = prev_remote_commitment_txid { + check_htlc_fails!(txid, "previous", 'prev_loop); + } + } + if let Some(revocation_points) = self.their_cur_revocation_points { let revocation_point_option = if revocation_points.0 == commitment_number { Some(&revocation_points.1) } @@ -1405,10 +1443,6 @@ impl ChannelMonitor { output: spend_tx.output[0].clone(), }); txn_to_broadcast.push(spend_tx); - - // TODO: We need to fail back HTLCs that were't included in the broadcast - // commitment transaction, either because they didn't meet dust or because a - // stale (but not yet revoked) commitment transaction was broadcast! } } } @@ -1619,7 +1653,7 @@ impl ChannelMonitor { if tx.input[0].sequence == 0xFFFFFFFF && !tx.input[0].witness.is_empty() && tx.input[0].witness.last().unwrap().len() == 71 { match self.key_storage { Storage::Local { ref shutdown_pubkey, .. } => { - let our_channel_close_key_hash = Hash160::from_data(&shutdown_pubkey.serialize()); + let our_channel_close_key_hash = Hash160::hash(&shutdown_pubkey.serialize()); let shutdown_script = Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0).push_slice(&our_channel_close_key_hash[..]).into_script(); for (idx, output) in tx.output.iter().enumerate() { if shutdown_script == output.script_pubkey {