Track outputs fron local commitment tx
authorAntoine Riard <ariard@student.42.fr>
Tue, 27 Nov 2018 00:54:00 +0000 (19:54 -0500)
committerMatt Corallo <git@bluematt.me>
Tue, 11 Dec 2018 21:47:02 +0000 (16:47 -0500)
Aims to detect onchain resolution of channel

Modify in consequence test_txn_broadcast to still pass
channel_monitor_network_test

Modify some tests due to block re-scan caused by
detections extensions

src/ln/channelmanager.rs
src/ln/channelmonitor.rs

index e0d2b9aaaa37222a17f5b134a994bf1080ed4f2b..438602d8c0291db8d7d09fe2bb8c831ed153b053 100644 (file)
@@ -5344,7 +5344,10 @@ mod tests {
                                        false
                                } else { true }
                        });
-                       assert_eq!(res.len(), 2);
+                       assert!(res.len() == 2 || res.len() == 3);
+                       if res.len() == 3 {
+                               assert_eq!(res[1], res[2]);
+                       }
                }
 
                assert!(node_txn.is_empty());
@@ -8429,10 +8432,12 @@ mod tests {
                        _ => panic!("Unexpected event"),
                }
                let revoked_htlc_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
-               assert_eq!(revoked_htlc_txn.len(), 2);
+               assert_eq!(revoked_htlc_txn.len(), 3);
+               assert_eq!(revoked_htlc_txn[0], revoked_htlc_txn[2]);
                assert_eq!(revoked_htlc_txn[0].input.len(), 1);
                assert_eq!(revoked_htlc_txn[0].input[0].witness.last().unwrap().len(), 133);
                check_spends!(revoked_htlc_txn[0], revoked_local_txn[0].clone());
+               check_spends!(revoked_htlc_txn[1], chan_1.3.clone());
 
                // B will generate justice tx from A's revoked commitment/HTLC tx
                nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone(), revoked_htlc_txn[0].clone()] }, 1);
@@ -8479,7 +8484,8 @@ mod tests {
                }
                let revoked_htlc_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
 
-               assert_eq!(revoked_htlc_txn.len(), 2);
+               assert_eq!(revoked_htlc_txn.len(), 3);
+               assert_eq!(revoked_htlc_txn[0], revoked_htlc_txn[2]);
                assert_eq!(revoked_htlc_txn[0].input.len(), 1);
                assert_eq!(revoked_htlc_txn[0].input[0].witness.last().unwrap().len(), 138);
                check_spends!(revoked_htlc_txn[0], revoked_local_txn[0].clone());
@@ -8540,8 +8546,9 @@ mod tests {
 
                // Verify that B is able to spend its own HTLC-Success tx thanks to spendable output event given back by its ChannelMonitor
                let spend_txn = check_spendable_outputs!(nodes[1], 1);
-               assert_eq!(spend_txn.len(), 1);
+               assert_eq!(spend_txn.len(), 2);
                check_spends!(spend_txn[0], node_txn[0].clone());
+               check_spends!(spend_txn[1], node_txn[2].clone());
        }
 
        #[test]
@@ -8571,9 +8578,13 @@ mod tests {
 
                // Verify that A is able to spend its own HTLC-Timeout tx thanks to spendable output event given back by its ChannelMonitor
                let spend_txn = check_spendable_outputs!(nodes[0], 1);
-               assert_eq!(spend_txn.len(), 4);
+               assert_eq!(spend_txn.len(), 8);
                assert_eq!(spend_txn[0], spend_txn[2]);
+               assert_eq!(spend_txn[0], spend_txn[4]);
+               assert_eq!(spend_txn[0], spend_txn[6]);
                assert_eq!(spend_txn[1], spend_txn[3]);
+               assert_eq!(spend_txn[1], spend_txn[5]);
+               assert_eq!(spend_txn[1], spend_txn[7]);
                check_spends!(spend_txn[0], local_txn[0].clone());
                check_spends!(spend_txn[1], node_txn[0].clone());
        }
index 48e5c002c34543b56648014033a209fa7a61d31c..ed940375bea3f7f16ad5f36c9199dbc208d4015f 100644 (file)
@@ -1319,9 +1319,10 @@ impl ChannelMonitor {
                } else { (None, None) }
        }
 
