Skip to content

Commit f423ae2

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 ae96c7d commit f423ae2

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;
@@ -110,6 +110,66 @@ impl_writeable_tlv_based_enum_upgradable!(NetworkUpdate,
110110
},
111111
);
112112

113+
/// An [`EventHandler`] decorator for applying updates from [`Event::PaymentFailed`] to the
114+
/// [`NetworkGraph`].
115+
pub struct NetworkUpdateHandler<G: Deref<Target=NetworkGraph>, L: Deref, E: EventHandler>
116+
where L::Target: Logger {
117+
secp_ctx: Secp256k1<secp256k1::VerifyOnly>,
118+
network_graph: G,
119+
logger: L,
120+
inner: E,
121+
}
122+
123+
impl<G: Deref<Target=NetworkGraph>, L: Deref, E: EventHandler> NetworkUpdateHandler<G, L, E>
124+
where L::Target: Logger {
125+
/// Creates a handler that decorates `event_handler` with functionality for updating the given
126+
/// `network_graph`.
127+
pub fn new(network_graph: G, logger: L, event_handler: E) -> Self {
128+
Self {
129+
secp_ctx: Secp256k1::verification_only(),
130+
network_graph,
131+
logger,
132+
inner: event_handler,
133+
}
134+
}
135+
136+
/// Applies changes to the [`NetworkGraph`] from the given update.
137+
fn handle_network_update(&self, update: &NetworkUpdate) {
138+
match *update {
139+
NetworkUpdate::ChannelUpdateMessage { ref msg } => {
140+
let short_channel_id = msg.contents.short_channel_id;
141+
let is_enabled = msg.contents.flags & (1 << 1) != (1 << 1);
142+
let status = if is_enabled { "enabled" } else { "disabled" };
143+
log_debug!(self.logger, "Updating channel with channel_update from a payment failure. Channel {} is {}.", short_channel_id, status);
144+
let _ = self.network_graph.update_channel(msg, &self.secp_ctx);
145+
},
146+
NetworkUpdate::ChannelClosed { short_channel_id, is_permanent } => {
147+
let action = if is_permanent { "Removing" } else { "Disabling" };
148+
log_debug!(self.logger, "{} channel graph entry for {} due to a payment failure.", action, short_channel_id);
149+
self.network_graph.close_channel_from_update(short_channel_id, is_permanent);
150+
},
151+
NetworkUpdate::NodeFailure { ref node_id, is_permanent } => {
152+
let action = if is_permanent { "Removing" } else { "Disabling" };
153+
log_debug!(self.logger, "{} node graph entry for {} due to a payment failure.", action, node_id);
154+
self.network_graph.fail_node(node_id, is_permanent);
155+
},
156+
}
157+
}
158+
}
159+
160+
impl<G: Deref<Target=NetworkGraph>, L: Deref, E: EventHandler> EventHandler for NetworkUpdateHandler<G, L, E>
161+
where L::Target: Logger {
162+
fn handle_event(&self, event: &Event) {
163+
if let Event::PaymentFailed { payment_hash: _, rejected_by_dest: _, network_update, .. } = event {
164+
if let Some(network_update) = network_update {
165+
self.handle_network_update(network_update);
166+
}
167+
}
168+
169+
self.inner.handle_event(event)
170+
}
171+
}
172+
113173
/// Receives and validates network updates from peers,
114174
/// stores authentic and relevant data as a network graph.
115175
/// This network graph is then used for routing payments.
@@ -1109,15 +1169,16 @@ impl ReadOnlyNetworkGraph<'_> {
11091169
#[cfg(test)]
11101170
mod tests {
11111171
use chain;
1172+
use ln::PaymentHash;
11121173
use ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
1113-
use routing::network_graph::{NetGraphMsgHandler, NetworkGraph, MAX_EXCESS_BYTES_FOR_RELAY};
1174+
use routing::network_graph::{NetGraphMsgHandler, NetworkGraph, NetworkUpdate, NetworkUpdateHandler, MAX_EXCESS_BYTES_FOR_RELAY};
11141175
use ln::msgs::{Init, OptionalField, RoutingMessageHandler, UnsignedNodeAnnouncement, NodeAnnouncement,
11151176
UnsignedChannelAnnouncement, ChannelAnnouncement, UnsignedChannelUpdate, ChannelUpdate,
11161177
ReplyChannelRange, ReplyShortChannelIdsEnd, QueryChannelRange, QueryShortChannelIds, MAX_VALUE_MSAT};
11171178
use util::test_utils;
11181179
use util::logger::Logger;
11191180
use util::ser::{Readable, Writeable};
1120-
use util::events::{MessageSendEvent, MessageSendEventsProvider};
1181+
use util::events::{Event, EventHandler, MessageSendEvent, MessageSendEventsProvider};
11211182
use util::scid_utils::scid_from_parts;
11221183

11231184
use bitcoin::hashes::sha256d::Hash as Sha256dHash;
@@ -1614,8 +1675,13 @@ mod tests {
16141675
}
16151676

16161677
#[test]
1617-
fn handling_htlc_fail_channel_update() {
1618-
let (secp_ctx, net_graph_msg_handler) = create_net_graph_msg_handler();
1678+
fn handling_network_update() {
1679+
let logger = test_utils::TestLogger::new();
1680+
let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
1681+
let network_graph = NetworkGraph::new(genesis_hash);
1682+
let handler = NetworkUpdateHandler::new(&network_graph, &logger, |_: &_| {});
1683+
let secp_ctx = Secp256k1::new();
1684+
16191685
let node_1_privkey = &SecretKey::from_slice(&[42; 32]).unwrap();
16201686
let node_2_privkey = &SecretKey::from_slice(&[41; 32]).unwrap();
16211687
let node_id_1 = PublicKey::from_secret_key(&secp_ctx, node_1_privkey);
@@ -1628,8 +1694,7 @@ mod tests {
16281694

16291695
{
16301696
// There is no nodes in the table at the beginning.
1631-
let network = &net_graph_msg_handler.network_graph;
1632-
assert_eq!(network.read_only().nodes().len(), 0);
1697+
assert_eq!(network_graph.read_only().nodes().len(), 0);
16331698
}
16341699

16351700
{
@@ -1653,10 +1718,9 @@ mod tests {
16531718
bitcoin_signature_2: secp_ctx.sign(&msghash, node_2_btckey),
16541719
contents: unsigned_announcement.clone(),
16551720
};
1656-
match net_graph_msg_handler.handle_channel_announcement(&valid_channel_announcement) {
1657-
Ok(_) => (),
1658-
Err(_) => panic!()
1659-
};
1721+
let chain_source: Option<&test_utils::TestChainSource> = None;
1722+
assert!(network_graph.update_channel_from_announcement(&valid_channel_announcement, &chain_source, &secp_ctx).is_ok());
1723+
assert!(network_graph.read_only().channels().get(&short_channel_id).is_some());
16601724

16611725
let unsigned_channel_update = UnsignedChannelUpdate {
16621726
chain_hash,
@@ -1676,44 +1740,65 @@ mod tests {
16761740
contents: unsigned_channel_update.clone()
16771741
};
16781742

1679-
match net_graph_msg_handler.handle_channel_update(&valid_channel_update) {
1680-
Ok(res) => assert!(res),
1681-
_ => panic!()
1682-
};
1743+
assert!(network_graph.read_only().channels().get(&short_channel_id).unwrap().one_to_two.is_none());
1744+
1745+
handler.handle_event(&Event::PaymentFailed {
1746+
payment_hash: PaymentHash([0; 32]),
1747+
rejected_by_dest: false,
1748+
network_update: Some(NetworkUpdate::ChannelUpdateMessage {
1749+
msg: valid_channel_update,
1750+
}),
1751+
error_code: None,
1752+
error_data: None,
1753+
});
1754+
1755+
assert!(network_graph.read_only().channels().get(&short_channel_id).unwrap().one_to_two.is_some());
16831756
}
16841757

16851758
// Non-permanent closing just disables a channel
16861759
{
1687-
let network = &net_graph_msg_handler.network_graph;
1688-
match network.read_only().channels().get(&short_channel_id) {
1760+
match network_graph.read_only().channels().get(&short_channel_id) {
16891761
None => panic!(),
16901762
Some(channel_info) => {
1691-
assert!(channel_info.one_to_two.is_some());
1763+
assert!(channel_info.one_to_two.as_ref().unwrap().enabled);
16921764
}
16931765
};
1694-
}
16951766

1696-
net_graph_msg_handler.network_graph.close_channel_from_update(short_channel_id, false);
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: false,
1773+
}),
1774+
error_code: None,
1775+
error_data: None,
1776+
});
16971777

1698-
// Non-permanent closing just disables a channel
1699-
{
1700-
let network = &net_graph_msg_handler.network_graph;
1701-
match network.read_only().channels().get(&short_channel_id) {
1778+
match network_graph.read_only().channels().get(&short_channel_id) {
17021779
None => panic!(),
17031780
Some(channel_info) => {
17041781
assert!(!channel_info.one_to_two.as_ref().unwrap().enabled);
17051782
}
17061783
};
17071784
}
17081785

1709-
net_graph_msg_handler.network_graph.close_channel_from_update(short_channel_id, true);
1710-
17111786
// Permanent closing deletes a channel
17121787
{
1713-
let network = &net_graph_msg_handler.network_graph;
1714-
assert_eq!(network.read_only().channels().len(), 0);
1788+
handler.handle_event(&Event::PaymentFailed {
1789+
payment_hash: PaymentHash([0; 32]),
1790+
rejected_by_dest: false,
1791+
network_update: Some(NetworkUpdate::ChannelClosed {
1792+
short_channel_id,
1793+
is_permanent: true,
1794+
}),
1795+
error_code: None,
1796+
error_data: None,
1797+
});
1798+
1799+
assert_eq!(network_graph.read_only().channels().len(), 0);
17151800
// Nodes are also deleted because there are no associated channels anymore
1716-
assert_eq!(network.read_only().nodes().len(), 0);
1801+
assert_eq!(network_graph.read_only().nodes().len(), 0);
17171802
}
17181803
// TODO: Test NetworkUpdate::NodeFailure, which is not implemented yet.
17191804
}
@@ -2494,6 +2579,30 @@ mod tests {
24942579
});
24952580
assert!(result.is_err());
24962581
}
2582+
2583+
#[test]
2584+
fn delegates_to_decorated_event_handler() {
2585+
let event_handled = core::cell::RefCell::new(false);
2586+
2587+
{
2588+
let logger = test_utils::TestLogger::new();
2589+
let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
2590+
let network_graph = NetworkGraph::new(genesis_hash);
2591+
2592+
let handler = NetworkUpdateHandler::new(&network_graph, &logger, |_: &_| {
2593+
*event_handled.borrow_mut() = true;
2594+
});
2595+
handler.handle_event(&Event::PaymentFailed {
2596+
payment_hash: PaymentHash([0; 32]),
2597+
rejected_by_dest: false,
2598+
network_update: None,
2599+
error_code: None,
2600+
error_data: None,
2601+
});
2602+
}
2603+
2604+
assert!(event_handled.into_inner());
2605+
}
24972606
}
24982607

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

0 commit comments

Comments
 (0)