@@ -56,6 +56,12 @@ impl PeerState {
5656 pending_remove_webhook_requests : BoundedMap :: new ( MAX_PENDING_REQUESTS ) ,
5757 }
5858 }
59+
60+ fn is_empty ( & self ) -> bool {
61+ self . pending_set_webhook_requests . is_empty ( )
62+ && self . pending_list_webhooks_requests . is_empty ( )
63+ && self . pending_remove_webhook_requests . is_empty ( )
64+ }
5965}
6066
6167/// Client-side handler for the LSPS5 (bLIP-55) webhook registration protocol.
@@ -345,6 +351,19 @@ where
345351 }
346352 } ;
347353 self . with_peer_state ( * counterparty_node_id, handle_response) ;
354+
355+ let mut outer_state_lock = self . per_peer_state . write ( ) . unwrap ( ) ;
356+ let should_remove =
357+ if let Some ( peer_state_mutex) = outer_state_lock. get ( counterparty_node_id) {
358+ let peer_state = peer_state_mutex. lock ( ) . unwrap ( ) ;
359+ peer_state. is_empty ( )
360+ } else {
361+ false
362+ } ;
363+
364+ if should_remove {
365+ outer_state_lock. remove ( counterparty_node_id) ;
366+ }
348367 result
349368 }
350369}
@@ -461,36 +480,6 @@ mod tests {
461480 }
462481 }
463482
464- #[ test]
465- fn test_handle_response_clears_pending_state ( ) {
466- let ( client, _, _, peer, _) = setup_test_client ( ) ;
467-
468- let req_id = client
469- . set_webhook ( peer, "test-app" . to_string ( ) , "https://example.com/hook" . to_string ( ) )
470- . unwrap ( ) ;
471-
472- let response = LSPS5Response :: SetWebhook ( SetWebhookResponse {
473- num_webhooks : 1 ,
474- max_webhooks : 5 ,
475- no_change : false ,
476- } ) ;
477- let response_msg = LSPS5Message :: Response ( req_id. clone ( ) , response) ;
478-
479- {
480- let outer_state_lock = client. per_peer_state . read ( ) . unwrap ( ) ;
481- let peer_state = outer_state_lock. get ( & peer) . unwrap ( ) . lock ( ) . unwrap ( ) ;
482- assert ! ( peer_state. pending_set_webhook_requests. contains_key( & req_id) ) ;
483- }
484-
485- client. handle_message ( response_msg, & peer) . unwrap ( ) ;
486-
487- {
488- let outer_state_lock = client. per_peer_state . read ( ) . unwrap ( ) ;
489- let peer_state = outer_state_lock. get ( & peer) . unwrap ( ) . lock ( ) . unwrap ( ) ;
490- assert ! ( !peer_state. pending_set_webhook_requests. contains_key( & req_id) ) ;
491- }
492- }
493-
494483 #[ test]
495484 fn test_unknown_request_id_handling ( ) {
496485 let ( client, _message_queue, _, peer, _) = setup_test_client ( ) ;
@@ -552,4 +541,68 @@ mod tests {
552541 assert ! ( peer_state. pending_set_webhook_requests. contains_key( & new_req_id) ) ;
553542 }
554543 }
544+
545+ #[ test]
546+ fn test_peer_state_cleanup_and_recreation ( ) {
547+ let ( client, _, _, peer, _) = setup_test_client ( ) ;
548+
549+ let set_webhook_req_id = client
550+ . set_webhook ( peer, "test-app" . to_string ( ) , "https://example.com/hook" . to_string ( ) )
551+ . unwrap ( ) ;
552+
553+ let list_webhooks_req_id = client. list_webhooks ( peer) ;
554+
555+ {
556+ let state = client. per_peer_state . read ( ) . unwrap ( ) ;
557+ assert ! ( state. contains_key( & peer) ) ;
558+ let peer_state = state. get ( & peer) . unwrap ( ) . lock ( ) . unwrap ( ) ;
559+ assert ! ( peer_state. pending_set_webhook_requests. contains_key( & set_webhook_req_id) ) ;
560+ assert ! ( peer_state. pending_list_webhooks_requests. contains_key( & list_webhooks_req_id) ) ;
561+ }
562+
563+ let set_webhook_response = LSPS5Response :: SetWebhook ( SetWebhookResponse {
564+ num_webhooks : 1 ,
565+ max_webhooks : 5 ,
566+ no_change : false ,
567+ } ) ;
568+ let response_msg = LSPS5Message :: Response ( set_webhook_req_id. clone ( ) , set_webhook_response) ;
569+ // trigger cleanup but there is still a pending request
570+ // so the peer state should not be removed
571+ client. handle_message ( response_msg, & peer) . unwrap ( ) ;
572+
573+ {
574+ let state = client. per_peer_state . read ( ) . unwrap ( ) ;
575+ assert ! ( state. contains_key( & peer) ) ;
576+ let peer_state = state. get ( & peer) . unwrap ( ) . lock ( ) . unwrap ( ) ;
577+ assert ! ( !peer_state. pending_set_webhook_requests. contains_key( & set_webhook_req_id) ) ;
578+ assert ! ( peer_state. pending_list_webhooks_requests. contains_key( & list_webhooks_req_id) ) ;
579+ }
580+
581+ let list_webhooks_response =
582+ LSPS5Response :: ListWebhooks ( crate :: lsps5:: msgs:: ListWebhooksResponse {
583+ app_names : vec ! [ ] ,
584+ max_webhooks : 5 ,
585+ } ) ;
586+ let response_msg = LSPS5Message :: Response ( list_webhooks_req_id, list_webhooks_response) ;
587+
588+ // now the pending request is handled, so the peer state should be removed
589+ client. handle_message ( response_msg, & peer) . unwrap ( ) ;
590+
591+ {
592+ let state = client. per_peer_state . read ( ) . unwrap ( ) ;
593+ assert ! ( !state. contains_key( & peer) ) ;
594+ }
595+
596+ // check that it's possible to recreate the peer state by sending a new request
597+ let new_req_id = client
598+ . set_webhook ( peer, "test-app-2" . to_string ( ) , "https://example.com/hook2" . to_string ( ) )
599+ . unwrap ( ) ;
600+
601+ {
602+ let state = client. per_peer_state . read ( ) . unwrap ( ) ;
603+ assert ! ( state. contains_key( & peer) ) ;
604+ let peer_state = state. get ( & peer) . unwrap ( ) . lock ( ) . unwrap ( ) ;
605+ assert ! ( peer_state. pending_set_webhook_requests. contains_key( & new_req_id) ) ;
606+ }
607+ }
555608}
0 commit comments