• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

MinaProtocol / mina / 511

22 Aug 2025 04:04PM UTC coverage: 32.207% (-29.1%) from 61.292%
511

push

buildkite

web-flow
Merge pull request #17655 from MinaProtocol/cjjdespres/prepare-fork-config-in-mina-lib

Prepare fork config inputs in mina_lib

0 of 90 new or added lines in 3 files covered. (0.0%)

19226 existing lines in 393 files now uncovered.

23294 of 72325 relevant lines covered (32.21%)

24698.94 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

4.58
/src/lib/transition_frontier/persistent_root/persistent_root.ml
1
open Core
58✔
2
open Mina_base
3
module Ledger = Mina_ledger.Ledger
4
open Frontier_base
5
module Ledger_transfer = Mina_ledger.Ledger_transfer.Make (Ledger) (Ledger.Db)
6
module Ledger_transfer_stable =
7
  Mina_ledger.Ledger_transfer.Make (Ledger.Db) (Ledger.Db)
8

9
let transfer_snarked_root =
10
  Ledger.Root.transfer_accounts_with
11
    ~stable:Ledger_transfer_stable.transfer_accounts
12

13
let genesis_root_identifier ~genesis_state_hash =
UNCOV
14
  let open Root_identifier.Stable.Latest in
×
15
  { state_hash = genesis_state_hash }
16

17
let with_file ?size filename access_level ~f =
UNCOV
18
  let open Unix in
×
19
  let shared, mode =
20
    match access_level with
UNCOV
21
    | `Read ->
×
22
        (false, [ O_RDONLY ])
UNCOV
23
    | `Write ->
×
24
        (true, [ O_RDWR; O_TRUNC; O_CREAT ])
25
  in
26
  let fd = Unix.openfile filename ~mode in
UNCOV
27
  let buf_size =
×
28
    match size with
UNCOV
29
    | None ->
×
UNCOV
30
        Int64.to_int_exn Unix.(fstat fd).st_size
×
UNCOV
31
    | Some sz ->
×
32
        sz
33
  in
34
  (* Bigstring.map_file has been removed. We copy its old implementation. *)
35
  let buf =
36
    Bigarray.(
UNCOV
37
      array1_of_genarray
×
UNCOV
38
        (Core.Unix.map_file fd char c_layout ~shared [| buf_size |]))
×
39
  in
40
  let x = f buf in
UNCOV
41
  Bigstring.unsafe_destroy buf ;
×
UNCOV
42
  Unix.close fd ;
×
UNCOV
43
  x
×
44

45
(* TODO: create a reusable singleton factory abstraction *)
46
module rec Instance_type : sig
47
  type t =
48
    { snarked_ledger : Ledger.Root.t
49
    ; potential_snarked_ledgers : Ledger.Root.Config.t Queue.t
50
    ; factory : Factory_type.t
51
    }
52
end =
53
  Instance_type
54

55
and Factory_type : sig
56
  type t =
57
    { directory : string
58
    ; logger : Logger.t
59
    ; mutable instance : Instance_type.t option
60
    ; ledger_depth : int
61
    ; backing_type : Ledger.Root.Config.backing_type
62
    }
63
end =
64
  Factory_type
65

66
open Instance_type
67
open Factory_type
68

69
module Instance = struct
70
  type t = Instance_type.t
71

72
  module Config = struct
73
    (** Helper to create a filesystem location (for a file or directory) inside
74
        the [Factory_type.t] directory. *)
UNCOV
75
    let make_instance_location filename t = Filename.concat t.directory filename
×
76

77
    (** Helper to create a [Root.Config.t] for a snarked ledger based on a
78
        subdirectory of the [Factory_type.t] directory *)
79
    let make_instance_config subdirectory t =
UNCOV
80
      Ledger.Root.Config.with_directory ~backing_type:t.backing_type
×
UNCOV
81
        ~directory_name:(make_instance_location subdirectory t)
×
82

83
    (** The config for the actual snarked ledger that is initialized and used by
84
        the daemon *)
85
    let snarked_ledger = make_instance_config "snarked_ledger"
58✔
86

