Skip to content

Commit ac7be89

Browse files
committed
EventHandler decorator for applying NetworkUpdate
PaymentFailed events contain an optional NetworkUpdate describing changes to the NetworkGraph as conveyed by a node along a failed payment path according to BOLT 4. An EventHandler should apply the update to the graph so that future routing decisions can account for it. Provide an EventHandler decorator that updates the NetworkGraph and then delegates Event handling to the decorated EventHandler. Previously, NetGraphMsgHandler::handle_htlc_fail_channel_update implemented this behavior.
1 parent 6499adf commit ac7be89

File tree

1 file changed

+138
-29
lines changed

1 file changed

+138
-29
lines changed

lightning/src/routing/network_graph.rs

+138-29
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use ln::msgs::{QueryChannelRange, ReplyChannelRange, QueryShortChannelIds, Reply
2929
use ln::msgs;
3030
use util::ser::{Writeable, Readable, Writer};
3131
use util::logger::{Logger, Level};
32-
use util::events::{MessageSendEvent, MessageSendEventsProvider};
32+
use util::events::{Event, EventHandler, MessageSendEvent, MessageSendEventsProvider};
3333
use util::scid_utils::{block_from_scid, scid_from_parts, MAX_SCID_BLOCK};
3434

3535
use io;
@@ -103,6 +103,66 @@ impl_writeable_tlv_based_enum!(NetworkUpdate,
103103
},
104104
;);
105105

