Skip to content

Commit b84ad65

Browse files
wpaulinoTheBlueMatt
authored andcommitted
Test inflight HTLC forward and resolution after locked splice
Test tweaked by: Matt Corallo <git@bluematt.me>
1 parent f2ada1a commit b84ad65

File tree

3 files changed

+160
-2
lines changed

3 files changed

+160
-2
lines changed

lightning/src/ln/channel.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1373,7 +1373,7 @@ pub(crate) const COINBASE_MATURITY: u32 = 100;
13731373
/// The number of blocks to wait for a channel_announcement to propagate such that payments using an
13741374
/// older SCID can still be relayed. Once the spend of the previous funding transaction has reached
13751375
/// this number of confirmations, the corresponding SCID will be forgotten.
1376-
const CHANNEL_ANNOUNCEMENT_PROPAGATION_DELAY: u32 = 144;
1376+
pub(crate) const CHANNEL_ANNOUNCEMENT_PROPAGATION_DELAY: u32 = 144;
13771377

13781378
struct PendingChannelMonitorUpdate {
13791379
update: ChannelMonitorUpdate,

lightning/src/ln/functional_test_utils.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2494,6 +2494,15 @@ pub fn expect_and_process_pending_htlcs(node: &Node<'_, '_, '_>, process_twice:
24942494
assert!(!node.node.needs_pending_htlc_processing());
24952495
}
24962496

2497+
/// Processes an HTLC which is pending forward but will fail to forward when we process it here.
2498+
pub fn expect_htlc_forwarding_fails(
2499+
node: &Node<'_, '_, '_>, expected_failure: &[HTLCHandlingFailureType],
2500+
) {
2501+
expect_and_process_pending_htlcs(node, false);
2502+
let events = node.node.get_and_clear_pending_events();
2503+
expect_htlc_failure_conditions(events, expected_failure);
2504+
}
2505+
24972506
#[macro_export]
24982507
/// Performs the "commitment signed dance" - the series of message exchanges which occur after a
24992508
/// commitment update.

lightning/src/ln/splicing_tests.rs

Lines changed: 150 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ use crate::chain::ChannelMonitorUpdateStatus;
1414
use crate::events::bump_transaction::sync::WalletSourceSync;
1515
use crate::events::{ClosureReason, Event, FundingInfo, HTLCHandlingFailureType};
1616
use crate::ln::chan_utils;
17-
use crate::ln::channelmanager::BREAKDOWN_TIMEOUT;
17+
use crate::ln::channel::CHANNEL_ANNOUNCEMENT_PROPAGATION_DELAY;
18+
use crate::ln::channelmanager::{PaymentId, RecipientOnionFields, BREAKDOWN_TIMEOUT};
1819
use crate::ln::functional_test_utils::*;
1920
use crate::ln::funding::{FundingTxInput, SpliceContribution};
2021
use crate::ln::msgs::{self, BaseMessageHandler, ChannelMessageHandler, MessageSendEvent};
2122
use crate::ln::types::ChannelId;
23+
use crate::routing::router::{PaymentParameters, RouteParameters};
2224
use crate::util::errors::APIError;
2325
use crate::util::ser::Writeable;
2426
use crate::util::test_channel_signer::SignerOp;
@@ -1801,3 +1803,150 @@ fn fail_quiescent_action_on_channel_close() {
18011803
check_closed_broadcast(&nodes[0], 1, true);
18021804
check_added_monitors(&nodes[0], 1);
18031805
}
1806+
1807+
fn do_test_splice_with_inflight_htlc_forward_and_resolution(expire_scid_pre_forward: bool) {
1808+
// Test that we are still able to forward and resolve HTLCs while the original SCIDs contained
1809+
// in the onion packets have now changed due channel splices becoming locked.
1810+
let chanmon_cfgs = create_chanmon_cfgs(3);
1811+
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
1812+
let mut config = test_default_channel_config();
1813+
config.channel_config.cltv_expiry_delta = CHANNEL_ANNOUNCEMENT_PROPAGATION_DELAY as u16 * 2;
1814+
let node_chanmgrs = create_node_chanmgrs(
1815+
3,
1816+
&node_cfgs,
1817+
&[Some(config.clone()), Some(config.clone()), Some(config)],
1818+
);
1819+
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
1820+
1821+
let node_id_0 = nodes[0].node.get_our_node_id();
1822+
let node_id_1 = nodes[1].node.get_our_node_id();
1823+
let node_id_2 = nodes[2].node.get_our_node_id();
1824+
1825+
let (_, _, channel_id_0_1, _) = create_announced_chan_between_nodes(&nodes, 0, 1);
1826+
let (chan_upd_1_2, _, channel_id_1_2, _) = create_announced_chan_between_nodes(&nodes, 1, 2);
1827+
1828+
let node_max_height =
1829+
nodes.iter().map(|node| node.blocks.lock().unwrap().len()).max().unwrap() as u32;
1830+
connect_blocks(&nodes[0], node_max_height - nodes[0].best_block_info().1);
1831+
connect_blocks(&nodes[1], node_max_height - nodes[1].best_block_info().1);
1832+
connect_blocks(&nodes[2], node_max_height - nodes[2].best_block_info().1);
1833+
1834+
// Send an outbound HTLC from node 0 to 2.
1835+
let payment_amount = 1_000_000;
1836+
let payment_params =
1837+
PaymentParameters::from_node_id(node_id_2, CHANNEL_ANNOUNCEMENT_PROPAGATION_DELAY * 2)
1838+
.with_bolt11_features(nodes[2].node.bolt11_invoice_features())
1839+
.unwrap();
1840+
let route_params =
1841+
RouteParameters::from_payment_params_and_value(payment_params, payment_amount);
1842+
let route = get_route(&nodes[0], &route_params).unwrap();
1843+
let (_, payment_hash, payment_secret) =
1844+
get_payment_preimage_hash(&nodes[2], Some(payment_amount), None);
1845+
let onion = RecipientOnionFields::secret_only(payment_secret);
1846+
let id = PaymentId(payment_hash.0);
1847+
nodes[0].node.send_payment_with_route(route.clone(), payment_hash, onion, id).unwrap();
1848+
check_added_monitors(&nodes[0], 1);
1849+
1850+
// Node 1 should now have a pending HTLC to forward to 2.
1851+
let update_add_0_1 = get_htlc_update_msgs(&nodes[0], &node_id_1);
1852+
nodes[1].node.handle_update_add_htlc(node_id_0, &update_add_0_1.update_add_htlcs[0]);
1853+
commitment_signed_dance!(nodes[1], nodes[0], update_add_0_1.commitment_signed, false);
1854+
assert!(nodes[1].node.needs_pending_htlc_processing());
1855+
1856+
// Splice both channels, lock them, and connect enough blocks to trigger the legacy SCID pruning
1857+
// logic while the HTLC is still pending.
1858+
let contribution = SpliceContribution::SpliceOut {
1859+
outputs: vec![TxOut {
1860+
value: Amount::from_sat(1_000),
1861+
script_pubkey: nodes[0].wallet_source.get_change_script().unwrap(),
1862+
}],
1863+
};
1864+
let splice_tx_0_1 = splice_channel(&nodes[0], &nodes[1], channel_id_0_1, contribution);
1865+
for node in &nodes {
1866+
mine_transaction(node, &splice_tx_0_1);
1867+
}
1868+
1869+
let contribution = SpliceContribution::SpliceOut {
1870+
outputs: vec![TxOut {
1871+
value: Amount::from_sat(1_000),
1872+
script_pubkey: nodes[1].wallet_source.get_change_script().unwrap(),
1873+
}],
1874+
};
1875+
let splice_tx_1_2 = splice_channel(&nodes[1], &nodes[2], channel_id_1_2, contribution);
1876+
for node in &nodes {
1877+
mine_transaction(node, &splice_tx_1_2);
1878+
}
1879+
1880+
for node in &nodes {
1881+
connect_blocks(node, ANTI_REORG_DELAY - 2);
1882+
}
1883+
let splice_locked = get_event_msg!(nodes[0], MessageSendEvent::SendSpliceLocked, node_id_1);
1884+
lock_splice(&nodes[0], &nodes[1], &splice_locked, false);
1885+
1886+
for node in &nodes {
1887+
connect_blocks(node, 1);
1888+
}
1889+
let splice_locked = get_event_msg!(nodes[1], MessageSendEvent::SendSpliceLocked, node_id_2);
1890+
lock_splice(&nodes[1], &nodes[2], &splice_locked, false);
1891+
1892+
if expire_scid_pre_forward {
1893+
for node in &nodes {
1894+
connect_blocks(node, CHANNEL_ANNOUNCEMENT_PROPAGATION_DELAY);
1895+
}
1896+
1897+
// Now attempt to forward the HTLC from node 1 to 2 which will fail because the SCID is no
1898+
// longer stored and has expired. Obviously this is somewhat of an absurd case - not
1899+
// forwarding for `CHANNEL_ANNOUNCEMENT_PROPAGATION_DELAY` blocks is kinda nuts.
1900+
let fail_type = HTLCHandlingFailureType::InvalidForward {
1901+
requested_forward_scid: chan_upd_1_2.contents.short_channel_id,
1902+
};
1903+
expect_htlc_forwarding_fails(&nodes[1], &[fail_type]);
1904+
check_added_monitors(&nodes[1], 1);
1905+
let update_fail_1_0 = get_htlc_update_msgs(&nodes[1], &node_id_0);
1906+
nodes[0].node.handle_update_fail_htlc(node_id_1, &update_fail_1_0.update_fail_htlcs[0]);
1907+
commitment_signed_dance!(nodes[0], nodes[1], update_fail_1_0.commitment_signed, false);
1908+
1909+
let conditions = PaymentFailedConditions::new();
1910+
expect_payment_failed_conditions(&nodes[0], payment_hash, false, conditions);
1911+
} else {
1912+
// Now attempt to forward the HTLC from node 1 to 2.
1913+
nodes[1].node.process_pending_htlc_forwards();
1914+
check_added_monitors(&nodes[1], 1);
1915+
let update_add_1_2 = get_htlc_update_msgs(&nodes[1], &node_id_2);
1916+
nodes[2].node.handle_update_add_htlc(node_id_1, &update_add_1_2.update_add_htlcs[0]);
1917+
commitment_signed_dance!(nodes[2], nodes[1], update_add_1_2.commitment_signed, false);
1918+
assert!(nodes[2].node.needs_pending_htlc_processing());
1919+
1920+
// Node 2 should see the claimable payment. Fail it back to make sure we also handle the SCID
1921+
// change on the way back.
1922+
nodes[2].node.process_pending_htlc_forwards();
1923+
expect_payment_claimable!(&nodes[2], payment_hash, payment_secret, payment_amount);
1924+
nodes[2].node.fail_htlc_backwards(&payment_hash);
1925+
let fail_type = HTLCHandlingFailureType::Receive { payment_hash };
1926+
expect_and_process_pending_htlcs_and_htlc_handling_failed(&nodes[2], &[fail_type]);
1927+
check_added_monitors(&nodes[2], 1);
1928+
1929+
let update_fail_1_2 = get_htlc_update_msgs(&nodes[2], &node_id_1);
1930+
nodes[1].node.handle_update_fail_htlc(node_id_2, &update_fail_1_2.update_fail_htlcs[0]);
1931+
commitment_signed_dance!(nodes[1], nodes[2], update_fail_1_2.commitment_signed, false);
1932+
let fail_type = HTLCHandlingFailureType::Forward {
1933+
node_id: Some(node_id_2),
1934+
channel_id: channel_id_1_2,
1935+
};
1936+
expect_and_process_pending_htlcs_and_htlc_handling_failed(&nodes[1], &[fail_type]);
1937+
check_added_monitors(&nodes[1], 1);
1938+
1939+
let update_fail_0_1 = get_htlc_update_msgs(&nodes[1], &node_id_0);
1940+
nodes[0].node.handle_update_fail_htlc(node_id_1, &update_fail_0_1.update_fail_htlcs[0]);
1941+
commitment_signed_dance!(nodes[0], nodes[1], update_fail_0_1.commitment_signed, false);
1942+
1943+
let conditions = PaymentFailedConditions::new();
1944+
expect_payment_failed_conditions(&nodes[0], payment_hash, true, conditions);
1945+
}
1946+
}
1947+
1948+
#[test]
1949+
fn test_splice_with_inflight_htlc_forward_and_resolution() {
1950+
do_test_splice_with_inflight_htlc_forward_and_resolution(true);
1951+
do_test_splice_with_inflight_htlc_forward_and_resolution(false);
1952+
}

0 commit comments

Comments
 (0)