Created
March 6, 2023 04:06
-
-
Save bshramin/6fe6cfe3b67908331a703a788f9b51f0 to your computer and use it in GitHub Desktop.
Add a hop to rust-lightning test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[test] | |
fn test_onchain_to_onchain_claim() { | |
// Test that in case of channel closure, we detect the state of output and claim HTLC | |
// on downstream peer's remote commitment tx. | |
// First, have C claim an HTLC against its own latest commitment transaction. | |
// Then, broadcast these to B, which should update the monitor downstream on the A<->B | |
// channel. | |
// Finally, check that B will claim the HTLC output if A's latest commitment transaction | |
// gets broadcast. | |
let chanmon_cfgs = create_chanmon_cfgs(4); | |
let node_cfgs = create_node_cfgs(4, &chanmon_cfgs); | |
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]); | |
let nodes = create_network(4, &node_cfgs, &node_chanmgrs); | |
// Create some initial channels | |
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1); | |
let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2); | |
let chan_3 = create_announced_chan_between_nodes(&nodes, 2, 3); | |
// Ensure all nodes are at the same height | |
let node_max_height = nodes.iter().map(|node| node.blocks.lock().unwrap().len()).max().unwrap() as u32; | |
connect_blocks(&nodes[0], node_max_height - nodes[0].best_block_info().1); | |
connect_blocks(&nodes[1], node_max_height - nodes[1].best_block_info().1); | |
connect_blocks(&nodes[2], node_max_height - nodes[2].best_block_info().1); | |
connect_blocks(&nodes[3], node_max_height - nodes[3].best_block_info().1); | |
// Rebalance the network a bit by relaying one payment through all the channels ... | |
send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 8000000); | |
send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 8000000); | |
let (payment_preimage, payment_hash, _payment_secret) = route_payment(&nodes[0], &[&nodes[1], &nodes[2], &nodes[3]], 3_000_000); | |
let commitment_tx = get_local_commitment_txn!(nodes[3], chan_3.2); | |
check_spends!(commitment_tx[0], chan_3.3); | |
nodes[3].node.claim_funds(payment_preimage); | |
expect_payment_claimed!(nodes[3], payment_hash, 3_000_000); | |
check_added_monitors!(nodes[3], 1); | |
let updates = get_htlc_update_msgs!(nodes[3], nodes[2].node.get_our_node_id()); | |
assert!(updates.update_add_htlcs.is_empty()); | |
assert!(updates.update_fail_htlcs.is_empty()); | |
assert_eq!(updates.update_fulfill_htlcs.len(), 1); | |
assert!(updates.update_fail_malformed_htlcs.is_empty()); | |
mine_transaction(&nodes[3], &commitment_tx[0]); | |
check_closed_broadcast!(nodes[3], true); | |
check_added_monitors!(nodes[3], 1); | |
check_closed_event!(nodes[3], 1, ClosureReason::CommitmentTxConfirmed); | |
let c_txn = nodes[3].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelMonitor: 1 (HTLC-Success tx) | |
assert_eq!(c_txn.len(), 1); | |
check_spends!(c_txn[0], commitment_tx[0]); | |
assert_eq!(c_txn[0].input[0].witness.clone().last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); | |
assert!(c_txn[0].output[0].script_pubkey.is_v0_p2wsh()); // revokeable output | |
assert_eq!(c_txn[0].lock_time.0, 0); // Success tx | |
// So we broadcast C's commitment tx and HTLC-Success on B's chain, we should successfully be able to extract preimage and update downstream monitor | |
let header = BlockHeader { version: 0x20000000, prev_blockhash: nodes[2].best_block_hash(), merkle_root: TxMerkleNode::all_zeros(), time: 42, bits: 42, nonce: 42}; | |
connect_block(&nodes[2], &Block { header, txdata: vec![commitment_tx[0].clone(), c_txn[0].clone()]}); | |
check_added_monitors!(nodes[2], 1); | |
let events = nodes[2].node.get_and_clear_pending_events(); | |
assert_eq!(events.len(), 2); | |
match events[0] { | |
Event::ChannelClosed { reason: ClosureReason::CommitmentTxConfirmed, .. } => {} | |
_ => panic!("Unexpected event"), | |
} | |
match events[1] { | |
Event::PaymentForwarded { fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id } => { | |
assert_eq!(fee_earned_msat, Some(1000)); | |
assert_eq!(prev_channel_id, Some(chan_2.2)); | |
assert_eq!(claim_from_onchain_tx, true); | |
assert_eq!(next_channel_id, Some(chan_3.2)); | |
}, | |
_ => panic!("Unexpected event"), | |
} | |
check_added_monitors!(nodes[2], 1); | |
let mut msg_events = nodes[2].node.get_and_clear_pending_msg_events(); | |
assert_eq!(msg_events.len(), 3); | |
let nodes_3_event = remove_first_msg_event_to_node(&nodes[3].node.get_our_node_id(), &mut msg_events); | |
let nodes_1_event = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut msg_events); | |
match nodes_3_event { | |
MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { .. }, node_id: _ } => {}, | |
_ => panic!("Unexpected event"), | |
} | |
match nodes_1_event { | |
MessageSendEvent::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, .. } } => { | |
assert!(update_add_htlcs.is_empty()); | |
assert!(update_fail_htlcs.is_empty()); | |
assert_eq!(update_fulfill_htlcs.len(), 1); | |
assert!(update_fail_malformed_htlcs.is_empty()); | |
assert_eq!(nodes[1].node.get_our_node_id(), *node_id); | |
}, | |
_ => panic!("Unexpected event"), | |
}; | |
// Ensure that the last remaining message event is the BroadcastChannelUpdate msg for chan_2 | |
match msg_events[0] { | |
MessageSendEvent::BroadcastChannelUpdate { .. } => {}, | |
_ => panic!("Unexpected event"), | |
} | |
// Broadcast A's commitment tx on B's chain to see if we are able to claim inbound HTLC with our HTLC-Success tx | |
let commitment_tx = get_local_commitment_txn!(nodes[1], chan_2.2); | |
mine_transaction(&nodes[2], &commitment_tx[0]); | |
check_closed_event!(nodes[2], 1, ClosureReason::CommitmentTxConfirmed); | |
let b_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); | |
// ChannelMonitor: HTLC-Success tx | |
assert_eq!(b_txn.len(), 1); | |
check_spends!(b_txn[0], commitment_tx[0]); | |
assert_eq!(b_txn[0].input[0].witness.clone().last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); | |
assert!(b_txn[0].output[0].script_pubkey.is_v0_p2wpkh()); // direct payment | |
assert_eq!(b_txn[0].lock_time.0, 0); // Success tx | |
check_closed_broadcast!(nodes[2], true); | |
check_added_monitors!(nodes[2], 1); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment