From 24351f5868ad8f379ecfd11253d3983305dd424d Mon Sep 17 00:00:00 2001 From: Jeffrey Czyz Date: Wed, 31 Mar 2021 13:54:01 -0400 Subject: [PATCH] Add txid to on-chain event tracking When using Electrum, transactions are individually unconfirmed during a reorg rather than by block. Store the txid of the transaction creating the on-chain event so that it can be used to determine which events need to be removed when a transaction is unconfirmed. --- lightning/src/chain/channelmonitor.rs | 13 +++++++++++-- lightning/src/ln/onchaintx.rs | 10 ++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index 0e8af8aa8..4651a55a6 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -465,11 +465,13 @@ pub(crate) struct ClaimRequest { pub(crate) witness_data: InputMaterial } -/// An entry for an [`OnchainEvent`], stating the block height when the event was observed. +/// An entry for an [`OnchainEvent`], stating the block height when the event was observed and the +/// transaction causing it. /// /// Used to determine when the on-chain event can be considered safe from a chain reorganization. #[derive(PartialEq)] struct OnchainEventEntry { + txid: Txid, height: u32, event: OnchainEvent, } @@ -954,6 +956,7 @@ impl Writeable for ChannelMonitorImpl { writer.write_all(&byte_utils::be64_to_array(self.onchain_events_waiting_threshold_conf.len() as u64))?; for ref entry in self.onchain_events_waiting_threshold_conf.iter() { + entry.txid.write(writer)?; writer.write_all(&byte_utils::be32_to_array(entry.height))?; match entry.event { OnchainEvent::HTLCUpdate { ref htlc_update } => { @@ -1665,6 +1668,7 @@ impl ChannelMonitorImpl { } }); let entry = OnchainEventEntry { + txid: *$txid, height, event: OnchainEvent::HTLCUpdate { htlc_update: ((**source).clone(), htlc.payment_hash.clone()) @@ -1730,6 +1734,7 @@ impl ChannelMonitorImpl { } }); self.onchain_events_waiting_threshold_conf.push(OnchainEventEntry { + txid: *$txid, height, event: OnchainEvent::HTLCUpdate { htlc_update: ((**source).clone(), htlc.payment_hash.clone()) @@ -1885,6 +1890,7 @@ impl ChannelMonitorImpl { } }); let entry = OnchainEventEntry { + txid: commitment_txid, height, event: OnchainEvent::HTLCUpdate { htlc_update: ($source, $payment_hash) }, }; @@ -2403,6 +2409,7 @@ impl ChannelMonitorImpl { } }); let entry = OnchainEventEntry { + txid: tx.txid(), height, event: OnchainEvent::HTLCUpdate { htlc_update: (source, payment_hash) }, }; @@ -2467,6 +2474,7 @@ impl ChannelMonitorImpl { } if let Some(spendable_output) = spendable_output { let entry = OnchainEventEntry { + txid: tx.txid(), height: height, event: OnchainEvent::MaturingOutput { descriptor: spendable_output.clone() }, }; @@ -2739,6 +2747,7 @@ impl<'a, Signer: Sign, K: KeysInterface> ReadableArgs<&'a K> let waiting_threshold_conf_len: u64 = Readable::read(reader)?; let mut onchain_events_waiting_threshold_conf = Vec::with_capacity(cmp::min(waiting_threshold_conf_len as usize, MAX_ALLOC_SIZE / 128)); for _ in 0..waiting_threshold_conf_len { + let txid = Readable::read(reader)?; let height = Readable::read(reader)?; let event = match ::read(reader)? { 0 => { @@ -2756,7 +2765,7 @@ impl<'a, Signer: Sign, K: KeysInterface> ReadableArgs<&'a K> }, _ => return Err(DecodeError::InvalidValue), }; - onchain_events_waiting_threshold_conf.push(OnchainEventEntry { height, event }); + onchain_events_waiting_threshold_conf.push(OnchainEventEntry { txid, height, event }); } let outputs_to_watch_len: u64 = Readable::read(reader)?; diff --git a/lightning/src/ln/onchaintx.rs b/lightning/src/ln/onchaintx.rs index 4ad013040..7613fa2b6 100644 --- a/lightning/src/ln/onchaintx.rs +++ b/lightning/src/ln/onchaintx.rs @@ -39,11 +39,13 @@ use std::mem::replace; const MAX_ALLOC_SIZE: usize = 64*1024; -/// An entry for an [`OnchainEvent`], stating the block height when the event was observed. +/// An entry for an [`OnchainEvent`], stating the block height when the event was observed and the +/// transaction causing it. /// /// Used to determine when the on-chain event can be considered safe from a chain reorganization. #[derive(PartialEq)] struct OnchainEventEntry { + txid: Txid, height: u32, event: OnchainEvent, } @@ -338,6 +340,7 @@ impl OnchainTxHandler { writer.write_all(&byte_utils::be64_to_array(self.onchain_events_waiting_threshold_conf.len() as u64))?; for ref entry in self.onchain_events_waiting_threshold_conf.iter() { + entry.txid.write(writer)?; writer.write_all(&byte_utils::be32_to_array(entry.height))?; match entry.event { OnchainEvent::Claim { ref claim_request } => { @@ -395,6 +398,7 @@ impl<'a, K: KeysInterface> ReadableArgs<&'a K> for OnchainTxHandler { let waiting_threshold_conf_len: u64 = Readable::read(reader)?; let mut onchain_events_waiting_threshold_conf = Vec::with_capacity(cmp::min(waiting_threshold_conf_len as usize, MAX_ALLOC_SIZE / 128)); for _ in 0..waiting_threshold_conf_len { + let txid = Readable::read(reader)?; let height = Readable::read(reader)?; let event = match ::read(reader)? { 0 => { @@ -413,7 +417,7 @@ impl<'a, K: KeysInterface> ReadableArgs<&'a K> for OnchainTxHandler { } _ => return Err(DecodeError::InvalidValue), }; - onchain_events_waiting_threshold_conf.push(OnchainEventEntry { height, event }); + onchain_events_waiting_threshold_conf.push(OnchainEventEntry { txid, height, event }); } let latest_height = Readable::read(reader)?; @@ -768,6 +772,7 @@ impl OnchainTxHandler { macro_rules! clean_claim_request_after_safety_delay { () => { let entry = OnchainEventEntry { + txid: tx.txid(), height, event: OnchainEvent::Claim { claim_request: first_claim_txid_height.0.clone() } }; @@ -807,6 +812,7 @@ impl OnchainTxHandler { } for (outpoint, input_material) in claimed_outputs_material.drain(..) { let entry = OnchainEventEntry { + txid: tx.txid(), height, event: OnchainEvent::ContentiousOutpoint { outpoint, input_material }, }; -- 2.39.5