Skip to content

Commit ae20f34

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 8b529a8 commit ae20f34

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
@@ -5356,115 +5356,119 @@ fn test_onchain_to_onchain_claim() {
53565356
#[test]
53575357
fn test_duplicate_payment_hash_one_failure_one_success() {
53585358
// Topology : A --> B --> C --> D
5359-
// We route 2 payments with same hash between B and C, one will be timeout, the other successfully claim
5360-
// Note that because C will refuse to generate two payment secrets for the same payment hash,
5361-
// we forward one of the payments onwards to D.
5362-
let chanmon_cfgs = create_chanmon_cfgs(4);
5363-
let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
5359+
// \-> E
5360+
// We route 2 payments with same hash between B and C, one we will time out on chain, the other
5361+
// successfully claim.
5362+
let chanmon_cfgs = create_chanmon_cfgs(5);
5363+
let node_cfgs = create_node_cfgs(5, &chanmon_cfgs);
53645364
// When this test was written, the default base fee floated based on the HTLC count.
53655365
// It is now fixed, so we simply set the fee to the expected value here.
53665366
let mut config = test_default_channel_config();
53675367
config.channel_config.forwarding_fee_base_msat = 196;
5368-
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs,
5369-
&[Some(config.clone()), Some(config.clone()), Some(config.clone()), Some(config.clone())]);
5370-
let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs);
5368+
let node_chanmgrs = create_node_chanmgrs(5, &node_cfgs,
5369+
&[Some(config.clone()), Some(config.clone()), Some(config.clone()), Some(config.clone()), Some(config.clone())]);
5370+
let mut nodes = create_network(5, &node_cfgs, &node_chanmgrs);
53715371

5372+
// Create the required channels and route one HTLC from A to D and another from A to E.
53725373
create_announced_chan_between_nodes(&nodes, 0, 1);
53735374
let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2);
53745375
create_announced_chan_between_nodes(&nodes, 2, 3);
5376+
create_announced_chan_between_nodes(&nodes, 2, 4);
53755377

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

53975400
mine_transaction(&nodes[1], &commitment_txn[0]);
53985401
check_closed_broadcast!(nodes[1], true);
53995402
check_added_monitors!(nodes[1], 1);
54005403
check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[2].node.get_our_node_id()], 100000);
5401-
connect_blocks(&nodes[1], TEST_FINAL_CLTV - 40 + MIN_CLTV_EXPIRY_DELTA as u32); // Confirm blocks until the HTLC expires
54025404

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

