X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannelmonitor.rs;h=9b25da5b4c9fd23ce938f551f798021a17efd592;hb=b7407b219d41f727f6967bd0cd046f15795367ab;hp=28ca6714acafaf51c16af07722af0b977fb8300e;hpb=aa84673cdb4ce3eb34e56204327c678100e31582;p=rust-lightning diff --git a/lightning/src/ln/channelmonitor.rs b/lightning/src/ln/channelmonitor.rs index 28ca6714..9b25da5b 100644 --- a/lightning/src/ln/channelmonitor.rs +++ b/lightning/src/ln/channelmonitor.rs @@ -594,6 +594,9 @@ enum OnchainEvent { HTLCUpdate { htlc_update: (HTLCSource, PaymentHash), }, + MaturingOutput { + descriptor: SpendableOutputDescriptor, + }, } const SERIALIZATION_VERSION: u8 = 1; @@ -1065,6 +1068,10 @@ impl ChannelMonitor { htlc_update.0.write(writer)?; htlc_update.1.write(writer)?; }, + OnchainEvent::MaturingOutput { ref descriptor } => { + 1u8.write(writer)?; + descriptor.write(writer)?; + }, } } } @@ -1561,6 +1568,7 @@ impl ChannelMonitor { OnchainEvent::HTLCUpdate { ref htlc_update } => { return htlc_update.0 != **source }, + _ => true } }); e.push(OnchainEvent::HTLCUpdate { htlc_update: ((**source).clone(), htlc.payment_hash.clone())}); @@ -1625,6 +1633,7 @@ impl ChannelMonitor { OnchainEvent::HTLCUpdate { ref htlc_update } => { return htlc_update.0 != **source }, + _ => true } }); e.push(OnchainEvent::HTLCUpdate { htlc_update: ((**source).clone(), htlc.payment_hash.clone())}); @@ -1808,6 +1817,7 @@ impl ChannelMonitor { OnchainEvent::HTLCUpdate { ref htlc_update } => { return htlc_update.0 != $source }, + _ => true } }); e.push(OnchainEvent::HTLCUpdate { htlc_update: ($source, $payment_hash)}); @@ -1961,7 +1971,6 @@ impl ChannelMonitor { log_trace!(self, "Block {} at height {} connected with {} txn matched", block_hash, height, txn_matched.len()); let mut watch_outputs = Vec::new(); - let mut spendable_outputs = Vec::new(); let mut claimable_outpoints = Vec::new(); for tx in txn_matched { if tx.input.len() == 1 { @@ -2011,9 +2020,7 @@ impl ChannelMonitor { // we call is_resolving_htlc_output here outside of the tx.input.len() == 1 check. self.is_resolving_htlc_output(&tx, height); - if let Some(spendable_output) = self.is_paying_spendable_output(&tx) { - spendable_outputs.push(spendable_output); - } + self.is_paying_spendable_output(&tx, height); } let should_broadcast = if let Some(_) = self.current_local_signed_commitment_tx { self.would_broadcast_at_height(height) @@ -2058,6 +2065,12 @@ impl ChannelMonitor { source: htlc_update.0, }); }, + OnchainEvent::MaturingOutput { descriptor } => { + log_trace!(self, "Descriptor {} has got enough confirmations to be passed upstream", log_spendable!(descriptor)); + self.pending_events.push(events::Event::SpendableOutputs { + outputs: vec![descriptor] + }); + } } } } @@ -2068,16 +2081,6 @@ impl ChannelMonitor { self.outputs_to_watch.insert(txid.clone(), output_scripts.iter().map(|o| o.script_pubkey.clone()).collect()); } - for spend in spendable_outputs.iter() { - log_trace!(self, "Announcing spendable output to user: {}", log_spendable!(spend)); - } - - if spendable_outputs.len() > 0 { - self.pending_events.push(events::Event::SpendableOutputs { - outputs: spendable_outputs, - }); - } - watch_outputs } @@ -2089,6 +2092,7 @@ impl ChannelMonitor { if let Some(_) = self.onchain_events_waiting_threshold_conf.remove(&(height + ANTI_REORG_DELAY - 1)) { //We may discard: //- htlc update there as failure-trigger tx (revoked commitment tx, non-revoked commitment tx, HTLC-timeout tx) has been disconnected + //- maturing spendable output has transaction paying us has been disconnected } self.onchain_tx_handler.block_disconnected(height, broadcaster, fee_estimator); @@ -2291,6 +2295,7 @@ impl ChannelMonitor { OnchainEvent::HTLCUpdate { ref htlc_update } => { return htlc_update.0 != source }, + _ => true } }); e.push(OnchainEvent::HTLCUpdate { htlc_update: (source, payment_hash)}); @@ -2305,39 +2310,54 @@ impl ChannelMonitor { } /// Check if any transaction broadcasted is paying fund back to some address we can assume to own - fn is_paying_spendable_output(&self, tx: &Transaction) -> Option { + fn is_paying_spendable_output(&mut self, tx: &Transaction, height: u32) { + let mut spendable_output = None; for (i, outp) in tx.output.iter().enumerate() { // There is max one spendable output for any channel tx, including ones generated by us if outp.script_pubkey == self.destination_script { - return Some(SpendableOutputDescriptor::StaticOutput { + spendable_output = Some(SpendableOutputDescriptor::StaticOutput { outpoint: BitcoinOutPoint { txid: tx.txid(), vout: i as u32 }, output: outp.clone(), }); + break; } else if let Some(ref broadcasted_local_revokable_script) = self.broadcasted_local_revokable_script { if broadcasted_local_revokable_script.0 == outp.script_pubkey { - return Some(SpendableOutputDescriptor::DynamicOutputP2WSH { + spendable_output = Some(SpendableOutputDescriptor::DynamicOutputP2WSH { outpoint: BitcoinOutPoint { txid: tx.txid(), vout: i as u32 }, key: broadcasted_local_revokable_script.1, witness_script: broadcasted_local_revokable_script.2.clone(), to_self_delay: self.their_to_self_delay.unwrap(), output: outp.clone(), }); + break; } } else if let Some(ref broadcasted_remote_payment_script) = self.broadcasted_remote_payment_script { if broadcasted_remote_payment_script.0 == outp.script_pubkey { - return Some(SpendableOutputDescriptor::DynamicOutputP2WPKH { + spendable_output = Some(SpendableOutputDescriptor::DynamicOutputP2WPKH { outpoint: BitcoinOutPoint { txid: tx.txid(), vout: i as u32 }, key: broadcasted_remote_payment_script.1, output: outp.clone(), }); + break; } } else if outp.script_pubkey == self.shutdown_script { - return Some(SpendableOutputDescriptor::StaticOutput { - outpoint: BitcoinOutPoint { txid: tx.txid(), vout: i as u32 }, - output: outp.clone(), + spendable_output = Some(SpendableOutputDescriptor::StaticOutput { + outpoint: BitcoinOutPoint { txid: tx.txid(), vout: i as u32 }, + output: outp.clone(), }); } } - None + if let Some(spendable_output) = spendable_output { + log_trace!(self, "Maturing {} until {}", log_spendable!(spendable_output), height + ANTI_REORG_DELAY - 1); + match self.onchain_events_waiting_threshold_conf.entry(height + ANTI_REORG_DELAY - 1) { + hash_map::Entry::Occupied(mut entry) => { + let e = entry.get_mut(); + e.push(OnchainEvent::MaturingOutput { descriptor: spendable_output }); + } + hash_map::Entry::Vacant(entry) => { + entry.insert(vec![OnchainEvent::MaturingOutput { descriptor: spendable_output }]); + } + } + } } } @@ -2588,6 +2608,12 @@ impl ReadableArgs> for (Sha256dH htlc_update: (htlc_source, hash) } }, + 1 => { + let descriptor = Readable::read(reader)?; + OnchainEvent::MaturingOutput { + descriptor + } + }, _ => return Err(DecodeError::InvalidValue), }; events.push(ev);