-       fn broadcast_by_local_state(&self, local_tx: &LocalSignedTx, per_commitment_point: &Option<PublicKey>, delayed_payment_base_key: &Option<SecretKey>) -> (Vec<Transaction>, Vec<SpendableOutputDescriptor>) {
+       fn broadcast_by_local_state(&self, local_tx: &LocalSignedTx, per_commitment_point: &Option<PublicKey>, delayed_payment_base_key: &Option<SecretKey>) -> (Vec<Transaction>, Vec<SpendableOutputDescriptor>, Vec<TxOut>) {
                let mut res = Vec::with_capacity(local_tx.htlc_outputs.len());
                let mut spendable_outputs = Vec::with_capacity(local_tx.htlc_outputs.len());
+               let mut watch_outputs = Vec::with_capacity(local_tx.htlc_outputs.len());
 
                macro_rules! add_dynamic_output {
                        ($father_tx: expr, $vout: expr) => {
@@ -1385,24 +1386,27 @@ impl ChannelMonitor {
                                        res.push(htlc_success_tx);
                                }
                        }
+                       watch_outputs.push(local_tx.tx.output[htlc.transaction_output_index as usize].clone());
                }
 
-               (res, spendable_outputs)
+               (res, spendable_outputs, watch_outputs)
        }
 
        /// Attempts to claim any claimable HTLCs in a commitment transaction which was not (yet)
        /// revoked using data in local_claimable_outpoints.
        /// Should not be used if check_spend_revoked_transaction succeeds.
-       fn check_spend_local_transaction(&self, tx: &Transaction, _height: u32) -> (Vec<Transaction>, Vec<SpendableOutputDescriptor>) {
+       fn check_spend_local_transaction(&self, tx: &Transaction, _height: u32) -> (Vec<Transaction>, Vec<SpendableOutputDescriptor>, (Sha256dHash, Vec<TxOut>)) {
                let commitment_txid = tx.txid();
                if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx {
                        if local_tx.txid == commitment_txid {
                                match self.key_storage {
                                        Storage::Local { ref delayed_payment_base_key, ref latest_per_commitment_point, .. } => {
-                                               return self.broadcast_by_local_state(local_tx, latest_per_commitment_point, &Some(*delayed_payment_base_key));
+                                               let (local_txn, spendable_outputs, watch_outputs) = self.broadcast_by_local_state(local_tx, latest_per_commitment_point, &Some(*delayed_payment_base_key));
+                                               return (local_txn, spendable_outputs, (commitment_txid, watch_outputs));
                                        },
                                        Storage::Watchtower { .. } => {
-                                               return self.broadcast_by_local_state(local_tx, &None, &None);
+                                               let (local_txn, spendable_outputs, watch_outputs) = self.broadcast_by_local_state(local_tx, &None, &None);
+                                               return (local_txn, spendable_outputs, (commitment_txid, watch_outputs));
                                        }
                                }
                        }
@@ -1411,15 +1415,17 @@ impl ChannelMonitor {
                        if local_tx.txid == commitment_txid {
                                match self.key_storage {
                                        Storage::Local { ref delayed_payment_base_key, ref prev_latest_per_commitment_point, .. } => {
-                                               return self.broadcast_by_local_state(local_tx, prev_latest_per_commitment_point, &Some(*delayed_payment_base_key));
+                                               let (local_txn, spendable_outputs, watch_outputs) = self.broadcast_by_local_state(local_tx, prev_latest_per_commitment_point, &Some(*delayed_payment_base_key));
+                                               return (local_txn, spendable_outputs, (commitment_txid, watch_outputs));
                                        },
                                        Storage::Watchtower { .. } => {
-                                               return self.broadcast_by_local_state(local_tx, &None, &None);
+                                               let (local_txn, spendable_outputs, watch_outputs) = self.broadcast_by_local_state(local_tx, &None, &None);
+                                               return (local_txn, spendable_outputs, (commitment_txid, watch_outputs));
                                        }
                                }
                        }
                }
-               (Vec::new(), Vec::new())
+               (Vec::new(), Vec::new(), (commitment_txid, Vec::new()))
        }
 
        /// Generate a spendable output event when closing_transaction get registered onchain.
@@ -1491,9 +1497,12 @@ impl ChannelMonitor {
                                                watch_outputs.push(new_outputs);
                                        }
                                        if txn.is_empty() {
-                                               let (remote_txn, mut outputs) = self.check_spend_local_transaction(tx, height);
-                                               spendable_outputs.append(&mut outputs);
-                                               txn = remote_txn;
+                                               let (local_txn, mut spendable_output, new_outputs) = self.check_spend_local_transaction(tx, height);
+                                               spendable_outputs.append(&mut spendable_output);
+                                               txn = local_txn;
+                                               if !new_outputs.1.is_empty() {
+                                                       watch_outputs.push(new_outputs);
+                                               }
                                        }
                                        if !funding_txo.is_none() && txn.is_empty() {
                                                if let Some(spendable_output) = self.check_spend_closing_transaction(tx) {
@@ -1521,15 +1530,21 @@ impl ChannelMonitor {
                                broadcaster.broadcast_transaction(&cur_local_tx.tx);
                                match self.key_storage {
                                        Storage::Local { ref delayed_payment_base_key, ref latest_per_commitment_point, .. } => {
-                                               let (txs, mut outputs) = self.broadcast_by_local_state(&cur_local_tx, latest_per_commitment_point, &Some(*delayed_payment_base_key));
-                                               spendable_outputs.append(&mut outputs);
+                                               let (txs, mut spendable_output, new_outputs) = self.broadcast_by_local_state(&cur_local_tx, latest_per_commitment_point, &Some(*delayed_payment_base_key));
+                                               spendable_outputs.append(&mut spendable_output);
+                                               if !new_outputs.is_empty() {
+                                                       watch_outputs.push((cur_local_tx.txid.clone(), new_outputs));
+                                               }
                                                for tx in txs {
                                                        broadcaster.broadcast_transaction(&tx);
                                                }
                                        },
                                        Storage::Watchtower { .. } => {
-                                               let (txs, mut outputs) = self.broadcast_by_local_state(&cur_local_tx, &None, &None);
-                                               spendable_outputs.append(&mut outputs);
+                                               let (txs, mut spendable_output, new_outputs) = self.broadcast_by_local_state(&cur_local_tx, &None, &None);
+                                               spendable_outputs.append(&mut spendable_output);
+                                               if !new_outputs.is_empty() {
+                                                       watch_outputs.push((cur_local_tx.txid.clone(), new_outputs));
+                                               }
                                                for tx in txs {
                                                        broadcaster.broadcast_transaction(&tx);
                                                }