@@ -424,21 +424,25 @@ pub async fn serve_leios_fetch(lf_send: CodecSend, lf_recv: CodecRecv, store: Ar
424424 match msg {
425425 LfMsg :: MsgLeiosBlockRequest { point } => {
426426 let block = match & point {
427- Point :: Specific { slot, hash } => {
428- store. get_block ( * slot, hash) . unwrap_or_default ( )
429- }
430- Point :: Origin => Vec :: new ( ) ,
427+ Point :: Specific { slot, hash } => store. get_block ( * slot, hash) ,
428+ Point :: Origin => None ,
429+ } ;
430+ let Some ( block) = block else {
431+ // CIP-0164: server should disconnect if it doesn't have the requested EB.
432+ break ;
431433 } ;
432434 if runner. send ( & LfMsg :: MsgLeiosBlock { block } ) . await . is_err ( ) {
433435 break ;
434436 }
435437 }
436438 LfMsg :: MsgLeiosBlockTxsRequest { point, bitmap : _ } => {
437439 let transactions = match & point {
438- Point :: Specific { slot, hash } => {
439- store. get_block_txs ( * slot, hash) . unwrap_or_default ( )
440- }
441- Point :: Origin => Vec :: new ( ) ,
440+ Point :: Specific { slot, hash } => store. get_block_txs ( * slot, hash) ,
441+ Point :: Origin => None ,
442+ } ;
443+ let Some ( transactions) = transactions else {
444+ // CIP-0164: server should disconnect if it doesn't have the requested EB txs.
445+ break ;
442446 } ;
443447 if runner
444448 . send ( & LfMsg :: MsgLeiosBlockTxs { transactions } )
@@ -732,4 +736,83 @@ mod tests {
732736 mux_a. abort ( ) ;
733737 mux_b. abort ( ) ;
734738 }
739+
740+ #[ tokio:: test]
741+ async fn leios_fetch_disconnects_on_missing_block ( ) {
742+ let lf_proto = ProtocolConfig {
743+ id : leios_fetch:: PROTOCOL_ID ,
744+ traffic_class : TrafficClass :: Priority ,
745+ ingress_limit : leios_fetch:: INGRESS_LIMIT ,
746+ egress_queue_size : 16 ,
747+ } ;
748+
749+ let ( ( client_send, client_recv) , ( server_send, server_recv) , mux_a, mux_b) =
750+ mux_pair_for_protocol ( & lf_proto) ;
751+
752+ // Empty store — no blocks injected.
753+ let ( store, _rx) = LeiosStore :: new ( 100 ) ;
754+
755+ let server_handle = tokio:: spawn ( serve_leios_fetch ( server_send, server_recv, store) ) ;
756+
757+ // Client: request a block that doesn't exist.
758+ let mut client = Runner :: < LeiosFetch > :: new ( Role :: Client , client_send, client_recv) ;
759+ let result = leios_fetch:: fetch_block (
760+ & mut client,
761+ Point :: Specific {
762+ slot : 99 ,
763+ hash : [ 0xFF ; 32 ] ,
764+ } ,
765+ )
766+ . await ;
767+
768+ // Server should have disconnected — client sees an error.
769+ assert ! (
770+ result. is_err( ) ,
771+ "expected error from disconnect, got {result:?}"
772+ ) ;
773+
774+ server_handle. await . ok ( ) ;
775+ mux_a. abort ( ) ;
776+ mux_b. abort ( ) ;
777+ }
778+
779+ #[ tokio:: test]
780+ async fn leios_fetch_disconnects_on_missing_block_txs ( ) {
781+ let lf_proto = ProtocolConfig {
782+ id : leios_fetch:: PROTOCOL_ID ,
783+ traffic_class : TrafficClass :: Priority ,
784+ ingress_limit : leios_fetch:: INGRESS_LIMIT ,
785+ egress_queue_size : 16 ,
786+ } ;
787+
788+ let ( ( client_send, client_recv) , ( server_send, server_recv) , mux_a, mux_b) =
789+ mux_pair_for_protocol ( & lf_proto) ;
790+
791+ // Empty store — no block txs injected.
792+ let ( store, _rx) = LeiosStore :: new ( 100 ) ;
793+
794+ let server_handle = tokio:: spawn ( serve_leios_fetch ( server_send, server_recv, store) ) ;
795+
796+ // Client: request txs for a block that doesn't exist.
797+ let mut client = Runner :: < LeiosFetch > :: new ( Role :: Client , client_send, client_recv) ;
798+ let result = leios_fetch:: fetch_block_txs (
799+ & mut client,
800+ Point :: Specific {
801+ slot : 99 ,
802+ hash : [ 0xFF ; 32 ] ,
803+ } ,
804+ std:: collections:: BTreeMap :: new ( ) ,
805+ )
806+ . await ;
807+
808+ // Server should have disconnected — client sees an error.
809+ assert ! (
810+ result. is_err( ) ,
811+ "expected error from disconnect, got {result:?}"
812+ ) ;
813+
814+ server_handle. await . ok ( ) ;
815+ mux_a. abort ( ) ;
816+ mux_b. abort ( ) ;
817+ }
735818}
0 commit comments