|
9 | 9 |
|
10 | 10 | //! Further functional tests which test blockchain reorganizations.
|
11 | 11 |
|
| 12 | +use crate::chain::chaininterface::LowerBoundedFeeEstimator; |
12 | 13 | use crate::chain::channelmonitor::{ANTI_REORG_DELAY, LATENCY_GRACE_PERIOD_BLOCKS};
|
13 | 14 | use crate::chain::transaction::OutPoint;
|
14 | 15 | use crate::chain::Confirm;
|
15 |
| -use crate::events::{Event, MessageSendEventsProvider, ClosureReason, HTLCDestination}; |
| 16 | +use crate::events::{Event, MessageSendEventsProvider, ClosureReason, HTLCDestination, MessageSendEvent}; |
16 | 17 | use crate::ln::msgs::{ChannelMessageHandler, Init};
|
17 | 18 | use crate::util::test_utils;
|
18 | 19 | use crate::util::ser::Writeable;
|
@@ -617,3 +618,139 @@ fn test_to_remote_after_local_detection() {
|
617 | 618 | do_test_to_remote_after_local_detection(ConnectStyle::TransactionsFirstReorgsOnlyTip);
|
618 | 619 | do_test_to_remote_after_local_detection(ConnectStyle::FullBlockViaListen);
|
619 | 620 | }
|
| 621 | + |
| 622 | +#[test] |
| 623 | +fn test_htlc_preimage_claim_holder_commitment_after_counterparty_commitment_reorg() { |
| 624 | + // We detect a counterparty commitment confirm onchain, followed by a reorg and a confirmation |
| 625 | + // of a holder commitment. Then, if we learn of the preimage for an HTLC in both commitments, |
| 626 | + // test that we only claim the currently confirmed commitment. |
| 627 | + let chanmon_cfgs = create_chanmon_cfgs(2); |
| 628 | + let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); |
| 629 | + let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None, None]); |
| 630 | + let nodes = create_network(2, &node_cfgs, &node_chanmgrs); |
| 631 | + |
| 632 | + let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 1); |
| 633 | + |
| 634 | + // Route an HTLC which we will claim onchain with the preimage. |
| 635 | + let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000); |
| 636 | + |
| 637 | + // Force close with the latest counterparty commitment, confirm it, and reorg it with the latest |
| 638 | + // holder commitment. |
| 639 | + nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id()).unwrap(); |
| 640 | + check_closed_broadcast(&nodes[0], 1, true); |
| 641 | + check_added_monitors(&nodes[0], 1); |
| 642 | + check_closed_event(&nodes[0], 1, ClosureReason::HolderForceClosed, false, &[nodes[1].node.get_our_node_id()], 100000); |
| 643 | + |
| 644 | + nodes[1].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[0].node.get_our_node_id()).unwrap(); |
| 645 | + check_closed_broadcast(&nodes[1], 1, true); |
| 646 | + check_added_monitors(&nodes[1], 1); |
| 647 | + check_closed_event(&nodes[1], 1, ClosureReason::HolderForceClosed, false, &[nodes[0].node.get_our_node_id()], 100000); |
| 648 | + |
| 649 | + let mut txn = nodes[0].tx_broadcaster.txn_broadcast(); |
| 650 | + assert_eq!(txn.len(), 1); |
| 651 | + let commitment_tx_a = txn.pop().unwrap(); |
| 652 | + check_spends!(commitment_tx_a, funding_tx); |
| 653 | + |
| 654 | + let mut txn = nodes[1].tx_broadcaster.txn_broadcast(); |
| 655 | + assert_eq!(txn.len(), 1); |
| 656 | + let commitment_tx_b = txn.pop().unwrap(); |
| 657 | + check_spends!(commitment_tx_b, funding_tx); |
| 658 | + |
| 659 | + mine_transaction(&nodes[0], &commitment_tx_a); |
| 660 | + mine_transaction(&nodes[1], &commitment_tx_a); |
| 661 | + |
| 662 | + disconnect_blocks(&nodes[0], 1); |
| 663 | + disconnect_blocks(&nodes[1], 1); |
| 664 | + |
| 665 | + mine_transaction(&nodes[0], &commitment_tx_b); |
| 666 | + mine_transaction(&nodes[1], &commitment_tx_b); |
| 667 | + |
| 668 | + // Provide the preimage now, such that we only claim from the holder commitment (since it's |
| 669 | + // currently confirmed) and not the counterparty's. |
| 670 | + get_monitor!(nodes[1], chan_id).provide_payment_preimage( |
| 671 | + &payment_hash, &payment_preimage, &nodes[1].tx_broadcaster, |
| 672 | + &LowerBoundedFeeEstimator(nodes[1].fee_estimator), &nodes[1].logger |
| 673 | + ); |
| 674 | + |
| 675 | + let mut txn = nodes[1].tx_broadcaster.txn_broadcast(); |
| 676 | + assert_eq!(txn.len(), 1); |
| 677 | + let htlc_success_tx = txn.pop().unwrap(); |
| 678 | + check_spends!(htlc_success_tx, commitment_tx_b); |
| 679 | +} |
| 680 | + |
| 681 | +#[test] |
| 682 | +fn test_htlc_preimage_claim_prev_counterparty_commitment_after_current_counterparty_commitment_reorg() { |
| 683 | + // We detect a counterparty commitment confirm onchain, followed by a reorg and a |
| 684 | + // confirmation of the previous (still unrevoked) counterparty commitment. Then, if we learn |
| 685 | + // of the preimage for an HTLC in both commitments, test that we only claim the currently |
| 686 | + // confirmed commitment. |
| 687 | + let chanmon_cfgs = create_chanmon_cfgs(2); |
| 688 | + let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); |
| 689 | + let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None, None]); |
| 690 | + let nodes = create_network(2, &node_cfgs, &node_chanmgrs); |
| 691 | + |
| 692 | + let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 1); |
| 693 | + |
| 694 | + // Route an HTLC which we will claim onchain with the preimage. |
| 695 | + let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000); |
| 696 | + |
| 697 | + // Obtain the current commitment, which will become the previous after a fee update. |
| 698 | + let prev_commitment_a = &get_local_commitment_txn!(nodes[0], chan_id)[0]; |
| 699 | + |
| 700 | + *nodes[0].fee_estimator.sat_per_kw.lock().unwrap() *= 4; |
| 701 | + nodes[0].node.timer_tick_occurred(); |
| 702 | + check_added_monitors(&nodes[0], 1); |
| 703 | + let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events(); |
| 704 | + assert_eq!(msg_events.len(), 1); |
| 705 | + let (update_fee, commit_sig) = if let MessageSendEvent::UpdateHTLCs { node_id, mut updates } = msg_events.pop().unwrap() { |
| 706 | + assert_eq!(node_id, nodes[1].node.get_our_node_id()); |
| 707 | + (updates.update_fee.take().unwrap(), updates.commitment_signed) |
| 708 | + } else { |
| 709 | + panic!("Unexpected message send event"); |
| 710 | + }; |
| 711 | + |
| 712 | + // Handle the fee update on the other side, but don't send the last RAA such that the previous |
| 713 | + // commitment is still valid (unrevoked). |
| 714 | + nodes[1].node().handle_update_fee(&nodes[0].node.get_our_node_id(), &update_fee); |
| 715 | + let _last_revoke_and_ack = commitment_signed_dance!(nodes[1], nodes[0], commit_sig, false, true, false, true); |
| 716 | + |
| 717 | + // Force close with the latest commitment, confirm it, and reorg it with the previous commitment. |
| 718 | + nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id()).unwrap(); |
| 719 | + check_closed_broadcast(&nodes[0], 1, true); |
| 720 | + check_added_monitors(&nodes[0], 1); |
| 721 | + check_closed_event(&nodes[0], 1, ClosureReason::HolderForceClosed, false, &[nodes[1].node.get_our_node_id()], 100000); |
| 722 | + |
| 723 | + let mut txn = nodes[0].tx_broadcaster.txn_broadcast(); |
| 724 | + assert_eq!(txn.len(), 1); |
| 725 | + let current_commitment_a = txn.pop().unwrap(); |
| 726 | + assert_ne!(current_commitment_a.txid(), prev_commitment_a.txid()); |
| 727 | + check_spends!(current_commitment_a, funding_tx); |
| 728 | + |
| 729 | + mine_transaction(&nodes[0], ¤t_commitment_a); |
| 730 | + mine_transaction(&nodes[1], ¤t_commitment_a); |
| 731 | + |
| 732 | + check_closed_broadcast(&nodes[1], 1, true); |
| 733 | + check_added_monitors(&nodes[1], 1); |
| 734 | + check_closed_event(&nodes[1], 1, ClosureReason::CommitmentTxConfirmed, false, &[nodes[0].node.get_our_node_id()], 100000); |
| 735 | + |
| 736 | + disconnect_blocks(&nodes[0], 1); |
| 737 | + disconnect_blocks(&nodes[1], 1); |
| 738 | + |
| 739 | + mine_transaction(&nodes[0], &prev_commitment_a); |
| 740 | + mine_transaction(&nodes[1], &prev_commitment_a); |
| 741 | + |
| 742 | + // Provide the preimage now, such that we only claim from the previous commitment (since it's |
| 743 | + // currently confirmed) and not the latest. |
| 744 | + get_monitor!(nodes[1], chan_id).provide_payment_preimage( |
| 745 | + &payment_hash, &payment_preimage, &nodes[1].tx_broadcaster, |
| 746 | + &LowerBoundedFeeEstimator(nodes[1].fee_estimator), &nodes[1].logger |
| 747 | + ); |
| 748 | + |
| 749 | + let mut txn = nodes[1].tx_broadcaster.txn_broadcast(); |
| 750 | + assert_eq!(txn.len(), 1); |
| 751 | + let htlc_preimage_tx = txn.pop().unwrap(); |
| 752 | + check_spends!(htlc_preimage_tx, prev_commitment_a); |
| 753 | + // Make sure it was indeed a preimage claim and not a revocation claim since the previous |
| 754 | + // commitment (still unrevoked) is the currently confirmed closing transaction. |
| 755 | + assert_eq!(htlc_preimage_tx.input[0].witness.second_to_last().unwrap(), &payment_preimage.0[..]); |
| 756 | +} |
0 commit comments