Skip to content

Commit 520b53e

Browse files
committed
Optionally reject HTLC forwards over priv chans with a new config
Private nodes should never wish to forward HTLCs at all, which we support here by disabling forwards out over private channels by default. As private nodes should not have any public channels, this suffices, without allowing users to disable forwarding over channels announced in the routing graph already. Closes #969
1 parent 99953ed commit 520b53e

File tree

4 files changed

+208
-13
lines changed

4 files changed

+208
-13
lines changed

lightning/src/ln/channelmanager.rs

+14-6
Original file line numberDiff line numberDiff line change
@@ -1555,15 +1555,23 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
15551555
// short_channel_id is non-0 in any ::Forward.
15561556
if let &PendingHTLCRouting::Forward { ref short_channel_id, .. } = routing {
15571557
let id_option = channel_state.as_ref().unwrap().short_to_id.get(&short_channel_id).cloned();
1558-
let forwarding_id = match id_option {
1559-
None => { // unknown_next_peer
1560-
return_err!("Don't have available channel for forwarding as requested.", 0x4000 | 10, &[0;0]);
1561-
},
1562-
Some(id) => id.clone(),
1563-
};
15641558
if let Some((err, code, chan_update)) = loop {
1559+
let forwarding_id = match id_option {
1560+
None => { // unknown_next_peer
1561+
break Some(("Don't have available channel for forwarding as requested.", 0x4000 | 10, None));
1562+
},
1563+
Some(id) => id.clone(),
1564+
};
1565+
15651566
let chan = channel_state.as_mut().unwrap().by_id.get_mut(&forwarding_id).unwrap();
15661567

1568+
if !chan.should_announce() && !self.default_configuration.accept_forwards_to_priv_channels {
1569+
// Note that the behavior here should be identical to the above block - we
1570+
// should NOT reveal the existence or non-existence of a private channel if
1571+
// we don't allow forwards outbound over them.
1572+
break Some(("Don't have available channel for forwarding as requested.", 0x4000 | 10, None));
1573+
}
1574+
15671575
// Note that we could technically not return an error yet here and just hope
15681576
// that the connection is reestablished or monitor updated by the time we get
15691577
// around to doing the actual forward, but better to fail early if we can and

lightning/src/ln/functional_test_utils.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1206,7 +1206,10 @@ pub const TEST_FINAL_CLTV: u32 = 70;
12061206
pub fn route_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) -> (PaymentPreimage, PaymentHash, PaymentSecret) {
12071207
let net_graph_msg_handler = &origin_node.net_graph_msg_handler;
12081208
let logger = test_utils::TestLogger::new();
1209-
let route = get_route(&origin_node.node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &expected_route.last().unwrap().node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), recv_value, TEST_FINAL_CLTV, &logger).unwrap();
1209+
let route = get_route(&origin_node.node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(),
1210+
&expected_route.last().unwrap().node.get_our_node_id(), Some(InvoiceFeatures::known()),
1211+
Some(&origin_node.node.list_usable_channels().iter().collect::<Vec<_>>()), &[],
1212+
recv_value, TEST_FINAL_CLTV, &logger).unwrap();
12101213
assert_eq!(route.paths.len(), 1);
12111214
assert_eq!(route.paths[0].len(), expected_route.len());
12121215
for (node, hop) in expected_route.iter().zip(route.paths[0].iter()) {

lightning/src/ln/functional_tests.rs

+164-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ use ln::channel::{COMMITMENT_TX_BASE_WEIGHT, COMMITMENT_TX_WEIGHT_PER_HTLC};
2222
use ln::channelmanager::{ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentSendFailure, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA};
2323
use ln::channel::{Channel, ChannelError};
2424
use ln::{chan_utils, onion_utils};
25-
use routing::router::{Route, RouteHop, get_route};
25+
use routing::router::{Route, RouteHop, RouteHint, RouteHintHop, get_route};
26+
use routing::network_graph::RoutingFees;
2627
use ln::features::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures};
2728
use ln::msgs;
2829
use ln::msgs::{ChannelMessageHandler,RoutingMessageHandler,HTLCFailChannelUpdate, ErrorAction};
@@ -7915,6 +7916,168 @@ fn test_announce_disable_channels() {
79157916
}
79167917
}
79177918

7919+
#[test]
7920+
fn test_priv_forwarding_rejection() {
7921+
// If we have a private channel with outbound liquidity, and
7922+
// UserConfig::accept_forwards_to_priv_channels is set to false, we should reject any attempts
7923+
// to forward through that channel.
7924+
let chanmon_cfgs = create_chanmon_cfgs(3);
7925+
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
7926+
let mut no_announce_cfg = test_default_channel_config();
7927+
no_announce_cfg.channel_options.announced_channel = false;
7928+
no_announce_cfg.accept_forwards_to_priv_channels = false;
7929+
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(no_announce_cfg), None]);
7930+
let persister: test_utils::TestPersister;
7931+
let new_chain_monitor: test_utils::TestChainMonitor;
7932+
let nodes_1_deserialized: ChannelManager<EnforcingSigner, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
7933+
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
7934+
7935+
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000, InitFeatures::known(), InitFeatures::known());
7936+
7937+
// Note that the create_*_chan functions in utils requires announcement_signatures, which we do
7938+
// not send for private channels.
7939+
nodes[1].node.create_channel(nodes[2].node.get_our_node_id(), 1_000_000, 500_000_000, 42, None).unwrap();
7940+
let open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[2].node.get_our_node_id());
7941+
nodes[2].node.handle_open_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &open_channel);
7942+
let accept_channel = get_event_msg!(nodes[2], MessageSendEvent::SendAcceptChannel, nodes[1].node.get_our_node_id());
7943+
nodes[1].node.handle_accept_channel(&nodes[2].node.get_our_node_id(), InitFeatures::known(), &accept_channel);
7944+
7945+
let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[1], 1_000_000, 42);
7946+
nodes[1].node.funding_transaction_generated(&temporary_channel_id, tx.clone()).unwrap();
7947+
nodes[2].node.handle_funding_created(&nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendFundingCreated, nodes[2].node.get_our_node_id()));
7948+
check_added_monitors!(nodes[2], 1);
7949+
7950+
nodes[1].node.handle_funding_signed(&nodes[2].node.get_our_node_id(), &get_event_msg!(nodes[2], MessageSendEvent::SendFundingSigned, nodes[1].node.get_our_node_id()));
7951+
check_added_monitors!(nodes[1], 1);
7952+
7953+
let conf_height = core::cmp::max(nodes[1].best_block_info().1 + 1, nodes[2].best_block_info().1 + 1);
7954+
confirm_transaction_at(&nodes[1], &tx, conf_height);
7955+
connect_blocks(&nodes[1], CHAN_CONFIRM_DEPTH - 1);
7956+
confirm_transaction_at(&nodes[2], &tx, conf_height);
7957+
connect_blocks(&nodes[2], CHAN_CONFIRM_DEPTH - 1);
7958+
let as_funding_locked = get_event_msg!(nodes[1], MessageSendEvent::SendFundingLocked, nodes[2].node.get_our_node_id());
7959+
nodes[1].node.handle_funding_locked(&nodes[2].node.get_our_node_id(), &get_event_msg!(nodes[2], MessageSendEvent::SendFundingLocked, nodes[1].node.get_our_node_id()));
7960+
get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[2].node.get_our_node_id());
7961+
nodes[2].node.handle_funding_locked(&nodes[1].node.get_our_node_id(), &as_funding_locked);
7962+
get_event_msg!(nodes[2], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id());
7963+
7964+
assert!(nodes[0].node.list_usable_channels()[0].is_public);
7965+
assert_eq!(nodes[1].node.list_usable_channels().len(), 2);
7966+
assert!(!nodes[2].node.list_usable_channels()[0].is_public);
7967+
7968+
// We should always be able to forward through nodes[1] as long as its out through a public
7969+
// channel:
7970+
send_payment(&nodes[2], &[&nodes[1], &nodes[0]], 10_000);
7971+
7972+
// ... however, if we send to nodes[2], we will have to pass the private channel from nodes[1]
7973+
// to nodes[2], which should be rejected:
7974+
let (our_payment_preimage, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[2]);
7975+
let route = get_route(&nodes[0].node.get_our_node_id(),
7976+
&nodes[0].net_graph_msg_handler.network_graph.read().unwrap(),
7977+
&nodes[2].node.get_our_node_id(), Some(InvoiceFeatures::known()), None,
7978+
&[&RouteHint(vec![RouteHintHop {
7979+
src_node_id: nodes[1].node.get_our_node_id(),
7980+
short_channel_id: nodes[2].node.list_channels()[0].short_channel_id.unwrap(),
7981+
fees: RoutingFees { base_msat: 1000, proportional_millionths: 0 },
7982+
cltv_expiry_delta: MIN_CLTV_EXPIRY_DELTA,
7983+
htlc_minimum_msat: None,
7984+
htlc_maximum_msat: None,
7985+
}])], 10_000, TEST_FINAL_CLTV, nodes[0].logger).unwrap();
7986+
7987+
nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
7988+
check_added_monitors!(nodes[0], 1);
7989+
let payment_event = SendEvent::from_event(nodes[0].node.get_and_clear_pending_msg_events().remove(0));
7990+
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
7991+
commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false, true);
7992+
7993+
let htlc_fail_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
7994+
assert!(htlc_fail_updates.update_add_htlcs.is_empty());
7995+
assert_eq!(htlc_fail_updates.update_fail_htlcs.len(), 1);
7996+
assert!(htlc_fail_updates.update_fail_malformed_htlcs.is_empty());
7997+
assert!(htlc_fail_updates.update_fee.is_none());
7998+
7999+
nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &htlc_fail_updates.update_fail_htlcs[0]);
8000+
commitment_signed_dance!(nodes[0], nodes[1], htlc_fail_updates.commitment_signed, true, true);
8001+
expect_payment_failed!(nodes[0], our_payment_hash, false);
8002+
expect_payment_failure_chan_update!(nodes[0], nodes[2].node.list_channels()[0].short_channel_id.unwrap(), true);
8003+
8004+
// Now disconnect nodes[1] from its peers and restart with accept_forwards_to_priv_channels set
8005+
// to true. Sadly there is currently no way to change it at runtime.
8006+
8007+
nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
8008+
nodes[2].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
8009+
8010+
let nodes_1_serialized = nodes[1].node.encode();
8011+
let mut monitor_a_serialized = test_utils::TestVecWriter(Vec::new());
8012+
let mut monitor_b_serialized = test_utils::TestVecWriter(Vec::new());
8013+
{
8014+
let mons = nodes[1].chain_monitor.chain_monitor.monitors.read().unwrap();
8015+
let mut mon_iter = mons.iter();
8016+
mon_iter.next().unwrap().1.write(&mut monitor_a_serialized).unwrap();
8017+
mon_iter.next().unwrap().1.write(&mut monitor_b_serialized).unwrap();
8018+
}
8019+
8020+
persister = test_utils::TestPersister::new();
8021+
let keys_manager = &chanmon_cfgs[1].keys_manager;
8022+
new_chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[1].chain_source), nodes[1].tx_broadcaster.clone(), nodes[1].logger, node_cfgs[1].fee_estimator, &persister, keys_manager);
8023+
nodes[1].chain_monitor = &new_chain_monitor;
8024+
8025+
let mut monitor_a_read = &monitor_a_serialized.0[..];
8026+
let mut monitor_b_read = &monitor_b_serialized.0[..];
8027+
let (_, mut monitor_a) = <(BlockHash, ChannelMonitor<EnforcingSigner>)>::read(&mut monitor_a_read, keys_manager).unwrap();
8028+
let (_, mut monitor_b) = <(BlockHash, ChannelMonitor<EnforcingSigner>)>::read(&mut monitor_b_read, keys_manager).unwrap();
8029+
assert!(monitor_a_read.is_empty());
8030+
assert!(monitor_b_read.is_empty());
8031+
8032+
no_announce_cfg.accept_forwards_to_priv_channels = true;
8033+
8034+
let mut nodes_1_read = &nodes_1_serialized[..];
8035+
let (_, nodes_1_deserialized_tmp) = {
8036+
let mut channel_monitors = HashMap::new();
8037+
channel_monitors.insert(monitor_a.get_funding_txo().0, &mut monitor_a);
8038+
channel_monitors.insert(monitor_b.get_funding_txo().0, &mut monitor_b);
8039+
<(BlockHash, ChannelManager<EnforcingSigner, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>)>::read(&mut nodes_1_read, ChannelManagerReadArgs {
8040+
default_config: no_announce_cfg,
8041+
keys_manager,
8042+
fee_estimator: node_cfgs[1].fee_estimator,
8043+
chain_monitor: nodes[1].chain_monitor,
8044+
tx_broadcaster: nodes[1].tx_broadcaster.clone(),
8045+
logger: nodes[1].logger,
8046+
channel_monitors,
8047+
}).unwrap()
8048+
};
8049+
assert!(nodes_1_read.is_empty());
8050+
nodes_1_deserialized = nodes_1_deserialized_tmp;
8051+
8052+
assert!(nodes[1].chain_monitor.watch_channel(monitor_a.get_funding_txo().0, monitor_a).is_ok());
8053+
assert!(nodes[1].chain_monitor.watch_channel(monitor_b.get_funding_txo().0, monitor_b).is_ok());
8054+
check_added_monitors!(nodes[1], 2);
8055+
nodes[1].node = &nodes_1_deserialized;
8056+
8057+
nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::known() });
8058+
nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
8059+
let as_reestablish = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReestablish, nodes[1].node.get_our_node_id());
8060+
let bs_reestablish = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
8061+
nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &as_reestablish);
8062+
nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reestablish);
8063+
get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id());
8064+
get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[0].node.get_our_node_id());
8065+
8066+
nodes[1].node.peer_connected(&nodes[2].node.get_our_node_id(), &msgs::Init { features: InitFeatures::known() });
8067+
nodes[2].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
8068+
let bs_reestablish = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[2].node.get_our_node_id());
8069+
let cs_reestablish = get_event_msg!(nodes[2], MessageSendEvent::SendChannelReestablish, nodes[1].node.get_our_node_id());
8070+
nodes[2].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reestablish);
8071+
nodes[1].node.handle_channel_reestablish(&nodes[2].node.get_our_node_id(), &cs_reestablish);
8072+
get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[2].node.get_our_node_id());
8073+
get_event_msg!(nodes[2], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id());
8074+
8075+
nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
8076+
check_added_monitors!(nodes[0], 1);
8077+
pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], 10_000, our_payment_hash, our_payment_secret);
8078+
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], our_payment_preimage);
8079+
}
8080+
79188081
#[test]
79198082
fn test_bump_penalty_txn_on_revoked_commitment() {
79208083
// In case of penalty txn with too low feerates for getting into mempools, RBF-bump them to be sure

lightning/src/util/config.rs

+26-5
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,14 @@ pub struct ChannelHandshakeLimits {
105105
///
106106
/// Default value: 144, or roughly one day and only applies to outbound channels.
107107
pub max_minimum_depth: u32,
108-
/// Set to force the incoming channel to match our announced channel preference in
109-
/// ChannelConfig.
108+
/// Set to force an incoming channel to match our announced channel preference in
109+
/// [`ChannelConfig::announced_channel`].
110110
///
111-
/// Default value: true, to make the default that no announced channels are possible (which is
112-
/// appropriate for any nodes which are not online very reliably).
111+
/// For a node which is not online reliably, this should be set to true and
112+
/// [`ChannelConfig::announced_channel`] set to false, ensuring that no announced (aka public)
113+
/// channels will ever be opened.
114+
///
115+
/// Default value: true.
113116
pub force_announced_channel_preference: bool,
114117
/// Set to the amount of time we're willing to wait to claim money back to us.
115118
///
@@ -186,7 +189,7 @@ pub struct ChannelConfig {
186189
/// This should only be set to true for nodes which expect to be online reliably.
187190
///
188191
/// As the node which funds a channel picks this value this will only apply for new outbound
189-
/// channels unless ChannelHandshakeLimits::force_announced_channel_preferences is set.
192+
/// channels unless [`ChannelHandshakeLimits::force_announced_channel_preference`] is set.
190193
///
191194
/// This cannot be changed after the initial channel handshake.
192195
///
@@ -239,6 +242,23 @@ pub struct UserConfig {
239242
pub peer_channel_config_limits: ChannelHandshakeLimits,
240243
/// Channel config which affects behavior during channel lifetime.
241244
pub channel_options: ChannelConfig,
245+
/// If this is set to false, we will reject any HTLCs which were to be forwarded over private
246+
/// channels. This prevents us from taking on HTLC-forwarding risk when we intend to run as a
247+
/// node which is not online reliably.
248+
///
249+
/// For nodes which are not online reliably, you should set all channels to *not* be announced
250+
/// (using [`ChannelConfig::announced_channel`] and
251+
/// [`ChannelHandshakeLimits::force_announced_channel_preference`]) and set this to false to
252+
/// ensure you are not exposed to any forwarding risk.
253+
///
254+
/// Note that because you cannot change a channel's announced state after creation, there is no
255+
/// way to disable forwarding on public channels retroactively. Thus, in order to change a node
256+
/// from a publicly-announced forwarding node to a private non-forwarding node you must close
257+
/// all your channels and open new ones. For privacy, you should also change your node_id
258+
/// (swapping all private and public key material for new ones) at that time.
259+
///
260+
/// Default value: false.
261+
pub accept_forwards_to_priv_channels: bool,
242262
}
243263

244264
impl Default for UserConfig {
@@ -247,6 +267,7 @@ impl Default for UserConfig {
247267
own_channel_config: ChannelHandshakeConfig::default(),
248268
peer_channel_config_limits: ChannelHandshakeLimits::default(),
249269
channel_options: ChannelConfig::default(),
270+
accept_forwards_to_priv_channels: false,
250271
}
251272
}
252273
}

0 commit comments

Comments
 (0)