Drop the redundant/broken `ChannelMonitor::get_monitored_outpoints`
authorMatt Corallo <git@bluematt.me>
Sun, 27 Sep 2020 21:52:09 +0000 (17:52 -0400)
committerMatt Corallo <git@bluematt.me>
Mon, 5 Oct 2020 16:19:41 +0000 (12:19 -0400)
In review of the final doc changes in #649, I noticed there
appeared to be redundant monitored-outpoints function in
`ChannelMonitor` - `get_monitored_outpoints()` and
`get_outputs_to_watch()`.

In 6f08779b0439e7e4367a75f4ee88de093dfb68cb,
get_monitored_outpoints() was added, with its behavior largely the
same as today's - only returning the set of remote commitment txn
outputs that we've learned about on-chain. This is clearly not
sufficient, and in 73dce207dd0ea6c3ac57af3ebb8b87ee03e82c9e,
`get_outputs_to_watch` was added which was overly cautious to
ensure nothing was missed. Still, the author of 73dce207dd0ea6c3ac5
(me) seemed entirely unaware of the work in 6f08779b0439e7e4367a75f
(also me), despite the function being the literal next function in
the same file. This is presumably because it was assumed that
`get_monitored_outpoints` referred to oupoints for which we should
monitor for spends of (which is true), while `get_outputs_to_watch`
referred to outpouts which we should monitor for the transaction
containing said output (which is not true), or something of that
nature. Specifically, it is the expected behavior that the only
time we care about `Filter::register_tx` is for the funding
transaction (which we aren't aware of the inputs of), but for all
other transactions we register interest on the basis of an outpoint
in the previous transaction (ie via `Filter::register_output`).

Here we drop the broken-on-day-one `get_monitored_outpoints()`
version, but assert in testing that the values which it would return
are all present in `get_outputs_to_watch()`.

lightning/src/chain/channelmonitor.rs
lightning/src/ln/channelmanager.rs

index feff3978603bb3d535c8c4c8c6e2f89a02c005a9..3adf3e0e70528d64985005d217730a4fd44a456e 100644 (file)
@@ -1214,23 +1214,17 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
        ///
        /// (C-not exported) because we have no HashMap bindings
        pub fn get_outputs_to_watch(&self) -> &HashMap<Txid, Vec<Script>> {
-               &self.outputs_to_watch
-       }
-
-       /// Gets the sets of all outpoints which this ChannelMonitor expects to hear about spends of.
-       /// Generally useful when deserializing as during normal operation the return values of
-       /// block_connected are sufficient to ensure all relevant outpoints are being monitored (note
-       /// that the get_funding_txo outpoint and transaction must also be monitored for!).
-       ///
-       /// (C-not exported) as there is no practical way to track lifetimes of returned values.
-       pub fn get_monitored_outpoints(&self) -> Vec<(Txid, u32, &Script)> {
-               let mut res = Vec::with_capacity(self.counterparty_commitment_txn_on_chain.len() * 2);
-               for (ref txid, &(_, ref outputs)) in self.counterparty_commitment_txn_on_chain.iter() {
-                       for (idx, output) in outputs.iter().enumerate() {
-                               res.push(((*txid).clone(), idx as u32, output));
+               // If we've detected a counterparty commitment tx on chain, we must include it in the set
+               // of outputs to watch for spends of, otherwise we're likely to lose user funds. Because
+               // its trivial to do, double-check that here.
+               for (txid, &(_, ref outputs)) in self.counterparty_commitment_txn_on_chain.iter() {
+                       let watched_outputs = self.outputs_to_watch.get(txid).expect("Counterparty commitment txn which have been broadcast should have outputs registered");
+                       assert_eq!(watched_outputs.len(), outputs.len());
+                       for (watched, output) in watched_outputs.iter().zip(outputs.iter()) {
+                               assert_eq!(watched, output);
                        }
                }
-               res
+               &self.outputs_to_watch
        }
 
        /// Get the list of HTLCs who's status has been updated on chain. This should be called by
index b5aa30896dd22acdf3c3b451fd6c25623fb75d65..6b2f50e9704b0a16312eb9f10134dcee0f9b6882 100644 (file)
@@ -3730,7 +3730,7 @@ impl<ChanSigner: ChannelKeys + Writeable, M: Deref, T: Deref, K: Deref, F: Deref
 ///    This may result in closing some Channels if the ChannelMonitor is newer than the stored
 ///    ChannelManager state to ensure no loss of funds. Thus, transactions may be broadcasted.
 /// 3) Register all relevant ChannelMonitor outpoints with your chain watch mechanism using
-///    ChannelMonitor::get_monitored_outpoints and ChannelMonitor::get_funding_txo().
+///    ChannelMonitor::get_outputs_to_watch() and ChannelMonitor::get_funding_txo().
 /// 4) Reconnect blocks on your ChannelMonitors.
 /// 5) Move the ChannelMonitors into your local chain::Watch.
 /// 6) Disconnect/connect blocks on the ChannelManager.