Skip to content

Commit 45825f5

Browse files
committed
Track the full list of outpoints a chanmon wants monitoring for.
Upon deserialization/reload we need to be able to register each outpoint which spends the commitment txo which a channelmonitor believes to be on chain. While our other internal tracking is likely sufficient to regenerate these, its much easier to simply track all outpouts we've ever generated, so we do that here.
1 parent 425e4ad commit 45825f5

File tree

1 file changed

+54
-4
lines changed

1 file changed

+54
-4
lines changed

lightning/src/ln/channelmonitor.rs

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,13 @@ pub struct HTLCUpdate {
117117
pub trait ManyChannelMonitor<ChanSigner: ChannelKeys>: Send + Sync {
118118
/// Adds or updates a monitor for the given `funding_txo`.
119119
///
120-
/// Implementor must also ensure that the funding_txo outpoint is registered with any relevant
121-
/// ChainWatchInterfaces such that the provided monitor receives block_connected callbacks with
122-
/// any spends of it.
120+
/// Implementer must also ensure that the funding_txo txid *and* outpoint are registered with
121+
/// any relevant ChainWatchInterfaces such that the provided monitor receives block_connected
122+
/// callbacks with the funding transaction, or any spends of it.
123+
///
124+
/// Further, the implementer must also ensure that each output returned in
125+
/// monitor.get_watch_outputs() is registered to ensure that the provided monitor learns about
126+
/// any spends of any of the outputs.
123127
fn add_update_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor<ChanSigner>) -> Result<(), ChannelMonitorUpdateErr>;
124128

125129
/// Used by ChannelManager to get list of HTLC resolved onchain and which needed to be updated
@@ -259,6 +263,11 @@ impl<Key : Send + cmp::Eq + hash::Hash + 'static, ChanSigner: ChannelKeys> Simpl
259263
self.chain_monitor.watch_all_txn();
260264
}
261265
}
266+
for (txid, outputs) in monitor.get_watch_outputs().iter() {
267+
for (idx, script) in outputs.iter().enumerate() {
268+
self.chain_monitor.install_watch_outpoint((*txid, idx as u32), script);
269+
}
270+
}
262271
monitors.insert(key, monitor);
263272
Ok(())
264273
}
@@ -666,6 +675,12 @@ pub struct ChannelMonitor<ChanSigner: ChannelKeys> {
666675
// actions when we receive a block with given height. Actions depend on OnchainEvent type.
667676
onchain_events_waiting_threshold_conf: HashMap<u32, Vec<OnchainEvent>>,
668677

678+
// If we get serialized out and re-read, we need to make sure that the chain monitoring
679+
// interface knows about the TXOs that we want to be notified of spends of. We could probably
680+
// be smart and derive them from the above storage fields, but its much simpler and more
681+
// Obviously Correct (tm) if we just keep track of them explicitly.
682+
watch_outputs: HashMap<Sha256dHash, Vec<Script>>,
683+
669684
// We simply modify last_block_hash in Channel's block_connected so that serialization is
670685
// consistent but hopefully the users' copy handles block_connected in a consistent way.
671686
// (we do *not*, however, update them in insert_combine to ensure any local user copies keep
@@ -736,7 +751,8 @@ impl<ChanSigner: ChannelKeys> PartialEq for ChannelMonitor<ChanSigner> {
736751
self.to_remote_rescue != other.to_remote_rescue ||
737752
self.pending_claim_requests != other.pending_claim_requests ||
738753
self.claimable_outpoints != other.claimable_outpoints ||
739-
self.onchain_events_waiting_threshold_conf != other.onchain_events_waiting_threshold_conf
754+
self.onchain_events_waiting_threshold_conf != other.onchain_events_waiting_threshold_conf ||
755+
self.watch_outputs != other.watch_outputs
740756
{
741757
false
742758
} else {
@@ -966,6 +982,15 @@ impl<ChanSigner: ChannelKeys + Writeable> ChannelMonitor<ChanSigner> {
966982
}
967983
}
968984

985+
(self.watch_outputs.len() as u64).write(writer)?;
986+
for (txid, output_scripts) in self.watch_outputs.iter() {
987+
txid.write(writer)?;
988+
(output_scripts.len() as u64).write(writer)?;
989+
for script in output_scripts.iter() {
990+
script.write(writer)?;
991+
}
992+
}
993+
969994
Ok(())
970995
}
971996

@@ -1036,6 +1061,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
10361061
claimable_outpoints: HashMap::new(),
10371062

10381063
onchain_events_waiting_threshold_conf: HashMap::new(),
1064+
watch_outputs: HashMap::new(),
10391065

10401066
last_block_hash: Default::default(),
10411067
secp_ctx: Secp256k1::new(),
@@ -1370,6 +1396,12 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
13701396
}
13711397
}
13721398

1399+
/// Gets a list of txids, with their output scripts (in the order they appear in the
1400+
/// transaction), which we must learn about spends of via block_connected().
1401+
pub fn get_watch_outputs(&self) -> &HashMap<Sha256dHash, Vec<Script>> {
1402+
&self.watch_outputs
1403+
}
1404+
13731405
/// Gets the sets of all outpoints which this ChannelMonitor expects to hear about spends of.
13741406
/// Generally useful when deserializing as during normal operation the return values of
13751407
/// block_connected are sufficient to ensure all relevant outpoints are being monitored (note
@@ -2589,6 +2621,9 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
25892621
}
25902622
}
25912623
self.last_block_hash = block_hash.clone();
2624+
for &(ref txid, ref output_scripts) in watch_outputs.iter() {
2625+
self.watch_outputs.insert(txid.clone(), output_scripts.iter().map(|o| o.script_pubkey.clone()).collect());
2626+
}
25922627
(watch_outputs, spendable_outputs, htlc_updated)
25932628
}
25942629

@@ -3242,6 +3277,20 @@ impl<R: ::std::io::Read, ChanSigner: ChannelKeys + Readable<R>> ReadableArgs<R,
32423277
onchain_events_waiting_threshold_conf.insert(height_target, events);
32433278
}
32443279

3280+
let watch_outputs_len: u64 = Readable::read(reader)?;
3281+
let mut watch_outputs = HashMap::with_capacity(cmp::min(watch_outputs_len as usize, MAX_ALLOC_SIZE / (32 + 3*8)));
3282+
for _ in 0..watch_outputs_len {
3283+
let txid = Readable::read(reader)?;
3284+
let outputs_len: u64 = Readable::read(reader)?;
3285+
let mut outputs = Vec::with_capacity(cmp::min(outputs_len as usize, MAX_ALLOC_SIZE / 3*8));
3286+
for _ in 0..outputs_len {
3287+
outputs.push(Readable::read(reader)?);
3288+
}
3289+
if let Some(_) = watch_outputs.insert(txid, outputs) {
3290+
return Err(DecodeError::InvalidValue);
3291+
}
3292+
}
3293+
32453294
Ok((last_block_hash.clone(), ChannelMonitor {
32463295
commitment_transaction_number_obscure_factor,
32473296

@@ -3274,6 +3323,7 @@ impl<R: ::std::io::Read, ChanSigner: ChannelKeys + Readable<R>> ReadableArgs<R,
32743323
claimable_outpoints,
32753324

32763325
onchain_events_waiting_threshold_conf,
3326+
watch_outputs,
32773327

32783328
last_block_hash,
32793329
secp_ctx,

0 commit comments

Comments
 (0)