1use alloc::collections::BTreeSet as Set;
2
3use bitcoin::absolute::LockTime;
4use bitcoin::blockdata::block::Header as BlockHeader;
5use bitcoin::secp256k1::Secp256k1;
6use bitcoin::transaction::Version;
7use bitcoin::{BlockHash, OutPoint, Transaction, TxIn, TxOut, Txid};
8use log::*;
9use push_decoder::Listener as _;
10use serde_derive::{Deserialize, Serialize};
11use serde_with::serde_as;
12
13use crate::chain::tracker::ChainListener;
14use crate::channel::ChannelId;
15use crate::policy::validator::ChainState;
16use crate::prelude::*;
17use crate::util::transaction_utils::{decode_commitment_number, decode_commitment_tx};
18use crate::{Arc, CommitmentPointProvider};
19
20const MIN_DEPTH: u32 = 100;
22
23const MAX_CLOSING_DEPTH: u32 = 2016;
25
26#[derive(Clone, Debug, Serialize, Deserialize)]
27struct SecondLevelHTLCOutput {
28 outpoint: OutPoint,
29 spent: bool,
30}
31
32impl SecondLevelHTLCOutput {
33 fn new(outpoint: OutPoint) -> Self {
34 Self { outpoint, spent: false }
35 }
36
37 fn set_spent(&mut self, spent: bool) {
38 self.spent = spent;
39 }
40
41 fn is_spent(&self) -> bool {
42 self.spent
43 }
44
45 fn matches_outpoint(&self, outpoint: &OutPoint) -> bool {
46 self.outpoint == *outpoint
47 }
48}
49
50#[derive(Clone, Debug, Serialize, Deserialize)]
54struct ClosingOutpoints {
55 txid: Txid,
56 our_output: Option<(u32, bool)>,
57 htlc_outputs: Vec<u32>,
58 htlc_spents: Vec<bool>,
59 second_level_htlc_outputs: Vec<SecondLevelHTLCOutput>,
60}
61
62impl ClosingOutpoints {
63 fn new(txid: Txid, our_output_index: Option<u32>, htlc_output_indexes: Vec<u32>) -> Self {
65 let v = vec![false; htlc_output_indexes.len()];
66 ClosingOutpoints {
67 txid,
68 our_output: our_output_index.map(|i| (i, false)),
69 htlc_outputs: htlc_output_indexes,
70 htlc_spents: v,
71 second_level_htlc_outputs: Vec::new(),
72 }
73 }
74
75 fn includes_our_output(&self, outpoint: &OutPoint) -> bool {
77 self.txid == outpoint.txid && self.our_output.map(|(i, _)| i) == Some(outpoint.vout)
78 }
79
80 fn includes_htlc_output(&self, outpoint: &OutPoint) -> bool {
82 self.txid == outpoint.txid && self.htlc_outputs.contains(&(outpoint.vout))
83 }
84
85 fn set_our_output_spent(&mut self, vout: u32, spent: bool) {
86 let p = self.our_output.as_mut().unwrap();
88 assert_eq!(p.0, vout);
89 p.1 = spent;
90 }
91
92 fn set_htlc_output_spent(&mut self, vout: u32, spent: bool) {
93 let i = self.htlc_outputs.iter().position(|&x| x == vout).unwrap();
95 self.htlc_spents[i] = spent;
96 }
97
98 fn is_all_spent(&self) -> bool {
104 let our_output_spent = self.our_output.as_ref().map(|(_, b)| *b).unwrap_or(true);
105 let htlc_outputs_spent = self.htlc_spents.iter().all(|b| *b);
106 let second_level_htlcs_spent = self.second_level_htlc_outputs.iter().all(|h| h.is_spent());
107
108 our_output_spent && htlc_outputs_spent && second_level_htlcs_spent
109 }
110
111 fn add_second_level_htlc_output(&mut self, outpoint: OutPoint) {
112 self.second_level_htlc_outputs.push(SecondLevelHTLCOutput::new(outpoint));
113 }
114
115 fn includes_second_level_htlc_output(&self, outpoint: &OutPoint) -> bool {
116 self.second_level_htlc_outputs.iter().any(|h| h.matches_outpoint(outpoint))
117 }
118
119 fn set_second_level_htlc_spent(&mut self, outpoint: OutPoint, spent: bool) {
120 let htlc_outpoint = self
121 .second_level_htlc_outputs
122 .iter_mut()
123 .find(|h| h.matches_outpoint(&outpoint))
124 .expect("second-level HTLC outpoint");
125 htlc_outpoint.set_spent(spent);
126 }
127
128 fn remove_second_level_htlc_output(&mut self, outpoint: &OutPoint) {
129 self.second_level_htlc_outputs.retain(|h| !h.matches_outpoint(outpoint));
130 }
131}
132
133#[serde_as]
135#[derive(Clone, Debug, Serialize, Deserialize)]
136pub struct State {
137 height: u32,
139 funding_txids: Vec<Txid>,
141 funding_vouts: Vec<u32>,
143 funding_inputs: Set<OutPoint>,
145 funding_height: Option<u32>,
147 funding_outpoint: Option<OutPoint>,
149 funding_double_spent_height: Option<u32>,
151 mutual_closing_height: Option<u32>,
153 unilateral_closing_height: Option<u32>,
155 closing_outpoints: Option<ClosingOutpoints>,
157 closing_swept_height: Option<u32>,
159 our_output_swept_height: Option<u32>,
161 #[serde(default)]
163 saw_block: bool,
164 #[serde(default)]
166 saw_forget_channel: bool,
167 #[serde(skip)]
170 channel_id: Option<ChannelId>,
171}
172
173struct PushListener<'a> {
177 commitment_point_provider: &'a dyn CommitmentPointProvider,
178 decode_state: &'a mut BlockDecodeState,
179 saw_block: bool,
180}
181
182#[derive(Clone, Debug, Serialize, Deserialize)]
184enum StateChange {
185 FundingConfirmed(OutPoint),
187 FundingInputSpent(OutPoint),
190 UnilateralCloseConfirmed(Txid, OutPoint, Option<u32>, Vec<u32>),
193 MutualCloseConfirmed(Txid, OutPoint),
195 OurOutputSpent(u32),
197 HTLCOutputSpent(u32, OutPoint),
200 SecondLevelHTLCOutputSpent(OutPoint),
202}
203
204#[derive(Clone, Debug)]
206struct BlockDecodeState {
207 changes: Vec<StateChange>,
209 version: i32,
211 input_num: u32,
213 output_num: u32,
215 closing_tx: Option<Transaction>,
217 spent_htlc_outputs: Vec<(u32, u32)>,
220 block_hash: Option<BlockHash>,
222 state: State,
225}
226
227impl BlockDecodeState {
228 fn new(state: &State) -> Self {
229 BlockDecodeState {
230 changes: Vec::new(),
231 version: 0,
232 input_num: 0,
233 output_num: 0,
234 closing_tx: None,
235 spent_htlc_outputs: Vec::new(),
236 block_hash: None,
237 state: state.clone(),
238 }
239 }
240
241 fn new_with_block_hash(state: &State, block_hash: &BlockHash) -> Self {
242 BlockDecodeState {
243 changes: Vec::new(),
244 version: 0,
245 input_num: 0,
246 output_num: 0,
247 closing_tx: None,
248 spent_htlc_outputs: Vec::new(),
249 block_hash: Some(*block_hash),
250 state: state.clone(),
251 }
252 }
253
254 fn add_change(&mut self, change: StateChange) {
259 self.changes.push(change.clone());
260 let mut adds = Vec::new();
261 let mut removes = Vec::new();
262 self.state.apply_forward_change(&mut adds, &mut removes, change);
263 }
264}
265
266const MAX_COMMITMENT_OUTPUTS: u32 = 600;
267
268impl<'a> PushListener<'a> {
269 fn is_not_ready_for_push(&self) -> bool {
273 if self.saw_block {
274 assert!(self.decode_state.block_hash.is_some(), "saw block but no decode state");
277 false
278 } else {
279 assert!(
281 self.decode_state.block_hash.is_none(),
282 "never saw a block but decode state is present"
283 );
284 true
285 }
286 }
287}
288
289impl<'a> push_decoder::Listener for PushListener<'a> {
290 fn on_block_start(&mut self, header: &BlockHeader) {
291 assert!(self.decode_state.block_hash.is_none(), "saw more than one on_block_start");
294 self.decode_state.block_hash = Some(header.block_hash());
295 self.saw_block = true;
296 }
297
298 fn on_transaction_start(&mut self, version: i32) {
299 if self.is_not_ready_for_push() {
300 return;
301 }
302 let state = &mut self.decode_state;
303 state.version = version;
304 state.input_num = 0;
305 state.output_num = 0;
306 state.closing_tx = None;
307 state.spent_htlc_outputs = Vec::new();
308 }
309
310 fn on_transaction_input(&mut self, input: &TxIn) {
311 if self.is_not_ready_for_push() {
312 return;
313 }
314
315 let decode_state = &mut self.decode_state;
316
317 if decode_state.state.funding_inputs.contains(&input.previous_output) {
318 decode_state.add_change(StateChange::FundingInputSpent(input.previous_output));
320 }
321
322 if Some(input.previous_output) == decode_state.state.funding_outpoint {
323 let tx = Transaction {
327 version: Version(decode_state.version),
328 lock_time: LockTime::ZERO,
329 input: vec![input.clone()],
330 output: vec![],
331 };
332 decode_state.closing_tx = Some(tx);
333 }
334
335 let closing_change = if let Some(ref c) = decode_state.state.closing_outpoints {
338 if c.includes_our_output(&input.previous_output) {
339 Some(StateChange::OurOutputSpent(input.previous_output.vout))
341 } else if c.includes_htlc_output(&input.previous_output) {
342 decode_state
344 .spent_htlc_outputs
345 .push((input.previous_output.vout, decode_state.input_num));
346 None
347 } else if c.includes_second_level_htlc_output(&input.previous_output) {
348 Some(StateChange::SecondLevelHTLCOutputSpent(input.previous_output))
349 } else {
350 None
351 }
352 } else {
353 None
354 };
355
356 closing_change.map(|c| decode_state.add_change(c));
357
358 if decode_state.closing_tx.is_some() {
359 assert_eq!(decode_state.input_num, 0, "closing tx must have only one input");
360 }
361 decode_state.input_num += 1;
362 }
363
364 fn on_transaction_output(&mut self, output: &TxOut) {
365 if self.is_not_ready_for_push() {
366 return;
367 }
368
369 let decode_state = &mut self.decode_state;
370 if let Some(closing_tx) = &mut decode_state.closing_tx {
371 closing_tx.output.push(output.clone());
372 assert!(
373 decode_state.output_num < MAX_COMMITMENT_OUTPUTS,
374 "more than {} commitment outputs",
375 MAX_COMMITMENT_OUTPUTS
376 );
377 }
378
379 decode_state.output_num += 1;
380 }
381
382 fn on_transaction_end(&mut self, lock_time: LockTime, txid: Txid) {
383 if self.is_not_ready_for_push() {
384 return;
385 }
386
387 let decode_state = &mut self.decode_state;
388
389 if let Some(ind) = decode_state.state.funding_txids.iter().position(|i| *i == txid) {
390 let vout = decode_state.state.funding_vouts[ind];
391 assert!(
393 vout < decode_state.output_num,
394 "tx {} doesn't have funding output index {}",
395 txid,
396 vout
397 );
398 let outpoint = OutPoint { txid, vout };
399 decode_state.add_change(StateChange::FundingConfirmed(outpoint));
400 }
401
402 if let Some(mut closing_tx) = decode_state.closing_tx.take() {
404 closing_tx.lock_time = lock_time;
405 assert_eq!(closing_tx.input.len(), 1);
407 let provider = self.commitment_point_provider;
408 let parameters = provider.get_transaction_parameters();
409
410 let commitment_number_opt = decode_commitment_number(&closing_tx, ¶meters);
412 if let Some(commitment_number) = commitment_number_opt {
413 let secp_ctx = Secp256k1::new();
414 info!("unilateral close {} at commitment {} confirmed", txid, commitment_number);
415 let holder_per_commitment = provider.get_holder_commitment_point(commitment_number);
416 let cp_per_commitment =
417 provider.get_counterparty_commitment_point(commitment_number);
418 let (our_output_index, htlc_indices) = decode_commitment_tx(
419 &closing_tx,
420 &holder_per_commitment,
421 &cp_per_commitment,
422 ¶meters,
423 &secp_ctx,
424 );
425 let spendable_htlc_indices = if htlc_indices.is_empty() {
426 Vec::new()
427 } else {
428 provider
429 .get_spendable_htlc_indices(&closing_tx, commitment_number)
430 .expect("valid spendable HTLC indices for a decoded commitment transaction")
431 };
432 debug!(
433 "our_output_index: {:?}, htlc_indices: {:?}, spendable_htlc_indices: {:?}",
434 our_output_index, htlc_indices, spendable_htlc_indices
435 );
436 decode_state.add_change(StateChange::UnilateralCloseConfirmed(
437 txid,
438 closing_tx.input[0].previous_output,
439 our_output_index,
440 spendable_htlc_indices,
441 ));
442 } else {
443 decode_state.add_change(StateChange::MutualCloseConfirmed(
444 txid,
445 closing_tx.input[0].previous_output,
446 ));
447 info!("mutual close {} confirmed", txid);
448 }
449 }
450
451 let htlc_changes: Vec<StateChange> = decode_state
452 .spent_htlc_outputs
453 .drain(..)
454 .map(|(spent_vout, input_index)| {
455 let second_level_outpoint = OutPoint { txid, vout: input_index };
456 StateChange::HTLCOutputSpent(spent_vout, second_level_outpoint)
457 })
458 .collect();
459
460 for change in htlc_changes {
461 decode_state.add_change(change);
462 }
463 }
464
465 fn on_block_end(&mut self) {
466 }
469}
470
471impl State {
472 fn channel_id(&self) -> &ChannelId {
473 self.channel_id.as_ref().expect("missing associated channel_id in monitor::State")
475 }
476
477 fn depth_of(&self, other_height: Option<u32>) -> u32 {
478 (self.height + 1).saturating_sub(other_height.unwrap_or(self.height + 1))
479 }
480
481 fn deep_enough_and_saw_node_forget(&self, other_height: Option<u32>, limit: u32) -> bool {
482 let depth = self.depth_of(other_height);
485 if depth < limit {
486 false
488 } else if self.saw_forget_channel {
489 true
491 } else {
492 warn!(
494 "expected forget_channel for {} overdue by {} blocks",
495 self.channel_id(),
496 depth - limit
497 );
498 false
499 }
500 }
501
502 fn diagnostic(&self, is_closed: bool) -> String {
503 if self.funding_height.is_none() {
504 format!("UNCOMFIRMED hold till funding doublespent + {}", MIN_DEPTH)
505 } else if let Some(height) = self.funding_double_spent_height {
506 format!("AGING_FUNDING_DOUBLESPENT at {} until {}", height, height + MIN_DEPTH)
507 } else if let Some(height) = self.mutual_closing_height {
508 format!("AGING_MUTUALLY_CLOSED at {} until {}", height, height + MIN_DEPTH)
509 } else if let Some(height) = self.closing_swept_height {
510 format!("AGING_CLOSING_SWEPT at {} until {}", height, height + MIN_DEPTH)
511 } else if let Some(height) = self.our_output_swept_height {
512 format!("AGING_OUR_OUTPUT_SWEPT at {} until {}", height, height + MAX_CLOSING_DEPTH)
513 } else if is_closed {
514 "CLOSING".into()
515 } else {
516 "ACTIVE".into()
517 }
518 }
519
520 fn is_done(&self) -> bool {
521 if self.deep_enough_and_saw_node_forget(self.funding_double_spent_height, MIN_DEPTH) {
528 debug!(
529 "{} is_done because funding double spent {} blocks ago",
530 self.channel_id(),
531 MIN_DEPTH
532 );
533 return true;
534 }
535
536 if self.deep_enough_and_saw_node_forget(self.mutual_closing_height, MIN_DEPTH) {
537 debug!("{} is_done because mutual closed {} blocks ago", self.channel_id(), MIN_DEPTH);
538 return true;
539 }
540
541 if self.deep_enough_and_saw_node_forget(self.closing_swept_height, MIN_DEPTH) {
542 debug!("{} is_done because closing swept {} blocks ago", self.channel_id(), MIN_DEPTH);
543 return true;
544 }
545
546 return false;
547 }
548
549 fn on_add_block_end(
550 &mut self,
551 block_hash: &BlockHash,
552 decode_state: &mut BlockDecodeState,
553 ) -> (Vec<OutPoint>, Vec<OutPoint>) {
554 assert_eq!(decode_state.block_hash.as_ref(), Some(block_hash));
555
556 self.saw_block = true;
557 self.height += 1;
558
559 let closing_was_swept = self.is_closing_swept();
560 let our_output_was_swept = self.is_our_output_swept();
561
562 let mut adds = Vec::new();
563 let mut removes = Vec::new();
564
565 let changed = !decode_state.changes.is_empty();
566
567 if changed {
568 debug!(
569 "{} detected add-changes at height {}: {:?}",
570 self.channel_id(),
571 self.height,
572 decode_state.changes
573 );
574 }
575
576 for change in decode_state.changes.drain(..) {
578 self.apply_forward_change(&mut adds, &mut removes, change);
579 }
580
581 let closing_is_swept = self.is_closing_swept();
582 let our_output_is_swept = self.is_our_output_swept();
583
584 if !closing_was_swept && closing_is_swept {
585 info!("{} closing tx was swept at height {}", self.channel_id(), self.height);
586 self.closing_swept_height = Some(self.height);
587 }
588
589 if !our_output_was_swept && our_output_is_swept {
590 info!("{} our output was swept at height {}", self.channel_id(), self.height);
591 self.our_output_swept_height = Some(self.height);
592 }
593
594 if self.is_done() {
595 info!("{} done at height {}", self.channel_id(), self.height);
596 }
597
598 if changed {
599 #[cfg(not(feature = "log_pretty_print"))]
600 info!("on_add_block_end state changed: {:?}", self);
601 #[cfg(feature = "log_pretty_print")]
602 info!("on_add_block_end state changed: {:#?}", self);
603 }
604
605 (adds, removes)
606 }
607
608 fn on_remove_block_end(
609 &mut self,
610 block_hash: &BlockHash,
611 decode_state: &mut BlockDecodeState,
612 ) -> (Vec<OutPoint>, Vec<OutPoint>) {
613 assert_eq!(decode_state.block_hash.as_ref(), Some(block_hash));
614
615 let closing_was_swept = self.is_closing_swept();
616 let our_output_was_swept = self.is_our_output_swept();
617
618 let mut adds = Vec::new();
619 let mut removes = Vec::new();
620
621 let changed = !decode_state.changes.is_empty();
622
623 if changed {
624 debug!(
625 "{} detected remove-changes at height {}: {:?}",
626 self.channel_id(),
627 self.height,
628 decode_state.changes
629 );
630 }
631
632 for change in decode_state.changes.drain(..) {
633 self.apply_backward_change(&mut adds, &mut removes, change);
634 }
635
636 let closing_is_swept = self.is_closing_swept();
637 let our_output_is_swept = self.is_our_output_swept();
638
639 if closing_was_swept && !closing_is_swept {
640 info!("{} closing tx was un-swept at height {}", self.channel_id(), self.height);
641 self.closing_swept_height = None;
642 }
643
644 if our_output_was_swept && !our_output_is_swept {
645 info!("{} our output was un-swept at height {}", self.channel_id(), self.height);
646 self.our_output_swept_height = None;
647 }
648
649 self.height -= 1;
650
651 if changed {
652 #[cfg(not(feature = "log_pretty_print"))]
653 info!("on_remove_block_end state changed: {:?}", self);
654 #[cfg(feature = "log_pretty_print")]
655 info!("on_remove_block_end state changed: {:#?}", self);
656 }
657
658 (adds, removes)
660 }
661
662 fn is_closing_swept(&self) -> bool {
664 self.closing_outpoints.as_ref().map(|o| o.is_all_spent()).unwrap_or(false)
665 }
666
667 fn is_our_output_swept(&self) -> bool {
669 self.closing_outpoints
670 .as_ref()
671 .map(|o| o.our_output.map(|(_, s)| s).unwrap_or(true))
672 .unwrap_or(false)
673 }
674
675 fn apply_forward_change(
676 &mut self,
677 adds: &mut Vec<OutPoint>,
678 removes: &mut Vec<OutPoint>,
679 change: StateChange,
680 ) {
681 match change {
683 StateChange::FundingConfirmed(outpoint) => {
684 self.funding_height = Some(self.height);
685 self.funding_outpoint = Some(outpoint);
686 self.funding_double_spent_height = None;
688 adds.push(outpoint);
689 }
690 StateChange::FundingInputSpent(outpoint) => {
691 self.funding_double_spent_height.get_or_insert(self.height);
697 removes.push(outpoint);
699 }
700 StateChange::UnilateralCloseConfirmed(
701 txid,
702 funding_outpoint,
703 our_output_index,
704 htlcs_indices,
705 ) => {
706 self.unilateral_closing_height = Some(self.height);
707 removes.push(funding_outpoint);
708 our_output_index.map(|i| adds.push(OutPoint { txid, vout: i }));
709 for i in htlcs_indices.iter() {
710 adds.push(OutPoint { txid, vout: *i });
711 }
712 self.closing_outpoints =
713 Some(ClosingOutpoints::new(txid, our_output_index, htlcs_indices));
714 }
715 StateChange::OurOutputSpent(vout) => {
716 let outpoints = self.closing_outpoints.as_mut().unwrap();
717 outpoints.set_our_output_spent(vout, true);
718 let outpoint = OutPoint { txid: outpoints.txid, vout };
719 removes.push(outpoint);
720 }
721 StateChange::HTLCOutputSpent(vout, second_level_htlc_outpoint) => {
722 let outpoints = self.closing_outpoints.as_mut().unwrap();
723 outpoints.set_htlc_output_spent(vout, true);
724 let outpoint = OutPoint { txid: outpoints.txid, vout };
725 outpoints.add_second_level_htlc_output(second_level_htlc_outpoint);
726 removes.push(outpoint);
727 adds.push(second_level_htlc_outpoint);
728 }
729 StateChange::SecondLevelHTLCOutputSpent(outpoint) => {
730 let closing_outpoints = self.closing_outpoints.as_mut().unwrap();
731 closing_outpoints.set_second_level_htlc_spent(outpoint, true);
732 removes.push(outpoint);
733 }
734 StateChange::MutualCloseConfirmed(_txid, funding_outpoint) => {
735 self.mutual_closing_height = Some(self.height);
736 removes.push(funding_outpoint);
737 }
738 }
739 }
740
741 fn apply_backward_change(
745 &mut self,
746 adds: &mut Vec<OutPoint>,
747 removes: &mut Vec<OutPoint>,
748 change: StateChange,
749 ) {
750 match change {
751 StateChange::FundingConfirmed(outpoint) => {
752 assert_eq!(self.funding_height, Some(self.height));
754 self.funding_height = None;
755 self.funding_outpoint = None;
756 adds.push(outpoint);
757 }
758 StateChange::FundingInputSpent(outpoint) => {
759 if self.funding_double_spent_height == Some(self.height) {
765 self.funding_double_spent_height = None
766 }
767 removes.push(outpoint);
769 }
770 StateChange::UnilateralCloseConfirmed(
771 txid,
772 funding_outpoint,
773 our_output_index,
774 htlcs_indices,
775 ) => {
776 assert_eq!(self.unilateral_closing_height, Some(self.height));
778 self.unilateral_closing_height = None;
779 self.closing_outpoints = None;
780 our_output_index.map(|i| adds.push(OutPoint { txid, vout: i }));
781 for i in htlcs_indices {
782 adds.push(OutPoint { txid, vout: i });
783 }
784 removes.push(funding_outpoint)
785 }
786 StateChange::OurOutputSpent(vout) => {
787 let outpoints = self.closing_outpoints.as_mut().unwrap();
788 outpoints.set_our_output_spent(vout, false);
789 let outpoint = OutPoint { txid: outpoints.txid, vout };
790 removes.push(outpoint);
791 }
792 StateChange::HTLCOutputSpent(vout, second_level_htlc_outpoint) => {
793 let outpoints = self.closing_outpoints.as_mut().unwrap();
794 outpoints.set_htlc_output_spent(vout, false);
795 let outpoint = OutPoint { txid: outpoints.txid, vout };
796 outpoints.remove_second_level_htlc_output(&second_level_htlc_outpoint);
797 adds.push(outpoint);
798 removes.push(second_level_htlc_outpoint);
799 }
800 StateChange::SecondLevelHTLCOutputSpent(outpoint) => {
801 let closing_outpoints = self.closing_outpoints.as_mut().unwrap();
802 closing_outpoints.set_second_level_htlc_spent(outpoint, false);
803 adds.push(outpoint);
804 }
805 StateChange::MutualCloseConfirmed(_txid, funding_outpoint) => {
806 self.mutual_closing_height = None;
807 removes.push(funding_outpoint);
808 }
809 }
810 }
811}
812
813#[derive(Clone)]
815pub struct ChainMonitorBase {
816 pub(crate) funding_outpoint: OutPoint,
818 state: Arc<Mutex<State>>,
820}
821
822impl ChainMonitorBase {
823 pub fn new(funding_outpoint: OutPoint, height: u32, chan_id: &ChannelId) -> Self {
826 let state = State {
827 height,
828 funding_txids: Vec::new(),
829 funding_vouts: Vec::new(),
830 funding_inputs: OrderedSet::new(),
831 funding_height: None,
832 funding_outpoint: None,
833 funding_double_spent_height: None,
834 mutual_closing_height: None,
835 unilateral_closing_height: None,
836 closing_outpoints: None,
837 closing_swept_height: None,
838 our_output_swept_height: None,
839 saw_block: false,
840 saw_forget_channel: false,
841 channel_id: Some(chan_id.clone()),
842 };
843
844 Self { funding_outpoint, state: Arc::new(Mutex::new(state)) }
845 }
846
847 pub fn new_from_persistence(
849 funding_outpoint: OutPoint,
850 state: State,
851 channel_id: &ChannelId,
852 ) -> Self {
853 let state = Arc::new(Mutex::new(state));
854 state.lock().unwrap().channel_id = Some(channel_id.clone());
855 Self { funding_outpoint, state }
856 }
857
858 pub fn as_monitor(
860 &self,
861 commitment_point_provider: Box<dyn CommitmentPointProvider>,
862 ) -> ChainMonitor {
863 ChainMonitor {
864 funding_outpoint: self.funding_outpoint,
865 state: self.state.clone(),
866 decode_state: Arc::new(Mutex::new(None)),
867 commitment_point_provider,
868 }
869 }
870
871 pub fn add_funding_outpoint(&self, outpoint: &OutPoint) {
874 let mut state = self.get_state();
875 assert!(state.funding_txids.is_empty(), "only a single funding tx currently supported");
876 assert_eq!(state.funding_txids.len(), state.funding_vouts.len());
877 state.funding_txids.push(outpoint.txid);
878 state.funding_vouts.push(outpoint.vout);
879 }
880
881 pub fn add_funding_inputs(&self, tx: &Transaction) {
884 let mut state = self.get_state();
885 state.funding_inputs.extend(tx.input.iter().map(|i| i.previous_output));
886 }
887
888 pub fn as_chain_state(&self) -> ChainState {
890 let state = self.get_state();
891 ChainState {
892 current_height: state.height,
893 funding_depth: state.funding_height.map(|h| state.height + 1 - h).unwrap_or(0),
894 funding_double_spent_depth: state
895 .funding_double_spent_height
896 .map(|h| state.height + 1 - h)
897 .unwrap_or(0),
898 closing_depth: state
899 .mutual_closing_height
900 .or(state.unilateral_closing_height)
901 .map(|h| state.height + 1 - h)
902 .unwrap_or(0),
903 }
904 }
905
906 pub fn is_done(&self) -> bool {
908 self.get_state().is_done()
909 }
910
911 pub fn forget_channel(&self) {
913 let mut state = self.get_state();
914 state.saw_forget_channel = true;
915 }
916
917 pub fn funding_outpoint(&self) -> Option<OutPoint> {
919 self.get_state().funding_outpoint
920 }
921
922 pub fn forget_seen(&self) -> bool {
924 self.get_state().saw_forget_channel
925 }
926
927 pub fn diagnostic(&self, is_closed: bool) -> String {
929 self.get_state().diagnostic(is_closed)
930 }
931
932 fn get_state(&self) -> MutexGuard<'_, State> {
934 self.state.lock().expect("lock")
935 }
936}
937
938#[derive(Clone)]
941pub struct ChainMonitor {
942 pub funding_outpoint: OutPoint,
944 pub state: Arc<Mutex<State>>,
946 decode_state: Arc<Mutex<Option<BlockDecodeState>>>,
949 commitment_point_provider: Box<dyn CommitmentPointProvider>,
951}
952
953impl ChainMonitor {
954 pub fn as_base(&self) -> ChainMonitorBase {
956 ChainMonitorBase { funding_outpoint: self.funding_outpoint, state: self.state.clone() }
957 }
958
959 pub fn get_state(&self) -> MutexGuard<'_, State> {
961 self.state.lock().expect("lock")
962 }
963
964 pub fn add_funding(&self, tx: &Transaction, vout: u32) {
967 let mut state = self.get_state();
968 assert!(state.funding_txids.is_empty(), "only a single funding tx currently supported");
969 assert_eq!(state.funding_txids.len(), state.funding_vouts.len());
970 state.funding_txids.push(tx.compute_txid());
971 state.funding_vouts.push(vout);
972 state.funding_inputs.extend(tx.input.iter().map(|i| i.previous_output));
973 }
974
975 pub fn funding_depth(&self) -> u32 {
978 let state = self.get_state();
979 state.depth_of(state.funding_height)
980 }
981
982 pub fn funding_double_spent_depth(&self) -> u32 {
985 let state = self.get_state();
986 state.depth_of(state.funding_double_spent_height)
987 }
988
989 pub fn closing_depth(&self) -> u32 {
991 let state = self.get_state();
992 let closing_height = state.unilateral_closing_height.or(state.mutual_closing_height);
993 state.depth_of(closing_height)
994 }
995
996 pub fn is_done(&self) -> bool {
1002 self.get_state().is_done()
1003 }
1004
1005 fn push_transactions(&self, block_hash: &BlockHash, txs: &[Transaction]) -> BlockDecodeState {
1007 let mut state = self.get_state();
1008
1009 state.saw_block = true;
1011
1012 let mut decode_state = BlockDecodeState::new_with_block_hash(&*state, block_hash);
1013
1014 let mut listener = PushListener {
1015 commitment_point_provider: &*self.commitment_point_provider,
1016 decode_state: &mut decode_state,
1017 saw_block: true,
1018 };
1019
1020 for tx in txs {
1022 listener.on_transaction_start(tx.version.0);
1023 for input in tx.input.iter() {
1024 listener.on_transaction_input(input);
1025 }
1026
1027 for output in tx.output.iter() {
1028 listener.on_transaction_output(output);
1029 }
1030 listener.on_transaction_end(tx.lock_time, tx.compute_txid());
1031 }
1032
1033 decode_state
1034 }
1035}
1036
1037impl ChainListener for ChainMonitor {
1038 type Key = OutPoint;
1039
1040 fn key(&self) -> &Self::Key {
1041 &self.funding_outpoint
1042 }
1043
1044 fn on_add_block(
1045 &self,
1046 txs: &[Transaction],
1047 block_hash: &BlockHash,
1048 ) -> (Vec<OutPoint>, Vec<OutPoint>) {
1049 debug!("on_add_block for {}", self.funding_outpoint);
1050 let mut decode_state = self.push_transactions(block_hash, txs);
1051
1052 let mut state = self.get_state();
1053 state.on_add_block_end(block_hash, &mut decode_state)
1054 }
1055
1056 fn on_add_streamed_block_end(&self, block_hash: &BlockHash) -> (Vec<OutPoint>, Vec<OutPoint>) {
1057 let mut state = self.get_state();
1058 let mut decode_state = self.decode_state.lock().expect("lock").take();
1059 if !state.saw_block {
1060 return (Vec::new(), Vec::new());
1062 }
1063 state.on_add_block_end(block_hash, decode_state.as_mut().unwrap())
1065 }
1066
1067 fn on_remove_block(
1068 &self,
1069 txs: &[Transaction],
1070 block_hash: &BlockHash,
1071 ) -> (Vec<OutPoint>, Vec<OutPoint>) {
1072 debug!("on_remove_block for {}", self.funding_outpoint);
1073 let mut decode_state = self.push_transactions(block_hash, txs);
1074
1075 let mut state = self.get_state();
1076 state.on_remove_block_end(block_hash, &mut decode_state)
1077 }
1078
1079 fn on_remove_streamed_block_end(
1080 &self,
1081 block_hash: &BlockHash,
1082 ) -> (Vec<OutPoint>, Vec<OutPoint>) {
1083 let mut state = self.get_state();
1084 let mut decode_state = self.decode_state.lock().expect("lock").take();
1085 if !state.saw_block {
1086 return (Vec::new(), Vec::new());
1088 }
1089 state.on_remove_block_end(block_hash, decode_state.as_mut().unwrap())
1091 }
1092
1093 fn on_push<F>(&self, f: F)
1094 where
1095 F: FnOnce(&mut dyn push_decoder::Listener),
1096 {
1097 let mut state = self.get_state();
1098 let saw_block = state.saw_block;
1099
1100 let mut decode_state_lock = self.decode_state.lock().expect("lock");
1101
1102 let decode_state = decode_state_lock.get_or_insert_with(|| BlockDecodeState::new(&*state));
1103
1104 let mut listener = PushListener {
1105 commitment_point_provider: &*self.commitment_point_provider,
1106 decode_state,
1107 saw_block,
1108 };
1109 f(&mut listener);
1110
1111 state.saw_block = listener.saw_block;
1113 }
1114}
1115
1116impl SendSync for ChainMonitor {}
1117
1118#[cfg(test)]
1119mod tests {
1120 use crate::channel::{
1121 Channel, ChannelBase, ChannelCommitmentPointProvider, ChannelId, ChannelSetup,
1122 CommitmentType,
1123 };
1124 use crate::node::{Node, RoutedPayment};
1125 use crate::tx::tx::HTLCInfo2;
1126 use crate::util::test_utils::htlc::make_htlc;
1127 use crate::util::test_utils::key::{make_test_counterparty_points, make_test_pubkey};
1128 use crate::util::test_utils::*;
1129 use bitcoin::block::Version;
1130 use bitcoin::hash_types::TxMerkleNode;
1131 use bitcoin::hashes::Hash;
1132 use bitcoin::CompactTarget;
1133 use test_log::test;
1134
1135 use super::*;
1136
1137 #[test]
1138 fn test_funding() {
1139 let tx = make_tx(vec![make_txin(1), make_txin(2)]);
1140 let outpoint = OutPoint::new(tx.compute_txid(), 0);
1141 let cpp = Box::new(DummyCommitmentPointProvider {});
1142 let chan_id = ChannelId::new(&[33u8; 32]);
1143 let monitor = ChainMonitorBase::new(outpoint, 0, &chan_id).as_monitor(cpp);
1144 let block_hash = BlockHash::all_zeros();
1145 monitor.add_funding(&tx, 0);
1146 monitor.on_add_block(&[], &block_hash);
1147 monitor.on_add_block(&[tx.clone()], &block_hash);
1148 assert_eq!(monitor.funding_depth(), 1);
1149 assert_eq!(monitor.funding_double_spent_depth(), 0);
1150 monitor.on_add_block(&[], &block_hash);
1151 assert_eq!(monitor.funding_depth(), 2);
1152 monitor.on_remove_block(&[], &block_hash);
1153 assert_eq!(monitor.funding_depth(), 1);
1154 monitor.on_remove_block(&[tx], &block_hash);
1155 assert_eq!(monitor.funding_depth(), 0);
1156 monitor.on_remove_block(&[], &block_hash);
1157 assert_eq!(monitor.funding_depth(), 0);
1158 }
1159
1160 #[test]
1161 fn test_funding_double_spent() {
1162 let tx = make_tx(vec![make_txin(1), make_txin(2)]);
1163 let tx2 = make_tx(vec![make_txin(2)]);
1164 let outpoint = OutPoint::new(tx.compute_txid(), 0);
1165 let cpp = Box::new(DummyCommitmentPointProvider {});
1166 let chan_id = ChannelId::new(&[33u8; 32]);
1167 let monitor = ChainMonitorBase::new(outpoint, 0, &chan_id).as_monitor(cpp);
1168 let block_hash = BlockHash::all_zeros();
1169 monitor.add_funding(&tx, 0);
1170 monitor.on_add_block(&[], &block_hash);
1171 monitor.on_add_block(&[tx2.clone()], &block_hash);
1172 assert_eq!(monitor.funding_depth(), 0);
1173 assert_eq!(monitor.funding_double_spent_depth(), 1);
1174 monitor.on_add_block(&[], &block_hash);
1175 assert_eq!(monitor.funding_depth(), 0);
1176 assert_eq!(monitor.funding_double_spent_depth(), 2);
1177 monitor.on_remove_block(&[], &block_hash);
1178 assert_eq!(monitor.funding_double_spent_depth(), 1);
1179 monitor.on_remove_block(&[tx2], &block_hash);
1180 assert_eq!(monitor.funding_double_spent_depth(), 0);
1181 monitor.on_remove_block(&[], &block_hash);
1182 assert_eq!(monitor.funding_double_spent_depth(), 0);
1183 }
1184
1185 #[test]
1186 fn test_stream() {
1187 let outpoint = OutPoint::new(Txid::from_slice(&[1; 32]).unwrap(), 0);
1188 let cpp = Box::new(DummyCommitmentPointProvider {});
1189 let chan_id = ChannelId::new(&[33u8; 32]);
1190 let monitor = ChainMonitorBase::new(outpoint, 0, &chan_id).as_monitor(cpp);
1191 let header = BlockHeader {
1192 version: Version::from_consensus(0),
1193 prev_blockhash: BlockHash::all_zeros(),
1194 merkle_root: TxMerkleNode::all_zeros(),
1195 time: 0,
1196 bits: CompactTarget::from_consensus(0),
1197 nonce: 0,
1198 };
1199 let tx = make_tx(vec![make_txin(1), make_txin(2)]);
1200
1201 monitor.on_push(|listener| {
1203 listener.on_transaction_input(&tx.input[1]);
1204 listener.on_transaction_output(&tx.output[0]);
1205 listener.on_transaction_end(tx.lock_time, tx.compute_txid());
1206 listener.on_block_end();
1207 });
1208
1209 assert!(!monitor.state.lock().unwrap().saw_block);
1210
1211 monitor.on_push(|listener| {
1213 listener.on_block_start(&header);
1214 listener.on_transaction_start(2);
1215 listener.on_transaction_input(&tx.input[0]);
1216 listener.on_transaction_input(&tx.input[1]);
1217 listener.on_transaction_output(&tx.output[0]);
1218 listener.on_transaction_end(tx.lock_time, tx.compute_txid());
1219 listener.on_block_end();
1220 });
1221 monitor.on_add_streamed_block_end(&header.block_hash());
1222
1223 assert!(monitor.state.lock().unwrap().saw_block);
1224
1225 monitor.on_push(|listener| {
1227 listener.on_block_start(&header);
1228 listener.on_transaction_start(2);
1229 listener.on_transaction_input(&tx.input[0]);
1230 listener.on_transaction_input(&tx.input[1]);
1231 listener.on_transaction_output(&tx.output[0]);
1232 listener.on_transaction_end(tx.lock_time, tx.compute_txid());
1233 listener.on_block_end();
1234 });
1235 monitor.on_add_streamed_block_end(&header.block_hash());
1236
1237 assert!(monitor.state.lock().unwrap().saw_block);
1238 }
1239
1240 #[test]
1241 fn test_streamed_block_operations() {
1242 let outpoint = OutPoint::new(Txid::from_slice(&[1; 32]).unwrap(), 0);
1243 let cpp = Box::new(DummyCommitmentPointProvider {});
1244 let chan_id = ChannelId::new(&[33u8; 32]);
1245 let monitor = ChainMonitorBase::new(outpoint, 0, &chan_id).as_monitor(cpp);
1246 let block_hash = BlockHash::all_zeros();
1247
1248 let (adds, removes) = monitor.on_add_streamed_block_end(&block_hash);
1250 assert!(adds.is_empty());
1251 assert!(removes.is_empty());
1252
1253 let (adds, removes) = monitor.on_remove_streamed_block_end(&block_hash);
1254 assert!(adds.is_empty());
1255 assert!(removes.is_empty());
1256
1257 let funding_tx = make_tx(vec![make_txin(1), make_txin(2)]);
1258 let funding_outpoint = OutPoint::new(funding_tx.compute_txid(), 0);
1259 let monitor2 = ChainMonitorBase::new(funding_outpoint, 0, &chan_id)
1260 .as_monitor(Box::new(DummyCommitmentPointProvider {}));
1261 monitor2.add_funding(&funding_tx, 0);
1262
1263 let header = BlockHeader {
1264 version: Version::from_consensus(0),
1265 prev_blockhash: BlockHash::all_zeros(),
1266 merkle_root: TxMerkleNode::all_zeros(),
1267 time: 0,
1268 bits: CompactTarget::from_consensus(0),
1269 nonce: 0,
1270 };
1271 let header_block_hash = header.block_hash();
1272
1273 monitor2.on_push(|listener| {
1274 listener.on_block_start(&header);
1275 listener.on_transaction_start(funding_tx.version.0);
1276
1277 for input in &funding_tx.input {
1278 listener.on_transaction_input(input);
1279 }
1280
1281 for output in &funding_tx.output {
1282 listener.on_transaction_output(output);
1283 }
1284
1285 listener.on_transaction_end(funding_tx.lock_time, funding_tx.compute_txid());
1286 listener.on_block_end();
1287 });
1288
1289 let (adds, _) = monitor2.on_add_streamed_block_end(&header_block_hash);
1290 assert!(!adds.is_empty());
1291
1292 monitor2.on_push(|listener| {
1293 listener.on_block_start(&header);
1294 listener.on_transaction_start(funding_tx.version.0);
1295
1296 for input in &funding_tx.input {
1297 listener.on_transaction_input(input);
1298 }
1299
1300 for output in &funding_tx.output {
1301 listener.on_transaction_output(output);
1302 }
1303
1304 listener.on_transaction_end(funding_tx.lock_time, funding_tx.compute_txid());
1305 listener.on_block_end();
1306 });
1307
1308 let (adds, _) = monitor2.on_remove_streamed_block_end(&header_block_hash);
1309 assert!(!adds.is_empty());
1310 }
1311
1312 #[test]
1313 fn test_chain_monitor_conversions_and_getters() {
1314 let outpoint = OutPoint::new(Txid::from_slice(&[1; 32]).unwrap(), 0);
1315 let chan_id = ChannelId::new(&[33u8; 32]);
1316 let base = ChainMonitorBase::new(outpoint, 0, &chan_id);
1317
1318 let cpp = Box::new(DummyCommitmentPointProvider {});
1319 let monitor = base.as_monitor(cpp);
1320 let base2 = monitor.as_base();
1321 assert_eq!(base2.funding_outpoint, outpoint);
1322
1323 assert_eq!(base.funding_outpoint(), None);
1324 assert!(!base.forget_seen());
1325
1326 base.forget_channel();
1327 assert!(base.forget_seen());
1328 }
1329 #[test]
1330 fn test_mutual_close() {
1331 let block_hash = BlockHash::all_zeros();
1332 let (node, channel_id, monitor, funding_txid) = setup_funded_channel();
1333
1334 node.get_heartbeat();
1336 assert!(node.get_channel(&channel_id).is_ok());
1337 assert_eq!(node.get_tracker().listeners.len(), 1);
1338
1339 let close_tx = make_tx(vec![TxIn {
1340 previous_output: OutPoint::new(funding_txid, 0),
1341 script_sig: Default::default(),
1342 sequence: Default::default(),
1343 witness: Default::default(),
1344 }]);
1345 monitor.on_add_block(&[close_tx.clone()], &block_hash);
1346 assert_eq!(monitor.closing_depth(), 1);
1347 assert!(!monitor.is_done());
1348
1349 node.get_heartbeat();
1351 assert!(node.get_channel(&channel_id).is_ok());
1352 assert_eq!(node.get_tracker().listeners.len(), 1);
1353
1354 for _ in 1..MIN_DEPTH - 1 {
1355 monitor.on_add_block(&[], &block_hash);
1356 }
1357 assert!(!monitor.is_done());
1358 node.forget_channel(&channel_id).unwrap();
1359 monitor.on_add_block(&[], &block_hash);
1360 assert!(monitor.is_done());
1361
1362 assert!(node.get_channel(&channel_id).is_ok());
1364
1365 node.get_heartbeat();
1367 assert!(node.get_channel(&channel_id).is_err());
1368 assert_eq!(node.get_tracker().listeners.len(), 0);
1369 }
1370
1371 #[test]
1372 fn test_mutual_close_with_forget_channel() {
1373 let block_hash = BlockHash::all_zeros();
1374 let (node, channel_id, monitor, funding_txid) = setup_funded_channel();
1375
1376 node.get_heartbeat();
1378 assert!(node.get_channel(&channel_id).is_ok());
1379 assert_eq!(node.get_tracker().listeners.len(), 1);
1380
1381 let close_tx = make_tx(vec![TxIn {
1382 previous_output: OutPoint::new(funding_txid, 0),
1383 script_sig: Default::default(),
1384 sequence: Default::default(),
1385 witness: Default::default(),
1386 }]);
1387 monitor.on_add_block(&[close_tx.clone()], &block_hash);
1388 assert_eq!(monitor.closing_depth(), 1);
1389 assert!(!monitor.is_done());
1390
1391 node.get_heartbeat();
1393 assert!(node.get_channel(&channel_id).is_ok());
1394 assert_eq!(node.get_tracker().listeners.len(), 1);
1395
1396 for _ in 1..MIN_DEPTH - 1 {
1397 monitor.on_add_block(&[], &block_hash);
1398 }
1399 assert!(!monitor.is_done());
1400 monitor.on_add_block(&[], &block_hash);
1401 assert!(!monitor.is_done());
1402
1403 assert!(node.get_channel(&channel_id).is_ok());
1405 node.forget_channel(&channel_id).unwrap();
1406
1407 assert!(node.get_channel(&channel_id).is_ok());
1409 node.get_heartbeat();
1410 assert!(node.get_channel(&channel_id).is_err());
1411 assert_eq!(node.get_tracker().listeners.len(), 0);
1412 }
1413
1414 #[test]
1415 fn test_mutual_close_with_missing_forget_channel() {
1416 let block_hash = BlockHash::all_zeros();
1417 let (node, channel_id, monitor, funding_txid) = setup_funded_channel();
1418
1419 node.get_heartbeat();
1421 assert!(node.get_channel(&channel_id).is_ok());
1422 assert_eq!(node.get_tracker().listeners.len(), 1);
1423
1424 let close_tx = make_tx(vec![TxIn {
1425 previous_output: OutPoint::new(funding_txid, 0),
1426 script_sig: Default::default(),
1427 sequence: Default::default(),
1428 witness: Default::default(),
1429 }]);
1430 monitor.on_add_block(&[close_tx.clone()], &block_hash);
1431 assert_eq!(monitor.closing_depth(), 1);
1432 assert!(!monitor.is_done());
1433
1434 node.get_heartbeat();
1436 assert!(node.get_channel(&channel_id).is_ok());
1437 assert_eq!(node.get_tracker().listeners.len(), 1);
1438
1439 for _ in 1..MIN_DEPTH - 1 {
1440 monitor.on_add_block(&[], &block_hash);
1441 }
1442 assert!(!monitor.is_done());
1443 monitor.on_add_block(&[], &block_hash);
1444
1445 assert!(!monitor.is_done());
1447 assert!(node.get_channel(&channel_id).is_ok());
1448
1449 node.get_heartbeat();
1451 assert!(node.get_channel(&channel_id).is_ok());
1452
1453 for _ in 0..2016 - 1 {
1455 monitor.on_add_block(&[], &block_hash);
1456 }
1457 assert!(!monitor.is_done());
1458
1459 monitor.on_add_block(&[], &block_hash);
1461 assert!(!monitor.is_done());
1462
1463 assert!(node.get_channel(&channel_id).is_ok());
1465
1466 node.get_heartbeat();
1468 assert!(node.get_channel(&channel_id).is_ok());
1469 }
1470
1471 #[test]
1472 fn test_unilateral_holder_close() {
1473 let block_hash = BlockHash::all_zeros();
1474 let (node, channel_id, monitor, _funding_txid) = setup_funded_channel();
1475
1476 let commit_num = 23;
1477 let feerate_per_kw = 1000;
1478 let to_holder = 100000;
1479 let to_cp = 200000;
1480 let htlcs = Vec::new();
1481 let closing_commitment_tx = node
1482 .with_channel(&channel_id, |chan| {
1483 chan.set_next_holder_commit_num_for_testing(commit_num);
1484 let per_commitment_point = chan.get_per_commitment_point(commit_num)?;
1485
1486 chan.set_next_counterparty_commit_num_for_testing(
1487 commit_num + 1,
1488 per_commitment_point.clone(),
1489 );
1490
1491 Ok(chan.make_holder_commitment_tx(
1492 commit_num,
1493 &per_commitment_point,
1494 feerate_per_kw,
1495 to_holder,
1496 to_cp,
1497 htlcs.clone(),
1498 ))
1499 })
1500 .expect("make_holder_commitment_tx failed");
1501 let closing_tx = closing_commitment_tx.trust().built_transaction().transaction.clone();
1502 let closing_txid = closing_tx.compute_txid();
1503 let holder_output_index =
1504 closing_tx.output.iter().position(|out| out.value.to_sat() == to_holder).unwrap()
1505 as u32;
1506 monitor.on_add_block(&[closing_tx.clone()], &block_hash);
1507 assert_eq!(monitor.closing_depth(), 1);
1508 assert!(!monitor.is_done());
1509 for _ in 1..MAX_CLOSING_DEPTH {
1511 monitor.on_add_block(&[], &block_hash);
1512 }
1513 assert!(!monitor.is_done());
1514 let sweep_cp_tx = make_tx(vec![make_txin2(closing_txid, 1 - holder_output_index)]);
1515 monitor.on_add_block(&[sweep_cp_tx], &block_hash);
1516 for _ in 1..MAX_CLOSING_DEPTH {
1518 monitor.on_add_block(&[], &block_hash);
1519 }
1520 assert!(!monitor.is_done());
1521 let sweep_holder_tx = make_tx(vec![make_txin2(closing_txid, holder_output_index)]);
1522 monitor.on_add_block(&[sweep_holder_tx], &block_hash);
1523 for _ in 1..MIN_DEPTH {
1525 monitor.on_add_block(&[], &block_hash);
1526 }
1527 node.forget_channel(&channel_id).unwrap();
1528 assert!(monitor.is_done());
1529 }
1530
1531 #[test]
1532 fn test_unilateral_cp_and_htlcs_close() {
1533 let block_hash = BlockHash::all_zeros();
1534 let (node, channel_id, monitor, _funding_txid) = setup_funded_channel();
1535
1536 let payment_hashes = make_test_payment_hashes(4);
1537 let (preimage_1, hash_1) = payment_hashes[0];
1538 let (_, hash_2) = payment_hashes[1];
1539 let (_, hash_3) = payment_hashes[2];
1540 let (_, hash_4) = payment_hashes[3];
1541
1542 let offered_htlcs = vec![make_htlc(hash_1, 500, 100), make_htlc(hash_2, 600, 150)];
1543 let received_htlcs = vec![make_htlc(hash_3, 500, 200), make_htlc(hash_4, 600, 250)];
1544
1545 let mut node_state = node.get_state();
1546 let mut payment = RoutedPayment::new();
1547 payment.preimage = Some(preimage_1);
1548 node_state.payments.insert(hash_1, payment);
1549 drop(node_state);
1550
1551 let commit_num = 23;
1552 let feerate_per_kw = 1000;
1553 let to_holder = 100000;
1554 let to_cp = 200000;
1555
1556 let htlcs = Channel::htlcs_info2_to_oic(&offered_htlcs, &received_htlcs);
1557
1558 let closing_commitment_tx = node
1559 .with_channel(&channel_id, |chan| {
1560 let per_commitment_point = make_test_pubkey(12);
1561 let info2 = chan.build_counterparty_commitment_info(
1562 to_holder,
1563 to_cp,
1564 offered_htlcs.clone(),
1565 received_htlcs.clone(),
1566 feerate_per_kw,
1567 )?;
1568 chan.set_next_counterparty_commit_num_for_testing(
1569 commit_num + 1,
1570 per_commitment_point.clone(),
1571 );
1572 chan.enforcement_state.current_counterparty_commit_info = Some(info2);
1573
1574 Ok(chan.make_counterparty_commitment_tx(
1575 &per_commitment_point,
1576 commit_num,
1577 feerate_per_kw,
1578 to_holder,
1579 to_cp,
1580 htlcs.clone(),
1581 ))
1582 })
1583 .expect("make_counterparty_commitment_tx failed");
1584
1585 let closing_tx = closing_commitment_tx.trust().built_transaction().transaction.clone();
1586 let (closing_txid, holder_output_index, cp_output_index, htlc_output_indices) =
1587 extract_tx_info(&closing_tx, to_holder, to_cp, &htlcs);
1588
1589 assert_eq!(monitor.closing_depth(), 0);
1590 assert!(!monitor.is_done());
1591
1592 monitor.on_add_block(&[closing_tx.clone()], &block_hash);
1593 assert_eq!(monitor.closing_depth(), 1);
1594 assert!(!monitor.is_done());
1595
1596 let spendable_indices = node
1597 .with_channel(&channel_id, |chan| {
1598 chan.get_spendable_htlc_indices(&closing_tx, commit_num)
1599 })
1600 .expect("spendable indices");
1601
1602 assert_eq!(spendable_indices.len(), 3);
1603
1604 let state = monitor.get_state();
1605 let closing_outpoints = state.closing_outpoints.as_ref().unwrap();
1606
1607 assert!(!closing_outpoints.is_all_spent());
1608
1609 let holder_outpoint = OutPoint { txid: closing_txid, vout: holder_output_index };
1610 let cp_outpoint = OutPoint { txid: closing_txid, vout: cp_output_index };
1611 let trackable_htlc_outpoints: Vec<OutPoint> = htlc_output_indices
1612 .iter()
1613 .enumerate()
1614 .filter(|(i, _)| htlcs[*i].amount_msat != 600_000)
1615 .map(|(_, &vout)| OutPoint { txid: closing_txid, vout })
1616 .collect();
1617
1618 assert!(closing_outpoints.includes_our_output(&holder_outpoint));
1619 assert!(!closing_outpoints.includes_our_output(&cp_outpoint));
1620 for trackable_htlc_outpoint in &trackable_htlc_outpoints {
1621 assert!(closing_outpoints.includes_htlc_output(trackable_htlc_outpoint));
1622 assert!(!closing_outpoints.includes_second_level_htlc_output(trackable_htlc_outpoint));
1623 }
1624 assert!(!closing_outpoints.includes_htlc_output(&holder_outpoint));
1625
1626 drop(state);
1627 assert!(!monitor.is_done());
1628
1629 let sweep_cp_tx = make_tx(vec![make_txin2(closing_txid, cp_output_index)]);
1630 monitor.on_add_block(&[sweep_cp_tx], &block_hash);
1631 assert!(!monitor.is_done());
1632
1633 let sweep_holder_tx = make_tx(vec![make_txin2(closing_txid, holder_output_index)]);
1634 monitor.on_add_block(&[sweep_holder_tx], &block_hash);
1635
1636 let state = monitor.get_state();
1637 let closing_outpoints = state.closing_outpoints.as_ref().unwrap();
1638 assert!(!closing_outpoints.is_all_spent());
1639 drop(state);
1640
1641 let monitor1 = monitor.clone();
1642
1643 assert!(!monitor.is_done());
1645 monitor.on_add_block(&[], &block_hash);
1646 assert!(!monitor.is_done());
1647
1648 let mut swept_htlc_txids = Vec::new();
1650 let mut second_level_outpoints = Vec::new();
1651
1652 for (_, &htlc_index) in spendable_indices.iter().enumerate() {
1654 let sweep_htlc_tx = make_tx(vec![make_txin2(closing_txid, htlc_index)]);
1655 let sweep_htlc_txid = sweep_htlc_tx.compute_txid();
1656 swept_htlc_txids.push(sweep_htlc_txid);
1657
1658 monitor1.on_add_block(&[sweep_htlc_tx], &block_hash);
1659
1660 let state = monitor1.get_state();
1661 let closing_outpoints = state.closing_outpoints.as_ref().unwrap();
1662
1663 let second_level_outpoint = OutPoint { txid: sweep_htlc_txid, vout: 0 };
1664 second_level_outpoints.push(second_level_outpoint);
1665
1666 assert!(closing_outpoints.includes_second_level_htlc_output(&second_level_outpoint));
1667 assert!(!closing_outpoints.is_all_spent());
1668 drop(state);
1669 }
1670
1671 let state = monitor1.get_state();
1672 let closing_outpoints = state.closing_outpoints.as_ref().unwrap();
1673 for (_, &second_level_outpoint) in second_level_outpoints.iter().enumerate() {
1674 assert!(closing_outpoints.includes_second_level_htlc_output(&second_level_outpoint));
1675 }
1676 drop(state);
1677 assert!(!monitor1.is_done());
1678
1679 for (i, &outpoint) in second_level_outpoints.iter().enumerate() {
1681 let sweep_second_level_tx = make_tx(vec![make_txin2(outpoint.txid, 0)]);
1682 monitor1.on_add_block(&[sweep_second_level_tx], &block_hash);
1683
1684 let state = monitor1.get_state();
1685 let closing_outpoints = state.closing_outpoints.as_ref().unwrap();
1686
1687 if i == second_level_outpoints.len() - 1 {
1688 assert!(closing_outpoints.is_all_spent());
1689 } else {
1690 assert!(!closing_outpoints.is_all_spent());
1691 }
1692 drop(state);
1693 }
1694
1695 let state = monitor1.get_state();
1697 let closing_outpoints = state.closing_outpoints.as_ref().unwrap();
1698 assert!(closing_outpoints.is_all_spent());
1699 drop(state);
1700
1701 for _ in 1..MIN_DEPTH {
1702 monitor1.on_add_block(&[], &block_hash);
1703 }
1704 assert!(!monitor1.is_done());
1706
1707 node.forget_channel(&channel_id).unwrap();
1709 assert!(monitor.is_done());
1710 assert!(monitor1.is_done());
1711 }
1712
1713 #[test]
1714 fn test_unilateral_cp_and_htlcs_backward_change() {
1715 let block_hash = BlockHash::all_zeros();
1716 let (node, channel_id, monitor, _funding_txid) = setup_funded_channel();
1717
1718 let payment_hashes = make_test_payment_hashes(4);
1719 let (preimage_1, hash_1) = payment_hashes[0];
1720 let (_, hash_2) = payment_hashes[1];
1721 let (_, hash_3) = payment_hashes[2];
1722 let (_, hash_4) = payment_hashes[3];
1723
1724 let offered_htlcs = vec![
1725 HTLCInfo2 { value_sat: 500, payment_hash: hash_1, cltv_expiry: 100 },
1726 HTLCInfo2 { value_sat: 600, payment_hash: hash_2, cltv_expiry: 150 },
1727 ];
1728
1729 let received_htlcs = vec![
1730 HTLCInfo2 { value_sat: 500, payment_hash: hash_3, cltv_expiry: 200 },
1731 HTLCInfo2 { value_sat: 400, payment_hash: hash_4, cltv_expiry: 250 },
1732 ];
1733
1734 let mut node_state = node.get_state();
1735 let mut payment = RoutedPayment::new();
1736 payment.preimage = Some(preimage_1);
1737 node_state.payments.insert(hash_1, payment);
1738 drop(node_state);
1739
1740 let commit_num = 23;
1741 let feerate_per_kw = 1000;
1742 let to_holder = 100000;
1743 let to_cp = 200000;
1744
1745 let htlcs = Channel::htlcs_info2_to_oic(&offered_htlcs, &received_htlcs);
1746
1747 let closing_commitment_tx = node
1748 .with_channel(&channel_id, |chan| {
1749 let per_commitment_point = make_test_pubkey(12);
1750 let info2 = chan.build_counterparty_commitment_info(
1751 to_holder,
1752 to_cp,
1753 offered_htlcs.clone(),
1754 received_htlcs.clone(),
1755 feerate_per_kw,
1756 )?;
1757 chan.set_next_counterparty_commit_num_for_testing(
1758 commit_num + 1,
1759 per_commitment_point.clone(),
1760 );
1761 chan.enforcement_state.current_counterparty_commit_info = Some(info2);
1762
1763 Ok(chan.make_counterparty_commitment_tx(
1764 &per_commitment_point,
1765 commit_num,
1766 feerate_per_kw,
1767 to_holder,
1768 to_cp,
1769 htlcs.clone(),
1770 ))
1771 })
1772 .expect("make_counterparty_commitment_tx failed");
1773
1774 let closing_tx = closing_commitment_tx.trust().built_transaction().transaction.clone();
1775 let (closing_txid, holder_output_index, cp_output_index, htlc_output_indices) =
1776 extract_tx_info(&closing_tx, to_holder, to_cp, &htlcs);
1777
1778 assert_eq!(monitor.closing_depth(), 0);
1779 monitor.on_add_block(&[closing_tx.clone()], &block_hash);
1780 assert_eq!(monitor.closing_depth(), 1);
1781
1782 let spendable_indices = node
1783 .with_channel(&channel_id, |chan| {
1784 chan.get_spendable_htlc_indices(&closing_tx, commit_num)
1785 })
1786 .expect("spendable indices");
1787 assert_eq!(spendable_indices.len(), 3);
1788
1789 let state = monitor.get_state();
1790 let closing_outpoints = state.closing_outpoints.as_ref().unwrap();
1791 assert!(!closing_outpoints.is_all_spent());
1792
1793 let holder_outpoint = OutPoint { txid: closing_txid, vout: holder_output_index };
1794 let cp_outpoint = OutPoint { txid: closing_txid, vout: cp_output_index };
1795 let trackable_htlc_outpoints: Vec<OutPoint> = htlc_output_indices
1797 .iter()
1798 .enumerate()
1799 .filter(|(i, _)| htlcs[*i].amount_msat != 600_000)
1800 .map(|(_, &vout)| OutPoint { txid: closing_txid, vout })
1801 .collect();
1802
1803 assert!(!closing_outpoints.is_all_spent());
1804 assert!(closing_outpoints.includes_our_output(&holder_outpoint));
1805 assert!(!closing_outpoints.includes_our_output(&cp_outpoint));
1806 for trackable_htlc_outpoint in &trackable_htlc_outpoints {
1807 assert!(closing_outpoints.includes_htlc_output(trackable_htlc_outpoint));
1808 assert!(!closing_outpoints.includes_second_level_htlc_output(trackable_htlc_outpoint));
1809 }
1810 assert!(!closing_outpoints.includes_htlc_output(&holder_outpoint));
1811 drop(state);
1812
1813 let sweep_holder_tx = make_tx(vec![make_txin2(closing_txid, holder_output_index)]);
1814 monitor.on_add_block(&[sweep_holder_tx.clone()], &block_hash);
1815
1816 let state = monitor.get_state();
1817 let closing_outpoints = state.closing_outpoints.as_ref().unwrap();
1818 assert!(!closing_outpoints.is_all_spent());
1819 drop(state);
1820
1821 let mut swept_htlc_txs = Vec::new();
1822 let mut swept_htlc_txids = Vec::new();
1823 let mut second_level_outpoints = Vec::new();
1824
1825 for (_, &htlc_index) in spendable_indices.iter().enumerate() {
1826 let sweep_htlc_tx = make_tx(vec![make_txin2(closing_txid, htlc_index)]);
1827 let sweep_htlc_txid = sweep_htlc_tx.compute_txid();
1828 swept_htlc_txs.push(sweep_htlc_tx.clone());
1829 swept_htlc_txids.push(sweep_htlc_txid);
1830
1831 monitor.on_add_block(&[sweep_htlc_tx], &block_hash);
1832
1833 let state = monitor.get_state();
1834 let closing_outpoints = state.closing_outpoints.as_ref().unwrap();
1835
1836 let second_level_outpoint = OutPoint { txid: sweep_htlc_txid, vout: 0 };
1837 second_level_outpoints.push(second_level_outpoint);
1838
1839 assert!(closing_outpoints.includes_second_level_htlc_output(&second_level_outpoint));
1840 assert!(!closing_outpoints.is_all_spent());
1841 drop(state);
1842 }
1843
1844 let mut sweep_second_level_txs = Vec::new();
1845 for (i, &outpoint) in second_level_outpoints.iter().enumerate() {
1846 let sweep_second_level_tx = make_tx(vec![make_txin2(outpoint.txid, 0)]);
1847 sweep_second_level_txs.push(sweep_second_level_tx.clone());
1848 monitor.on_add_block(&[sweep_second_level_tx], &block_hash);
1849
1850 let state = monitor.get_state();
1851 let closing_outpoints = state.closing_outpoints.as_ref().unwrap();
1852
1853 if i == second_level_outpoints.len() - 1 {
1854 assert!(closing_outpoints.is_all_spent());
1855 } else {
1856 assert!(!closing_outpoints.is_all_spent());
1857 }
1858 drop(state);
1859 }
1860
1861 let state = monitor.get_state();
1862 let closing_outpoints = state.closing_outpoints.as_ref().unwrap();
1863 assert!(closing_outpoints.is_all_spent());
1864 drop(state);
1865
1866 for (i, sweep_second_level_tx) in sweep_second_level_txs.iter().rev().enumerate() {
1868 monitor.on_remove_block(&[sweep_second_level_tx.clone()], &block_hash);
1869
1870 let state = monitor.get_state();
1871 let closing_outpoints = state.closing_outpoints.as_ref().unwrap();
1872 assert!(!closing_outpoints.is_all_spent());
1873
1874 let remaining_second_levels = second_level_outpoints.len() - 1 - i;
1875 if remaining_second_levels > 0 {
1876 for &outpoint in second_level_outpoints.iter().take(remaining_second_levels) {
1877 assert!(closing_outpoints.includes_second_level_htlc_output(&outpoint));
1878 }
1879 }
1880 drop(state);
1881 }
1882
1883 for (i, sweep_htlc_tx) in swept_htlc_txs.iter().rev().enumerate() {
1885 monitor.on_remove_block(&[sweep_htlc_tx.clone()], &block_hash);
1886
1887 let state = monitor.get_state();
1888 let closing_outpoints = state.closing_outpoints.as_ref().unwrap();
1889
1890 let rolled_back_second_level =
1891 &second_level_outpoints[second_level_outpoints.len() - 1 - i];
1892 assert!(!closing_outpoints.includes_second_level_htlc_output(rolled_back_second_level));
1893
1894 let rolled_back_htlc =
1895 &trackable_htlc_outpoints[trackable_htlc_outpoints.len() - 1 - i];
1896 assert!(closing_outpoints.includes_htlc_output(rolled_back_htlc));
1897
1898 assert!(!closing_outpoints.is_all_spent());
1899 drop(state);
1900 }
1901
1902 monitor.on_remove_block(&[sweep_holder_tx], &block_hash);
1904 let state = monitor.get_state();
1905 let closing_outpoints = state.closing_outpoints.as_ref().unwrap();
1906 assert!(closing_outpoints.includes_our_output(&holder_outpoint));
1907 for trackable_htlc_outpoint in &trackable_htlc_outpoints {
1908 assert!(closing_outpoints.includes_htlc_output(trackable_htlc_outpoint));
1909 }
1910 assert!(!closing_outpoints.is_all_spent());
1911 drop(state);
1912
1913 monitor.on_remove_block(&[closing_tx], &block_hash);
1915 let state = monitor.get_state();
1916 assert!(state.closing_outpoints.is_none());
1917 assert_eq!(state.unilateral_closing_height, None);
1918 }
1919
1920 #[test]
1921 fn test_apply_backward_change_funding_confirmed() {
1922 let funding_tx = make_tx(vec![make_txin(1), make_txin(2)]);
1923 let funding_outpoint = OutPoint::new(funding_tx.compute_txid(), 0);
1924 let setup = make_channel_setup(funding_outpoint);
1925 let (node, channel_id) =
1926 init_node_and_channel(TEST_NODE_CONFIG, TEST_SEED[1], setup.clone());
1927 let channel = node.get_channel(&channel_id).unwrap();
1928 let cpp = Box::new(ChannelCommitmentPointProvider::new(channel.clone()));
1929 let monitor = node
1930 .with_channel(&channel_id, |chan| Ok(chan.monitor.clone().as_monitor(cpp.clone())))
1931 .unwrap();
1932 let block_hash = BlockHash::all_zeros();
1933
1934 monitor.on_add_block(&[], &block_hash);
1935 monitor.on_add_block(&[funding_tx.clone()], &block_hash);
1936 assert_eq!(monitor.funding_depth(), 1);
1937 assert!(monitor.get_state().funding_outpoint.is_some());
1938
1939 monitor.on_remove_block(&[funding_tx], &block_hash);
1940 assert_eq!(monitor.funding_depth(), 0);
1941 assert!(monitor.get_state().funding_outpoint.is_none());
1942 }
1943
1944 #[test]
1945 fn test_apply_backward_change_mutual_close() {
1946 let block_hash = BlockHash::all_zeros();
1947 let (_, _, monitor, funding_txid) = setup_funded_channel();
1948
1949 let close_tx = make_tx(vec![TxIn {
1950 previous_output: OutPoint::new(funding_txid, 0),
1951 script_sig: Default::default(),
1952 sequence: Default::default(),
1953 witness: Default::default(),
1954 }]);
1955
1956 monitor.on_add_block(&[close_tx.clone()], &block_hash);
1957 assert_eq!(monitor.closing_depth(), 1);
1958 assert!(monitor.get_state().mutual_closing_height.is_some());
1959
1960 monitor.on_remove_block(&[close_tx], &block_hash);
1961 assert_eq!(monitor.closing_depth(), 0);
1962 assert!(monitor.get_state().mutual_closing_height.is_none());
1963 }
1964
1965 #[test]
1966 fn test_closing_outpoints_is_all_spent_logic() {
1967 let txid = Txid::all_zeros();
1968 let mut closing_outpoints = ClosingOutpoints::new(txid, Some(0), vec![1, 2]);
1969
1970 assert!(!closing_outpoints.is_all_spent());
1971
1972 closing_outpoints.set_our_output_spent(0, true);
1973 assert!(!closing_outpoints.is_all_spent());
1974
1975 closing_outpoints.set_htlc_output_spent(1, true);
1976 assert!(!closing_outpoints.is_all_spent());
1977
1978 closing_outpoints.set_htlc_output_spent(2, true);
1979 assert!(closing_outpoints.is_all_spent());
1981
1982 let second_level_outpoint = OutPoint { txid, vout: 10 };
1983 closing_outpoints.add_second_level_htlc_output(second_level_outpoint);
1984 assert!(!closing_outpoints.is_all_spent());
1985
1986 closing_outpoints.set_second_level_htlc_spent(second_level_outpoint, true);
1987 assert!(closing_outpoints.is_all_spent());
1988 }
1989
1990 #[test]
1991 fn test_closing_outpoints_without_our_output() {
1992 let txid = Txid::all_zeros();
1993 let mut closing_outpoints = ClosingOutpoints::new(txid, None, vec![1]);
1994
1995 assert!(!closing_outpoints.is_all_spent());
1996
1997 closing_outpoints.set_htlc_output_spent(1, true);
1998 assert!(closing_outpoints.is_all_spent());
1999 }
2000
2001 #[test]
2002 fn test_closing_outpoints_boolean_logic_edge_cases() {
2003 let txid = Txid::all_zeros();
2004
2005 let closing_outpoints = ClosingOutpoints::new(txid, None, vec![]);
2006 assert!(closing_outpoints.is_all_spent());
2007
2008 let mut closing_outpoints = ClosingOutpoints::new(txid, Some(0), vec![1]);
2009
2010 closing_outpoints.set_our_output_spent(0, false);
2011 closing_outpoints.set_htlc_output_spent(1, false);
2012 assert!(!closing_outpoints.is_all_spent());
2013
2014 closing_outpoints.set_our_output_spent(0, true);
2015 closing_outpoints.set_htlc_output_spent(1, false);
2016 assert!(!closing_outpoints.is_all_spent());
2017 }
2018
2019 #[test]
2020 fn test_closing_outpoints_second_level_management() {
2021 let txid = Txid::all_zeros();
2022 let mut closing_outpoints = ClosingOutpoints::new(txid, None, vec![]);
2023
2024 let outpoint1 = OutPoint { txid, vout: 10 };
2025 let outpoint2 = OutPoint { txid, vout: 11 };
2026
2027 closing_outpoints.add_second_level_htlc_output(outpoint1);
2028 closing_outpoints.add_second_level_htlc_output(outpoint2);
2029
2030 assert!(closing_outpoints.includes_second_level_htlc_output(&outpoint1));
2031 assert!(closing_outpoints.includes_second_level_htlc_output(&outpoint2));
2032
2033 closing_outpoints.set_second_level_htlc_spent(outpoint1, true);
2034 assert!(!closing_outpoints.is_all_spent());
2035
2036 closing_outpoints.set_second_level_htlc_spent(outpoint2, true);
2037 assert!(closing_outpoints.is_all_spent());
2038
2039 closing_outpoints.remove_second_level_htlc_output(&outpoint1);
2040 assert!(!closing_outpoints.includes_second_level_htlc_output(&outpoint1));
2041 assert!(closing_outpoints.includes_second_level_htlc_output(&outpoint2));
2042 assert!(closing_outpoints.is_all_spent());
2043 }
2044
2045 #[test]
2046 fn test_second_level_htlc_output_methods() {
2047 let outpoint = OutPoint { txid: Txid::all_zeros(), vout: 0 };
2048 let mut htlc_output = SecondLevelHTLCOutput::new(outpoint);
2049
2050 assert!(!htlc_output.is_spent());
2051 assert!(htlc_output.matches_outpoint(&outpoint));
2052
2053 let different_outpoint = OutPoint { txid: Txid::all_zeros(), vout: 1 };
2054 assert!(!htlc_output.matches_outpoint(&different_outpoint));
2055
2056 htlc_output.set_spent(true);
2057 assert!(htlc_output.is_spent());
2058
2059 htlc_output.set_spent(false);
2060 assert!(!htlc_output.is_spent());
2061 }
2062
2063 #[test]
2064 fn test_transaction_state_isolation() {
2065 let block_hash = BlockHash::all_zeros();
2066 let (_, _, monitor, funding_txid) = setup_funded_channel();
2067 let funding_outpoint = OutPoint::new(funding_txid, 0);
2068
2069 let closing_tx = make_tx(vec![TxIn {
2070 previous_output: funding_outpoint,
2071 script_sig: Default::default(),
2072 sequence: Default::default(),
2073 witness: Default::default(),
2074 }]);
2075 let closing_txid = closing_tx.compute_txid();
2076
2077 let unrelated_tx = make_tx(vec![make_txin2(Txid::all_zeros(), 0)]);
2078
2079 let mut decode_state =
2080 BlockDecodeState::new_with_block_hash(&monitor.get_state(), &block_hash);
2081 let mut listener = PushListener {
2082 commitment_point_provider: &*monitor.commitment_point_provider,
2083 decode_state: &mut decode_state,
2084 saw_block: true,
2085 };
2086
2087 listener.on_transaction_start(closing_tx.version.0);
2088 listener.on_transaction_input(&closing_tx.input[0]);
2089 listener.on_transaction_output(&closing_tx.output[0]);
2090 listener.on_transaction_end(closing_tx.lock_time, closing_txid);
2091
2092 assert!(listener.decode_state.closing_tx.is_none());
2093
2094 listener.on_transaction_start(unrelated_tx.version.0);
2095
2096 assert_eq!(listener.decode_state.version, unrelated_tx.version.0);
2097 assert_eq!(listener.decode_state.input_num, 0);
2098 assert_eq!(listener.decode_state.output_num, 0);
2099 assert!(listener.decode_state.closing_tx.is_none());
2100 assert!(listener.decode_state.spent_htlc_outputs.is_empty());
2101 }
2102
2103 #[test]
2104 fn test_is_done_conditions() {
2105 let outpoint = OutPoint::new(Txid::from_slice(&[1; 32]).unwrap(), 0);
2106 let chan_id = ChannelId::new(&[33u8; 32]);
2107
2108 let base1 = ChainMonitorBase::new(outpoint, MIN_DEPTH + 10, &chan_id);
2109 {
2110 let mut state = base1.get_state();
2111 state.funding_double_spent_height = Some(10);
2112 state.saw_forget_channel = true;
2113 }
2114 assert!(base1.is_done());
2115
2116 let base2 = ChainMonitorBase::new(outpoint, MAX_CLOSING_DEPTH + 10, &chan_id);
2117 {
2118 let mut state = base2.get_state();
2119 state.closing_swept_height = Some(10);
2120 state.saw_forget_channel = true;
2121 }
2122 assert!(base2.is_done());
2123 }
2124
2125 #[test]
2126 fn test_diagnostic_all_states() {
2127 let outpoint = OutPoint::new(Txid::from_slice(&[1; 32]).unwrap(), 0);
2128 let chan_id = ChannelId::new(&[33u8; 32]);
2129 let base = ChainMonitorBase::new(outpoint, 100, &chan_id);
2130
2131 let diagnostic = base.diagnostic(false);
2132 assert_eq!(
2133 diagnostic,
2134 format!("UNCOMFIRMED hold till funding doublespent + {}", MIN_DEPTH)
2135 );
2136
2137 {
2138 let mut state = base.get_state();
2139 state.funding_height = Some(90);
2140 }
2141 assert_eq!(base.diagnostic(false), "ACTIVE");
2142 assert_eq!(base.diagnostic(true), "CLOSING");
2143
2144 let test_cases = vec![
2146 ("funding_double_spent_height", 95, MIN_DEPTH, "AGING_FUNDING_DOUBLESPENT"),
2147 ("mutual_closing_height", 98, MIN_DEPTH, "AGING_MUTUALLY_CLOSED"),
2148 ("closing_swept_height", 99, MIN_DEPTH, "AGING_CLOSING_SWEPT"),
2149 ("our_output_swept_height", 97, MAX_CLOSING_DEPTH, "AGING_OUR_OUTPUT_SWEPT"),
2150 ];
2151
2152 for (field, height, depth_limit, expected_prefix) in test_cases {
2153 {
2154 let mut state = base.get_state();
2155 state.funding_height = Some(90);
2156 state.funding_double_spent_height = None;
2157 state.mutual_closing_height = None;
2158 state.closing_swept_height = None;
2159 state.our_output_swept_height = None;
2160
2161 match field {
2162 "funding_double_spent_height" =>
2163 state.funding_double_spent_height = Some(height),
2164 "mutual_closing_height" => state.mutual_closing_height = Some(height),
2165 "closing_swept_height" => state.closing_swept_height = Some(height),
2166 "our_output_swept_height" => state.our_output_swept_height = Some(height),
2167 _ => unreachable!(),
2168 }
2169 }
2170
2171 let diagnostic = base.diagnostic(false);
2172 let expected =
2173 format!("{} at {} until {}", expected_prefix, height, height + depth_limit);
2174 assert_eq!(diagnostic, expected);
2175 }
2176 }
2177
2178 fn setup_funded_channel() -> (Arc<Node>, ChannelId, ChainMonitor, Txid) {
2179 let funding_tx = make_tx(vec![make_txin(1), make_txin(2)]);
2180 let funding_outpoint = OutPoint::new(funding_tx.compute_txid(), 0);
2181 let setup = make_channel_setup(funding_outpoint);
2182
2183 let (node, channel_id) =
2184 init_node_and_channel(TEST_NODE_CONFIG, TEST_SEED[1], setup.clone());
2185 let channel = node.get_channel(&channel_id).unwrap();
2186 let cpp = Box::new(ChannelCommitmentPointProvider::new(channel.clone()));
2187 let monitor = node
2188 .with_channel(&channel_id, |chan| Ok(chan.monitor.clone().as_monitor(cpp.clone())))
2189 .unwrap();
2190 let block_hash = BlockHash::all_zeros();
2191 monitor.on_add_block(&[], &block_hash);
2192 monitor.on_add_block(&[funding_tx.clone()], &block_hash);
2193 assert_eq!(monitor.funding_depth(), 1);
2194 (node, channel_id, monitor, funding_tx.compute_txid())
2195 }
2196
2197 fn make_txin2(prev_txid: Txid, prevout: u32) -> TxIn {
2198 TxIn {
2199 previous_output: OutPoint::new(prev_txid, prevout),
2200 script_sig: Default::default(),
2201 sequence: Default::default(),
2202 witness: Default::default(),
2203 }
2204 }
2205
2206 fn make_channel_setup(funding_outpoint: OutPoint) -> ChannelSetup {
2207 ChannelSetup {
2208 is_outbound: true,
2209 channel_value_sat: 3_000_000,
2210 push_value_msat: 0,
2211 funding_outpoint,
2212 holder_selected_contest_delay: 6,
2213 holder_shutdown_script: None,
2214 counterparty_points: make_test_counterparty_points(),
2215 counterparty_selected_contest_delay: 7,
2216 counterparty_shutdown_script: None,
2217 commitment_type: CommitmentType::StaticRemoteKey,
2218 }
2219 }
2220}