87
    (** The config for the temporary snarked ledger, used while recovering a
88
        vaild potential snarked ledger during startup *)
89
    let tmp_snarked_ledger = make_instance_config "tmp_snarked_ledger"
58✔
90

91
    (** The name of a json file that lists the directory names of the potential
92
        snarked ledgers in the [potential_snarked_ledgers] queue *)
93
    let potential_snarked_ledgers =
94
      make_instance_location "potential_snarked_ledgers.json"
58✔
95

96
    (** A method that generates fresh potential snarked ledger configs, each
97
        using a distinct root subdirectory *)
98
    let make_potential_snarked_ledger t =
99
      let uuid = Uuid_unix.create () in
×
100
      make_instance_config ("snarked_ledger" ^ Uuid.to_string_hum uuid) t
×
101

102
    (** The name of the file recording the [Root_identifier.t] of the snarked
103
        root *)
104
    let root_identifier = make_instance_location "root"
58✔
105
  end
106

107
  let potential_snarked_ledgers_to_yojson queue =
108
    `List
×
109
      (List.map (Queue.to_list queue) ~f:(fun config ->
×
110
           `String (Ledger.Root.Config.primary_directory config) ) )
×
111

112
  let potential_snarked_ledgers_of_yojson factory json =
113
    Yojson.Safe.Util.to_list json
×
114
    |> List.map ~f:(fun x ->
115
           let directory_name = Yojson.Safe.Util.to_string x in
×
116
           Config.make_instance_config directory_name factory )
×
117

118
  let load_potential_snarked_ledgers_from_disk factory =
UNCOV
119
    let location = Config.potential_snarked_ledgers factory in
