Skip to content

Commit ac74d96

Browse files
committed
Clean up test_duplicate_payment_hash_one_failure_one_success
`test_duplicate_payment_hash_one_failure_one_success` makes a number of assumptions which rely on our specific CLTV constants, which we intend to change. Specifically, it relies on forwarding two HTLCs, one which goes one hop longer, and that it can close the channel with both HTLCs sitting on chain with enough time to claim that it doesn't give up on them but also that they get claimed in separate transactions. Here we clean up, simplify, and better document the test such that it is more resilient to future CLTV constant changes.
1 parent e027783 commit ac74d96

File tree

1 file changed

+84
-81
lines changed

1 file changed

+84
-81
lines changed

lightning/src/ln/functional_tests.rs

Lines changed: 84 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -5362,115 +5362,119 @@ pub fn test_onchain_to_onchain_claim() {
53625362
#[xtest(feature = "_externalize_tests")]
53635363
pub fn test_duplicate_payment_hash_one_failure_one_success() {
53645364
// Topology : A --> B --> C --> D
5365-
// We route 2 payments with same hash between B and C, one will be timeout, the other successfully claim
5366-
// Note that because C will refuse to generate two payment secrets for the same payment hash,
5367-
// we forward one of the payments onwards to D.
5368-
let chanmon_cfgs = create_chanmon_cfgs(4);
5369-
let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
5365+
// \-> E
5366+
// We route 2 payments with same hash between B and C, one we will time out on chain, the other
5367+
// successfully claim.
5368+
let chanmon_cfgs = create_chanmon_cfgs(5);
5369+
let node_cfgs = create_node_cfgs(5, &chanmon_cfgs);
53705370
// When this test was written, the default base fee floated based on the HTLC count.
53715371
// It is now fixed, so we simply set the fee to the expected value here.
53725372
let mut config = test_default_channel_config();
53735373
config.channel_config.forwarding_fee_base_msat = 196;
5374-
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs,
5375-
&[Some(config.clone()), Some(config.clone()), Some(config.clone()), Some(config.clone())]);
5376-
let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs);
5374+
let node_chanmgrs = create_node_chanmgrs(5, &node_cfgs,
5375+
&[Some(config.clone()), Some(config.clone()), Some(config.clone()), Some(config.clone()), Some(config.clone())]);
5376+
let mut nodes = create_network(5, &node_cfgs, &node_chanmgrs);
53775377

5378+
// Create the required channels and route one HTLC from A to D and another from A to E.
53785379
create_announced_chan_between_nodes(&nodes, 0, 1);
53795380
let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2);
53805381
create_announced_chan_between_nodes(&nodes, 2, 3);
5382+
create_announced_chan_between_nodes(&nodes, 2, 4);
53815383

53825384
let node_max_height = nodes.iter().map(|node| node.blocks.lock().unwrap().len()).max().unwrap() as u32;
5383-
connect_blocks(&nodes[0], node_max_height - nodes[0].best_block_info().1);
5384-
connect_blocks(&nodes[1], node_max_height - nodes[1].best_block_info().1);
5385-
connect_blocks(&nodes[2], node_max_height - nodes[2].best_block_info().1);
5386-
connect_blocks(&nodes[3], node_max_height - nodes[3].best_block_info().1);
5387-
5388-
let (our_payment_preimage, duplicate_payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 900_000);
5389-
5390-
let payment_secret = nodes[3].node.create_inbound_payment_for_hash(duplicate_payment_hash, None, 7200, None).unwrap();
5391-
// We reduce the final CLTV here by a somewhat arbitrary constant to keep it under the one-byte
5392-
// script push size limit so that the below script length checks match
5393-
// ACCEPTED_HTLC_SCRIPT_WEIGHT.
5394-
let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV - 40)
5395-
.with_bolt11_features(nodes[3].node.bolt11_invoice_features()).unwrap();
5396-
let (route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[3], payment_params, 800_000);
5397-
send_along_route_with_secret(&nodes[0], route, &[&[&nodes[1], &nodes[2], &nodes[3]]], 800_000, duplicate_payment_hash, payment_secret);
5398-
5385+
connect_blocks(&nodes[0], node_max_height * 2 - nodes[0].best_block_info().1);
5386+
connect_blocks(&nodes[1], node_max_height * 2 - nodes[1].best_block_info().1);
5387+
connect_blocks(&nodes[2], node_max_height * 2 - nodes[2].best_block_info().1);
5388+
connect_blocks(&nodes[3], node_max_height * 2 - nodes[3].best_block_info().1);
5389+
connect_blocks(&nodes[4], node_max_height * 2 - nodes[4].best_block_info().1);
5390+
5391+
let (our_payment_preimage, duplicate_payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2], &nodes[3]], 900_000);
5392+
5393+
let payment_secret = nodes[4].node.create_inbound_payment_for_hash(duplicate_payment_hash, None, 7200, None).unwrap();
5394+
let payment_params = PaymentParameters::from_node_id(nodes[4].node.get_our_node_id(), TEST_FINAL_CLTV)
5395+
.with_bolt11_features(nodes[4].node.bolt11_invoice_features()).unwrap();
5396+
let (route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[4], payment_params, 800_000);
5397+
send_along_route_with_secret(&nodes[0], route, &[&[&nodes[1], &nodes[2], &nodes[4]]], 800_000, duplicate_payment_hash, payment_secret);
5398+
5399+
// Now mine C's commitment transaction on node B and mine enough blocks to get the HTLC timeout
5400+
// transaction (which we'll split in two so that we can resolve the HTLCs differently).
53995401
let commitment_txn = get_local_commitment_txn!(nodes[2], chan_2.2);
54005402
assert_eq!(commitment_txn[0].input.len(), 1);
5403+
assert_eq!(commitment_txn[0].output.len(), 3);
54015404
check_spends!(commitment_txn[0], chan_2.3);
54025405

