@@ -15,7 +15,7 @@ use crate::chain;
15
15
use crate::chain::{ChannelMonitorUpdateStatus, Confirm, Listen, Watch};
16
16
use crate::chain::chaininterface::LowerBoundedFeeEstimator;
17
17
use crate::chain::channelmonitor;
18
- use crate::chain::channelmonitor::{Balance, ChannelMonitorUpdateStep, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY};
18
+ use crate::chain::channelmonitor::{Balance, ChannelMonitorUpdateStep, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY, COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE };
19
19
use crate::chain::transaction::OutPoint;
20
20
use crate::sign::{ecdsa::EcdsaChannelSigner, EntropySource, OutputSpender, SignerProvider};
21
21
use crate::events::bump_transaction::WalletSource;
@@ -2631,14 +2631,12 @@ fn test_justice_tx_htlc_timeout() {
2631
2631
mine_transaction(&nodes[1], &revoked_local_txn[0]);
2632
2632
{
2633
2633
let mut node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
2634
- // The unpinnable, revoked to_self output, and the pinnable, revoked htlc output will
2635
- // be claimed in separate transactions.
2636
- assert_eq!(node_txn.len(), 2);
2637
- for tx in node_txn.iter() {
2638
- assert_eq!(tx.input.len(), 1);
2639
- check_spends!(tx, revoked_local_txn[0]);
2640
- }
2641
- assert_ne!(node_txn[0].input[0].previous_output, node_txn[1].input[0].previous_output);
2634
+ // The revoked HTLC output is not pinnable for another `TEST_FINAL_CLTV` blocks, and is
2635
+ // thus claimed in the same transaction with the revoked to_self output.
2636
+ assert_eq!(node_txn.len(), 1);
2637
+ assert_eq!(node_txn[0].input.len(), 2);
2638
+ check_spends!(node_txn[0], revoked_local_txn[0]);
2639
+ assert_ne!(node_txn[0].input[0].previous_output, node_txn[0].input[1].previous_output);
2642
2640
node_txn.clear();
2643
2641
}
2644
2642
check_added_monitors!(nodes[1], 1);
@@ -2858,28 +2856,26 @@ fn claim_htlc_outputs() {
2858
2856
assert!(nodes[1].node.get_and_clear_pending_events().is_empty());
2859
2857
2860
2858
let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
2861
- assert_eq!(node_txn.len(), 2); // Two penalty transactions:
2862
- assert_eq!(node_txn[0].input.len(), 1); // Claims the unpinnable, revoked output.
2863
- assert_eq!(node_txn[1].input.len(), 2); // Claims both pinnable, revoked HTLC outputs separately.
2864
- check_spends!(node_txn[0], revoked_local_txn[0]);
2865
- check_spends!(node_txn[1], revoked_local_txn[0]);
2866
- assert_ne!(node_txn[0].input[0].previous_output, node_txn[1].input[0].previous_output);
2867
- assert_ne!(node_txn[0].input[0].previous_output, node_txn[1].input[1].previous_output);
2868
- assert_ne!(node_txn[1].input[0].previous_output, node_txn[1].input[1].previous_output);
2859
+ assert_eq!(node_txn.len(), 2); // ChannelMonitor: penalty txn
2860
+
2861
+ // The ChannelMonitor should claim the accepted HTLC output separately from the offered
2862
+ // HTLC and to_self outputs.
2863
+ let accepted_claim = node_txn.iter().filter(|tx| tx.input.len() == 1).next().unwrap();
2864
+ let offered_to_self_claim = node_txn.iter().filter(|tx| tx.input.len() == 2).next().unwrap();
2865
+ check_spends!(accepted_claim, revoked_local_txn[0]);
2866
+ check_spends!(offered_to_self_claim, revoked_local_txn[0]);
2867
+ assert_eq!(accepted_claim.input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
2869
2868
2870
2869
let mut witness_lens = BTreeSet::new();
2871
- witness_lens.insert(node_txn[0].input[0].witness.last().unwrap().len());
2872
- witness_lens.insert(node_txn[1].input[0].witness.last().unwrap().len());
2873
- witness_lens.insert(node_txn[1].input[1].witness.last().unwrap().len());
2874
- assert_eq!(witness_lens.len(), 3);
2870
+ witness_lens.insert(offered_to_self_claim.input[0].witness.last().unwrap().len());
2871
+ witness_lens.insert(offered_to_self_claim.input[1].witness.last().unwrap().len());
2872
+ assert_eq!(witness_lens.len(), 2);
2875
2873
assert_eq!(*witness_lens.iter().skip(0).next().unwrap(), 77); // revoked to_local
2876
- assert_eq!(*witness_lens.iter().skip(1).next().unwrap(), OFFERED_HTLC_SCRIPT_WEIGHT); // revoked offered HTLC
2877
- assert_eq!(*witness_lens.iter().skip(2).next().unwrap(), ACCEPTED_HTLC_SCRIPT_WEIGHT); // revoked received HTLC
2874
+ assert_eq!(*witness_lens.iter().skip(1).next().unwrap(), OFFERED_HTLC_SCRIPT_WEIGHT);
2878
2875
2879
- // Finally, mine the penalty transactions and check that we get an HTLC failure after
2876
+ // Finally, mine the penalty transaction and check that we get an HTLC failure after
2880
2877
// ANTI_REORG_DELAY confirmations.
2881
- mine_transaction(&nodes[1], &node_txn[0]);
2882
- mine_transaction(&nodes[1], &node_txn[1]);
2878
+ mine_transaction(&nodes[1], accepted_claim);
2883
2879
connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1);
2884
2880
expect_payment_failed!(nodes[1], payment_hash_2, false);
2885
2881
}
@@ -5042,8 +5038,7 @@ fn test_static_spendable_outputs_timeout_tx() {
5042
5038
check_spends!(spend_txn[2], node_txn[0], commitment_tx[0]); // All outputs
5043
5039
}
5044
5040
5045
- #[test]
5046
- fn test_static_spendable_outputs_justice_tx_revoked_commitment_tx() {
5041
+ fn do_test_static_spendable_outputs_justice_tx_revoked_commitment_tx(split_tx: bool) {
5047
5042
let chanmon_cfgs = create_chanmon_cfgs(2);
5048
5043
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
5049
5044
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
@@ -5059,20 +5054,28 @@ fn test_static_spendable_outputs_justice_tx_revoked_commitment_tx() {
5059
5054
5060
5055
claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage);
5061
5056
5057
+ if split_tx {
5058
+ connect_blocks(&nodes[1], TEST_FINAL_CLTV - COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE + 1);
5059
+ }
5060
+
5062
5061
mine_transaction(&nodes[1], &revoked_local_txn[0]);
5063
5062
check_closed_broadcast!(nodes[1], true);
5064
5063
check_added_monitors!(nodes[1], 1);
5065
5064
check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 100000);
5066
5065
5067
- // The unpinnable, revoked to_self output and the pinnable, revoked HTLC output will be claimed
5068
- // in separate transactions.
5066
+ // If the HTLC expires in more than COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE blocks, we'll
5067
+ // claim both the revoked and HTLC outputs in one transaction, otherwise we'll split them as we
5068
+ // consider the HTLC output as pinnable and want to claim pinnable and unpinnable outputs
5069
+ // separately.
5069
5070
let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().clone();
5070
- assert_eq!(node_txn.len(), 2 );
5071
+ assert_eq!(node_txn.len(), if split_tx { 2 } else { 1 } );
5071
5072
for tx in node_txn.iter() {
5072
- assert_eq!(tx.input.len(), 1 );
5073
+ assert_eq!(tx.input.len(), if split_tx { 1 } else { 2 } );
5073
5074
check_spends!(tx, revoked_local_txn[0]);
5074
5075
}
5075
- assert_ne!(node_txn[0].input[0].previous_output, node_txn[1].input[0].previous_output);
5076
+ if split_tx {
5077
+ assert_ne!(node_txn[0].input[0].previous_output, node_txn[1].input[0].previous_output);
5078
+ }
5076
5079
5077
5080
mine_transaction(&nodes[1], &node_txn[0]);
5078
5081
connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1);
@@ -5082,6 +5085,12 @@ fn test_static_spendable_outputs_justice_tx_revoked_commitment_tx() {
5082
5085
check_spends!(spend_txn[0], node_txn[0]);
5083
5086
}
5084
5087
5088
+ #[test]
5089
+ fn test_static_spendable_outputs_justice_tx_revoked_commitment_tx() {
5090
+ do_test_static_spendable_outputs_justice_tx_revoked_commitment_tx(true);
5091
+ do_test_static_spendable_outputs_justice_tx_revoked_commitment_tx(false);
5092
+ }
5093
+
5085
5094
#[test]
5086
5095
fn test_static_spendable_outputs_justice_tx_revoked_htlc_timeout_tx() {
5087
5096
let mut chanmon_cfgs = create_chanmon_cfgs(2);
@@ -5114,6 +5123,10 @@ fn test_static_spendable_outputs_justice_tx_revoked_htlc_timeout_tx() {
5114
5123
check_spends!(revoked_htlc_txn[0], revoked_local_txn[0]);
5115
5124
assert_ne!(revoked_htlc_txn[0].lock_time, LockTime::ZERO); // HTLC-Timeout
5116
5125
5126
+ // In order to connect `revoked_htlc_txn[0]` we must first advance the chain by
5127
+ // `TEST_FINAL_CLTV` blocks as otherwise the transaction is consensus-invalid due to its
5128
+ // locktime.
5129
+ connect_blocks(&nodes[1], TEST_FINAL_CLTV);
5117
5130
// B will generate justice tx from A's revoked commitment/HTLC tx
5118
5131
connect_block(&nodes[1], &create_dummy_block(nodes[1].best_block_hash(), 42, vec![revoked_local_txn[0].clone(), revoked_htlc_txn[0].clone()]));
5119
5132
check_closed_broadcast!(nodes[1], true);
0 commit comments