LSPS2: Prune empty PeerStates

In addition to pruning expired requests on peer disconnection we also
regularly prune for all peers on block connection, and also remove the
entire `PeerState` if it's empty after pruning (i.e., has no pending
requsts or in-flight channels left).
This commit is contained in:
Elias Rohrer 2024-12-11 13:45:31 +01:00
parent 776ede44cb
commit 440962e4fe
No known key found for this signature in database
GPG key ID: 36153082BDF676FD
2 changed files with 30 additions and 5 deletions

View file

@ -474,7 +474,7 @@ impl PeerState {
self.outbound_channels_by_intercept_scid.insert(intercept_scid, channel);
}
fn peer_disconnected(&mut self) {
fn prune_expired_request_state(&mut self) {
self.pending_requests.retain(|_, entry| {
match entry {
LSPS2Request::GetInfo(_) => false,
@ -495,6 +495,11 @@ impl PeerState {
true
});
}
fn is_prunable(&self) -> bool {
// Return whether the entire state is empty.
self.pending_requests.is_empty() && self.outbound_channels_by_intercept_scid.is_empty()
}
}
/// The main object allowing to send and receive LSPS2 messages.
@ -1270,12 +1275,29 @@ where
}
pub(crate) fn peer_disconnected(&self, counterparty_node_id: PublicKey) {
let outer_state_lock = self.per_peer_state.write().unwrap();
let mut outer_state_lock = self.per_peer_state.write().unwrap();
let is_prunable =
if let Some(inner_state_lock) = outer_state_lock.get(&counterparty_node_id) {
let mut peer_state_lock = inner_state_lock.lock().unwrap();
peer_state_lock.peer_disconnected();
peer_state_lock.prune_expired_request_state();
peer_state_lock.is_prunable()
} else {
return;
};
if is_prunable {
outer_state_lock.remove(&counterparty_node_id);
}
}
#[allow(clippy::bool_comparison)]
pub(crate) fn prune_peer_state(&self) {
let mut outer_state_lock = self.per_peer_state.write().unwrap();
outer_state_lock.retain(|_, inner_state_lock| {
let mut peer_state_lock = inner_state_lock.lock().unwrap();
peer_state_lock.prune_expired_request_state();
peer_state_lock.is_prunable() == false
});
}
}
impl<CM: Deref + Clone> ProtocolMessageHandler for LSPS2ServiceHandler<CM>

View file

@ -684,6 +684,9 @@ where
fn best_block_updated(&self, _header: &bitcoin::block::Header, _height: u32) {
// TODO: Call best_block_updated on all sub-modules that require it, e.g., LSPS1MessageHandler.
if let Some(lsps2_service_handler) = self.lsps2_service_handler.as_ref() {
lsps2_service_handler.prune_peer_state();
}
}
fn get_relevant_txids(&self) -> Vec<(bitcoin::Txid, u32, Option<bitcoin::BlockHash>)> {