From 41efe853aee6e002826b6de41bd69c60e7d3f55e Mon Sep 17 00:00:00 2001 From: Robin Bate Boerop Date: Sat, 13 Apr 2024 14:16:14 +0000 Subject: [PATCH] Revert "Revert "Precomputed block logging local compatible (#3)"" This reverts commit 2200c82bafabfdc95c47ea8d3aa5f698bdf38f9e. --- .../src/cli_entrypoint/mina_cli_entrypoint.ml | 16 ++- src/lib/mina_lib/coda_subscriptions.ml | 120 +++++++++++++----- src/lib/mina_lib/config.ml | 3 +- src/lib/mina_lib/mina_lib.ml | 40 +++++- src/lib/mina_lib/mina_lib.mli | 1 + 5 files changed, 136 insertions(+), 44 deletions(-) diff --git a/src/app/cli/src/cli_entrypoint/mina_cli_entrypoint.ml b/src/app/cli/src/cli_entrypoint/mina_cli_entrypoint.ml index a78496da6bb0..2832fa96a82d 100644 --- a/src/app/cli/src/cli_entrypoint/mina_cli_entrypoint.ml +++ b/src/app/cli/src/cli_entrypoint/mina_cli_entrypoint.ml @@ -352,11 +352,15 @@ let setup_daemon logger = with full proving (full), snark-testing with dummy proofs (check), or \ dummy proofs (none)" and plugins = plugin_flag - and precomputed_blocks_path = + and precomputed_blocks_file = flag "--precomputed-blocks-file" ~aliases:[ "precomputed-blocks-file" ] (optional string) - ~doc:"PATH Path to write precomputed blocks to, for replay or archiving" + ~doc:"PATH File to append precomputed blocks to, for replay or archiving." + and precomputed_blocks_dir = + flag "--precomputed-blocks-dir" + ~aliases:[ "precomputed-blocks-dir" ] + (optional string) ~doc:"PATH Directory to dump precomputed blocks to." and log_precomputed_blocks = flag "--log-precomputed-blocks" ~aliases:[ "log-precomputed-blocks" ] @@ -1304,10 +1308,10 @@ Pass one of -peer, -peer-list-file, -seed, -peer-list-url.|} ; ~consensus_local_state ~is_archive_rocksdb ~work_reassignment_wait ~archive_process_location ~log_block_creation ~precomputed_values ~start_time - ?precomputed_blocks_path ~log_precomputed_blocks - ~upload_blocks_to_gcloud ~block_reward_threshold ~uptime_url - ~uptime_submitter_keypair ~stop_time ~node_status_url - ~node_status_type () ) + ?precomputed_blocks_file ?precomputed_blocks_dir + ~log_precomputed_blocks ~upload_blocks_to_gcloud + ~block_reward_threshold ~uptime_url ~uptime_submitter_keypair + ~stop_time ~node_status_url () ) in { Coda_initialization.coda ; client_trustlist diff --git a/src/lib/mina_lib/coda_subscriptions.ml b/src/lib/mina_lib/coda_subscriptions.ml index 1c270b6225f9..baee582c3397 100644 --- a/src/lib/mina_lib/coda_subscriptions.ml +++ b/src/lib/mina_lib/coda_subscriptions.ml @@ -14,6 +14,11 @@ module Optional_public_key = struct include Hashable.Make (T) end +module Precomputed_block_writer = struct + type t = { file : string option; dir : string option; log : bool } + [@@deriving fields] +end + type t = { subscribed_payment_users : Signed_command.t reader_and_writer Public_key.Compressed.Table.t @@ -98,16 +103,56 @@ let create ~logger ~constraint_constants ~wallets ~new_blocks Pipe.write_without_pushback writer { With_hash.data; hash } ) ) ~if_not_found:ignore in + let dump_precomputed_blocks = + is_some (!precomputed_block_writer : Precomputed_block_writer.t).dir + in + let network = + match Core.Sys.getenv "NETWORK_NAME" with + | Some network -> + if upload_blocks_to_gcloud || dump_precomputed_blocks then + [%log info] "NETWORK_NAME environment variable set to %s" network ; + network + | _ -> + if upload_blocks_to_gcloud || dump_precomputed_blocks then + [%log warn] + "NETWORK_NAME environment variable not set. Default to 'mainnet'" ; + "mainnet" + in let gcloud_keyfile = match Core.Sys.getenv "GCLOUD_KEYFILE" with | Some keyfile -> + if upload_blocks_to_gcloud then + [%log info] "GCLOUD_KEYFILE environment variable set to %s" keyfile ; Some keyfile | _ -> - [%log warn] - "GCLOUD_KEYFILE environment variable not set. Must be set to use \ - upload_blocks_to_gcloud" ; + if upload_blocks_to_gcloud then + [%log warn] + "GCLOUD_KEYFILE environment variable not set. Must be set to use \ + upload_blocks_to_gcloud" ; None in + let gcloud_bucket = + match Core.Sys.getenv "GCLOUD_BLOCK_UPLOAD_BUCKET" with + | Some bucket -> + if upload_blocks_to_gcloud then + [%log info] + "GCLOUD_BLOCK_UPLOAD_BUCKET environment variable set to %s" bucket ; + Some bucket + | _ -> + if upload_blocks_to_gcloud then + [%log warn] + "GCLOUD_BLOCK_UPLOAD_BUCKET environment variable not set. Must be \ + set to use upload_blocks_to_gcloud" ; + None + in + Option.iter !precomputed_block_writer.file ~f:(fun path -> + [%log info] + ~metadata:[ ("path", `String path) ] + "Precomputed blocks will be logged to the same file $path" ) ; + Option.iter !precomputed_block_writer.dir ~f:(fun path -> + [%log info] + ~metadata:[ ("path", `String path) ] + "Precomputed blocks will be logged to individual files in $path" ) ; Option.iter gcloud_keyfile ~f:(fun path -> ignore ( Core.Sys.command @@ -121,7 +166,9 @@ let create ~logger ~constraint_constants ~wallets ~new_blocks Mina_block.Validated.forget new_block |> State_hash.With_state_hashes.state_hash in - (let path, log = !precomputed_block_writer in + (let Precomputed_block_writer.{ file; dir; log } = + !precomputed_block_writer + in let precomputed_block = lazy (let scheduled_time = Block_time.now time_controller in @@ -132,31 +179,11 @@ let create ~logger ~constraint_constants ~wallets ~new_blocks in Precomputed.to_yojson precomputed_block ) in - if upload_blocks_to_gcloud then ( - [%log info] "log" ; + (* Upload precomputed blocks to gcloud *) + ( if upload_blocks_to_gcloud then let json = Yojson.Safe.to_string (Lazy.force precomputed_block) in - let network = - match Core.Sys.getenv "NETWORK_NAME" with - | Some network -> - Some network - | _ -> - [%log warn] - "NETWORK_NAME environment variable not set. Must be set \ - to use upload_blocks_to_gcloud" ; - None - in - let bucket = - match Core.Sys.getenv "GCLOUD_BLOCK_UPLOAD_BUCKET" with - | Some bucket -> - Some bucket - | _ -> - [%log warn] - "GCLOUD_BLOCK_UPLOAD_BUCKET environment variable not set. \ - Must be set to use upload_blocks_to_gcloud" ; - None - in - match (gcloud_keyfile, network, bucket) with - | Some _, Some network, Some bucket -> + match (gcloud_keyfile, gcloud_bucket) with + | Some _, Some bucket -> let hash_string = State_hash.to_base58_check hash in let height = Mina_block.Validated.forget new_block @@ -166,6 +193,13 @@ let create ~logger ~constraint_constants ~wallets ~new_blocks let name = sprintf "%s-%s-%s.json" network height hash_string in + [%log info] + ~metadata: + [ ("hash", `String hash_string) + ; ("height", `String height) + ; ("bucket", `String bucket) + ] + "Uploading precomputed block with $hash to gcloud $bucket" ; (* TODO: Use a pipe to queue this if these are building up *) don't_wait_for ( Mina_metrics.( @@ -217,16 +251,38 @@ let create ~logger ~constraint_constants ~wallets ~new_blocks ) | _ -> () ) ; - Option.iter path ~f:(fun (`Path path) -> + (* Write precomputed blocks locally *) + Option.iter file ~f:(fun path -> + let json = + Yojson.Safe.to_string (Lazy.force precomputed_block) + in + (* original functionality, appends to single file *) Out_channel.with_file ~append:true path ~f:(fun out_channel -> - Out_channel.output_lines out_channel - [ Yojson.Safe.to_string (Lazy.force precomputed_block) ] ) ) ; + Out_channel.output_lines out_channel [ json ] ) ) ; + Option.iter dir ~f:(fun path -> + (* write precomputed blocks to individual files in the directory *) + let json = + Yojson.Safe.to_string (Lazy.force precomputed_block) + in + let hash_string = State_hash.to_base58_check hash in + let height = + Mina_block.Validated.forget new_block + |> With_hash.data |> Mina_block.blockchain_length + |> Mina_numbers.Length.to_string + in + let name = sprintf "%s-%s-%s.json" network height hash_string in + let fpath = Core.Filename.(parts path @ [ name ] |> of_parts) in + Out_channel.with_file ~append:false fpath ~f:(fun out_channel -> + Out_channel.output_lines out_channel [ json ] ) ; + [%log info] + ~metadata:[ ("block", `String name); ("path", `String path) ] + "Logged precomputed $block to $path" ) ; [%log info] "Saw block with state hash $state_hash" ~metadata: (let state_hash_data = [ ("state_hash", `String (State_hash.to_base58_check hash)) ] in - if is_some log then + if log then state_hash_data @ [ ("precomputed_block", Lazy.force precomputed_block) ] else state_hash_data ) ) ; diff --git a/src/lib/mina_lib/config.ml b/src/lib/mina_lib/config.ml index 7a049af7150c..a805635606e1 100644 --- a/src/lib/mina_lib/config.ml +++ b/src/lib/mina_lib/config.ml @@ -51,7 +51,8 @@ type t = ; log_block_creation : bool [@default false] ; precomputed_values : Precomputed_values.t ; start_time : Time.t - ; precomputed_blocks_path : string option + ; precomputed_blocks_file : string option + ; precomputed_blocks_dir : string option ; log_precomputed_blocks : bool ; upload_blocks_to_gcloud : bool ; block_reward_threshold : Currency.Amount.t option [@default None] diff --git a/src/lib/mina_lib/mina_lib.ml b/src/lib/mina_lib/mina_lib.ml index 24cdb3dcb266..dca076f6eb84 100644 --- a/src/lib/mina_lib/mina_lib.ml +++ b/src/lib/mina_lib/mina_lib.ml @@ -10,6 +10,7 @@ module Archive_client = Archive_client module Config = Config module Conf_dir = Conf_dir module Subscriptions = Coda_subscriptions +module Precomputed_block_writer = Subscriptions.Precomputed_block_writer module Snark_worker_lib = Snark_worker module Timeout = Timeout_lib.Core_time @@ -104,8 +105,7 @@ type t = Daemon_rpcs.Types.Status.Next_producer_timing.t option ; subscriptions : Coda_subscriptions.t ; sync_status : Sync_status.t Mina_incremental.Status.Observer.t - ; precomputed_block_writer : - ([ `Path of string ] option * [ `Log ] option) ref + ; precomputed_block_writer : Precomputed_block_writer.t ref ; block_production_status : [ `Producing | `Producing_in_ms of float | `Free ] ref ; in_memory_reverse_structured_log_messages_for_integration_test : @@ -1986,11 +1986,41 @@ let create ?wallets (config : Config.t) = Archive_client.run ~logger:config.logger ~frontier_broadcast_pipe:frontier_broadcast_pipe_r archive_process_port ) ; + (* Local block writing *) let precomputed_block_writer = + let file = + try + Option.map config.precomputed_blocks_file ~f:(fun path -> + match Core.Unix.(lstat path).st_kind with + | S_REG -> + path + | _ -> + [%log' error config.logger] + ~metadata:[ ("path", `String path) ] + "$path is not a regular Unix file. Local precomputed \ + block appending disabled." ; + failwith "No precomputed block appending" ) + with _ -> None + in + let dir = + try + Option.map config.precomputed_blocks_dir ~f:(fun path -> + match Core.Unix.(lstat path).st_kind with + | S_DIR -> + path + | _ -> + [%log' error config.logger] + ~metadata:[ ("path", `String path) ] + "$path is not a regular Unix directory. Local \ + precomputed block dumping disabled." ; + failwith "No precomputed block dumping" ) + with _ -> None + in ref - ( Option.map config.precomputed_blocks_path ~f:(fun path -> - `Path path ) - , if config.log_precomputed_blocks then Some `Log else None ) + { Precomputed_block_writer.file + ; dir + ; log = config.log_precomputed_blocks + } in let subscriptions = Coda_subscriptions.create ~logger:config.logger diff --git a/src/lib/mina_lib/mina_lib.mli b/src/lib/mina_lib/mina_lib.mli index f47de5999a2e..94a1e91c018f 100644 --- a/src/lib/mina_lib/mina_lib.mli +++ b/src/lib/mina_lib/mina_lib.mli @@ -9,6 +9,7 @@ module Archive_client = Archive_client module Config = Config module Conf_dir = Conf_dir module Subscriptions = Coda_subscriptions +module Precomputed_block_writer = Subscriptions.Precomputed_block_writer type t