Skip to content

Commit 50ea516

Browse files
author
Antoine Riard
committed
Extend test_justice_tx to test broadcast of revoked preimage
1 parent 1a7e897 commit 50ea516

File tree

2 files changed

+103
-38
lines changed

2 files changed

+103
-38
lines changed

src/ln/functional_test_utils.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -862,26 +862,33 @@ pub fn test_txn_broadcast(node: &Node, chan: &(msgs::ChannelUpdate, msgs::Channe
862862
false
863863
} else { true }
864864
});
865-
assert!(res.len() == 2 || res.len() == 3);
865+
assert!(res.len() == 2 || res.len() == 3 || res.len() == 5);
866866
if res.len() == 3 {
867867
assert_eq!(res[1], res[2]);
868868
}
869+
if res.len() == 5 {
870+
assert_eq!(res[1], res[3]);
871+
assert_eq!(res[2], res[4]);
872+
}
869873
}
870874

871875
assert!(node_txn.is_empty());
872876
res
873877
}
874878

875-
/// Tests that the given node has broadcast a claim transaction against the provided revoked
876-
/// HTLC transaction.
877-
pub fn test_revoked_htlc_claim_txn_broadcast(node: &Node, revoked_tx: Transaction) {
879+
/// Tests that the given node has broadcast a claim transaction against one of the provided revoked
880+
/// HTLC transactions.
881+
pub fn test_revoked_htlc_claim_txn_broadcast(node: &Node, revoked_txn: Vec<Transaction>, expected: usize) {
878882
let mut node_txn = node.tx_broadcaster.txn_broadcasted.lock().unwrap();
879-
assert_eq!(node_txn.len(), 1);
883+
assert_eq!(node_txn.len(), expected);
880884
node_txn.retain(|tx| {
881-
if tx.input.len() == 1 && tx.input[0].previous_output.txid == revoked_tx.txid() {
882-
check_spends!(tx, revoked_tx.clone());
883-
false
884-
} else { true }
885+
for revoked_tx in &revoked_txn {
886+
if tx.input.len() == 1 && tx.input[0].previous_output.txid == revoked_tx.txid() {
887+
check_spends!(tx, revoked_tx.clone());
888+
return false
889+
}
890+
}
891+
true
885892
});
886893
assert!(node_txn.is_empty());
887894
}

src/ln/functional_tests.rs

Lines changed: 87 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1580,24 +1580,25 @@ fn channel_monitor_network_test() {
15801580
#[test]
15811581
fn test_justice_tx() {
15821582
// Test justice txn built on revoked HTLC-Success tx, against both sides
1583+
// Also, test we're able to extract payment preimage cleanly from revoked HTLC-Success tx and pass it backward
15831584

1584-
let nodes = create_network(2);
1585+
let nodes = create_network(3);
15851586
// Create some new channels:
1586-
let chan_5 = create_announced_chan_between_nodes(&nodes, 0, 1);
1587+
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
15871588

15881589
// A pending HTLC which will be revoked:
1589-
let payment_preimage_3 = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
1590+
let payment_preimage_1 = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
15901591
// Get the will-be-revoked local txn from nodes[0]
15911592
let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.iter().next().unwrap().1.last_local_commitment_txn.clone();
15921593
assert_eq!(revoked_local_txn.len(), 2); // First commitment tx, then HTLC tx
15931594
assert_eq!(revoked_local_txn[0].input.len(), 1);
1594-
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_5.3.txid());
1595+
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.txid());
15951596
assert_eq!(revoked_local_txn[0].output.len(), 2); // Only HTLC and output back to 0 are present
15961597
assert_eq!(revoked_local_txn[1].input.len(), 1);
15971598
assert_eq!(revoked_local_txn[1].input[0].previous_output.txid, revoked_local_txn[0].txid());
15981599
assert_eq!(revoked_local_txn[1].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); // HTLC-Timeout
15991600
// Revoke the old state
1600-
claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_3);
1601+
claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_1);
16011602

