Skip to content

Commit 45dcd93

Browse files
committed
Add test for aggregated revoked HTLC claim on anchors channel
1 parent 4240f5d commit 45dcd93

File tree

1 file changed

+232
-1
lines changed

1 file changed

+232
-1
lines changed

lightning/src/ln/monitor_tests.rs

Lines changed: 232 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,19 @@ use crate::chain::chaininterface::LowerBoundedFeeEstimator;
1919
use crate::ln::channel;
2020
#[cfg(anchors)]
2121
use crate::ln::chan_utils;
22+
#[cfg(anchors)]
23+
use crate::ln::channelmanager::ChannelManager;
2224
use crate::ln::channelmanager::{BREAKDOWN_TIMEOUT, PaymentId};
2325
use crate::ln::msgs::ChannelMessageHandler;
2426
#[cfg(anchors)]
2527
use crate::util::config::UserConfig;
2628
#[cfg(anchors)]
2729
use crate::util::events::BumpTransactionEvent;
2830
use crate::util::events::{Event, MessageSendEvent, MessageSendEventsProvider, ClosureReason, HTLCDestination};
31+
#[cfg(anchors)]
32+
use crate::util::ser::Writeable;
33+
#[cfg(anchors)]
34+
use crate::util::test_utils;
2935

3036
use bitcoin::blockdata::script::Builder;
3137
use bitcoin::blockdata::opcodes;
@@ -1749,7 +1755,7 @@ fn test_yield_anchors_events() {
17491755

17501756
let mut holder_events = nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events();
17511757
// Certain block `ConnectStyle`s cause an extra `ChannelClose` event to be emitted since the
1752-
// best block is being updated prior to the confirmed transactions.
1758+
// best block is updated before the confirmed transactions are notified.
17531759
match *nodes[0].connect_style.borrow() {
17541760
ConnectStyle::BestBlockFirst|ConnectStyle::BestBlockFirstReorgsOnlyTip|ConnectStyle::BestBlockFirstSkippingBlocks => {
17551761
assert_eq!(holder_events.len(), 3);
@@ -1816,3 +1822,228 @@ fn test_yield_anchors_events() {
18161822
// Clear the remaining events as they're not relevant to what we're testing.
18171823
nodes[0].node.get_and_clear_pending_events();
18181824
}
1825+
1826+
#[cfg(anchors)]
1827+
#[test]
1828+
fn test_anchors_aggregated_revoked_htlc_tx() {
1829+
// Test that `ChannelMonitor`s can properly detect and claim funds from a counterparty claiming
1830+
// multiple HTLCs in a single transaction via the success path from a revoked commitment.
1831+
let secp = Secp256k1::new();
1832+
let mut chanmon_cfgs = create_chanmon_cfgs(2);
1833+
// Required to sign a revoked commitment transaction
1834+
chanmon_cfgs[1].keys_manager.disable_revocation_policy_check = true;
1835+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
1836+
let mut anchors_config = UserConfig::default();
1837+
anchors_config.channel_handshake_config.announced_channel = true;
1838+
anchors_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
1839+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(anchors_config), Some(anchors_config)]);
1840+
1841+
let bob_persister: test_utils::TestPersister;
1842+
let bob_chain_monitor: test_utils::TestChainMonitor;
1843+
let bob_deserialized: ChannelManager<
1844+
&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface,
1845+
&test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator,
1846+
&test_utils::TestRouter, &test_utils::TestLogger,
1847+
>;
1848+
1849+
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
1850+
1851+
let chan_id = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000).2;
1852+
1853+
// Route two payments from Alice to Bob to lock in the HTLCs.
1854+
let (payment_preimage_a, payment_hash_a, _) = route_payment(&nodes[0], &[&nodes[1]], 100_000_000);
1855+
let (payment_preimage_b, payment_hash_b, _) = route_payment(&nodes[0], &[&nodes[1]], 100_000_000);
1856+
1857+
// Serialize Bob with the HTLCs locked in. We'll restart Bob later on with the state at this
1858+
// point such that he broadcasts a revoked commitment transaction.
1859+
let bob_serialized = nodes[1].node.encode();
1860+
let bob_serialized_monitor = get_monitor!(nodes[1], chan_id).encode();
1861+
1862+
// Bob claims both HTLCs...
1863+
claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_a);
1864+
claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_b);
1865+
1866+
// ...and sends one back such that he has a motive to broadcast his revoked state.
1867+
send_payment(&nodes[1], &[&nodes[0]], 30_000_000);
1868+
1869+
// Restart Bob with the revoked state and provide the HTLC preimages he claimed.
1870+
reload_node!(nodes[1], anchors_config, bob_serialized, &[&bob_serialized_monitor], bob_persister, bob_chain_monitor, bob_deserialized);
1871+
get_monitor!(nodes[1], chan_id).provide_payment_preimage(
1872+
&payment_hash_a, &payment_preimage_a, &node_cfgs[1].tx_broadcaster,
1873+
&LowerBoundedFeeEstimator::new(node_cfgs[1].fee_estimator), &nodes[1].logger
1874+
);
1875+
get_monitor!(nodes[1], chan_id).provide_payment_preimage(
1876+
&payment_hash_b, &payment_preimage_b, &node_cfgs[1].tx_broadcaster,
1877+
&LowerBoundedFeeEstimator::new(node_cfgs[1].fee_estimator), &nodes[1].logger
1878+
);
1879+
1880+
// Bob force closes by broadcasting his revoked state.
1881+
nodes[1].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[0].node.get_our_node_id()).unwrap();
1882+
{
1883+
let mut txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
1884+
assert_eq!(txn.len(), 1);
1885+
let revoked_commitment = txn.pop().unwrap();
1886+
assert_eq!(revoked_commitment.output.len(), 6); // 2 HTLC outputs + 1 to_self output + 1 to_remote output + 2 anchor outputs
1887+
}
1888+
1889+
// Bob should now receive an event to bump his revoked commitment transaction's fee.
1890+
assert!(nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty());
1891+
let events = nodes[1].chain_monitor.chain_monitor.get_and_clear_pending_events();
1892+
assert_eq!(events.len(), 1);
1893+
let (revoked_commitment, anchor_tx) = match &events[0] {
1894+
Event::BumpTransaction(BumpTransactionEvent::ChannelClose { commitment_tx, anchor_descriptor, .. }) => {
1895+
let mut anchor_tx = Transaction {
1896+
version: 2,
1897+
lock_time: PackedLockTime::ZERO,
1898+
input: vec![
1899+
TxIn { previous_output: anchor_descriptor.outpoint, ..Default::default() },
1900+
TxIn { ..Default::default() },
1901+
],
1902+
output: vec![TxOut {
1903+
value: Amount::ONE_BTC.to_sat(),
1904+
script_pubkey: Script::new_op_return(&[]),
1905+
}],
1906+
};
1907+
let signer = nodes[1].keys_manager.derive_channel_keys(
1908+
anchor_descriptor.channel_value_satoshis, &anchor_descriptor.channel_keys_id,
1909+
);
1910+
let funding_sig = signer.sign_holder_anchor_input(&mut anchor_tx, 0, &secp).unwrap();
1911+
anchor_tx.input[0].witness = chan_utils::build_anchor_input_witness(
1912+
&signer.pubkeys().funding_pubkey, &funding_sig
1913+
);
1914+
(commitment_tx, anchor_tx)
1915+
},
1916+
_ => panic!("Unexpected event"),
1917+
};
1918+
1919+
for node in &nodes {
1920+
mine_transactions(node, &[&revoked_commitment, &anchor_tx]);
1921+
check_added_monitors!(node, 1);
1922+
check_closed_broadcast!(node, true);
1923+
}
1924+
check_closed_event!(&nodes[0], 1, ClosureReason::CommitmentTxConfirmed);
1925+
check_closed_event!(&nodes[1], 1, ClosureReason::HolderForceClosed);
1926+
1927+
// Alice should detect the confirmed revoked commitment, and attempts to claim all of the
1928+
// revoked outputs.
1929+
{
1930+
let mut txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
1931+
assert_eq!(txn.len(), 1);
1932+
let tx = txn.pop().unwrap();
1933+
// TODO: to_self claim must be separate from HTLC claims
1934+
assert_eq!(tx.input.len(), 3); // Spends both HTLC outputs and to_self output
1935+
assert_eq!(tx.output.len(), 1);
1936+
check_spends!(tx, revoked_commitment);
1937+
}
1938+
1939+
// Since Bob was able to confirm his revoked commitment, he'll now try to claim the HTLCs
1940+
// through the success path.
1941+
assert!(nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty());
1942+
let mut events = nodes[1].chain_monitor.chain_monitor.get_and_clear_pending_events();
1943+
// Certain block `ConnectStyle`s cause an extra `ChannelClose` event to be emitted since the
1944+
// best block is updated before the confirmed transactions are notified.
1945+
match *nodes[1].connect_style.borrow() {
1946+
ConnectStyle::BestBlockFirst|ConnectStyle::BestBlockFirstReorgsOnlyTip|ConnectStyle::BestBlockFirstSkippingBlocks => {
1947+
assert_eq!(events.len(), 2);
1948+
if let Event::BumpTransaction(BumpTransactionEvent::ChannelClose { .. }) = events.remove(0) {}
1949+
else { panic!("unexpected event"); }
1950+
1951+
},
1952+
_ => assert_eq!(events.len(), 1),
1953+
};
1954+
let mut htlc_tx = Transaction {
1955+
version: 2,
1956+
lock_time: PackedLockTime::ZERO,
1957+
input: vec![TxIn { ..Default::default() }], // Fee input
1958+
output: vec![TxOut { // Fee input change
1959+
value: Amount::ONE_BTC.to_sat(),
1960+
script_pubkey: Script::new_op_return(&[]),
1961+
}]
1962+
};
1963+
match &events[0] {
1964+
Event::BumpTransaction(BumpTransactionEvent::HTLCResolution { htlc_descriptors, .. }) => {
1965+
assert_eq!(htlc_descriptors.len(), 2);
1966+
for htlc_descriptor in htlc_descriptors {
1967+
assert!(!htlc_descriptor.htlc.offered);
1968+
let signer = nodes[1].keys_manager.derive_channel_keys(
1969+
htlc_descriptor.channel_value_satoshis, &htlc_descriptor.channel_keys_id
1970+
);
1971+
let per_commitment_point = signer.get_per_commitment_point(htlc_descriptor.per_commitment_number, &secp);
1972+
htlc_tx.input.push(htlc_descriptor.unsigned_tx_input());
1973+
htlc_tx.output.push(htlc_descriptor.tx_output(&per_commitment_point, &secp));
1974+
}
1975+
for (idx, htlc_descriptor) in htlc_descriptors.iter().enumerate() {
1976+
let htlc_input_idx = idx + 1;
1977+
let signer = nodes[1].keys_manager.derive_channel_keys(
1978+
htlc_descriptor.channel_value_satoshis, &htlc_descriptor.channel_keys_id
1979+
);
1980+
let our_sig = signer.sign_holder_htlc_transaction(&htlc_tx, htlc_input_idx, htlc_descriptor, &secp).unwrap();
1981+
let per_commitment_point = signer.get_per_commitment_point(htlc_descriptor.per_commitment_number, &secp);
1982+
let witness_script = htlc_descriptor.witness_script(&per_commitment_point, &secp);
1983+
htlc_tx.input[htlc_input_idx].witness = htlc_descriptor.tx_input_witness(&our_sig, &witness_script);
1984+
}
1985+
},
1986+
_ => panic!("Unexpected event"),
1987+
}
1988+
1989+
for node in &nodes {
1990+
mine_transaction(node, &htlc_tx);
1991+
}
1992+
1993+
// Alice should see that Bob is trying to claim to HTLCs, so she should now try to claim them at
1994+
// the second level instead.
1995+
let (revoked_to_self_claim, revoked_htlc_claim) = {
1996+
let mut txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
1997+
assert_eq!(txn.len(), 2);
1998+
1999+
let revoked_to_self_claim = txn.pop().unwrap();
2000+
assert_eq!(revoked_to_self_claim.input.len(), 1);
2001+
assert_eq!(revoked_to_self_claim.output.len(), 1);
2002+
check_spends!(revoked_to_self_claim, revoked_commitment);
2003+
2004+
let revoked_htlc_claim = txn.pop().unwrap();
2005+
assert_eq!(revoked_htlc_claim.input.len(), 2);
2006+
assert_eq!(revoked_htlc_claim.output.len(), 1);
2007+
check_spends!(revoked_htlc_claim, htlc_tx);
2008+
2009+
(revoked_to_self_claim, revoked_htlc_claim)
2010+
};
2011+
for node in &nodes {
2012+
mine_transactions(node, &[&revoked_to_self_claim, &revoked_htlc_claim]);
2013+
}
2014+
2015+
2016+
// Connect one block to make sure the HTLC events are not yielded while ANTI_REORG_DELAY has not
2017+
// been reached.
2018+
connect_blocks(&nodes[0], 1);
2019+
connect_blocks(&nodes[1], 1);
2020+
2021+
assert!(nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty());
2022+
assert!(nodes[1].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty());
2023+
2024+
// Connect the remaining blocks to reach ANTI_REORG_DELAY.
2025+
connect_blocks(&nodes[0], ANTI_REORG_DELAY - 2);
2026+
connect_blocks(&nodes[1], ANTI_REORG_DELAY - 2);
2027+
2028+
assert!(nodes[1].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty());
2029+
let spendable_output_events = nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events();
2030+
for (idx, event) in spendable_output_events.iter().enumerate() {
2031+
if let Event::SpendableOutputs { outputs } = event {
2032+
assert_eq!(outputs.len(), 1);
2033+
let spend_tx = nodes[0].keys_manager.backing.spend_spendable_outputs(
2034+
&[&outputs[0]], Vec::new(), Script::new_op_return(&[]), 253, &Secp256k1::new(),
2035+
).unwrap();
2036+
check_spends!(spend_tx, if idx == 0 { &revoked_to_self_claim } else { &revoked_htlc_claim });
2037+
} else {
2038+
panic!("unexpected event");
2039+
}
2040+
}
2041+
2042+
assert!(nodes[0].node.list_channels().is_empty());
2043+
assert!(nodes[1].node.list_channels().is_empty());
2044+
assert!(nodes[0].chain_monitor.chain_monitor.get_claimable_balances(&[]).is_empty());
2045+
// TODO: From Bob's PoV, he still thinks he can claim the outputs from his revoked commitment.
2046+
// This needs to be fixed before we enable pruning `ChannelMonitor`s once they don't have any
2047+
// balances to claim.
2048+
assert_eq!(nodes[1].chain_monitor.chain_monitor.get_claimable_balances(&[]).len(), 3);
2049+
}

0 commit comments

Comments
 (0)