×
UNCOV
120
    if phys_equal (Sys.file_exists location) `Yes then
×
121
      Yojson.Safe.from_file location
×
122
      |> potential_snarked_ledgers_of_yojson factory
UNCOV
123
    else []
×
124

125
  let write_potential_snarked_ledgers_to_disk t =
126
    Yojson.Safe.to_file
×
127
      (Config.potential_snarked_ledgers t.factory)
×
128
      (potential_snarked_ledgers_to_yojson t.potential_snarked_ledgers)
×
129

130
  let enqueue_snarked_ledger ~config t =
131
    Queue.enqueue t.potential_snarked_ledgers config ;
×
132
    write_potential_snarked_ledgers_to_disk t
×
133

134
  let dequeue_snarked_ledger t =
135
    let config = Queue.dequeue_exn t.potential_snarked_ledgers in
×
136
    Ledger.Root.Config.delete_any_backing config ;
×
137
    write_potential_snarked_ledgers_to_disk t
×
138

139
  let destroy t =
UNCOV
140
    List.iter
×
UNCOV
141
      (Queue.to_list t.potential_snarked_ledgers)
×
142
      ~f:Ledger.Root.Config.delete_any_backing ;
UNCOV
143
    Mina_stdlib_unix.File_system.rmrf
×
UNCOV
144
      (Config.potential_snarked_ledgers t.factory) ;
×
UNCOV
145
    Ledger.Root.close t.snarked_ledger ;
×
UNCOV
146
    t.factory.instance <- None
×
147

148
  let close t =
UNCOV
149
    Ledger.Root.close t.snarked_ledger ;
×
UNCOV
150
    t.factory.instance <- None
×
151

152
  let create factory =
UNCOV
153
    let snarked_ledger =
×
154
      Ledger.Root.create ~depth:factory.ledger_depth
UNCOV
155
        ~config:(Config.snarked_ledger factory)
×
156
        ()
157
    in
UNCOV
158
    { snarked_ledger; potential_snarked_ledgers = Queue.create (); factory }
×
159

160
  (** When we load from disk,
161
      1. Check the potential_snarked_ledgers to see if any one of these
162
         matches the snarked_ledger_hash in persistent_frontier;
163
      2. if none of those works, we load the old snarked_ledger and check if
164
         the old snarked_ledger matches with persistent_frontier;
165
      3. if not, we just reset all the persisted data and start from genesis
166
   *)
167
  let load_from_disk factory ~snarked_ledger_hash ~logger =
UNCOV
168
    let potential_snarked_ledgers =
×
169
      load_potential_snarked_ledgers_from_disk factory
170
    in
UNCOV
171
    let snarked_ledger =
×
172
      List.fold_until potential_snarked_ledgers ~init:None
173
        ~f:(fun _ config ->
174
          let potential_snarked_ledger =
×
175
            Ledger.Root.create ~depth:factory.ledger_depth ~config ()
176
          in
177
          let potential_snarked_ledger_hash =
×
178
            Frozen_ledger_hash.of_ledger_hash
179
            @@ Ledger.Root.merkle_root potential_snarked_ledger
×
180
          in
181
          [%log debug]
×
182
            ~metadata:
183
              [ ( "potential_snarked_ledger_hash"
184
                , Frozen_ledger_hash.to_yojson potential_snarked_ledger_hash )
×
185
              ]
186
            "loaded potential_snarked_ledger from disk" ;
187
          if
×
188
            Frozen_ledger_hash.equal potential_snarked_ledger_hash
189
              snarked_ledger_hash
190
          then (
×
191
            let snarked_ledger =
192
              Ledger.Root.create ~depth:factory.ledger_depth
193
                ~config:(Config.tmp_snarked_ledger factory)
×
194
                ()
195
            in
196
            match
×
197
              transfer_snarked_root ~src:potential_snarked_ledger
198
                ~dest:snarked_ledger
199
            with
200
            | Ok _ ->
×
201
                Ledger.Root.close potential_snarked_ledger ;
202
                Ledger.Root.Config.delete_any_backing
×
203
                @@ Config.snarked_ledger factory ;
×
204
                Ledger.Root.Config.move_backing_exn
×
205
                  ~src:(Config.tmp_snarked_ledger factory)
×
206
                  ~dst:(Config.snarked_ledger factory) ;
×
207
                List.iter potential_snarked_ledgers
208
                  ~f:Ledger.Root.Config.delete_any_backing ;
209
                Mina_stdlib_unix.File_system.rmrf
×
210
                  (Config.potential_snarked_ledgers factory) ;
×
211
                Stop (Some snarked_ledger)
×
212
            | Error e ->
×
213
                Ledger.Root.close potential_snarked_ledger ;
214
                List.iter potential_snarked_ledgers
×
215
                  ~f:Ledger.Root.Config.delete_any_backing ;
216
                Mina_stdlib_unix.File_system.rmrf
×
217
                  (Config.potential_snarked_ledgers factory) ;
×
218
                [%log' error factory.logger]
×
219
                  ~metadata:[ ("error", `String (Error.to_string_hum e)) ]
×
220
                  "Ledger_transfer failed" ;
221
                Stop None )
×
222
          else (
×
223
            Ledger.Root.close potential_snarked_ledger ;
224
            Continue None ) )
×
225
        ~finish:(fun _ ->
UNCOV
226
          List.iter potential_snarked_ledgers
×
227
            ~f:Ledger.Root.Config.delete_any_backing ;
UNCOV
228
          Mina_stdlib_unix.File_system.rmrf
×
UNCOV
229
            (Config.potential_snarked_ledgers factory) ;
×
UNCOV
230
          None )
×
231
    in
UNCOV
232
    match snarked_ledger with
×
UNCOV
233
    | None ->
×
234
        let snarked_ledger =
235
          Ledger.Root.create ~depth:factory.ledger_depth
UNCOV
236
            ~config:(Config.snarked_ledger factory)
×
237
            ()
238
        in
UNCOV
239
        let potential_snarked_ledger_hash =
×
240
          Frozen_ledger_hash.of_ledger_hash
UNCOV
241
          @@ Ledger.Root.merkle_root snarked_ledger
×
242
        in
UNCOV
243
        if
×
244
          Frozen_ledger_hash.equal potential_snarked_ledger_hash
245
            snarked_ledger_hash
246
        then
UNCOV
247
          Ok
×
248
            { snarked_ledger
UNCOV
249
            ; potential_snarked_ledgers = Queue.create ()
×
250
            ; factory
251
            }