16021603
{
16031604
let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
@@ -1611,56 +1612,113 @@ fn test_justice_tx() {
16111612
check_spends!(node_txn[0], revoked_local_txn[0].clone());
16121613
node_txn.swap_remove(0);
16131614
}
1614-
test_txn_broadcast(&nodes[1], &chan_5, None, HTLCType::NONE);
1615+
test_txn_broadcast(&nodes[1], &chan_1, None, HTLCType::NONE);
16151616

16161617
nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
1617-
let node_txn = test_txn_broadcast(&nodes[0], &chan_5, Some(revoked_local_txn[0].clone()), HTLCType::TIMEOUT);
1618+
let node_txn = test_txn_broadcast(&nodes[0], &chan_1, Some(revoked_local_txn[0].clone()), HTLCType::TIMEOUT);
16181619
header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
16191620
nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[1].clone()] }, 1);
1620-
test_revoked_htlc_claim_txn_broadcast(&nodes[1], node_txn[1].clone());
1621+
test_revoked_htlc_claim_txn_broadcast(&nodes[1], vec![node_txn[1].clone()], 1);
16211622
}
16221623
get_announce_close_broadcast_events(&nodes, 0, 1);
16231624

16241625
assert_eq!(nodes[0].node.list_channels().len(), 0);
16251626
assert_eq!(nodes[1].node.list_channels().len(), 0);
16261627

1627-
// We test justice_tx build by A on B's revoked HTLC-Success tx
1628+
// We test justice_tx build by B on C's revoked HTLC-Success tx
16281629
// Create some new channels:
1629-
let chan_6 = create_announced_chan_between_nodes(&nodes, 0, 1);
1630+
create_announced_chan_between_nodes(&nodes, 0, 1);
1631+
let chan_3 = create_announced_chan_between_nodes(&nodes, 1, 2);
16301632

