From 2f61b641e525258925a6da535ddfbc908e93dd14 Mon Sep 17 00:00:00 2001 From: glyh Date: Fri, 24 Oct 2025 15:47:19 +0800 Subject: [PATCH 01/13] Lucy lib: Unify Node.{infra_id, id} -> Node.id --- .../test_executive/chain_reliability_test.ml | 4 ++-- .../test_executive/peers_reliability_test.ml | 6 ++--- src/app/test_executive/test_common.ml | 11 ++++------ src/app/test_executive/test_executive.ml | 6 ++--- .../integration_test_lib/event_router.ml | 2 +- .../graphql_polling_log_engine.ml | 6 ++--- src/lib/testing/integration_test_lib/intf.ml | 2 -- .../integration_test_lib/network_state.ml | 22 +++++++++---------- .../docker_network.ml | 2 -- 9 files changed, 27 insertions(+), 34 deletions(-) diff --git a/src/app/test_executive/chain_reliability_test.ml b/src/app/test_executive/chain_reliability_test.ml index 0a0290790aed..8c21ce6fbd97 100644 --- a/src/app/test_executive/chain_reliability_test.ml +++ b/src/app/test_executive/chain_reliability_test.ml @@ -54,12 +54,12 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct section "short bootstrap" (let%bind () = Node.stop node_c in [%log info] "%s stopped, will now wait for blocks to be produced" - (Node.infra_id node_c) ; + (Node.id node_c) ; let%bind _ = wait_for t (Wait_condition.blocks_to_be_produced 2) in let%bind () = Node.start ~fresh_state:true node_c in [%log info] "%s started again, will now wait for this node to initialize" - (Node.infra_id node_c) ; + (Node.id node_c) ; let%bind () = wait_for t (Wait_condition.node_to_initialize node_c) in wait_for t ( Wait_condition.nodes_to_synchronize [ node_a; node_b; node_c ] diff --git a/src/app/test_executive/peers_reliability_test.ml b/src/app/test_executive/peers_reliability_test.ml index 64e0fb6eb835..234aa7979147 100644 --- a/src/app/test_executive/peers_reliability_test.ml +++ b/src/app/test_executive/peers_reliability_test.ml @@ -44,7 +44,7 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct [ ( "peers" , `List (List.map (Core.String.Map.data all_mina_nodes) ~f:(fun n -> - `String (Node.infra_id n) ) ) ) + `String (Node.id n) ) ) ) ] ; let node_a = Core.String.Map.find_exn (Network.block_producers network) "node-a" @@ -176,7 +176,7 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct section "short bootstrap" (let%bind () = Node.stop node_c in [%log info] "%s stopped, will now wait for blocks to be produced" - (Node.infra_id node_c) ; + (Node.id node_c) ; let%bind () = wait_for t ( Wait_condition.blocks_to_be_produced 1 @@ -188,7 +188,7 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct let%bind () = Node.start ~fresh_state:true node_c in [%log info] "%s started again, will now wait for this node to initialize" - (Node.infra_id node_c) ; + (Node.id node_c) ; (* we've witnessed the loading of the node_c frontier on initialization so the event here must be the frontier loading on the node_c restart *) diff --git a/src/app/test_executive/test_common.ml b/src/app/test_executive/test_common.ml index 2312c4ca6e01..98db238ef9d0 100644 --- a/src/app/test_executive/test_common.ml +++ b/src/app/test_executive/test_common.ml @@ -86,7 +86,7 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct Malleable_error.hard_error_format "Node '%s' did not have a network keypair, if node is a block \ producer this should not happen" - (Engine.Network.Node.infra_id node) + (Engine.Network.Node.id node) let pub_key_of_node = make_get_key ~f:(fun nk -> @@ -157,10 +157,8 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct this property will only hold true on small networks *) let check_peer_connected_to_all_others ~nodes_by_peer_id ~peer_id ~connected_peers = - let get_node_infra_id p = - p - |> String.Map.find_exn nodes_by_peer_id - |> Engine.Network.Node.infra_id + let get_node_id p = + p |> String.Map.find_exn nodes_by_peer_id |> Engine.Network.Node.id in let expected_peers = nodes_by_peer_id |> String.Map.keys @@ -169,8 +167,7 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct Malleable_error.List.iter expected_peers ~f:(fun p -> let error = Printf.sprintf "node %s (id=%s) is not connected to node %s (id=%s)" - (get_node_infra_id peer_id) - peer_id (get_node_infra_id p) p + (get_node_id peer_id) peer_id (get_node_id p) p |> Error.of_string in Malleable_error.ok_if_true diff --git a/src/app/test_executive/test_executive.ml b/src/app/test_executive/test_executive.ml index 687bd5798c34..05a1f90a577a 100644 --- a/src/app/test_executive/test_executive.ml +++ b/src/app/test_executive/test_executive.ml @@ -386,9 +386,9 @@ let main inputs = [%log info] "Starting the daemons within the pods" ; let start_print (node : Engine.Network.Node.t) = let open Malleable_error.Let_syntax in - [%log info] "starting %s ..." (Engine.Network.Node.infra_id node) ; + [%log info] "starting %s ..." (Engine.Network.Node.id node) ; let%bind res = Engine.Network.Node.start ~fresh_state:false node in - [%log info] "%s started" (Engine.Network.Node.infra_id node) ; + [%log info] "%s started" (Engine.Network.Node.id node) ; Malleable_error.return res in let seed_nodes = @@ -403,7 +403,7 @@ let main inputs = *) Dsl.Event_router.on (Dsl.event_router dsl) Node_offline ~f:(fun offline_node () -> - let node_name = Engine.Network.Node.infra_id offline_node in + let node_name = Engine.Network.Node.id offline_node in [%log info] "Detected node offline $node" ~metadata:[ ("node", `String node_name) ] ; if Engine.Network.Node.should_be_running offline_node then ( diff --git a/src/lib/testing/integration_test_lib/event_router.ml b/src/lib/testing/integration_test_lib/event_router.ml index bf24a8746556..d7fbf3202bcc 100644 --- a/src/lib/testing/integration_test_lib/event_router.ml +++ b/src/lib/testing/integration_test_lib/event_router.ml @@ -73,7 +73,7 @@ module Make (Engine : Intf.Engine.S) () : [%log debug] "Dispatching event $event for $node" ~metadata: [ ("event", Event_type.event_to_yojson event) - ; ("node", `String (Node.infra_id node)) + ; ("node", `String (Node.id node)) ] ; dispatch_event handlers node event ) ) ; { logger; handlers } diff --git a/src/lib/testing/integration_test_lib/graphql_polling_log_engine.ml b/src/lib/testing/integration_test_lib/graphql_polling_log_engine.ml index 8482fa3052ef..2f29b92ea6cd 100644 --- a/src/lib/testing/integration_test_lib/graphql_polling_log_engine.ml +++ b/src/lib/testing/integration_test_lib/graphql_polling_log_engine.ml @@ -84,7 +84,7 @@ struct | Error err -> [%log error] "Encountered an error while polling $node for logs: $err" ~metadata: - [ ("node", `String (Node.infra_id node)) + [ ("node", `String (Node.id node)) ; ("err", Error_json.error_to_yojson err) ] ; (* Declare the node to be offline. *) @@ -112,10 +112,10 @@ struct (node : Node.t) = let open Deferred.Or_error.Let_syntax in [%log info] "Requesting for $node to start its filtered logs" - ~metadata:[ ("node", `String (Node.infra_id node)) ] ; + ~metadata:[ ("node", `String (Node.id node)) ] ; let%bind () = start_filtered_log ~logger ~log_filter ~event_writer node in [%log info] "$node has started its filtered logs. Beginning polling" - ~metadata:[ ("node", `String (Node.infra_id node)) ] ; + ~metadata:[ ("node", `String (Node.id node)) ] ; let%bind () = filtered_log_entries_poll node ~last_log_index_seen:0 ~logger ~event_writer diff --git a/src/lib/testing/integration_test_lib/intf.ml b/src/lib/testing/integration_test_lib/intf.ml index 843d7e76a338..bce76bfbad64 100644 --- a/src/lib/testing/integration_test_lib/intf.ml +++ b/src/lib/testing/integration_test_lib/intf.ml @@ -49,8 +49,6 @@ module Engine = struct val id : t -> string - val infra_id : t -> string - val network_keypair : t -> Network_keypair.t option val start : fresh_state:bool -> t -> unit Malleable_error.t diff --git a/src/lib/testing/integration_test_lib/network_state.ml b/src/lib/testing/integration_test_lib/network_state.ml index 1e12001e7515..4328eb47f779 100644 --- a/src/lib/testing/integration_test_lib/network_state.ml +++ b/src/lib/testing/integration_test_lib/network_state.ml @@ -101,7 +101,7 @@ module Make ] ; update ~f:(fun state -> [%log debug] "handling block production from $node" - ~metadata:[ ("node", `String (Node.infra_id node)) ] ; + ~metadata:[ ("node", `String (Node.id node)) ] ; if block_produced.block_height > state.block_height then let snarked_ledgers_generated = if block_produced.snarked_ledger_generated then 1 else 0 @@ -137,7 +137,7 @@ module Make application event" ; update ~f:(fun state -> [%log debug] "handling frontier diff application of $node" - ~metadata:[ ("node", `String (Node.infra_id node)) ] ; + ~metadata:[ ("node", `String (Node.id node)) ] ; Option.value_map diff_application.best_tip_changed ~default:state ~f:(fun new_best_tip -> let best_tips_by_node' = @@ -163,7 +163,7 @@ module Make state in [%log debug] "GOSSIP RECEIVED by $node" - ~metadata:[ ("node", `String (Node.infra_id node)) ] ; + ~metadata:[ ("node", `String (Node.id node)) ] ; [%log debug] "GOSSIP RECEIVED received event: $event" ~metadata: [ ( "event" @@ -187,7 +187,7 @@ module Make update ~f:(fun state -> [%log debug] "Updating network state with initialization event of $node" - ~metadata:[ ("node", `String (Node.infra_id node)) ] ; + ~metadata:[ ("node", `String (Node.id node)) ] ; let node_initialization' = String.Map.set state.node_initialization ~key:(Node.id node) ~data:true @@ -202,7 +202,7 @@ module Make [%log debug] "Updating network state with persisted frontier loaded event \ of $node" - ~metadata:[ ("node", `String (Node.infra_id node)) ] ; + ~metadata:[ ("node", `String (Node.id node)) ] ; { state with num_persisted_frontier_loaded = state.num_persisted_frontier_loaded + 1 @@ -216,7 +216,7 @@ module Make [%log debug] "Updating network state with persisted frontier fresh boot \ event of $node" - ~metadata:[ ("node", `String (Node.infra_id node)) ] ; + ~metadata:[ ("node", `String (Node.id node)) ] ; { state with num_persisted_frontier_fresh_boot = state.num_persisted_frontier_fresh_boot + 1 @@ -230,7 +230,7 @@ module Make [%log debug] "Updating network state with bootstrap required event of \ $node" - ~metadata:[ ("node", `String (Node.infra_id node)) ] ; + ~metadata:[ ("node", `String (Node.id node)) ] ; { state with num_bootstrap_required = state.num_bootstrap_required + 1 } ) ) @@ -243,7 +243,7 @@ module Make [%log debug] "Updating network state with persisted frontier dropped \ event of $node" - ~metadata:[ ("node", `String (Node.infra_id node)) ] ; + ~metadata:[ ("node", `String (Node.id node)) ] ; { state with num_persisted_frontier_dropped = state.num_persisted_frontier_dropped + 1 @@ -258,7 +258,7 @@ module Make [%log debug] "Updating network state with transition frontier loaded \ event of $node" - ~metadata:[ ("node", `String (Node.infra_id node)) ] ; + ~metadata:[ ("node", `String (Node.id node)) ] ; { state with num_transition_frontier_loaded_from_persistence = state.num_transition_frontier_loaded_from_persistence + 1 @@ -270,7 +270,7 @@ module Make update ~f:(fun state -> [%log debug] "Updating network state with event of $node going offline" - ~metadata:[ ("node", `String (Node.infra_id node)) ] ; + ~metadata:[ ("node", `String (Node.id node)) ] ; let node_initialization' = String.Map.set state.node_initialization ~key:(Node.id node) ~data:false @@ -290,7 +290,7 @@ module Make update ~f:(fun state -> [%log debug] "Updating network state with Breadcrumb added to $node" - ~metadata:[ ("node", `String (Node.infra_id node)) ] ; + ~metadata:[ ("node", `String (Node.id node)) ] ; let blocks_seen_by_node' = String.Map.update state.blocks_seen_by_node (Node.id node) ~f:(fun block_set -> diff --git a/src/lib/testing/integration_test_local_engine/docker_network.ml b/src/lib/testing/integration_test_local_engine/docker_network.ml index ba1d8f3f2cfc..ea337f33283e 100644 --- a/src/lib/testing/integration_test_local_engine/docker_network.ml +++ b/src/lib/testing/integration_test_local_engine/docker_network.ml @@ -35,8 +35,6 @@ module Node = struct let id { config; _ } = config.service_id - let infra_id { config; _ } = config.service_id - let should_be_running { should_be_running; _ } = should_be_running let network_keypair { config; _ } = config.network_keypair From 9f9a4683e58252673eb1a040da0df8a088db96d4 Mon Sep 17 00:00:00 2001 From: glyh Date: Fri, 24 Oct 2025 16:51:03 +0800 Subject: [PATCH 02/13] Lucy lib: Documentation on Intf.Network_intf.Node --- src/lib/testing/integration_test_lib/intf.ml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/lib/testing/integration_test_lib/intf.ml b/src/lib/testing/integration_test_lib/intf.ml index bce76bfbad64..3fec42ae62d6 100644 --- a/src/lib/testing/integration_test_lib/intf.ml +++ b/src/lib/testing/integration_test_lib/intf.ml @@ -60,8 +60,11 @@ module Engine = struct *) val should_be_running : t -> bool + (** Returns the GraphQL endpoint of this node that's reachable from host + environment. *) val get_ingress_uri : t -> Uri.t + (** Dump archive data of an archive node to host at [data_file]. *) val dump_archive_data : logger:Logger.t -> t -> data_file:string -> unit Malleable_error.t @@ -71,9 +74,12 @@ module Engine = struct -> t -> string Malleable_error.t + (** Dump JSON logs of the node to host at [data_file]. *) val dump_mina_logs : logger:Logger.t -> t -> log_file:string -> unit Malleable_error.t + (** Dump a bunch of precomputed block json files with name formatted as + state_hash.json in CWD. *) val dump_precomputed_blocks : logger:Logger.t -> t -> unit Malleable_error.t end From 287c20efeafed5004f4d50b6d2df504810464d5f Mon Sep 17 00:00:00 2001 From: glyh Date: Fri, 24 Oct 2025 16:51:58 +0800 Subject: [PATCH 03/13] Lucy Lib: rename Network_intf.all_{mina -> daemon}_nodes This clarify the intention of this function. --- src/app/test_executive/block_production_priority.ml | 4 ++-- src/app/test_executive/block_reward_test.ml | 4 ++-- src/app/test_executive/chain_reliability_test.ml | 6 +++--- src/app/test_executive/epoch_ledger.ml | 4 ++-- src/app/test_executive/gossip_consistency.ml | 2 +- src/app/test_executive/medium_bootstrap.ml | 8 ++++---- src/app/test_executive/payments_test.ml | 4 ++-- src/app/test_executive/peers_reliability_test.ml | 10 +++++----- src/app/test_executive/post_hard_fork.ml | 4 ++-- src/app/test_executive/slot_end_test.ml | 2 +- src/app/test_executive/verification_key_update.ml | 2 +- src/app/test_executive/zkapps.ml | 2 +- src/app/test_executive/zkapps_nonce_test.ml | 2 +- src/app/test_executive/zkapps_timing.ml | 4 ++-- src/lib/testing/integration_test_lib/intf.ml | 2 +- .../integration_test_local_engine/docker_network.ml | 2 +- 16 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/app/test_executive/block_production_priority.ml b/src/app/test_executive/block_production_priority.ml index 701e2389f56d..492fcac5c302 100644 --- a/src/app/test_executive/block_production_priority.ml +++ b/src/app/test_executive/block_production_priority.ml @@ -107,11 +107,11 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct let window_ms = (Network.constraint_constants network).block_window_duration_ms in - let all_mina_nodes = Network.all_mina_nodes network in + let all_daemon_nodes = Network.all_daemon_nodes network in let%bind () = wait_for t (Wait_condition.nodes_to_initialize - (Core.String.Map.data all_mina_nodes) ) + (Core.String.Map.data all_daemon_nodes) ) in let%bind () = section_hard "wait for 3 blocks to be produced (warm-up)" diff --git a/src/app/test_executive/block_reward_test.ml b/src/app/test_executive/block_reward_test.ml index f67bce2e476e..0cbb542c18d0 100644 --- a/src/app/test_executive/block_reward_test.ml +++ b/src/app/test_executive/block_reward_test.ml @@ -30,11 +30,11 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct let run ~config:_ network t = let open Malleable_error.Let_syntax in let logger = Logger.create () in - let all_mina_nodes = Network.all_mina_nodes network in + let all_daemon_nodes = Network.all_daemon_nodes network in let%bind () = wait_for t (Wait_condition.nodes_to_initialize - (Core.String.Map.data all_mina_nodes) ) + (Core.String.Map.data all_daemon_nodes) ) in let node = Network.block_producer_exn network "node" in let bp_keypair = (Network.genesis_keypair_exn network "node-key").keypair in diff --git a/src/app/test_executive/chain_reliability_test.ml b/src/app/test_executive/chain_reliability_test.ml index 8c21ce6fbd97..5326cc89a677 100644 --- a/src/app/test_executive/chain_reliability_test.ml +++ b/src/app/test_executive/chain_reliability_test.ml @@ -37,11 +37,11 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct let open Network in let open Malleable_error.Let_syntax in let logger = Logger.create () in - let all_mina_nodes = Network.all_mina_nodes network in + let all_daemon_nodes = Network.all_daemon_nodes network in let%bind () = wait_for t (Wait_condition.nodes_to_initialize - (Core.String.Map.data all_mina_nodes) ) + (Core.String.Map.data all_daemon_nodes) ) in let node_a = Network.block_producer_exn network "node-a" in let node_b = Network.block_producer_exn network "node-b" in @@ -105,7 +105,7 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct further block production is needed. if previous sections change, then this may need to be re-adjusted*) (let%bind (labeled_chains : (string * string list) list) = - Malleable_error.List.map (Core.String.Map.data all_mina_nodes) + Malleable_error.List.map (Core.String.Map.data all_daemon_nodes) ~f:(fun node -> let%map chain = Integration_test_lib.Graphql_requests.must_get_best_chain ~logger diff --git a/src/app/test_executive/epoch_ledger.ml b/src/app/test_executive/epoch_ledger.ml index ccaa6b243a87..0bf54629575a 100644 --- a/src/app/test_executive/epoch_ledger.ml +++ b/src/app/test_executive/epoch_ledger.ml @@ -63,11 +63,11 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct let run ~config:_ network t = let open Malleable_error.Let_syntax in - let all_mina_nodes = Network.all_mina_nodes network in + let all_daemon_nodes = Network.all_daemon_nodes network in let%bind () = wait_for t (Wait_condition.nodes_to_initialize - (Core.String.Map.data all_mina_nodes) ) + (Core.String.Map.data all_daemon_nodes) ) in (* Since I made the balances of block producers in genesis ledger and next epoch ledgers to be 0, then blocks would only be produced, if the diff --git a/src/app/test_executive/gossip_consistency.ml b/src/app/test_executive/gossip_consistency.ml index 15a9c57eff2e..d87e147e0539 100644 --- a/src/app/test_executive/gossip_consistency.ml +++ b/src/app/test_executive/gossip_consistency.ml @@ -38,7 +38,7 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct let%bind () = wait_for t (Wait_condition.nodes_to_initialize - (Core.String.Map.data (Network.all_mina_nodes network)) ) + (Core.String.Map.data (Network.all_daemon_nodes network)) ) in [%log info] "gossip_consistency test: done waiting for initializations" ; let receiver_bp = Network.block_producer_exn network "node-a" in diff --git a/src/app/test_executive/medium_bootstrap.ml b/src/app/test_executive/medium_bootstrap.ml index bffd7eb86751..ccfb9edcef9d 100644 --- a/src/app/test_executive/medium_bootstrap.ml +++ b/src/app/test_executive/medium_bootstrap.ml @@ -55,12 +55,12 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct let open Network in let open Malleable_error.Let_syntax in let logger = Logger.create () in - let all_mina_nodes = Network.all_mina_nodes network in + let all_daemon_nodes = Network.all_daemon_nodes network in let%bind () = section_hard "Wait for nodes to initialize" (wait_for t (Wait_condition.nodes_to_initialize - (Core.String.Map.data all_mina_nodes) ) ) + (Core.String.Map.data all_daemon_nodes) ) ) in let node_a = Network.block_producer_exn network "node-a" in let node_b = Network.block_producer_exn network "node-b" in @@ -87,7 +87,7 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct section_hard "network is fully connected after one node was restarted" (let%bind () = Malleable_error.lift (after (Time.Span.of_sec 240.0)) in let%bind final_connectivity_data = - fetch_connectivity_data ~logger (Core.String.Map.data all_mina_nodes) + fetch_connectivity_data ~logger (Core.String.Map.data all_daemon_nodes) in assert_peers_completely_connected final_connectivity_data ) in @@ -119,7 +119,7 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct section_hard "network is fully connected after one node was restarted" (let%bind () = Malleable_error.lift (after (Time.Span.of_sec 240.0)) in let%bind final_connectivity_data = - fetch_connectivity_data ~logger (Core.String.Map.data all_mina_nodes) + fetch_connectivity_data ~logger (Core.String.Map.data all_daemon_nodes) in assert_peers_completely_connected final_connectivity_data ) end diff --git a/src/app/test_executive/payments_test.ml b/src/app/test_executive/payments_test.ml index 1d1b17e776c5..e44d813c67f0 100644 --- a/src/app/test_executive/payments_test.ml +++ b/src/app/test_executive/payments_test.ml @@ -69,11 +69,11 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct let run ~config:(Test_config.{ signature_kind; _ } as config) network t = let open Malleable_error.Let_syntax in let logger = Logger.create () in - let all_mina_nodes = Network.all_mina_nodes network in + let all_daemon_nodes = Network.all_daemon_nodes network in let%bind () = wait_for t (Wait_condition.nodes_to_initialize - (Core.String.Map.data all_mina_nodes) ) + (Core.String.Map.data all_daemon_nodes) ) in let untimed_node_a = Network.block_producer_exn network "untimed-node-a" in let untimed_node_b = Network.block_producer_exn network "untimed-node-b" in diff --git a/src/app/test_executive/peers_reliability_test.ml b/src/app/test_executive/peers_reliability_test.ml index 234aa7979147..cc1046fae7a0 100644 --- a/src/app/test_executive/peers_reliability_test.ml +++ b/src/app/test_executive/peers_reliability_test.ml @@ -38,12 +38,12 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct let open Network in let open Malleable_error.Let_syntax in let logger = Logger.create () in - let all_mina_nodes = Network.all_mina_nodes network in + let all_daemon_nodes = Network.all_daemon_nodes network in [%log info] "peers_list" ~metadata: [ ( "peers" , `List - (List.map (Core.String.Map.data all_mina_nodes) ~f:(fun n -> + (List.map (Core.String.Map.data all_daemon_nodes) ~f:(fun n -> `String (Node.id n) ) ) ) ] ; let node_a = @@ -71,10 +71,10 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct let%bind () = wait_for t (Wait_condition.nodes_to_initialize - (Core.String.Map.data all_mina_nodes) ) + (Core.String.Map.data all_daemon_nodes) ) in let%bind initial_connectivity_data = - fetch_connectivity_data ~logger (Core.String.Map.data all_mina_nodes) + fetch_connectivity_data ~logger (Core.String.Map.data all_daemon_nodes) in let%bind () = section "network is fully connected upon initialization" @@ -206,7 +206,7 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct section "network is fully connected after one node was restarted" (let%bind () = Malleable_error.lift (after (Time.Span.of_sec 240.0)) in let%bind final_connectivity_data = - fetch_connectivity_data ~logger (Core.String.Map.data all_mina_nodes) + fetch_connectivity_data ~logger (Core.String.Map.data all_daemon_nodes) in assert_peers_completely_connected final_connectivity_data ) end diff --git a/src/app/test_executive/post_hard_fork.ml b/src/app/test_executive/post_hard_fork.ml index c1233692de63..60ee90939f9c 100644 --- a/src/app/test_executive/post_hard_fork.ml +++ b/src/app/test_executive/post_hard_fork.ml @@ -216,11 +216,11 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct let open Malleable_error.Let_syntax in let constraint_constants = Network.constraint_constants network in let logger = Logger.create () in - let all_mina_nodes = Network.all_mina_nodes network in + let all_daemon_nodes = Network.all_daemon_nodes network in let%bind () = wait_for t (Wait_condition.nodes_to_initialize - (Core.String.Map.data all_mina_nodes) ) + (Core.String.Map.data all_daemon_nodes) ) in let node_a = Network.block_producer_exn network "node-a" in let node_b = Network.block_producer_exn network "node-b" in diff --git a/src/app/test_executive/slot_end_test.ml b/src/app/test_executive/slot_end_test.ml index 077b8ca00aa8..9c86e4671cfb 100644 --- a/src/app/test_executive/slot_end_test.ml +++ b/src/app/test_executive/slot_end_test.ml @@ -100,7 +100,7 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct let window_ms = (Network.constraint_constants network).block_window_duration_ms in - let all_nodes = Network.all_mina_nodes network in + let all_nodes = Network.all_daemon_nodes network in let%bind () = wait_for t (Wait_condition.nodes_to_initialize (String.Map.data all_nodes)) diff --git a/src/app/test_executive/verification_key_update.ml b/src/app/test_executive/verification_key_update.ml index 34825b2c904b..7ac905f5abeb 100644 --- a/src/app/test_executive/verification_key_update.ml +++ b/src/app/test_executive/verification_key_update.ml @@ -103,7 +103,7 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct section_hard "Wait for nodes to initialize" (wait_for t (Wait_condition.nodes_to_initialize - (Core.String.Map.data (Network.all_mina_nodes network)) ) ) + (Core.String.Map.data (Network.all_daemon_nodes network)) ) ) in let whale1 = Network.block_producer_exn network "whale1" in let%bind whale1_pk = pub_key_of_node whale1 in diff --git a/src/app/test_executive/zkapps.ml b/src/app/test_executive/zkapps.ml index 58f0bedffe86..e780ae10e34b 100644 --- a/src/app/test_executive/zkapps.ml +++ b/src/app/test_executive/zkapps.ml @@ -137,7 +137,7 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct section_hard "Wait for nodes to initialize" (wait_for t ( Wait_condition.nodes_to_initialize - @@ (Network.all_mina_nodes network |> Core.String.Map.data) ) ) + @@ (Network.all_daemon_nodes network |> Core.String.Map.data) ) ) in let node = Network.block_producer_exn network "node-a" in let constraint_constants = Network.constraint_constants network in diff --git a/src/app/test_executive/zkapps_nonce_test.ml b/src/app/test_executive/zkapps_nonce_test.ml index 01189f013fd9..8c7ad546e909 100644 --- a/src/app/test_executive/zkapps_nonce_test.ml +++ b/src/app/test_executive/zkapps_nonce_test.ml @@ -129,7 +129,7 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct (List.filter ~f:(fun n -> String.(Network.Node.id n <> Network.Node.id first_bp) ) - (Core.String.Map.data (Network.all_mina_nodes network)) ) ) + (Core.String.Map.data (Network.all_daemon_nodes network)) ) ) in let keymap = List.fold [ fish1_kp ] ~init:Signature_lib.Public_key.Compressed.Map.empty diff --git a/src/app/test_executive/zkapps_timing.ml b/src/app/test_executive/zkapps_timing.ml index c50030735b13..82ad6679650b 100644 --- a/src/app/test_executive/zkapps_timing.ml +++ b/src/app/test_executive/zkapps_timing.ml @@ -36,11 +36,11 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct let run ~config:Test_config.{ signature_kind; _ } network t = let open Malleable_error.Let_syntax in let logger = Logger.create () in - let all_mina_nodes = Network.all_mina_nodes network in + let all_daemon_nodes = Network.all_daemon_nodes network in let%bind () = wait_for t (Wait_condition.nodes_to_initialize - (Core.String.Map.data all_mina_nodes) ) + (Core.String.Map.data all_daemon_nodes) ) in let block_producer_nodes = Network.block_producers network |> Core.String.Map.data diff --git a/src/lib/testing/integration_test_lib/intf.ml b/src/lib/testing/integration_test_lib/intf.ml index 3fec42ae62d6..11b5a6856963 100644 --- a/src/lib/testing/integration_test_lib/intf.ml +++ b/src/lib/testing/integration_test_lib/intf.ml @@ -106,7 +106,7 @@ module Engine = struct val archive_nodes : t -> Node.t Core.String.Map.t - val all_mina_nodes : t -> Node.t Core.String.Map.t + val all_daemon_nodes : t -> Node.t Core.String.Map.t val all_nodes : t -> Node.t Core.String.Map.t diff --git a/src/lib/testing/integration_test_local_engine/docker_network.ml b/src/lib/testing/integration_test_local_engine/docker_network.ml index ea337f33283e..5cbc428e6797 100644 --- a/src/lib/testing/integration_test_local_engine/docker_network.ml +++ b/src/lib/testing/integration_test_local_engine/docker_network.ml @@ -293,7 +293,7 @@ let snark_coordinators { snark_coordinators; _ } = snark_coordinators let archive_nodes { archive_nodes; _ } = archive_nodes -let all_mina_nodes { seeds; block_producers; snark_coordinators; _ } = +let all_daemon_nodes { seeds; block_producers; snark_coordinators; _ } = List.concat [ Core.String.Map.to_alist seeds ; Core.String.Map.to_alist block_producers From a297e7e6284a0c23f9eae6ea4250d555bf26c4df Mon Sep 17 00:00:00 2001 From: glyh Date: Fri, 24 Oct 2025 16:57:35 +0800 Subject: [PATCH 04/13] Lucy Lib: remove Network.initialize_infra as it's a noop --- src/app/test_executive/test_executive.ml | 2 -- src/lib/testing/integration_test_lib/intf.ml | 2 -- .../testing/integration_test_local_engine/docker_network.ml | 5 ----- 3 files changed, 9 deletions(-) diff --git a/src/app/test_executive/test_executive.ml b/src/app/test_executive/test_executive.ml index 05a1f90a577a..23bf3335bacc 100644 --- a/src/app/test_executive/test_executive.ml +++ b/src/app/test_executive/test_executive.ml @@ -380,8 +380,6 @@ let main inputs = in (network, dsl) in - [%log trace] "initializing network abstraction" ; - let%bind () = Engine.Network.initialize_infra ~logger network in [%log info] "Starting the daemons within the pods" ; let start_print (node : Engine.Network.Node.t) = diff --git a/src/lib/testing/integration_test_lib/intf.ml b/src/lib/testing/integration_test_lib/intf.ml index 11b5a6856963..a16369370b0e 100644 --- a/src/lib/testing/integration_test_lib/intf.ml +++ b/src/lib/testing/integration_test_lib/intf.ml @@ -115,8 +115,6 @@ module Engine = struct val genesis_keypairs : t -> Network_keypair.t Core.String.Map.t val genesis_keypair_exn : t -> String.t -> Network_keypair.t - - val initialize_infra : logger:Logger.t -> t -> unit Malleable_error.t end module type Network_manager_intf = sig diff --git a/src/lib/testing/integration_test_local_engine/docker_network.ml b/src/lib/testing/integration_test_local_engine/docker_network.ml index 5cbc428e6797..f9480963fe3b 100644 --- a/src/lib/testing/integration_test_local_engine/docker_network.ml +++ b/src/lib/testing/integration_test_local_engine/docker_network.ml @@ -331,8 +331,3 @@ let all_ids t = let deployments = all_nodes t |> Core.Map.to_alist in List.fold deployments ~init:[] ~f:(fun acc (_, node) -> List.cons node.config.service_id acc ) - -let initialize_infra ~logger network = - let _ = logger in - let _ = network in - Malleable_error.return () From 4bd72427f50a671f25304e8003c78b5e9dfeadad Mon Sep 17 00:00:00 2001 From: glyh Date: Fri, 24 Oct 2025 18:11:11 +0800 Subject: [PATCH 05/13] Lucy Lib > Event Router: rename some type variables --- src/lib/testing/integration_test_lib/event_router.ml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/testing/integration_test_lib/event_router.ml b/src/lib/testing/integration_test_lib/event_router.ml index d7fbf3202bcc..716bdfb57934 100644 --- a/src/lib/testing/integration_test_lib/event_router.ml +++ b/src/lib/testing/integration_test_lib/event_router.ml @@ -8,8 +8,8 @@ module Make (Engine : Intf.Engine.S) () : module Event_handler_id = Unique_id.Int () - type ('a, 'b) handler_func = - Node.t -> 'a -> [ `Stop of 'b | `Continue ] Deferred.t + type ('data, 'result) handler_func = + Node.t -> 'data -> [ `Stop of 'result | `Continue ] Deferred.t type event_handler = | Event_handler : @@ -19,8 +19,8 @@ module Make (Engine : Intf.Engine.S) () : (* event subscriptions surface information from the handler (as type witnesses), but do not existentially hide the result parameter *) type _ event_subscription = | Event_subscription : - Event_handler_id.t * 'b Ivar.t * 'a Event_type.t - -> 'b event_subscription + Event_handler_id.t * 'result Ivar.t * 'data Event_type.t + -> 'result event_subscription type handler_map = event_handler list Event_type.Map.t From 98813488c8e9378406f371de6ca6cadd05083c10 Mon Sep 17 00:00:00 2001 From: glyh Date: Fri, 24 Oct 2025 18:12:46 +0800 Subject: [PATCH 06/13] Lucy Lib > Event Router: rename finished_ivar -> result --- .../testing/integration_test_lib/event_router.ml | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/lib/testing/integration_test_lib/event_router.ml b/src/lib/testing/integration_test_lib/event_router.ml index 716bdfb57934..5f410f219f7e 100644 --- a/src/lib/testing/integration_test_lib/event_router.ml +++ b/src/lib/testing/integration_test_lib/event_router.ml @@ -46,10 +46,7 @@ module Make (Engine : Intf.Engine.S) () : (* assuming the dispatch for `f` is already parallel, and not the execution of the deferred it returns *) let (Event (event_type, event_data)) = event in let (Event_handler - ( handler_id - , handler_finished_ivar - , handler_type - , handler_callback ) ) = + (handler_id, handler_result, handler_type, handler_callback) ) = handler in match%map @@ -59,7 +56,7 @@ module Make (Engine : Intf.Engine.S) () : | `Continue -> None | `Stop result -> - Ivar.fill handler_finished_ivar result ; + Ivar.fill handler_result result ; Some handler_id ) in unregister_event_handlers_by_id handlers @@ -81,11 +78,11 @@ module Make (Engine : Intf.Engine.S) () : let on t event_type ~f = let event_type_ex = Event_type.Event_type event_type in let handler_id = Event_handler_id.create () in - let finished_ivar = Ivar.create () in - let handler = Event_handler (handler_id, finished_ivar, event_type, f) in + let result = Ivar.create () in + let handler = Event_handler (handler_id, result, event_type, f) in t.handlers := Event_type.Map.add_multi !(t.handlers) ~key:event_type_ex ~data:handler ; - Event_subscription (handler_id, finished_ivar, event_type) + Event_subscription (handler_id, result, event_type) (* TODO: On cancellation, should we notify active subscriptions? Would involve changing await type to option or result. *) let cancel t event_subscription cancellation = From 1dbb703f26bceea4f523176b0d042fe2189ab23a Mon Sep 17 00:00:00 2001 From: glyh Date: Fri, 24 Oct 2025 19:13:30 +0800 Subject: [PATCH 07/13] Lucy: Don't expose internal of network state generator writer --- src/app/test_executive/test_executive.ml | 25 +- src/lib/testing/integration_test_lib/intf.ml | 14 +- .../integration_test_lib/network_state.ml | 482 +++++++++--------- 3 files changed, 271 insertions(+), 250 deletions(-) diff --git a/src/app/test_executive/test_executive.ml b/src/app/test_executive/test_executive.ml index 23bf3335bacc..12680718f332 100644 --- a/src/app/test_executive/test_executive.ml +++ b/src/app/test_executive/test_executive.ml @@ -1,7 +1,6 @@ open Core open Async open Cmdliner -open Pipe_lib open Integration_test_lib type test = string * (module Intf.Test.Functor_intf) @@ -203,16 +202,17 @@ let report_test_errors ~log_error_set ~internal_error_set = let dispatch_cleanup ~logger ~pause_cleanup_func ~network_cleanup_func ~log_engine_cleanup_func ~lift_accumulated_errors_func ~net_manager_ref - ~log_engine_ref ~network_state_writer_ref ~cleanup_deferred_ref ~exit_reason - ~test_result : unit Deferred.t = + ~log_engine_ref ~network_state_generator_ref ~cleanup_deferred_ref + ~exit_reason ~test_result ~cleanup_state_generator : unit Deferred.t = let cleanup () : unit Deferred.t = let%bind log_engine_cleanup_result = Option.value_map !log_engine_ref ~default:(Deferred.Or_error.return ()) ~f:log_engine_cleanup_func in - Option.value_map !network_state_writer_ref ~default:() - ~f:Broadcast_pipe.Writer.close ; + Option.value_map + !network_state_generator_ref + ~default:() ~f:cleanup_state_generator ; let%bind test_error_set = Malleable_error.lift_error_set_unit test_result in let log_error_set = lift_accumulated_errors_func () in let internal_error_set = @@ -305,7 +305,7 @@ let main inputs = let net_manager_ref : Engine.Network_manager.t option ref = ref None in let log_engine_ref : Engine.Log_engine.t option ref = ref None in let error_accumulator_ref = ref None in - let network_state_writer_ref = ref None in + let network_state_generator_ref = ref None in let cleanup_deferred_ref = ref None in [%log trace] "preparing up cleanup phase" ; let f_dispatch_cleanup = @@ -322,7 +322,8 @@ let main inputs = ~network_cleanup_func:Engine.Network_manager.cleanup ~log_engine_cleanup_func:Engine.Log_engine.destroy ~lift_accumulated_errors_func ~net_manager_ref ~log_engine_ref - ~network_state_writer_ref ~cleanup_deferred_ref + ~network_state_generator_ref ~cleanup_deferred_ref + ~cleanup_state_generator:Dsl.Network_state.Generator.close in (* run test while gracefully recovering handling exceptions and interrupts *) [%log trace] "attaching signal handler" ; @@ -370,13 +371,15 @@ let main inputs = error_accumulator_ref := Some (Dsl.watch_log_errors ~logger ~event_router ~on_fatal_error) ; [%log trace] "beginning to process network events" ; - let network_state_reader, network_state_writer = - Dsl.Network_state.listen ~logger event_router + let network_state_generator = + Dsl.Network_state.Generator.from_router ~logger event_router in - network_state_writer_ref := Some network_state_writer ; + network_state_generator_ref := Some network_state_generator ; [%log trace] "initializing dsl" ; let (`Don't_call_in_tests dsl) = - Dsl.create ~logger ~network ~event_router ~network_state_reader + Dsl.create ~logger ~network ~event_router + ~network_state_reader: + (Dsl.Network_state.Generator.reader network_state_generator) in (network, dsl) in diff --git a/src/lib/testing/integration_test_lib/intf.ml b/src/lib/testing/integration_test_lib/intf.ml index a16369370b0e..421361d3d68b 100644 --- a/src/lib/testing/integration_test_lib/intf.ml +++ b/src/lib/testing/integration_test_lib/intf.ml @@ -222,10 +222,16 @@ module Dsl = struct State_hash.Set.t Mina_transaction.Transaction_hash.Map.t } - val listen : - logger:Logger.t - -> Event_router.t - -> t Broadcast_pipe.Reader.t * t Broadcast_pipe.Writer.t + module Generator : sig + (* HACK: I can't name it `gen` due to name collision *) + type gen + + val from_router : logger:Logger.t -> Event_router.t -> gen + + val reader : gen -> t Broadcast_pipe.Reader.t + + val close : gen -> unit + end end module type Wait_condition_intf = sig diff --git a/src/lib/testing/integration_test_lib/network_state.ml b/src/lib/testing/integration_test_lib/network_state.ml index 4328eb47f779..d812fe26df33 100644 --- a/src/lib/testing/integration_test_lib/network_state.ml +++ b/src/lib/testing/integration_test_lib/network_state.ml @@ -80,246 +80,258 @@ module Make ; num_persisted_frontier_dropped = 0 } - let listen ~logger event_router = - let r, w = Broadcast_pipe.create empty in - let update ~f = - (* should be safe to ignore the write here, so long as `f` is synchronous *) - let state = f (Broadcast_pipe.Reader.peek r) in - [%log debug] "updated network state to: $state" - ~metadata:[ ("state", to_yojson state) ] ; - ignore (Broadcast_pipe.Writer.write w state : unit Deferred.t) ; - Deferred.return `Continue - in - (* handle_block_produced *) - ignore - ( Event_router.on event_router Event_type.Block_produced - ~f:(fun node block_produced -> - [%log debug] "Updating network state with block produced event" - ~metadata: - [ ( "snark_ledger_generated" - , `Bool block_produced.snarked_ledger_generated ) - ] ; - update ~f:(fun state -> - [%log debug] "handling block production from $node" - ~metadata:[ ("node", `String (Node.id node)) ] ; - if block_produced.block_height > state.block_height then - let snarked_ledgers_generated = - if block_produced.snarked_ledger_generated then 1 else 0 - in - let blocks_produced_by_node_map = - Core.String.Map.update state.blocks_produced_by_node - (Node.id node) ~f:(fun ls_opt -> - match ls_opt with - | None -> - [ block_produced.state_hash ] - | Some ls -> - List.cons block_produced.state_hash ls ) + module Generator = struct + type gen = t Broadcast_pipe.Reader.t * t Broadcast_pipe.Writer.t + + let from_router ~logger event_router = + let r, w = Broadcast_pipe.create empty in + let update ~f = + (* should be safe to ignore the write here, so long as `f` is synchronous *) + let state = f (Broadcast_pipe.Reader.peek r) in + [%log debug] "updated network state to: $state" + ~metadata:[ ("state", to_yojson state) ] ; + ignore (Broadcast_pipe.Writer.write w state : unit Deferred.t) ; + Deferred.return `Continue + in + (* handle_block_produced *) + ignore + ( Event_router.on event_router Event_type.Block_produced + ~f:(fun node block_produced -> + [%log debug] "Updating network state with block produced event" + ~metadata: + [ ( "snark_ledger_generated" + , `Bool block_produced.snarked_ledger_generated ) + ] ; + update ~f:(fun state -> + [%log debug] "handling block production from $node" + ~metadata:[ ("node", `String (Node.id node)) ] ; + if block_produced.block_height > state.block_height then + let snarked_ledgers_generated = + if block_produced.snarked_ledger_generated then 1 else 0 + in + let blocks_produced_by_node_map = + Core.String.Map.update state.blocks_produced_by_node + (Node.id node) ~f:(fun ls_opt -> + match ls_opt with + | None -> + [ block_produced.state_hash ] + | Some ls -> + List.cons block_produced.state_hash ls ) + in + { state with + epoch = block_produced.global_slot + ; global_slot = block_produced.global_slot + ; block_height = block_produced.block_height + ; blocks_generated = state.blocks_generated + 1 + ; snarked_ledgers_generated = + state.snarked_ledgers_generated + + snarked_ledgers_generated + ; blocks_produced_by_node = blocks_produced_by_node_map + } + else state ) ) + : _ Event_router.event_subscription ) ; + (* handle_update_best_tips *) + ignore + ( Event_router.on event_router + Event_type.Transition_frontier_diff_application + ~f:(fun node diff_application -> + [%log debug] + "Updating network state with transition frontier diff \ + application event" ; + update ~f:(fun state -> + [%log debug] "handling frontier diff application of $node" + ~metadata:[ ("node", `String (Node.id node)) ] ; + Option.value_map diff_application.best_tip_changed + ~default:state ~f:(fun new_best_tip -> + let best_tips_by_node' = + String.Map.set state.best_tips_by_node + ~key:(Node.id node) ~data:new_best_tip + in + { state with best_tips_by_node = best_tips_by_node' } ) ) ) + : _ Event_router.event_subscription ) ; + let handle_gossip_received event_type = + ignore + ( Event_router.on event_router event_type + ~f:(fun node gossip_with_direction -> + update ~f:(fun state -> + { state with + gossip_received = + Map.update state.gossip_received (Node.id node) + ~f:(fun gossip_state_opt -> + let gossip_state = + match gossip_state_opt with + | None -> + Gossip_state.create (Node.id node) + | Some state -> + state + in + [%log debug] "GOSSIP RECEIVED by $node" + ~metadata:[ ("node", `String (Node.id node)) ] ; + [%log debug] + "GOSSIP RECEIVED received event: $event" + ~metadata: + [ ( "event" + , Event_type.event_to_yojson + (Event_type.Event + (event_type, gossip_with_direction) ) + ) + ] ; + Gossip_state.add gossip_state event_type + gossip_with_direction ; + gossip_state ) + } ) ) + : _ Event_router.event_subscription ) + in + handle_gossip_received Block_gossip ; + handle_gossip_received Snark_work_gossip ; + handle_gossip_received Transactions_gossip ; + (* handle_node_init *) + ignore + ( Event_router.on event_router Event_type.Node_initialization + ~f:(fun node () -> + update ~f:(fun state -> + [%log debug] + "Updating network state with initialization event of $node" + ~metadata:[ ("node", `String (Node.id node)) ] ; + let node_initialization' = + String.Map.set state.node_initialization ~key:(Node.id node) + ~data:true in + { state with node_initialization = node_initialization' } ) ) + : _ Event_router.event_subscription ) ; + (* handle_persisted_frontier_loaded *) + ignore + ( Event_router.on event_router Event_type.Persisted_frontier_loaded + ~f:(fun node () -> + update ~f:(fun state -> + [%log debug] + "Updating network state with persisted frontier loaded \ + event of $node" + ~metadata:[ ("node", `String (Node.id node)) ] ; { state with - epoch = block_produced.global_slot - ; global_slot = block_produced.global_slot - ; block_height = block_produced.block_height - ; blocks_generated = state.blocks_generated + 1 - ; snarked_ledgers_generated = - state.snarked_ledgers_generated - + snarked_ledgers_generated - ; blocks_produced_by_node = blocks_produced_by_node_map - } - else state ) ) - : _ Event_router.event_subscription ) ; - (* handle_update_best_tips *) - ignore - ( Event_router.on event_router - Event_type.Transition_frontier_diff_application - ~f:(fun node diff_application -> - [%log debug] - "Updating network state with transition frontier diff \ - application event" ; - update ~f:(fun state -> - [%log debug] "handling frontier diff application of $node" - ~metadata:[ ("node", `String (Node.id node)) ] ; - Option.value_map diff_application.best_tip_changed - ~default:state ~f:(fun new_best_tip -> - let best_tips_by_node' = - String.Map.set state.best_tips_by_node ~key:(Node.id node) - ~data:new_best_tip - in - { state with best_tips_by_node = best_tips_by_node' } ) ) ) - : _ Event_router.event_subscription ) ; - let handle_gossip_received event_type = + num_persisted_frontier_loaded = + state.num_persisted_frontier_loaded + 1 + } ) ) + : _ Event_router.event_subscription ) ; + (* handle_persisted_frontier_fresh_boot *) ignore - ( Event_router.on event_router event_type - ~f:(fun node gossip_with_direction -> + ( Event_router.on event_router Event_type.Persisted_frontier_fresh_boot + ~f:(fun node () -> update ~f:(fun state -> + [%log debug] + "Updating network state with persisted frontier fresh boot \ + event of $node" + ~metadata:[ ("node", `String (Node.id node)) ] ; { state with - gossip_received = - Map.update state.gossip_received (Node.id node) - ~f:(fun gossip_state_opt -> - let gossip_state = - match gossip_state_opt with - | None -> - Gossip_state.create (Node.id node) - | Some state -> - state - in - [%log debug] "GOSSIP RECEIVED by $node" - ~metadata:[ ("node", `String (Node.id node)) ] ; - [%log debug] "GOSSIP RECEIVED received event: $event" - ~metadata: - [ ( "event" - , Event_type.event_to_yojson - (Event_type.Event - (event_type, gossip_with_direction) ) ) - ] ; - Gossip_state.add gossip_state event_type - gossip_with_direction ; - gossip_state ) + num_persisted_frontier_fresh_boot = + state.num_persisted_frontier_fresh_boot + 1 } ) ) - : _ Event_router.event_subscription ) - in - handle_gossip_received Block_gossip ; - handle_gossip_received Snark_work_gossip ; - handle_gossip_received Transactions_gossip ; - (* handle_node_init *) - ignore - ( Event_router.on event_router Event_type.Node_initialization - ~f:(fun node () -> - update ~f:(fun state -> - [%log debug] - "Updating network state with initialization event of $node" - ~metadata:[ ("node", `String (Node.id node)) ] ; - let node_initialization' = - String.Map.set state.node_initialization ~key:(Node.id node) - ~data:true - in - { state with node_initialization = node_initialization' } ) ) - : _ Event_router.event_subscription ) ; - (* handle_persisted_frontier_loaded *) - ignore - ( Event_router.on event_router Event_type.Persisted_frontier_loaded - ~f:(fun node () -> - update ~f:(fun state -> - [%log debug] - "Updating network state with persisted frontier loaded event \ - of $node" - ~metadata:[ ("node", `String (Node.id node)) ] ; - { state with - num_persisted_frontier_loaded = - state.num_persisted_frontier_loaded + 1 - } ) ) - : _ Event_router.event_subscription ) ; - (* handle_persisted_frontier_fresh_boot *) - ignore - ( Event_router.on event_router Event_type.Persisted_frontier_fresh_boot - ~f:(fun node () -> - update ~f:(fun state -> - [%log debug] - "Updating network state with persisted frontier fresh boot \ - event of $node" - ~metadata:[ ("node", `String (Node.id node)) ] ; - { state with - num_persisted_frontier_fresh_boot = - state.num_persisted_frontier_fresh_boot + 1 - } ) ) - : _ Event_router.event_subscription ) ; - (* handle_bootstrap_required *) - ignore - ( Event_router.on event_router Event_type.Bootstrap_required - ~f:(fun node () -> - update ~f:(fun state -> - [%log debug] - "Updating network state with bootstrap required event of \ - $node" - ~metadata:[ ("node", `String (Node.id node)) ] ; - { state with - num_bootstrap_required = state.num_bootstrap_required + 1 - } ) ) - : _ Event_router.event_subscription ) ; - (* handle_persisted_frontier_dropped *) - ignore - ( Event_router.on event_router Event_type.Persisted_frontier_dropped - ~f:(fun node () -> - update ~f:(fun state -> - [%log debug] - "Updating network state with persisted frontier dropped \ - event of $node" - ~metadata:[ ("node", `String (Node.id node)) ] ; - { state with - num_persisted_frontier_dropped = - state.num_persisted_frontier_dropped + 1 - } ) ) - : _ Event_router.event_subscription ) ; - (* handle_transition frontier loaded *) - ignore - ( Event_router.on event_router - Event_type.Transition_frontier_loaded_from_persistence - ~f:(fun node () -> - update ~f:(fun state -> - [%log debug] - "Updating network state with transition frontier loaded \ - event of $node" - ~metadata:[ ("node", `String (Node.id node)) ] ; - { state with - num_transition_frontier_loaded_from_persistence = - state.num_transition_frontier_loaded_from_persistence + 1 - } ) ) - : _ Event_router.event_subscription ) ; - (* handle_node_offline *) - ignore - ( Event_router.on event_router Event_type.Node_offline ~f:(fun node () -> - update ~f:(fun state -> - [%log debug] - "Updating network state with event of $node going offline" - ~metadata:[ ("node", `String (Node.id node)) ] ; - let node_initialization' = - String.Map.set state.node_initialization ~key:(Node.id node) - ~data:false - in - let best_tips_by_node' = - String.Map.remove state.best_tips_by_node (Node.id node) - in - { state with - node_initialization = node_initialization' - ; best_tips_by_node = best_tips_by_node' - } ) ) - : _ Event_router.event_subscription ) ; - (* handle_breadcrumb_added *) - ignore - ( Event_router.on event_router Event_type.Breadcrumb_added - ~f:(fun node breadcrumb -> - update ~f:(fun state -> - [%log debug] - "Updating network state with Breadcrumb added to $node" - ~metadata:[ ("node", `String (Node.id node)) ] ; - let blocks_seen_by_node' = - String.Map.update state.blocks_seen_by_node (Node.id node) - ~f:(fun block_set -> - State_hash.Set.add - (Option.value block_set ~default:State_hash.Set.empty) - breadcrumb.state_hash ) - in - let transaction_hashes = - List.map breadcrumb.transaction_hashes ~f:With_status.data - in - let blocks_including_txn' = - List.fold transaction_hashes ~init:state.blocks_including_txn - ~f:(fun accum hash -> - let block_set' = + : _ Event_router.event_subscription ) ; + (* handle_bootstrap_required *) + ignore + ( Event_router.on event_router Event_type.Bootstrap_required + ~f:(fun node () -> + update ~f:(fun state -> + [%log debug] + "Updating network state with bootstrap required event of \ + $node" + ~metadata:[ ("node", `String (Node.id node)) ] ; + { state with + num_bootstrap_required = state.num_bootstrap_required + 1 + } ) ) + : _ Event_router.event_subscription ) ; + (* handle_persisted_frontier_dropped *) + ignore + ( Event_router.on event_router Event_type.Persisted_frontier_dropped + ~f:(fun node () -> + update ~f:(fun state -> + [%log debug] + "Updating network state with persisted frontier dropped \ + event of $node" + ~metadata:[ ("node", `String (Node.id node)) ] ; + { state with + num_persisted_frontier_dropped = + state.num_persisted_frontier_dropped + 1 + } ) ) + : _ Event_router.event_subscription ) ; + (* handle_transition frontier loaded *) + ignore + ( Event_router.on event_router + Event_type.Transition_frontier_loaded_from_persistence + ~f:(fun node () -> + update ~f:(fun state -> + [%log debug] + "Updating network state with transition frontier loaded \ + event of $node" + ~metadata:[ ("node", `String (Node.id node)) ] ; + { state with + num_transition_frontier_loaded_from_persistence = + state.num_transition_frontier_loaded_from_persistence + 1 + } ) ) + : _ Event_router.event_subscription ) ; + (* handle_node_offline *) + ignore + ( Event_router.on event_router Event_type.Node_offline + ~f:(fun node () -> + update ~f:(fun state -> + [%log debug] + "Updating network state with event of $node going offline" + ~metadata:[ ("node", `String (Node.id node)) ] ; + let node_initialization' = + String.Map.set state.node_initialization ~key:(Node.id node) + ~data:false + in + let best_tips_by_node' = + String.Map.remove state.best_tips_by_node (Node.id node) + in + { state with + node_initialization = node_initialization' + ; best_tips_by_node = best_tips_by_node' + } ) ) + : _ Event_router.event_subscription ) ; + (* handle_breadcrumb_added *) + ignore + ( Event_router.on event_router Event_type.Breadcrumb_added + ~f:(fun node breadcrumb -> + update ~f:(fun state -> + [%log debug] + "Updating network state with Breadcrumb added to $node" + ~metadata:[ ("node", `String (Node.id node)) ] ; + let blocks_seen_by_node' = + String.Map.update state.blocks_seen_by_node (Node.id node) + ~f:(fun block_set -> State_hash.Set.add - ( Transaction_hash.Map.find accum hash - |> Option.value ~default:State_hash.Set.empty ) - breadcrumb.state_hash - in - [%log debug] - "adding or updating txn_hash %s to \ - state.blocks_including_txn" - (Transaction_hash.to_base58_check hash) ; - Transaction_hash.Map.set accum ~key:hash ~data:block_set' ) - in - { state with - blocks_seen_by_node = blocks_seen_by_node' - ; blocks_including_txn = blocks_including_txn' - } ) ) - : _ Event_router.event_subscription ) ; - (r, w) + (Option.value block_set ~default:State_hash.Set.empty) + breadcrumb.state_hash ) + in + let transaction_hashes = + List.map breadcrumb.transaction_hashes ~f:With_status.data + in + let blocks_including_txn' = + List.fold transaction_hashes + ~init:state.blocks_including_txn ~f:(fun accum hash -> + let block_set' = + State_hash.Set.add + ( Transaction_hash.Map.find accum hash + |> Option.value ~default:State_hash.Set.empty ) + breadcrumb.state_hash + in + [%log debug] + "adding or updating txn_hash %s to \ + state.blocks_including_txn" + (Transaction_hash.to_base58_check hash) ; + Transaction_hash.Map.set accum ~key:hash + ~data:block_set' ) + in + { state with + blocks_seen_by_node = blocks_seen_by_node' + ; blocks_including_txn = blocks_including_txn' + } ) ) + : _ Event_router.event_subscription ) ; + (r, w) + + let reader ((reader, _) : gen) = reader + + let close ((_, writer) : gen) = Broadcast_pipe.Writer.close writer + end end From ba6acdf3b62f4bb0a25a311d84327e2b9de0ed46 Mon Sep 17 00:00:00 2001 From: glyh Date: Fri, 24 Oct 2025 19:23:08 +0800 Subject: [PATCH 08/13] Lucy Lib > Network State Generator: ensure all subscription is canceled after the generator is closed --- src/lib/testing/integration_test_lib/intf.ml | 3 ++ .../integration_test_lib/network_state.ml | 29 ++++++++++++------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/lib/testing/integration_test_lib/intf.ml b/src/lib/testing/integration_test_lib/intf.ml index 421361d3d68b..000c435bdbab 100644 --- a/src/lib/testing/integration_test_lib/intf.ml +++ b/src/lib/testing/integration_test_lib/intf.ml @@ -226,6 +226,9 @@ module Dsl = struct (* HACK: I can't name it `gen` due to name collision *) type gen + (* Create a network state generator that could be broadcast-consumed from + event router. Under the hood, it's aggregating on events interesting to + the network state *) val from_router : logger:Logger.t -> Event_router.t -> gen val reader : gen -> t Broadcast_pipe.Reader.t diff --git a/src/lib/testing/integration_test_lib/network_state.ml b/src/lib/testing/integration_test_lib/network_state.ml index d812fe26df33..2525e153950b 100644 --- a/src/lib/testing/integration_test_lib/network_state.ml +++ b/src/lib/testing/integration_test_lib/network_state.ml @@ -81,17 +81,24 @@ module Make } module Generator = struct - type gen = t Broadcast_pipe.Reader.t * t Broadcast_pipe.Writer.t + type gen = + { reader : t Broadcast_pipe.Reader.t + ; writer : t Broadcast_pipe.Writer.t + ; closed : unit Ivar.t + } let from_router ~logger event_router = let r, w = Broadcast_pipe.create empty in + let closed = Ivar.create () in let update ~f = - (* should be safe to ignore the write here, so long as `f` is synchronous *) - let state = f (Broadcast_pipe.Reader.peek r) in - [%log debug] "updated network state to: $state" - ~metadata:[ ("state", to_yojson state) ] ; - ignore (Broadcast_pipe.Writer.write w state : unit Deferred.t) ; - Deferred.return `Continue + if Ivar.is_full closed then Deferred.return (`Stop ()) + else + (* should be safe to ignore the write here, so long as `f` is synchronous *) + let state = f (Broadcast_pipe.Reader.peek r) in + [%log debug] "updated network state to: $state" + ~metadata:[ ("state", to_yojson state) ] ; + ignore (Broadcast_pipe.Writer.write w state : unit Deferred.t) ; + Deferred.return `Continue in (* handle_block_produced *) ignore @@ -328,10 +335,12 @@ module Make ; blocks_including_txn = blocks_including_txn' } ) ) : _ Event_router.event_subscription ) ; - (r, w) + { reader = r; writer = w; closed } - let reader ((reader, _) : gen) = reader + let reader ({ reader; _ } : gen) = reader - let close ((_, writer) : gen) = Broadcast_pipe.Writer.close writer + let close ({ writer; closed; _ } : gen) = + Ivar.fill closed () ; + Broadcast_pipe.Writer.close writer end end From b9a4e44dcf7f8d97d52af89f01108bc0fab40104 Mon Sep 17 00:00:00 2001 From: glyh Date: Fri, 24 Oct 2025 19:26:22 +0800 Subject: [PATCH 09/13] Lucy > Wait_condition: simplify all_equal --- src/lib/testing/integration_test_lib/wait_condition.ml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/lib/testing/integration_test_lib/wait_condition.ml b/src/lib/testing/integration_test_lib/wait_condition.ml index ebd8bf6cd59b..a660d96ccca8 100644 --- a/src/lib/testing/integration_test_lib/wait_condition.ml +++ b/src/lib/testing/integration_test_lib/wait_condition.ml @@ -1,9 +1,11 @@ open Core_kernel open Mina_base -let all_equal ~equal ~compare ls = - Option.value_map (List.hd ls) ~default:true ~f:(fun h -> - List.equal equal [ h ] (List.find_all_dups ~compare ls) ) +let all_equal ~equal = function + | [] -> + true + | hd :: rest -> + List.for_all ~f:(equal hd) rest module Make (Engine : Intf.Engine.S) @@ -193,7 +195,6 @@ struct let check () state = let all_best_tips_equal = all_equal ~equal:[%equal: State_hash.t option] - ~compare:[%compare: State_hash.t option] in let best_tips = List.map nodes ~f:(fun node -> From 0dd1faba0e588d5399879d25d516fc8427bdfc09 Mon Sep 17 00:00:00 2001 From: glyh Date: Fri, 24 Oct 2025 19:41:13 +0800 Subject: [PATCH 10/13] Lucy Lib: Wait Condition: Simplify transition_frontier_loaded_from_persistence implementation --- .../testing/integration_test_lib/wait_condition.ml | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/lib/testing/integration_test_lib/wait_condition.ml b/src/lib/testing/integration_test_lib/wait_condition.ml index a660d96ccca8..e89bc207be82 100644 --- a/src/lib/testing/integration_test_lib/wait_condition.ml +++ b/src/lib/testing/integration_test_lib/wait_condition.ml @@ -120,13 +120,13 @@ struct , state.num_transition_frontier_loaded_from_persistence ) in - let check init state = + let check condition state = let ( num_init_persisted_frontier_loaded , num_init_persisted_frontier_fresh_boot , num_init_bootstrap_required , num_init_persisted_frontier_dropped , num_init_transition_frontier_loaded_from_persistence ) = - init + condition in let fresh_data_condition = @@ -153,13 +153,7 @@ struct && state.num_transition_frontier_loaded_from_persistence > num_init_transition_frontier_loaded_from_persistence then Predicate_passed - else - Predicate_continuation - ( num_init_persisted_frontier_loaded - , num_init_persisted_frontier_fresh_boot - , num_init_bootstrap_required - , num_init_persisted_frontier_dropped - , num_init_transition_frontier_loaded_from_persistence ) + else Predicate_continuation condition in { id = Transition_frontier_loaded_from_persistence ; description = From c68241ac214ca7e7dccabb413cf9d34bcd86dc31 Mon Sep 17 00:00:00 2001 From: glyh Date: Fri, 24 Oct 2025 19:45:32 +0800 Subject: [PATCH 11/13] Lucy Lib > Wait Condition: Format some comments --- src/lib/testing/integration_test_lib/wait_condition.ml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib/testing/integration_test_lib/wait_condition.ml b/src/lib/testing/integration_test_lib/wait_condition.ml index e89bc207be82..1e2be03021c0 100644 --- a/src/lib/testing/integration_test_lib/wait_condition.ml +++ b/src/lib/testing/integration_test_lib/wait_condition.ml @@ -167,7 +167,9 @@ struct } let block_height_growth ~height_growth = - (* block height is an objective measurement for the whole chain. block height growth checks that the block height increased by the desired_height since the wait condition was called *) + (* block height is an objective measurement for the whole chain. block + this condition checks that the block height increased by [height_growth] + since the wait condition was called *) let init state = Predicate_continuation state.block_height in let check initial_height (state : Network_state.t) = if state.block_height - initial_height >= height_growth then From c68daa02440a17818602d9555e9ad43b13a96147 Mon Sep 17 00:00:00 2001 From: glyh Date: Fri, 24 Oct 2025 20:22:18 +0800 Subject: [PATCH 12/13] Fix formatting issue for medium bootstrap --- src/app/test_executive/medium_bootstrap.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/test_executive/medium_bootstrap.ml b/src/app/test_executive/medium_bootstrap.ml index ccfb9edcef9d..1814083698f3 100644 --- a/src/app/test_executive/medium_bootstrap.ml +++ b/src/app/test_executive/medium_bootstrap.ml @@ -87,7 +87,8 @@ module Make (Inputs : Intf.Test.Inputs_intf) = struct section_hard "network is fully connected after one node was restarted" (let%bind () = Malleable_error.lift (after (Time.Span.of_sec 240.0)) in let%bind final_connectivity_data = - fetch_connectivity_data ~logger (Core.String.Map.data all_daemon_nodes) + fetch_connectivity_data ~logger + (Core.String.Map.data all_daemon_nodes) in assert_peers_completely_connected final_connectivity_data ) in From 3c584283cc4e05e6aa2fb6a04a95a3f1770def76 Mon Sep 17 00:00:00 2001 From: glyh Date: Fri, 24 Oct 2025 20:47:39 +0800 Subject: [PATCH 13/13] Lucy Lib: remove mina_agent_image and mina_points_image, unused --- src/app/test_executive/test_executive.ml | 2 -- src/lib/testing/integration_test_lib/test_config.ml | 7 +------ .../testing/integration_test_local_engine/mina_docker.ml | 4 ---- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/src/app/test_executive/test_executive.ml b/src/app/test_executive/test_executive.ml index 12680718f332..2334c89d1e1f 100644 --- a/src/app/test_executive/test_executive.ml +++ b/src/app/test_executive/test_executive.ml @@ -290,8 +290,6 @@ let main inputs = { Test_config.Container_images.mina = inputs.mina_image ; archive_node = Option.value inputs.archive_image ~default:"archive_image_unused" - ; user_agent = "codaprotocol/coda-user-agent:0.1.5" - ; points = "codaprotocol/coda-points-hack:32b.4" } in let test_config = T.config ~constants in diff --git a/src/lib/testing/integration_test_lib/test_config.ml b/src/lib/testing/integration_test_lib/test_config.ml index a8aadc2800ea..5e2f4a5b4d67 100644 --- a/src/lib/testing/integration_test_lib/test_config.ml +++ b/src/lib/testing/integration_test_lib/test_config.ml @@ -1,12 +1,7 @@ open Core_kernel module Container_images = struct - type t = - { mina : string - ; archive_node : string - ; user_agent : string - ; points : string - } + type t = { mina : string; archive_node : string } end module Test_account = struct diff --git a/src/lib/testing/integration_test_local_engine/mina_docker.ml b/src/lib/testing/integration_test_local_engine/mina_docker.ml index 8674a29e73d1..61ea50c4546a 100644 --- a/src/lib/testing/integration_test_local_engine/mina_docker.ml +++ b/src/lib/testing/integration_test_local_engine/mina_docker.ml @@ -14,8 +14,6 @@ module Network_config = struct { docker_swarm_version : string ; stack_name : string ; mina_image : string - ; mina_agent_image : string - ; mina_points_image : string ; mina_archive_image : string ; runtime_config : Yojson.Safe.t ; seed_configs : Docker_node_config.Seed_config.t list @@ -561,8 +559,6 @@ module Network_config = struct { docker_swarm_version ; stack_name ; mina_image = images.mina - ; mina_agent_image = images.user_agent - ; mina_points_image = images.points ; mina_archive_image = images.archive_node ; runtime_config = Runtime_config.to_yojson runtime_config ; log_precomputed_blocks