5409-
check_spends!(node_txn[0], commitment_txn[0]);
5410-
assert_eq!(node_txn[0].input.len(), 1);
5411-
assert_eq!(node_txn[0].output.len(), 1);
5412-
5413-
if node_txn.len() > 2 {
5414-
check_spends!(node_txn[1], commitment_txn[0]);
5415-
assert_eq!(node_txn[1].input.len(), 1);
5416-
assert_eq!(node_txn[1].output.len(), 1);
5417-
assert_eq!(node_txn[0].input[0].previous_output, node_txn[1].input[0].previous_output);
5418-
5419-
check_spends!(node_txn[2], commitment_txn[0]);
5420-
assert_eq!(node_txn[2].input.len(), 1);
5421-
assert_eq!(node_txn[2].output.len(), 1);
5422-
assert_ne!(node_txn[0].input[0].previous_output, node_txn[2].input[0].previous_output);
5423-
} else {
5424-
check_spends!(node_txn[1], commitment_txn[0]);
5425-
assert_eq!(node_txn[1].input.len(), 1);
5426-
assert_eq!(node_txn[1].output.len(), 1);
5427-
assert_ne!(node_txn[0].input[0].previous_output, node_txn[1].input[0].previous_output);
5428-
}
5408+
let htlc_timeout_tx = {
5409+
let mut node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
5410+
assert_eq!(node_txn.len(), 1);
54295411

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

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

5443+
// Mine the commitment transaction on node C and get the HTLC success transactions it will
5444+
// generate (note that the ChannelMonitor doesn't differentiate between HTLCs once it has the
5445+
// preimage).
54455446
mine_transaction(&nodes[2], &commitment_txn[0]);
5446-
check_added_monitors!(nodes[2], 2);
5447+
check_added_monitors!(nodes[2], 1);
54475448
check_closed_event!(nodes[2], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000);
5448-
let events = nodes[2].node.get_and_clear_pending_msg_events();
5449-
match events[0] {
5450-
MessageSendEvent::UpdateHTLCs { .. } => {},
5451-
_ => panic!("Unexpected event"),
5452-
}
5453-
match events[2] {
5454-
MessageSendEvent::BroadcastChannelUpdate { .. } => {},
5455-
_ => panic!("Unexepected event"),
5456-
}
5449+
check_closed_broadcast(&nodes[2], 1, true);
5450+
54575451
let htlc_success_txn: Vec<_> = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone();
54585452
assert_eq!(htlc_success_txn.len(), 2); // ChannelMonitor: HTLC-Success txn (*2 due to 2-HTLC outputs)
54595453
check_spends!(htlc_success_txn[0], commitment_txn[0]);
54605454
check_spends!(htlc_success_txn[1], commitment_txn[0]);
54615455
assert_eq!(htlc_success_txn[0].input.len(), 1);
5462-
assert_eq!(htlc_success_txn[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
5456+
// Note that the witness script lengths are one longer than our constant as the CLTV value went
5457+
// to two bytes rather than one.
5458+
assert_eq!(htlc_success_txn[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT + 1);
54635459
assert_eq!(htlc_success_txn[1].input.len(), 1);
5464-
assert_eq!(htlc_success_txn[1].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
5460+
assert_eq!(htlc_success_txn[1].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT + 1);
54655461
assert_ne!(htlc_success_txn[0].input[0].previous_output, htlc_success_txn[1].input[0].previous_output);
5466-
assert_ne!(htlc_success_txn[1].input[0].previous_output, htlc_timeout_tx.input[0].previous_output);
54675462

5463+
let htlc_success_tx_to_confirm =
5464+
if htlc_success_txn[0].input[0].previous_output == htlc_timeout_tx.input[0].previous_output {
5465+
&htlc_success_txn[1]
5466+
} else {
5467+
&htlc_success_txn[0]
5468+
};
5469+
assert_ne!(htlc_success_tx_to_confirm.input[0].previous_output, htlc_timeout_tx.input[0].previous_output);
5470+
5471+
// Mine the HTLC timeout transaction on node B.
54685472
mine_transaction(&nodes[1], &htlc_timeout_tx);
54695473
connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1);
54705474
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 }]);
@@ -5478,14 +5482,13 @@ fn test_duplicate_payment_hash_one_failure_one_success() {
54785482

54795483
nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &htlc_updates.update_fail_htlcs[0]);
54805484
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
5481-
{
5482-
commitment_signed_dance!(nodes[0], nodes[1], &htlc_updates.commitment_signed, false, true);
5483-
}
5485+
commitment_signed_dance!(nodes[0], nodes[1], &htlc_updates.commitment_signed, false, true);
54845486
expect_payment_failed_with_update!(nodes[0], duplicate_payment_hash, false, chan_2.0.contents.short_channel_id, true);
54855487

5486-
// Solve 2nd HTLC by broadcasting on B's chain HTLC-Success Tx from C
5487-
mine_transaction(&nodes[1], &htlc_success_txn[1]);
5488-
expect_payment_forwarded!(nodes[1], nodes[0], nodes[2], Some(196), true, true);
5488+
// Finally, give node B the HTLC success transaction and ensure it extracts the preimage to
5489+
// provide to node A.
5490+
mine_transaction(&nodes[1], htlc_success_tx_to_confirm);
5491+
expect_payment_forwarded!(nodes[1], nodes[0], nodes[2], Some(392), true, true);
54895492
let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
54905493
assert!(updates.update_add_htlcs.is_empty());
54915494
assert!(updates.update_fail_htlcs.is_empty());

0 commit comments

Comments
 (0)