106+
/// An [`EventHandler`] decorator for applying updates from [`Event::PaymentFailed`] to the
107+
/// [`NetworkGraph`].
108+
pub struct NetworkUpdateHandler<G: Deref<Target=NetworkGraph>, L: Deref, E: EventHandler>
109+
where L::Target: Logger {
110+
secp_ctx: Secp256k1<secp256k1::VerifyOnly>,
111+
network_graph: G,
112+
logger: L,
113+
inner: E,
114+
}
115+
116+
impl<G: Deref<Target=NetworkGraph>, L: Deref, E: EventHandler> NetworkUpdateHandler<G, L, E>
117+
where L::Target: Logger {
118+
/// Creates a handler that decorates `event_handler` with functionality for updating the given
119+
/// `network_graph`.
120+
pub fn new(network_graph: G, logger: L, event_handler: E) -> Self {
121+
Self {
122+
secp_ctx: Secp256k1::verification_only(),
123+
network_graph,
124+
logger,
125+
inner: event_handler,
126+
}
127+
}
128+
129+
/// Applies changes to the [`NetworkGraph`] from the given update.
130+
fn handle_network_update(&self, update: &NetworkUpdate) {
131+
match *update {
132+
NetworkUpdate::ChannelUpdateMessage { ref msg } => {
133+
let short_channel_id = msg.contents.short_channel_id;
134+
let is_enabled = msg.contents.flags & (1 << 1) != (1 << 1);
135+
let status = if is_enabled { "enabled" } else { "disabled" };
136+
log_debug!(self.logger, "Updating channel with channel_update from a payment failure. Channel {} is {}.", short_channel_id, status);
137+
let _ = self.network_graph.update_channel(msg, &self.secp_ctx);
138+
},
139+
NetworkUpdate::ChannelClosed { short_channel_id, is_permanent } => {
140+
let action = if is_permanent { "Removing" } else { "Disabling" };
141+
log_debug!(self.logger, "{} channel graph entry for {} due to a payment failure.", action, short_channel_id);
142+
self.network_graph.close_channel_from_update(short_channel_id, is_permanent);
143+
},
144+
NetworkUpdate::NodeFailure { ref node_id, is_permanent } => {
145+
let action = if is_permanent { "Removing" } else { "Disabling" };
146+
log_debug!(self.logger, "{} node graph entry for {} due to a payment failure.", action, node_id);
147+
self.network_graph.fail_node(node_id, is_permanent);
148+
},
149+
}
150+
}
151+
}
152+
153+
impl<G: Deref<Target=NetworkGraph>, L: Deref, E: EventHandler> EventHandler for NetworkUpdateHandler<G, L, E>
154+
where L::Target: Logger {
155+
fn handle_event(&self, event: Event) {
156+
if let Event::PaymentFailed { payment_hash: _, rejected_by_dest: _, network_update, .. } = &event {
157+
if let Some(network_update) = network_update {
158+
self.handle_network_update(network_update);
159+
}
160+
}
161+
162+
self.inner.handle_event(event)
163+
}
164+
}
165+
106166
/// Receives and validates network updates from peers,
107167
/// stores authentic and relevant data as a network graph.
108168
/// This network graph is then used for routing payments.
@@ -1088,15 +1148,16 @@ impl NetworkGraph {
10881148
#[cfg(test)]
10891149
mod tests {
10901150
use chain;
1151+
use ln::PaymentHash;
10911152
use ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
1092-
use routing::network_graph::{NetGraphMsgHandler, NetworkGraph, MAX_EXCESS_BYTES_FOR_RELAY};
1153+
use routing::network_graph::{NetGraphMsgHandler, NetworkGraph, NetworkUpdate, NetworkUpdateHandler, MAX_EXCESS_BYTES_FOR_RELAY};
10931154
use ln::msgs::{Init, OptionalField, RoutingMessageHandler, UnsignedNodeAnnouncement, NodeAnnouncement,
10941155
UnsignedChannelAnnouncement, ChannelAnnouncement, UnsignedChannelUpdate, ChannelUpdate,
10951156
ReplyChannelRange, ReplyShortChannelIdsEnd, QueryChannelRange, QueryShortChannelIds, MAX_VALUE_MSAT};
10961157
use util::test_utils;
10971158
use util::logger::Logger;
10981159
use util::ser::{Readable, Writeable};
1099-
use util::events::{MessageSendEvent, MessageSendEventsProvider};
1160+
use util::events::{Event, EventHandler, MessageSendEvent, MessageSendEventsProvider};
11001161
use util::scid_utils::scid_from_parts;
11011162

11021163
use bitcoin::hashes::sha256d::Hash as Sha256dHash;
@@ -1593,8 +1654,13 @@ mod tests {
15931654
}
15941655

15951656
#[test]
1596-
fn handling_htlc_fail_channel_update() {
1597-
let (secp_ctx, net_graph_msg_handler) = create_net_graph_msg_handler();
1657+
fn handling_network_update() {
1658+
let logger = test_utils::TestLogger::new();
1659+
let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
1660+
let network_graph = NetworkGraph::new(genesis_hash);
1661+
let handler = NetworkUpdateHandler::new(&network_graph, &logger, |_| {});
1662+
let secp_ctx = Secp256k1::new();
1663+
15981664
let node_1_privkey = &SecretKey::from_slice(&[42; 32]).unwrap();
15991665
let node_2_privkey = &SecretKey::from_slice(&[41; 32]).unwrap();
16001666
let node_id_1 = PublicKey::from_secret_key(&secp_ctx, node_1_privkey);
@@ -1607,8 +1673,7 @@ mod tests {
16071673

16081674
{
16091675
// There is no nodes in the table at the beginning.
1610-
let network = &net_graph_msg_handler.network_graph;
1611-
assert_eq!(network.get_nodes().len(), 0);
1676+
assert_eq!(network_graph.get_nodes().len(), 0);
16121677
}
16131678

16141679
{
@@ -1632,10 +1697,9 @@ mod tests {
16321697
bitcoin_signature_2: secp_ctx.sign(&msghash, node_2_btckey),
16331698
contents: unsigned_announcement.clone(),
16341699
};
1635-
match net_graph_msg_handler.handle_channel_announcement(&valid_channel_announcement) {
1636-
Ok(_) => (),
1637-
Err(_) => panic!()
1638-
};
1700+
let chain_source: Option<&test_utils::TestChainSource> = None;
1701+
assert!(network_graph.update_channel_from_announcement(&valid_channel_announcement, &chain_source, &secp_ctx).is_ok());
1702+
assert!(network_graph.get_channels().get(&short_channel_id).is_some());
16391703

16401704
let unsigned_channel_update = UnsignedChannelUpdate {
16411705
chain_hash,
@@ -1655,44 +1719,65 @@ mod tests {
16551719
contents: unsigned_channel_update.clone()
16561720
};
16571721

1658-
match net_graph_msg_handler.handle_channel_update(&valid_channel_update) {
1659-
Ok(res) => assert!(res),
1660-
_ => panic!()
1661-
};
1722+
assert!(network_graph.get_channels().get(&short_channel_id).unwrap().one_to_two.is_none());
1723+
1724+
handler.handle_event(Event::PaymentFailed {
1725+
payment_hash: PaymentHash([0; 32]),
1726+
rejected_by_dest: false,
1727+
network_update: Some(NetworkUpdate::ChannelUpdateMessage {
1728+
msg: valid_channel_update,
1729+
}),
1730+
error_code: None,
1731+
error_data: None,
1732+
});
1733+
1734+
assert!(network_graph.get_channels().get(&short_channel_id).unwrap().one_to_two.is_some());
16621735
}
16631736

16641737
// Non-permanent closing just disables a channel
16651738
{
1666-
let network = &net_graph_msg_handler.network_graph;
1667-
match network.get_channels().get(&short_channel_id) {
1739+
match network_graph.get_channels().get(&short_channel_id) {
16681740
None => panic!(),
16691741
Some(channel_info) => {
1670-
assert!(channel_info.one_to_two.is_some());
1742+
assert!(channel_info.one_to_two.as_ref().unwrap().enabled);
16711743
}
16721744
};
1673-
}
16741745

1675-
net_graph_msg_handler.network_graph.close_channel_from_update(short_channel_id, false);
1746+
handler.handle_event(Event::PaymentFailed {
1747+
payment_hash: PaymentHash([0; 32]),
1748+
rejected_by_dest: false,
1749+
network_update: Some(NetworkUpdate::ChannelClosed {
1750+
short_channel_id,
1751+
is_permanent: false,
1752+
}),
1753+
error_code: None,
1754+
error_data: None,
1755+
});
16761756

1677-
// Non-permanent closing just disables a channel
1678-
{
1679-
let network = &net_graph_msg_handler.network_graph;
1680-
match network.get_channels().get(&short_channel_id) {
1757+
match network_graph.get_channels().get(&short_channel_id) {
16811758
None => panic!(),
16821759
Some(channel_info) => {
16831760
assert!(!channel_info.one_to_two.as_ref().unwrap().enabled);
16841761
}
16851762
};
16861763
}
16871764

1688-
net_graph_msg_handler.network_graph.close_channel_from_update(short_channel_id, true);
1689-
16901765
// Permanent closing deletes a channel
16911766
{
1692-
let network = &net_graph_msg_handler.network_graph;
1693-
assert_eq!(network.get_channels().len(), 0);
1767+
handler.handle_event(Event::PaymentFailed {
1768+
payment_hash: PaymentHash([0; 32]),
1769+
rejected_by_dest: false,
1770+
network_update: Some(NetworkUpdate::ChannelClosed {
1771+
short_channel_id,
1772+
is_permanent: true,
1773+
}),
1774+
error_code: None,
1775+
error_data: None,
1776+
});
1777+
1778+
assert_eq!(network_graph.get_channels().len(), 0);
16941779
// Nodes are also deleted because there are no associated channels anymore
1695-
assert_eq!(network.get_nodes().len(), 0);
1780+
assert_eq!(network_graph.get_nodes().len(), 0);
16961781
}
16971782
// TODO: Test NetworkUpdate::NodeFailure, which is not implemented yet.
16981783
}
@@ -2473,6 +2558,30 @@ mod tests {
24732558
});
24742559
assert!(result.is_err());
24752560
}
2561+
2562+
#[test]
2563+
fn delegates_to_decorated_event_handler() {
2564+
let event_handled = core::cell::RefCell::new(false);
2565+
2566+
{
2567+
let logger = test_utils::TestLogger::new();
2568+
let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
2569+
let network_graph = NetworkGraph::new(genesis_hash);
2570+
2571+
let handler = NetworkUpdateHandler::new(&network_graph, &logger, |_| {
2572+
*event_handled.borrow_mut() = true;
2573+
});
2574+
handler.handle_event(Event::PaymentFailed {
2575+
payment_hash: PaymentHash([0; 32]),
2576+
rejected_by_dest: false,
2577+
network_update: None,
2578+
error_code: None,
2579+
error_data: None,
2580+
});
2581+
}
2582+
2583+
assert!(event_handled.into_inner());
2584+
}
24762585
}
24772586

24782587
#[cfg(all(test, feature = "unstable"))]

0 commit comments

Comments
 (0)