16311633
// A pending HTLC which will be revoked:
1632-
let payment_preimage_4 = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
1633-
// Get the will-be-revoked local txn from B
1634-
let revoked_local_txn = nodes[1].node.channel_state.lock().unwrap().by_id.iter().next().unwrap().1.last_local_commitment_txn.clone();
1634+
let payment_preimage_2 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 3000000).0;
1635+
let payment_preimage_3 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 3000000).0;
1636+
// Get the will-be-revoked local txn from C
1637+
let revoked_local_txn = nodes[2].node.channel_state.lock().unwrap().by_id.iter().next().unwrap().1.last_local_commitment_txn.clone();
16351638
assert_eq!(revoked_local_txn.len(), 1); // Only commitment tx
16361639
assert_eq!(revoked_local_txn[0].input.len(), 1);
1637-
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_6.3.txid());
1638-
assert_eq!(revoked_local_txn[0].output.len(), 2); // Only HTLC and output back to A are present
1639-
// Revoke the old state
1640-
claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_4);
1640+
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_3.3.txid());
1641+
assert_eq!(revoked_local_txn[0].output.len(), 3); // Only 2 HTLC and output back to B are present
1642+
1643+
// Revoke the old state - but only between B and C as we test update_fulfill_htlc to A generation from B ability to extract preimage from C's revoked HTLC-success
1644+
//claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], payment_preimage_2);
1645+
nodes[2].node.claim_funds(payment_preimage_2);
1646+
check_added_monitors!(nodes[2], 1);
1647+
let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
1648+
assert_eq!(updates.update_fulfill_htlcs.len(), 1);
1649+
nodes[1].node.handle_update_fulfill_htlc(&nodes[2].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]).unwrap();
1650+
check_added_monitors!(nodes[1], 1);
1651+
let updates_2 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
1652+
commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, false);
1653+
nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &updates_2.update_fulfill_htlcs[0]).unwrap();
1654+
commitment_signed_dance!(nodes[0], nodes[1], updates_2.commitment_signed, false);
1655+
let events = nodes[0].node.get_and_clear_pending_events();
1656+
assert_eq!(events.len(), 1);
1657+
match events[0] {
1658+
Event::PaymentSent { payment_preimage } => {
1659+
assert_eq!(payment_preimage, payment_preimage_2);
1660+
},
1661+
_ => panic!("Unexpected event"),
1662+
}
1663+
1664+
nodes[2].node.claim_funds(payment_preimage_3);
1665+
check_added_monitors!(nodes[2], 1);
1666+
get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
16411667
{
16421668
let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
1643-
nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
1669+
nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
16441670
{
1645-
let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
1646-
assert_eq!(node_txn.len(), 3);
1671+
let mut node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
1672+
assert_eq!(node_txn.len(), 4);
16471673
assert_eq!(node_txn.pop().unwrap(), node_txn[0]); // An outpoint registration will result in a 2nd block_connected
1648-
assert_eq!(node_txn[0].input.len(), 1); // We claim the received HTLC output
1674+
assert_eq!(node_txn[0].input.len(), 2); // We claim the received HTLC output
16491675

16501676
check_spends!(node_txn[0], revoked_local_txn[0].clone());
1677+
check_spends!(node_txn[1], chan_3.3.clone()); // Local commitment tx
1678+
check_spends!(node_txn[2], node_txn[1].clone()); // HTLC-Timeout tx on local
16511679
node_txn.swap_remove(0);
16521680
}
1653-
test_txn_broadcast(&nodes[0], &chan_6, None, HTLCType::NONE);
1681+
test_txn_broadcast(&nodes[1], &chan_3, None, HTLCType::TIMEOUT);
1682+
let events = nodes[1].node.get_and_clear_pending_msg_events();
1683+
assert_eq!(events.len(), 1);
1684+
match events[0] {
1685+
MessageSendEvent::BroadcastChannelUpdate { .. } => {},
1686+
_ => panic!("Unexpected event"),
1687+
}
1688+
let events = nodes[1].node.get_and_clear_pending_events();
1689+
assert_eq!(events.len(), 1);
1690+
match events[0] {
1691+
Event::PendingHTLCsForwardable { .. } => {},
1692+
_ => panic!("Unexpected event"),
1693+
}
16541694

1655-
nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
1656-
let node_txn = test_txn_broadcast(&nodes[1], &chan_6, Some(revoked_local_txn[0].clone()), HTLCType::SUCCESS);
1695+
nodes[2].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
1696+
let events = nodes[2].node.get_and_clear_pending_msg_events();
1697+
assert_eq!(events.len(), 1);
1698+
match events[0] {
1699+
MessageSendEvent::BroadcastChannelUpdate { .. } => {},
1700+
_ => panic!("Unexpected event"),
1701+
}
1702+
let node_txn = test_txn_broadcast(&nodes[2], &chan_3, Some(revoked_local_txn[0].clone()), HTLCType::SUCCESS);
16571703
header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
1658-
nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[1].clone()] }, 1);
1659-
test_revoked_htlc_claim_txn_broadcast(&nodes[0], node_txn[1].clone());
1704+
nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[1].clone(), node_txn[2].clone()] }, 1);
1705+
test_revoked_htlc_claim_txn_broadcast(&nodes[1], vec![node_txn[1].clone(), node_txn[2].clone()], 2);
1706+
let updates_3 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
1707+
check_added_monitors!(nodes[1], 1);
1708+
nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &updates_3.update_fulfill_htlcs[0]).unwrap();
1709+
commitment_signed_dance!(nodes[0], nodes[1], updates_3.commitment_signed, false);
1710+
let events = nodes[0].node.get_and_clear_pending_events();
1711+
assert_eq!(events.len(), 1);
1712+
match events[0] {
1713+
Event::PaymentSent { payment_preimage } => {
1714+
assert_eq!(payment_preimage, payment_preimage_3);
1715+
},
1716+
_ => panic!("Unexpected event"),
1717+
}
16601718
}
1661-
get_announce_close_broadcast_events(&nodes, 0, 1);
1662-
assert_eq!(nodes[0].node.list_channels().len(), 0);
1663-
assert_eq!(nodes[1].node.list_channels().len(), 0);
1719+
assert_eq!(nodes[0].node.list_channels().len(), 1);
1720+
assert_eq!(nodes[1].node.list_channels().len(), 1);
1721+
assert_eq!(nodes[2].node.list_channels().len(), 0);
16641722
}
16651723

16661724
#[test]

0 commit comments

Comments
 (0)