252
        else (
×
253
          Ledger.Root.close snarked_ledger ;
254
          Error `Snarked_ledger_mismatch )
×
255
    | Some snarked_ledger ->
×
256
        Ok
257
          { snarked_ledger
258
          ; potential_snarked_ledgers = Queue.create ()
×
259
          ; factory
260
          }
261

UNCOV
262
  let snarked_ledger { snarked_ledger; _ } = snarked_ledger
×
263

264
  let set_root_identifier t new_root_identifier =
UNCOV
265
    [%log' trace t.factory.logger]
×
266
      ~metadata:
UNCOV
267
        [ ("root_identifier", Root_identifier.to_yojson new_root_identifier) ]
×
268
      "Setting persistent root identifier" ;
UNCOV
269
    let size = Root_identifier.Stable.Latest.bin_size_t new_root_identifier in
×
UNCOV
270
    with_file (Config.root_identifier t.factory) `Write ~size ~f:(fun buf ->
×
UNCOV
271
        ignore
×
UNCOV
272
          ( Root_identifier.Stable.Latest.bin_write_t buf ~pos:0
×
273
              new_root_identifier
274
            : int ) )
275

276
  (* defaults to genesis *)
277
  let load_root_identifier t =
UNCOV
278
    let file = Config.root_identifier t.factory in
×
UNCOV
279
    match Unix.access file [ `Exists; `Read ] with
×
280
    | Error _ ->
×
281
        None
UNCOV
282
    | Ok () ->
×
283
        with_file file `Read ~f:(fun buf ->
UNCOV
284
            let root_identifier =
×
285
              Root_identifier.Stable.Latest.bin_read_t buf ~pos_ref:(ref 0)
286
            in
UNCOV
287
            [%log' trace t.factory.logger]
×
288
              ~metadata:
UNCOV
289
                [ ("root_identifier", Root_identifier.to_yojson root_identifier)
×
290
                ]
291
              "Loaded persistent root identifier" ;
UNCOV
292
            Some root_identifier )
×
293

UNCOV
294
  let set_root_state_hash t state_hash = set_root_identifier t { state_hash }
×
295
end
296

297
type t = Factory_type.t
298

299
let create ~logger ~directory ~ledger_depth =
300
  (* TODO: Pass in from above. This should ultimately be determined by the value
301
     of the HF automation flag. *)
UNCOV
302
  let backing_type = Ledger.Root.Config.Stable_db in
×
303
  { directory; logger; instance = None; ledger_depth; backing_type }
304

305
let create_instance_exn t =
UNCOV
306
  assert (Option.is_none t.instance) ;
×
307
  let instance = Instance.create t in
UNCOV
308
  t.instance <- Some instance ;
×
309
  instance
310

311
let load_from_disk_exn t ~snarked_ledger_hash ~logger =
UNCOV
312
  let open Result.Let_syntax in
×
UNCOV
313
  assert (Option.is_none t.instance) ;
×
UNCOV
314
  let%map instance = Instance.load_from_disk t ~snarked_ledger_hash ~logger in
×
UNCOV
315
  t.instance <- Some instance ;
×
316
  instance
317

318
let with_instance_exn t ~f =
UNCOV
319
  let instance = create_instance_exn t in
×
UNCOV
320
  let x = f instance in
×
UNCOV
321
  Instance.close instance ; x
×
322

323
let reset_to_genesis_exn t ~precomputed_values =
UNCOV
324
  assert (Option.is_none t.instance) ;
×
325
  Mina_stdlib_unix.File_system.rmrf t.directory ;
UNCOV
326
  with_instance_exn t ~f:(fun instance ->
×
UNCOV
327
      ignore
×
UNCOV
328
        ( Precomputed_values.populate_root precomputed_values
×
UNCOV
329
            (Instance.snarked_ledger instance)
×
UNCOV
330
          |> Or_error.map ~f:Ledger.Root.as_unmasked
×
331
          : Ledger.Any_ledger.witness Or_error.t ) ;
332
      Instance.set_root_identifier instance
333
        (genesis_root_identifier
334
           ~genesis_state_hash:
UNCOV
335
             (Precomputed_values.genesis_state_hashes precomputed_values)
×
336
               .state_hash ) )
116✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc