Skip to content

Commit 39f6a9e

Browse files
WIP: Test async receive
1 parent 7bb99b4 commit 39f6a9e

File tree

2 files changed

+210
-3
lines changed

2 files changed

+210
-3
lines changed

lightning/src/ln/blinded_payment_tests.rs

Lines changed: 206 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::events::{Event, HTLCDestination, MessageSendEvent, MessageSendEventsP
1717
use crate::ln::types::ChannelId;
1818
use crate::types::payment::{PaymentHash, PaymentSecret};
1919
use crate::ln::channelmanager;
20-
use crate::ln::channelmanager::{HTLCFailureMsg, PaymentId, RecipientOnionFields};
20+
use crate::ln::channelmanager::{HTLCFailureMsg, PaymentId, RecipientOnionFields, Verification};
2121
use crate::types::features::{BlindedHopFeatures, ChannelFeatures, NodeFeatures};
2222
use crate::ln::functional_test_utils::*;
2323
use crate::ln::msgs;
@@ -37,8 +37,8 @@ use lightning_invoice::RawBolt11Invoice;
3737
#[cfg(async_payments)] use {
3838
crate::blinded_path::BlindedHop,
3939
crate::blinded_path::message::{AsyncPaymentsContext, BlindedMessagePath, OffersContext},
40-
crate::ln::channelmanager::Verification,
4140
crate::ln::inbound_payment,
41+
crate::ln::inbound_payment::ExpandedKey,
4242
crate::ln::msgs::OnionMessageHandler,
4343
crate::offers::nonce::Nonce,
4444
crate::onion_message::async_payments::{AsyncPaymentsMessage, AsyncPaymentsMessageHandler, ReleaseHeldHtlc},
@@ -1872,3 +1872,207 @@ fn route_blinding_spec_test_vector() {
18721872
_ => panic!("Unexpected error")
18731873
}
18741874
}
1875+
1876+
#[cfg(async_payments)]
1877+
#[test]
1878+
fn async_receive_flow_success() {
1879+
// Test that an always-online sender can successfully pay an async receiver.
1880+
let secp_ctx = Secp256k1::new();
1881+
let chanmon_cfgs = create_chanmon_cfgs(3);
1882+
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
1883+
let mut allow_priv_chan_fwds_cfg = test_default_channel_config();
1884+
allow_priv_chan_fwds_cfg.accept_forwards_to_priv_channels = true;
1885+
let mut mpp_keysend_config = test_default_channel_config();
1886+
mpp_keysend_config.accept_mpp_keysend = true;
1887+
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(allow_priv_chan_fwds_cfg), Some(mpp_keysend_config)]);
1888+
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
1889+
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
1890+
create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0);
1891+
1892+
let dummy_blinded_path_to_always_online_node = BlindedMessagePath::from_raw(
1893+
nodes[1].node.get_our_node_id(), test_utils::pubkey(42),
1894+
vec![BlindedHop { blinded_node_id: test_utils::pubkey(42), encrypted_payload: vec![42; 32] }]
1895+
);
1896+
let (offer_builder, offer_nonce) = nodes[2].node.create_async_receive_offer_builder(vec![dummy_blinded_path_to_always_online_node]).unwrap();
1897+
let offer = offer_builder.build().unwrap();
1898+
let static_invoice = nodes[2].node.create_static_invoice_builder_for_async_receive_offer(&offer, offer_nonce, None).unwrap().build_and_sign(&secp_ctx).unwrap();
1899+
1900+
// Check that we won't pay static invoices that aren't expected.
1901+
if nodes[0].node.handle_message(
1902+
OffersMessage::StaticInvoice(static_invoice.clone()),
1903+
Some(OffersContext::OutboundPayment { payment_id: PaymentId([0; 32]), nonce: offer_nonce, hmac: None }), None
1904+
).is_some() { panic!() }
1905+
1906+
let amt_msat = 5000;
1907+
let payment_id = PaymentId([1; 32]);
1908+
nodes[0].node.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(0), None).unwrap();
1909+
let _invreq_om = nodes[0].onion_messenger.next_onion_message_for_peer(nodes[1].node.get_our_node_id()).unwrap();
1910+
1911+
// Don't forward the invreq since we don't support retrieving the static invoice from the
1912+
// recipient's LSP yet, instead just provide the invoice directly to the payer.
1913+
let hardcoded_random_bytes = [42; 32];
1914+
let keysend_preimage = PaymentPreimage(hardcoded_random_bytes);
1915+
*nodes[0].keys_manager.override_random_bytes.lock().unwrap() = Some(hardcoded_random_bytes);
1916+
let expanded_key = ExpandedKey::new(&nodes[0].keys_manager.get_inbound_payment_key_material());
1917+
let hmac = Some(payment_id.hmac_for_offer_payment(offer_nonce, &expanded_key));
1918+
assert!(nodes[0].node.handle_message(
1919+
OffersMessage::StaticInvoice(static_invoice.clone()),
1920+
Some(OffersContext::OutboundPayment { payment_id, nonce: offer_nonce, hmac }), None
1921+
).is_none());
1922+
1923+
let held_htlc_available_om_0_1 = nodes[0].onion_messenger.next_onion_message_for_peer(nodes[1].node.get_our_node_id()).unwrap();
1924+
1925+
// Check that receiving a duplicate static invoice won't cause us to generate another
1926+
// held_htlc_available message.
1927+
assert!(nodes[0].node.handle_message(
1928+
OffersMessage::StaticInvoice(static_invoice),
1929+
Some(OffersContext::OutboundPayment { payment_id, nonce: offer_nonce, hmac }), None
1930+
).is_none());
1931+
assert!(nodes[0].onion_messenger.next_onion_message_for_peer(nodes[1].node.get_our_node_id()).is_none());
1932+
1933+
nodes[1].onion_messenger.handle_onion_message(nodes[0].node.get_our_node_id(), &held_htlc_available_om_0_1);
1934+
let held_htlc_available_om_1_2 = nodes[1].onion_messenger.next_onion_message_for_peer(nodes[2].node.get_our_node_id()).unwrap();
1935+
nodes[2].onion_messenger.handle_onion_message(nodes[1].node.get_our_node_id(), &held_htlc_available_om_1_2);
1936+
1937+
let release_held_htlc_om_2_0 = nodes[2].onion_messenger.next_onion_message_for_peer(nodes[0].node.get_our_node_id()).unwrap();
1938+
nodes[0].onion_messenger.handle_onion_message(nodes[2].node.get_our_node_id(), &release_held_htlc_om_2_0);
1939+
check_added_monitors(&nodes[0], 1);
1940+
1941+
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
1942+
assert_eq!(events.len(), 1);
1943+
let ev = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events);
1944+
let payment_hash = if let MessageSendEvent::UpdateHTLCs {
1945+
updates: msgs::CommitmentUpdate { ref update_add_htlcs, .. }, ..
1946+
} = ev {
1947+
update_add_htlcs[0].payment_hash
1948+
} else { panic!() };
1949+
1950+
let route: &[&[&Node]] = &[&[&nodes[1], &nodes[2]]];
1951+
let args = PassAlongPathArgs::new(&nodes[0], route[0], amt_msat, payment_hash, ev)
1952+
.with_payment_preimage(keysend_preimage);
1953+
do_pass_along_path(args);
1954+
claim_payment_along_route(ClaimAlongRouteArgs::new(&nodes[0], route, keysend_preimage));
1955+
}
1956+
1957+
#[cfg(async_payments)]
1958+
#[test]
1959+
fn retry_async_payment() {
1960+
// Test that we can successfully retry async payments.
1961+
let secp_ctx = Secp256k1::new();
1962+
let chanmon_cfgs = create_chanmon_cfgs(4);
1963+
let mut allow_priv_chan_fwds_cfg = test_default_channel_config();
1964+
allow_priv_chan_fwds_cfg.accept_forwards_to_priv_channels = true;
1965+
// Make one blinded path's fees slightly higher so they are tried in a deterministic order.
1966+
let mut higher_fee_chan_cfg = test_default_channel_config();
1967+
higher_fee_chan_cfg.channel_config.forwarding_fee_base_msat += 5000;
1968+
higher_fee_chan_cfg.accept_forwards_to_priv_channels = true;
1969+
let mut mpp_keysend_config = test_default_channel_config();
1970+
mpp_keysend_config.accept_mpp_keysend = true;
1971+
let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
1972+
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, Some(allow_priv_chan_fwds_cfg), Some(higher_fee_chan_cfg), Some(mpp_keysend_config)]);
1973+
let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs);
1974+
1975+
// Create this network topology so nodes[0] has a blinded route hint to retry over.
1976+
// n1
1977+
// / \
1978+
// n0 n3
1979+
// \ /
1980+
// n2
1981+
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
1982+
create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 1_000_000, 0);
1983+
let _chan_1_3 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 3, 1_000_000, 0);
1984+
let _chan_2_3 = create_unannounced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0);
1985+
1986+
let dummy_path_to_always_online_node = BlindedMessagePath::from_raw(
1987+
nodes[1].node.get_our_node_id(), test_utils::pubkey(42),
1988+
vec![BlindedHop { blinded_node_id: test_utils::pubkey(42), encrypted_payload: vec![42; 32] }]
1989+
);
1990+
let (offer_builder, offer_nonce) = nodes[3].node.create_async_receive_offer_builder(vec![dummy_path_to_always_online_node]).unwrap();
1991+
let offer = offer_builder.build().unwrap();
1992+
let static_invoice = nodes[3].node.create_static_invoice_builder_for_async_receive_offer(&offer, offer_nonce, None).unwrap().build_and_sign(&secp_ctx).unwrap();
1993+
1994+
let amt_msat = 5000;
1995+
let payment_id = PaymentId([1; 32]);
1996+
nodes[0].node.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(1), None).unwrap();
1997+
let _invreq_om = nodes[0].onion_messenger.next_onion_message_for_peer(nodes[1].node.get_our_node_id()).unwrap();
1998+
1999+
// Don't forward the invreq since we don't support retrieving the static invoice from the
2000+
// recipient's LSP yet, instead just provide the invoice directly to the payer.
2001+
let hardcoded_random_bytes = [42; 32];
2002+
let keysend_preimage = PaymentPreimage(hardcoded_random_bytes);
2003+
*nodes[0].keys_manager.override_random_bytes.lock().unwrap() = Some(hardcoded_random_bytes);
2004+
let expanded_key = ExpandedKey::new(&nodes[0].keys_manager.get_inbound_payment_key_material());
2005+
let hmac = Some(payment_id.hmac_for_offer_payment(offer_nonce, &expanded_key));
2006+
assert!(nodes[0].node.handle_message(
2007+
OffersMessage::StaticInvoice(static_invoice.clone()),
2008+
Some(OffersContext::OutboundPayment { payment_id, nonce: offer_nonce, hmac }), None
2009+
).is_none());
2010+
2011+
let held_htlc_available_om_0_3 = nodes[0].onion_messenger.next_onion_message_for_peer(nodes[3].node.get_our_node_id()).unwrap();
2012+
nodes[3].onion_messenger.handle_onion_message(nodes[0].node.get_our_node_id(), &held_htlc_available_om_0_3);
2013+
let release_held_htlc_om_3_0 = nodes[3].onion_messenger.next_onion_message_for_peer(nodes[0].node.get_our_node_id()).unwrap();
2014+
nodes[0].onion_messenger.handle_onion_message(nodes[3].node.get_our_node_id(), &release_held_htlc_om_3_0);
2015+
check_added_monitors(&nodes[0], 1);
2016+
2017+
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
2018+
assert_eq!(events.len(), 1);
2019+
let ev = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events);
2020+
let payment_hash = if let MessageSendEvent::UpdateHTLCs {
2021+
updates: msgs::CommitmentUpdate { ref update_add_htlcs, .. }, ..
2022+
} = ev {
2023+
update_add_htlcs[0].payment_hash
2024+
} else { panic!() };
2025+
2026+
let route: &[&[&Node]] = &[&[&nodes[1], &nodes[3]]];
2027+
let args = PassAlongPathArgs::new(&nodes[0], route[0], amt_msat, payment_hash, ev)
2028+
.with_payment_preimage(keysend_preimage);
2029+
do_pass_along_path(args);
2030+
2031+
// Fail the payment back to trigger the retry.
2032+
nodes[3].node.fail_htlc_backwards(&payment_hash);
2033+
expect_pending_htlcs_forwardable_conditions(
2034+
nodes[3].node.get_and_clear_pending_events(), &[HTLCDestination::FailedPayment { payment_hash }]
2035+
);
2036+
nodes[3].node.process_pending_htlc_forwards();
2037+
check_added_monitors!(nodes[3], 1);
2038+
2039+
let updates = get_htlc_update_msgs!(nodes[3], nodes[1].node.get_our_node_id());
2040+
assert_eq!(updates.update_fail_malformed_htlcs.len(), 1);
2041+
let update_malformed = &updates.update_fail_malformed_htlcs[0];
2042+
assert_eq!(update_malformed.sha256_of_onion, [0; 32]);
2043+
assert_eq!(update_malformed.failure_code, INVALID_ONION_BLINDING);
2044+
nodes[1].node.handle_update_fail_malformed_htlc(nodes[3].node.get_our_node_id(), update_malformed);
2045+
do_commitment_signed_dance(&nodes[1], &nodes[3], &updates.commitment_signed, true, false);
2046+
2047+
let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
2048+
assert_eq!(updates.update_fail_htlcs.len(), 1);
2049+
nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]);
2050+
do_commitment_signed_dance(&nodes[0], &nodes[1], &updates.commitment_signed, false, false);
2051+
2052+
let mut events = nodes[0].node.get_and_clear_pending_events();
2053+
assert_eq!(events.len(), 2);
2054+
match events[0] {
2055+
Event::PaymentPathFailed { payment_hash: ev_payment_hash, payment_failed_permanently, .. } => {
2056+
assert_eq!(payment_hash, ev_payment_hash);
2057+
assert_eq!(payment_failed_permanently, false);
2058+
},
2059+
_ => panic!("Unexpected event"),
2060+
}
2061+
match events[1] {
2062+
Event::PendingHTLCsForwardable { .. } => {},
2063+
_ => panic!("Unexpected event"),
2064+
}
2065+
nodes[0].node.process_pending_htlc_forwards();
2066+
check_added_monitors(&nodes[0], 1);
2067+
2068+
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
2069+
assert_eq!(events.len(), 1);
2070+
let ev = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events);
2071+
2072+
let route: &[&[&Node]] = &[&[&nodes[2], &nodes[3]]];
2073+
let args = PassAlongPathArgs::new(&nodes[0], route[0], amt_msat, payment_hash, ev)
2074+
.with_payment_preimage(keysend_preimage);
2075+
do_pass_along_path(args);
2076+
claim_payment_along_route(ClaimAlongRouteArgs::new(&nodes[0], route, keysend_preimage));
2077+
// TODO: check that the payment context is as expected
2078+
}

