Skip to content

Commit a23d50c

Browse files
author
Antoine Riard
committed
Add test_unordered_onchain_htlc_settlement
1 parent adb5dc0 commit a23d50c

File tree

1 file changed

+105
-0
lines changed

1 file changed

+105
-0
lines changed

lightning/src/ln/functional_tests.rs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8490,3 +8490,108 @@ fn test_htlc_no_detection() {
84908490
connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1, 201, true, header_201.block_hash());
84918491
expect_payment_failed!(nodes[0], our_payment_hash, true);
84928492
}
8493+
8494+
#[test]
8495+
fn test_unorderded_onchain_htlc_settlement() {
8496+
// A routing node must correctly claim an incoming HTLC for which the preimage has
8497+
// been learnt on the offchain upstream channel after the downstream one has reached
8498+
// the chain. HTLC settlement is ordered but not the underlying channel supporting
8499+
// the payment path.
8500+
//
8501+
// 1) Alice send a HTLC to Caroll through Bob.
8502+
// 2) Caroll doesn't settle the HTLC.
8503+
// 3) Alice close her channel with Bob.
8504+
// 4) Bob sees the Alice's commitment on his chain. An offered output is present but can't
8505+
// be claimed as Bob doesn't have yet knowledge of the preimage.
8506+
// 5) Caroll release offchain the preimage to Bob.
8507+
// 6) Bob claims the offered output on Alice's commitment.
8508+
// TODO: reverse the test with Bob's commitment reaching the chain instead of Alice's one.
8509+
8510+
let chanmon_cfgs = create_chanmon_cfgs(3);
8511+
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
8512+
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
8513+
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
8514+
8515+
// Create some initial channels
8516+
let chan_ab = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
8517+
create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 100000, 10001, InitFeatures::known(), InitFeatures::known());
8518+
8519+
// Step 1) and Step 2), `route_payment` implicitly verify Caroll receives the HTLC
8520+
let (payment_preimage, _payment_hash) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), 3_000_000);
8521+
8522+
let alice_txn = get_local_commitment_txn!(nodes[0], chan_ab.2);
8523+
check_spends!(alice_txn[0], chan_ab.3);
8524+
assert_eq!(alice_txn[0].output.len(), 2);
8525+
check_spends!(alice_txn[1], alice_txn[0]); // 2nd transaction is a non-final HTLC-timeout
8526+
assert_eq!(alice_txn[1].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT);
8527+
assert_eq!(alice_txn.len(), 2);
8528+
8529+
// Step 3) and Step 4), verify that Bob updates his monitor, broadcast a close and didn't broadcast
8530+
// yet transaction on Alice's commitment
8531+
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42};
8532+
connect_block(&nodes[1], &Block { header, txdata: vec![alice_txn[0].clone()]}, 1);
8533+
check_closed_broadcast!(nodes[1], false);
8534+
check_added_monitors!(nodes[1], 1);
8535+
{
8536+
let mut bob_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); // ChannelManager : 1 (commitment tx)
8537+
assert_eq!(bob_txn.len(), 1);
8538+
check_spends!(bob_txn[0], chan_ab.3);
8539+
bob_txn.clear();
8540+
}
8541+
8542+
// Step 5)
8543+
assert!(nodes[2].node.claim_funds(payment_preimage, &None, 3_000_000));
8544+
check_added_monitors!(nodes[2], 1);
8545+
let caroll_updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
8546+
assert!(caroll_updates.update_add_htlcs.is_empty());
8547+
assert!(caroll_updates.update_fail_htlcs.is_empty());
8548+
assert!(caroll_updates.update_fail_malformed_htlcs.is_empty());
8549+
assert!(caroll_updates.update_fee.is_none());
8550+
assert_eq!(caroll_updates.update_fulfill_htlcs.len(), 1);
8551+
8552+
nodes[1].node.handle_update_fulfill_htlc(&nodes[2].node.get_our_node_id(), &caroll_updates.update_fulfill_htlcs[0]);
8553+
nodes[1].node.handle_commitment_signed(&nodes[2].node.get_our_node_id(), &caroll_updates.commitment_signed);
8554+
check_added_monitors!(nodes[1], 1);
8555+
8556+
let events = nodes[1].node.get_and_clear_pending_msg_events();
8557+
assert_eq!(events.len(), 2);
8558+
let bob_revocation = match events[0] {
8559+
MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => {
8560+
assert_eq!(*node_id, nodes[2].node.get_our_node_id());
8561+
(*msg).clone()
8562+
},
8563+
_ => panic!("Unexpected event"),
8564+
};
8565+
let bob_updates = match events[1] {
8566+
MessageSendEvent::UpdateHTLCs { ref node_id, ref updates } => {
8567+
assert_eq!(*node_id, nodes[2].node.get_our_node_id());
8568+
(*updates).clone()
8569+
},
8570+
_ => panic!("Unexpected event"),
8571+
};
8572+
8573+
nodes[2].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bob_revocation);
8574+
check_added_monitors!(nodes[2], 1);
8575+
nodes[2].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bob_updates.commitment_signed);
8576+
check_added_monitors!(nodes[2], 1);
8577+
8578+
let events = nodes[2].node.get_and_clear_pending_msg_events();
8579+
assert_eq!(events.len(), 1);
8580+
let caroll_revocation = match events[0] {
8581+
MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => {
8582+
assert_eq!(*node_id, nodes[1].node.get_our_node_id());
8583+
(*msg).clone()
8584+
},
8585+
_ => panic!("Unexpected event"),
8586+
};
8587+
nodes[1].node.handle_revoke_and_ack(&nodes[2].node.get_our_node_id(), &caroll_revocation);
8588+
check_added_monitors!(nodes[1], 1);
8589+
8590+
// Step 6), verify Bob broadcast a preimage transaction on Alice's commitment
8591+
{
8592+
let bob_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelMonitor : 1 (htlc-preimage tx)
8593+
assert_eq!(bob_txn.len(), 1);
8594+
check_spends!(bob_txn[0], alice_txn[0]);
8595+
assert_eq!(bob_txn[0].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT);
8596+
}
8597+
}

0 commit comments

Comments
 (0)