54035406
mine_transaction(&nodes[1], &commitment_txn[0]);
54045407
check_closed_broadcast!(nodes[1], true);
54055408
check_added_monitors!(nodes[1], 1);
54065409
check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[2].node.get_our_node_id()], 100000);
5407-
connect_blocks(&nodes[1], TEST_FINAL_CLTV - 40 + MIN_CLTV_EXPIRY_DELTA as u32); // Confirm blocks until the HTLC expires
54085410

5409-
let htlc_timeout_tx;
5410-
{ // Extract one of the two HTLC-Timeout transaction
5411-
let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
5412-
// ChannelMonitor: timeout tx * 2-or-3
5413-
assert!(node_txn.len() == 2 || node_txn.len() == 3);
5411+
// Confirm blocks until both HTLCs expire and get a transaction which times out one HTLC.
5412+
connect_blocks(&nodes[1], TEST_FINAL_CLTV + config.channel_config.cltv_expiry_delta as u32);
54145413

5415-
check_spends!(node_txn[0], commitment_txn[0]);
5416-
assert_eq!(node_txn[0].input.len(), 1);
5417-
assert_eq!(node_txn[0].output.len(), 1);
5418-
5419-
if node_txn.len() > 2 {
5420-
check_spends!(node_txn[1], commitment_txn[0]);
5421-
assert_eq!(node_txn[1].input.len(), 1);
5422-
assert_eq!(node_txn[1].output.len(), 1);
5423-
assert_eq!(node_txn[0].input[0].previous_output, node_txn[1].input[0].previous_output);
5424-
5425-
check_spends!(node_txn[2], commitment_txn[0]);
5426-
assert_eq!(node_txn[2].input.len(), 1);
5427-
assert_eq!(node_txn[2].output.len(), 1);
5428-
assert_ne!(node_txn[0].input[0].previous_output, node_txn[2].input[0].previous_output);
5429-
} else {
5430-
check_spends!(node_txn[1], commitment_txn[0]);
5431-
assert_eq!(node_txn[1].input.len(), 1);
5432-
assert_eq!(node_txn[1].output.len(), 1);
5433-
assert_ne!(node_txn[0].input[0].previous_output, node_txn[1].input[0].previous_output);
5434-
}
5414+
let htlc_timeout_tx = {
5415+
let mut node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
5416+
assert_eq!(node_txn.len(), 1);
54355417

5436-
assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
5437-
assert_eq!(node_txn[1].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
5438-
// Assign htlc_timeout_tx to the forwarded HTLC (with value ~800 sats). The received HTLC
5439-
// (with value 900 sats) will be claimed in the below `claim_funds` call.
5440-
if node_txn.len() > 2 {
5441-
assert_eq!(node_txn[2].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
5442-
htlc_timeout_tx = if node_txn[2].output[0].value.to_sat() < 900 { node_txn[2].clone() } else { node_txn[0].clone() };
5443-
} else {
5444-
htlc_timeout_tx = if node_txn[0].output[0].value.to_sat() < 900 { node_txn[1].clone() } else { node_txn[0].clone() };
5418+
let mut tx = node_txn.pop().unwrap();
5419+
check_spends!(tx, commitment_txn[0]);
5420+
assert_eq!(tx.input.len(), 2);
5421+
assert_eq!(tx.output.len(), 1);
5422+
// Note that the witness script lengths are one longer than our constant as the CLTV value
5423+
// went to two bytes rather than one.
5424+
assert_eq!(tx.input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT + 1);
5425+
assert_eq!(tx.input[1].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT + 1);
5426+
5427+
// Split the HTLC claim transaction into two, one for each HTLC.
5428+
if commitment_txn[0].output[tx.input[1].previous_output.vout as usize].value.to_sat() < 850 {
5429+
tx.input.remove(1);
54455430
}
5446-
}
5431+
if commitment_txn[0].output[tx.input[0].previous_output.vout as usize].value.to_sat() < 850 {
5432+
tx.input.remove(0);
5433+
}
5434+
assert_eq!(tx.input.len(), 1);
5435+
tx
5436+
};
54475437

5448-
nodes[2].node.claim_funds(our_payment_preimage);
5449-
expect_payment_claimed!(nodes[2], duplicate_payment_hash, 900_000);
5438+
// Now give node E the payment preimage and pass it back to C.
5439+
nodes[4].node.claim_funds(our_payment_preimage);
5440+
expect_payment_claimed!(nodes[4], duplicate_payment_hash, 800_000);
5441+
check_added_monitors!(nodes[4], 1);
5442+
let updates = get_htlc_update_msgs!(nodes[4], nodes[2].node.get_our_node_id());
5443+
nodes[2].node.handle_update_fulfill_htlc(nodes[4].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]);
5444+
let _cs_updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
5445+
expect_payment_forwarded!(nodes[2], nodes[1], nodes[4], Some(196), false, false);
5446+
check_added_monitors!(nodes[2], 1);
5447+
commitment_signed_dance!(nodes[2], nodes[4], &updates.commitment_signed, false);
54505448

5449+
// Mine the commitment transaction on node C and get the HTLC success transactions it will
5450+
// generate (note that the ChannelMonitor doesn't differentiate between HTLCs once it has the
5451+
// preimage).
54515452
mine_transaction(&nodes[2], &commitment_txn[0]);
5452-
check_added_monitors!(nodes[2], 2);
5453+
check_added_monitors!(nodes[2], 1);
54535454
check_closed_event!(nodes[2], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000);
5454-
let events = nodes[2].node.get_and_clear_pending_msg_events();
5455-
match events[0] {
5456-
MessageSendEvent::UpdateHTLCs { .. } => {},
5457-
_ => panic!("Unexpected event"),
5458-
}
5459-
match events[2] {
5460-
MessageSendEvent::BroadcastChannelUpdate { .. } => {},
5461-
_ => panic!("Unexepected event"),
5462-
}
5455+
check_closed_broadcast(&nodes[2], 1, true);
5456+
54635457
let htlc_success_txn: Vec<_> = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone();
54645458
assert_eq!(htlc_success_txn.len(), 2); // ChannelMonitor: HTLC-Success txn (*2 due to 2-HTLC outputs)
54655459
check_spends!(htlc_success_txn[0], commitment_txn[0]);
54665460
check_spends!(htlc_success_txn[1], commitment_txn[0]);
54675461
assert_eq!(htlc_success_txn[0].input.len(), 1);
5468-
assert_eq!(htlc_success_txn[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
5462+
// Note that the witness script lengths are one longer than our constant as the CLTV value went
5463+
// to two bytes rather than one.
5464+
assert_eq!(htlc_success_txn[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT + 1);
54695465
assert_eq!(htlc_success_txn[1].input.len(), 1);
5470-
assert_eq!(htlc_success_txn[1].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
5466+
assert_eq!(htlc_success_txn[1].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT + 1);
54715467
assert_ne!(htlc_success_txn[0].input[0].previous_output, htlc_success_txn[1].input[0].previous_output);
5472-
assert_ne!(htlc_success_txn[1].input[0].previous_output, htlc_timeout_tx.input[0].previous_output);
54735468

5469+
let htlc_success_tx_to_confirm =
5470+
if htlc_success_txn[0].input[0].previous_output == htlc_timeout_tx.input[0].previous_output {
5471+
&htlc_success_txn[1]
5472+
} else {
5473+
&htlc_success_txn[0]
5474+
};
5475+
assert_ne!(htlc_success_tx_to_confirm.input[0].previous_output, htlc_timeout_tx.input[0].previous_output);
5476+
5477+
// Mine the HTLC timeout transaction on node B.
54745478
mine_transaction(&nodes[1], &htlc_timeout_tx);
54755479
connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1);
54765480
expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_2.2 }]);
@@ -5484,14 +5488,13 @@ pub fn test_duplicate_payment_hash_one_failure_one_success() {
54845488

54855489
nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &htlc_updates.update_fail_htlcs[0]);
54865490
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
5487-
{
5488-
commitment_signed_dance!(nodes[0], nodes[1], &htlc_updates.commitment_signed, false, true);
5489-
}
5491+
commitment_signed_dance!(nodes[0], nodes[1], &htlc_updates.commitment_signed, false, true);
54905492
expect_payment_failed_with_update!(nodes[0], duplicate_payment_hash, false, chan_2.0.contents.short_channel_id, true);
54915493

5492-
// Solve 2nd HTLC by broadcasting on B's chain HTLC-Success Tx from C
5493-
mine_transaction(&nodes[1], &htlc_success_txn[1]);
5494-
expect_payment_forwarded!(nodes[1], nodes[0], nodes[2], Some(196), true, true);
5494+
// Finally, give node B the HTLC success transaction and ensure it extracts the preimage to
5495+
// provide to node A.
5496+
mine_transaction(&nodes[1], htlc_success_tx_to_confirm);
5497+
expect_payment_forwarded!(nodes[1], nodes[0], nodes[2], Some(392), true, true);
54955498
let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
54965499
assert!(updates.update_add_htlcs.is_empty());
54975500
assert!(updates.update_fail_htlcs.is_empty());

0 commit comments

Comments
 (0)