Skip to content

Commit 5a5fb9c

Browse files
committed
Wrote test to explicitly test BOLT 2 requirements for update_add_htlc
1 parent 301f91e commit 5a5fb9c

File tree

2 files changed

+316
-2
lines changed

2 files changed

+316
-2
lines changed

src/ln/channel.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,9 @@ pub(super) struct Channel {
272272
// update_fee() during ChannelState::AwaitingRemoteRevoke.
273273
holding_cell_update_fee: Option<u64>,
274274
next_local_htlc_id: u64,
275+
#[cfg(test)]
276+
pub next_remote_htlc_id: u64,
277+
#[cfg(not(test))]
275278
next_remote_htlc_id: u64,
276279
channel_update_count: u32,
277280
feerate_per_kw: u64,
@@ -307,6 +310,9 @@ pub(super) struct Channel {
307310
pub(super) our_dust_limit_satoshis: u64,
308311
#[cfg(not(test))]
309312
our_dust_limit_satoshis: u64,
313+
#[cfg(test)]
314+
pub(super) their_max_htlc_value_in_flight_msat: u64,
315+
#[cfg(not(test))]
310316
their_max_htlc_value_in_flight_msat: u64,
311317
//get_our_max_htlc_value_in_flight_msat(): u64,
312318
/// minimum channel reserve for **self** to maintain - set by them.
@@ -316,6 +322,9 @@ pub(super) struct Channel {
316322
our_htlc_minimum_msat: u64,
317323
their_to_self_delay: u16,
318324
//implied by BREAKDOWN_TIMEOUT: our_to_self_delay: u16,
325+
#[cfg(test)]
326+
pub their_max_accepted_htlcs: u16,
327+
#[cfg(not(test))]
319328
their_max_accepted_htlcs: u16,
320329
//implied by OUR_MAX_HTLCS: our_max_accepted_htlcs: u16,
321330
minimum_depth: u32,
@@ -337,7 +346,7 @@ pub(super) struct Channel {
337346
logger: Arc<Logger>,
338347
}
339348

340-
const OUR_MAX_HTLCS: u16 = 50; //TODO
349+
pub const OUR_MAX_HTLCS: u16 = 50; //TODO
341350
/// Confirmation count threshold at which we close a channel. Ideally we'd keep the channel around
342351
/// on ice until the funding transaction gets more confirmations, but the LN protocol doesn't
343352
/// really allow for this, so instead we're stuck closing it out at that point.
@@ -382,7 +391,7 @@ macro_rules! secp_check {
382391

383392
impl Channel {
384393
// Convert constants + channel value to limits:
385-
fn get_our_max_htlc_value_in_flight_msat(channel_value_satoshis: u64) -> u64 {
394+
pub fn get_our_max_htlc_value_in_flight_msat(channel_value_satoshis: u64) -> u64 {
386395
channel_value_satoshis * 1000 / 10 //TODO
387396
}
388397

src/ln/functional_tests.rs

Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6602,3 +6602,308 @@ fn test_onion_failure() {
66026602
msg.onion_routing_packet = onion_packet;
66036603
}, ||{}, true, Some(21), None);
66046604
}
6605+
6606+
#[test]
6607+
fn test_update_add_htlc_bolt2() {
6608+
use util::rng;
6609+
use std::sync::atomic::Ordering;
6610+
use super::channelmanager::HTLCSource;
6611+
use super::channel::ChannelError;
6612+
6613+
let secp_ctx = Secp256k1::new();
6614+
6615+
// BOLT 2 Requirements for Sender
6616+
// BOLT 2 Requirement: MUST NOT offer amount_msat it cannot pay for in the remote commitment transaction at the current feerate_per_kw (see "Updating Fees") while maintaining its channel reserve.
6617+
//TODO: I don't believe this is explicitly enforced when sending an HTLC but as the Fee aspect of the BOLT specs is in flux leaving this as a TODO.
6618+
6619+
// BOLT2 Requirement: MUST offer amount_msat greater than 0.
6620+
// BOLT2 Requirement: MUST NOT offer amount_msat below the receiving node's htlc_minimum_msat (same validation check catches both of these)
6621+
let mut nodes = create_network(2);
6622+
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000);
6623+
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 100000, TEST_FINAL_CLTV).unwrap();
6624+
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
6625+
6626+
let session_priv = SecretKey::from_slice(&secp_ctx, &{
6627+
let mut session_key = [0; 32];
6628+
rng::fill_bytes(&mut session_key);
6629+
session_key
6630+
}).expect("RNG is bad!");
6631+
6632+
let cur_height = nodes[0].node.latest_block_height.load(Ordering::Acquire) as u32 + 1;
6633+
let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route, &session_priv).unwrap();
6634+
let (onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route, cur_height).unwrap();
6635+
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, &our_payment_hash);
6636+
6637+
let err = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&chan.2).unwrap().send_htlc(0, our_payment_hash, TEST_FINAL_CLTV, HTLCSource::OutboundRoute {
6638+
route: route.clone(),
6639+
session_priv: session_priv.clone(),
6640+
first_hop_htlc_msat: 100000,
6641+
}, onion_packet);
6642+
6643+
if let Err(ChannelError::Ignore(_)) = err {
6644+
assert!(true);
6645+
} else {
6646+
assert!(false);
6647+
}
6648+
6649+
//BOLT 2 Requirement: MUST set cltv_expiry less than 500000000.
6650+
//TODO: This is not currently explicitly checked when sending an HTLC and exists as TODO in the channel::send_htlc(...) function
6651+
//It is enforced when constructing a route.
6652+
6653+
// BOLT 2 Requirement: if result would be offering more than the remote's max_accepted_htlcs HTLCs, in the remote commitment transaction: MUST NOT add an HTLC.
6654+
let mut nodes = create_network(2);
6655+
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 0);
6656+
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 100000, TEST_FINAL_CLTV).unwrap();
6657+
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
6658+
6659+
let session_priv = SecretKey::from_slice(&secp_ctx, &{
6660+
let mut session_key = [0; 32];
6661+
rng::fill_bytes(&mut session_key);
6662+
session_key
6663+
}).expect("RNG is bad!");
6664+
6665+
let cur_height = nodes[0].node.latest_block_height.load(Ordering::Acquire) as u32 + 1;
6666+
let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route, &session_priv).unwrap();
6667+
let (onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route, cur_height).unwrap();
6668+
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, &our_payment_hash);
6669+
6670+
let max_accepted_htlcs = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().their_max_accepted_htlcs;
6671+
6672+
for _i in 0..max_accepted_htlcs {
6673+
let _ = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&chan.2).unwrap().send_htlc(10000, our_payment_hash, TEST_FINAL_CLTV, HTLCSource::OutboundRoute {
6674+
route: route.clone(),
6675+
session_priv: session_priv.clone(),
6676+
first_hop_htlc_msat: 0,
6677+
}, onion_packet.clone());
6678+
}
6679+
6680+
let err = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&chan.2).unwrap().send_htlc(10000, our_payment_hash, TEST_FINAL_CLTV, HTLCSource::OutboundRoute {
6681+
route: route.clone(),
6682+
session_priv: session_priv.clone(),
6683+
first_hop_htlc_msat: 0,
6684+
}, onion_packet);
6685+
6686+
if let Err(ChannelError::Ignore(_)) = err {
6687+
assert!(true);
6688+
} else {
6689+
assert!(false);
6690+
}
6691+
//Clear any unhandled msg events.
6692+
let _ = nodes[0].node.get_and_clear_pending_msg_events();
6693+
let _ = nodes[1].node.get_and_clear_pending_msg_events();
6694+
6695+
// BOLT 2 Requirement: if the sum of total offered HTLCs would exceed the remote's max_htlc_value_in_flight_msat: MUST NOT add an HTLC.
6696+
let mut nodes = create_network(2);
6697+
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 0);
6698+
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 100000, TEST_FINAL_CLTV).unwrap();
6699+
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
6700+
6701+
let session_priv = SecretKey::from_slice(&secp_ctx, &{
6702+
let mut session_key = [0; 32];
6703+
rng::fill_bytes(&mut session_key);
6704+
session_key
6705+
}).expect("RNG is bad!");
6706+
6707+
let cur_height = nodes[0].node.latest_block_height.load(Ordering::Acquire) as u32 + 1;
6708+
let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route, &session_priv).unwrap();
6709+
let (onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route, cur_height).unwrap();
6710+
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, &our_payment_hash);
6711+
6712+
let err = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&chan.2).unwrap().send_htlc(10000001, our_payment_hash, TEST_FINAL_CLTV, HTLCSource::OutboundRoute {
6713+
route: route.clone(),
6714+
session_priv: session_priv.clone(),
6715+
first_hop_htlc_msat: 0,
6716+
}, onion_packet);
6717+
6718+
if let Err(ChannelError::Ignore(_)) = err {
6719+
assert!(true);
6720+
} else {
6721+
assert!(false);
6722+
}
6723+
6724+
// BOLT 2 Requirement: if the sum of total offered HTLCs would exceed the remote's max_htlc_value_in_flight_msat: MUST NOT add an HTLC.
6725+
// BOLT 2 Requirement: MUST increase the value of id by 1 for each successive offer.
6726+
let mut nodes = create_network(2);
6727+
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 0);
6728+
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 100000, TEST_FINAL_CLTV).unwrap();
6729+
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
6730+
6731+
let session_priv = SecretKey::from_slice(&secp_ctx, &{
6732+
let mut session_key = [0; 32];
6733+
rng::fill_bytes(&mut session_key);
6734+
session_key
6735+
}).expect("RNG is bad!");
6736+
6737+
let cur_height = nodes[0].node.latest_block_height.load(Ordering::Acquire) as u32 + 1;
6738+
let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route, &session_priv).unwrap();
6739+
let (onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route, cur_height).unwrap();
6740+
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, &our_payment_hash);
6741+
6742+
for expected_id in 0..2 {
6743+
let res = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&chan.2).unwrap().send_htlc(100000, our_payment_hash, TEST_FINAL_CLTV, HTLCSource::OutboundRoute {
6744+
route: route.clone(),
6745+
session_priv: session_priv.clone(),
6746+
first_hop_htlc_msat: 0,
6747+
}, onion_packet.clone());
6748+
6749+
if let Ok(Some(msg)) = res {
6750+
assert_eq!(msg.htlc_id, expected_id);
6751+
} else {
6752+
assert!(false);
6753+
}
6754+
}
6755+
6756+
// BOLT 2 Requirements for Receiver
6757+
6758+
//BOLT2 Requirement: receiving an amount_msat equal to 0, OR less than its own htlc_minimum_msat -> SHOULD fail the channel.
6759+
let mut nodes = create_network(2);
6760+
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000);
6761+
let htlc_minimum_msat: u64;
6762+
{
6763+
let chan_lock = nodes[0].node.channel_state.lock().unwrap();
6764+
let channel = chan_lock.by_id.get(&chan.2).unwrap();
6765+
htlc_minimum_msat = channel.get_our_htlc_minimum_msat();
6766+
}
6767+
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], htlc_minimum_msat+1, TEST_FINAL_CLTV).unwrap();
6768+
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
6769+
nodes[0].node.send_payment(route, our_payment_hash).unwrap();
6770+
check_added_monitors!(nodes[0], 1);
6771+
let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
6772+
6773+
updates.update_add_htlcs[0].amount_msat = htlc_minimum_msat-1;
6774+
let err = nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
6775+
assert!(err.is_err());
6776+
//Confirm the channel was closed
6777+
{
6778+
assert_eq!(nodes[1].node.channel_state.lock().unwrap().by_id.len(), 0);
6779+
}
6780+
//Clear unhandled msg events.
6781+
let _ = nodes[1].node.get_and_clear_pending_msg_events();
6782+
6783+
//BOLT2 Requirement: receiving an amount_msat that the sending node cannot afford at the current feerate_per_kw (while maintaining its channel reserve): SHOULD fail the channel
6784+
let mut nodes = create_network(2);
6785+
let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000);
6786+
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 3999999, TEST_FINAL_CLTV).unwrap();
6787+
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
6788+
nodes[0].node.send_payment(route, our_payment_hash).unwrap();
6789+
check_added_monitors!(nodes[0], 1);
6790+
let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
6791+
6792+
updates.update_add_htlcs[0].amount_msat = 4000001;
6793+
let err = nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
6794+
assert!(err.is_err());
6795+
//Confirm the channel was closed
6796+
{
6797+
assert_eq!(nodes[1].node.channel_state.lock().unwrap().by_id.len(), 0);
6798+
}
6799+
//Clear unhandled msg events.
6800+
let _ = nodes[1].node.get_and_clear_pending_msg_events();
6801+
6802+
//BOLT 2 Requirement: if a sending node adds more than its max_accepted_htlcs HTLCs to its local commitment transaction: SHOULD fail the channel
6803+
//BOLT 2 Requirement: MUST allow multiple HTLCs with the same payment_hash.
6804+
let mut nodes = create_network(2);
6805+
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000);
6806+
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 3999999, TEST_FINAL_CLTV).unwrap();
6807+
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
6808+
6809+
let session_priv = SecretKey::from_slice(&secp_ctx, &{
6810+
let mut session_key = [0; 32];
6811+
rng::fill_bytes(&mut session_key);
6812+
session_key
6813+
}).expect("RNG is bad!");
6814+
6815+
let cur_height = nodes[0].node.latest_block_height.load(Ordering::Acquire) as u32 + 1;
6816+
let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route, &session_priv).unwrap();
6817+
let (onion_payloads, _htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route, cur_height).unwrap();
6818+
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, &our_payment_hash);
6819+
6820+
let mut msg = msgs::UpdateAddHTLC {
6821+
channel_id: chan.2,
6822+
htlc_id: 0,
6823+
amount_msat: 1000,
6824+
payment_hash: our_payment_hash,
6825+
cltv_expiry: htlc_cltv,
6826+
onion_routing_packet: onion_packet.clone(),
6827+
};
6828+
6829+
for i in 0..super::channel::OUR_MAX_HTLCS {
6830+
msg.htlc_id = i as u64;
6831+
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &msg).unwrap();
6832+
}
6833+
msg.htlc_id = (super::channel::OUR_MAX_HTLCS + 1) as u64;
6834+
let err = nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &msg);
6835+
assert!(err.is_err());
6836+
//Confirm the channel was closed
6837+
{
6838+
assert_eq!(nodes[1].node.channel_state.lock().unwrap().by_id.len(), 0);
6839+
}
6840+
//Clear unhandled msg events.
6841+
let _ = nodes[1].node.get_and_clear_pending_msg_events();
6842+
6843+
//OR adds more than its max_htlc_value_in_flight_msat worth of offered HTLCs to its local commitment transaction: SHOULD fail the channel
6844+
let mut nodes = create_network(2);
6845+
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000);
6846+
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 1000000, TEST_FINAL_CLTV).unwrap();
6847+
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
6848+
nodes[0].node.send_payment(route, our_payment_hash).unwrap();
6849+
check_added_monitors!(nodes[0], 1);
6850+
let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
6851+
updates.update_add_htlcs[0].amount_msat = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().their_max_htlc_value_in_flight_msat + 1;
6852+
let err = nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
6853+
assert!(err.is_err());
6854+
//Confirm the channel was closed
6855+
{
6856+
assert_eq!(nodes[1].node.channel_state.lock().unwrap().by_id.len(), 0);
6857+
}
6858+
//Clear unhandled msg events.
6859+
let _ = nodes[1].node.get_and_clear_pending_msg_events();
6860+
6861+
//BOLT2 Requirement: if sending node sets cltv_expiry to greater or equal to 500000000: SHOULD fail the channel.
6862+
let mut nodes = create_network(2);
6863+
let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000);
6864+
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 3999999, TEST_FINAL_CLTV).unwrap();
6865+
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
6866+
nodes[0].node.send_payment(route, our_payment_hash).unwrap();
6867+
check_added_monitors!(nodes[0], 1);
6868+
let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
6869+
updates.update_add_htlcs[0].cltv_expiry = 500000000;
6870+
let err = nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
6871+
assert!(err.is_err());
6872+
//Confirm the channel was closed
6873+
{
6874+
assert_eq!(nodes[1].node.channel_state.lock().unwrap().by_id.len(), 0);
6875+
}
6876+
//Clear unhandled msg events.
6877+
let _ = nodes[1].node.get_and_clear_pending_msg_events();
6878+
6879+
//BOLT 2 requirement: if the sender did not previously acknowledge the commitment of that HTLC: MUST ignore a repeated id value after a reconnection.
6880+
let mut nodes = create_network(2);
6881+
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000);
6882+
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 3999999, TEST_FINAL_CLTV).unwrap();
6883+
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
6884+
nodes[0].node.send_payment(route, our_payment_hash).unwrap();
6885+
check_added_monitors!(nodes[0], 1);
6886+
let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
6887+
let _ = nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
6888+
assert_eq!(nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().next_remote_htlc_id, 1);
6889+
6890+
//Disconnect and Reconnect
6891+
nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
6892+
nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
6893+
nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id());
6894+
let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
6895+
assert_eq!(reestablish_1.len(), 1);
6896+
nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id());
6897+
let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
6898+
assert_eq!(reestablish_2.len(), 1);
6899+
nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &reestablish_2[0]).unwrap();
6900+
let _ = handle_chan_reestablish_msgs!(nodes[0], nodes[1]);
6901+
nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &reestablish_1[0]).unwrap();
6902+
let _ = handle_chan_reestablish_msgs!(nodes[1], nodes[0]);
6903+
let _ = nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
6904+
//Confirm the HTLC was ignored
6905+
assert_eq!(nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().next_remote_htlc_id, 1);
6906+
6907+
//Clear unhandled msg events
6908+
let _ = nodes[1].node.get_and_clear_pending_msg_events();
6909+
}

0 commit comments

Comments
 (0)