lightning/src/ln/functional_test_utils.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1468,7 +1468,7 @@ pub fn create_announced_chan_between_nodes_with_value<'a, 'b, 'c: 'd, 'd>(nodes:
14681468
}
14691469

14701470
pub fn create_unannounced_chan_between_nodes_with_value<'a, 'b, 'c, 'd>(nodes: &'a Vec<Node<'b, 'c, 'd>>, a: usize, b: usize, channel_value: u64, push_msat: u64) -> (msgs::ChannelReady, Transaction) {
1471-
let mut no_announce_cfg = test_default_channel_config();
1471+
let mut no_announce_cfg = nodes[a].node.get_current_default_configuration().clone();
14721472
no_announce_cfg.channel_handshake_config.announce_for_forwarding = false;
14731473
nodes[a].node.create_channel(nodes[b].node.get_our_node_id(), channel_value, push_msat, 42, None, Some(no_announce_cfg)).unwrap();
14741474
let open_channel = get_event_msg!(nodes[a], MessageSendEvent::SendOpenChannel, nodes[b].node.get_our_node_id());
@@ -2700,6 +2700,9 @@ pub fn do_pass_along_path<'a, 'b, 'c>(args: PassAlongPathArgs) -> Option<Event>
27002700
PaymentPurpose::Bolt12OfferPayment { payment_preimage, payment_secret, .. } => {
27012701
assert_eq!(expected_preimage, *payment_preimage);
27022702
assert_eq!(our_payment_secret.unwrap(), *payment_secret);
2703+
if let Some(secret) = our_payment_secret {
2704+
assert_eq!(secret, *payment_secret);
2705+
}
27032706
assert_eq!(Some(*payment_secret), onion_fields.as_ref().unwrap().payment_secret);
27042707
},
27052708
PaymentPurpose::Bolt12RefundPayment { payment_preimage, payment_secret, .. } => {

0 commit comments

Comments
 (0)