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

MinaProtocol / mina / 2903

15 Nov 2024 01:59PM UTC coverage: 36.723% (-25.0%) from 61.682%
2903

Pull #16342

buildkite

dkijania
Merge branch 'dkijania/remove_publish_job_from_pr_comp' into dkijania/remove_publish_job_from_pr_dev
Pull Request #16342: [DEV] Publish debians only on nightly and stable

15 of 40 new or added lines in 14 files covered. (37.5%)

15175 existing lines in 340 files now uncovered.

24554 of 66863 relevant lines covered (36.72%)

20704.91 hits per line

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

22.69
/src/lib/runtime_config/runtime_config.ml
1
open Core_kernel
16✔
2
open Async
3

4
module Fork_config = struct
5
  (* Note that length might be smaller than the gernesis_slot
6
     or equal if a block was produced in every slot possible. *)
7
  type t =
16✔
8
    { state_hash : string
×
9
    ; blockchain_length : int (* number of blocks produced since genesis *)
×
10
    ; global_slot_since_genesis : int (* global slot since genesis *)
×
11
    }
12
  [@@deriving yojson, bin_io_unversioned]
64✔
13
end
14

15
let yojson_strip_fields ~keep_fields = function
16
  | `Assoc l ->
16✔
17
      `Assoc
18
        (List.filter l ~f:(fun (fld, _) ->
16✔
19
             Array.mem ~equal:String.equal keep_fields fld ) )
62✔
20
  | json ->
×
21
      json
22

23
let yojson_rename_fields ~alternates = function
24
  | `Assoc l ->
×
25
      `Assoc
26
        (List.map l ~f:(fun (fld, json) ->
×
27
             let fld =
×
28
               Option.value ~default:fld
29
                 (Array.find_map alternates ~f:(fun (alt, orig) ->
×
30
                      if String.equal fld alt then Some orig else None ) )
×
31
             in
32
             (fld, json) ) )
×
33
  | json ->
×
34
      json
35

36
let opt_fallthrough ~default x2 =
37
  Option.value_map ~default x2 ~f:(fun x -> Some x)
×
38

39
let result_opt ~f x =
40
  match x with
×
41
  | Some x ->
×
42
      Result.map ~f:Option.some (f x)
×
43
  | None ->
×
44
      Result.return None
45

46
let dump_on_error yojson x =
47
  Result.map_error x ~f:(fun str ->
16✔
48
      str ^ "\n\nCould not parse JSON:\n" ^ Yojson.Safe.pretty_to_string yojson )
×
49

50
let of_yojson_generic ~fields of_yojson json =
51
  dump_on_error json @@ of_yojson
16✔
52
  @@ yojson_strip_fields ~keep_fields:fields json
16✔
53

54
let rec deferred_list_fold ~init ~f = function
55
  | [] ->
×
56
      Async.Deferred.Result.return init
57
  | h :: t ->
×
58
      let open Async.Deferred.Result.Let_syntax in
59
      let%bind init = f init h in
×
60
      deferred_list_fold ~init ~f t
×
61

62
module Json_layout = struct
63
  module Accounts = struct
64
    module Single = struct
65
      module Timed = struct
66
        type t =
×
67
          { initial_minimum_balance : Currency.Balance.t
×
68
          ; cliff_time : Mina_numbers.Global_slot_since_genesis.t
×
69
          ; cliff_amount : Currency.Amount.t
×
70
          ; vesting_period : Mina_numbers.Global_slot_span.t
×
71
          ; vesting_increment : Currency.Amount.t
×
72
          }
73
        [@@deriving yojson, fields, sexp]
74

75
        let fields = Fields.names |> Array.of_list
16✔
76

77
        let of_yojson json = of_yojson_generic ~fields of_yojson json
×
78
      end
79

80
      module Permissions = struct
81
        module Auth_required = struct
82
          type t = None | Either | Proof | Signature | Impossible
×
83
          [@@deriving sexp, bin_io_unversioned]
64✔
84

85
          let to_yojson = function
86
            | None ->
3,388✔
87
                `String "none"
88
            | Either ->
×
89
                `String "either"
90
            | Proof ->
×
91
                `String "proof"
92
            | Signature ->
18,634✔
93
                `String "signature"
94
            | Impossible ->
×
95
                `String "impossible"
96

97
          let of_yojson = function
98
            | `String s -> (
×
99
                match String.lowercase s with
100
                | "none" ->
×
101
                    Ok None
102
                | "either" ->
×
103
                    Ok Either
104
                | "proof" ->
×
105
                    Ok Proof
106
                | "signature" ->
×
107
                    Ok Signature
108
                | "impossible" ->
×
109
                    Ok Impossible
110
                | _ ->
×
111
                    Error (sprintf "Invalid Auth_required.t value: %s" s) )
×
112
            | _ ->
×
113
                Error
114
                  "Runtime_config.Json_Account.Single.Permissions.Auth_Required.t"
115

116
          let of_account_perm = function
117
            | Mina_base.Permissions.Auth_required.None ->
×
118
                None
119
            | Either ->
×
120
                Either
121
            | Proof ->
×
122
                Proof
123
            | Signature ->
×
124
                Signature
125
            | Impossible ->
×
126
                Impossible
127

128
          let to_account_perm = function
129
            | None ->
×
130
                Mina_base.Permissions.Auth_required.None
131
            | Either ->
×
132
                Either
133
            | Proof ->
×
134
                Proof
135
            | Signature ->
×
136
                Signature
137
            | Impossible ->
×
138
                Impossible
139
        end
140

141
        module Txn_version = struct
142
          type t = Mina_numbers.Txn_version.Stable.Latest.t
16✔
143
          [@@deriving bin_io_unversioned]
64✔
144

145
          include (
146
            Mina_numbers.Txn_version :
147
              module type of Mina_numbers.Txn_version with type t := t )
148
        end
149

150
        module Verification_key_perm = struct
151
          type t = { auth : Auth_required.t; txn_version : Txn_version.t }
×
152
          [@@deriving sexp, yojson, bin_io_unversioned]
64✔
153
        end
154

155
        type t =
16✔
156
          { edit_state : Auth_required.t
×
157
                [@default
158
                  Auth_required.of_account_perm
×
159
                    Mina_base.Permissions.user_default.edit_state]
160
          ; send : Auth_required.t
×
161
                [@default
162
                  Auth_required.of_account_perm
×
163
                    Mina_base.Permissions.user_default.send]
164
          ; receive : Auth_required.t
×
165
                [@default
166
                  Auth_required.of_account_perm
×
167
                    Mina_base.Permissions.user_default.receive]
168
          ; access : Auth_required.t
×
169
                [@default
170
                  Auth_required.of_account_perm
×
171
                    Mina_base.Permissions.user_default.access]
172
          ; set_delegate : Auth_required.t
×
173
                [@default
174
                  Auth_required.of_account_perm
×
175
                    Mina_base.Permissions.user_default.set_delegate]
176
          ; set_permissions : Auth_required.t
×
177
                [@default
178
                  Auth_required.of_account_perm
×
179
                    Mina_base.Permissions.user_default.set_permissions]
180
          ; set_verification_key : Verification_key_perm.t
×
181
                [@default
182
                  { auth =
183
                      Auth_required.of_account_perm
×
184
                        (fst
×
185
                           Mina_base.Permissions.user_default
186
                             .set_verification_key )
187
                  ; txn_version =
188
                      snd
×
189
                        Mina_base.Permissions.user_default.set_verification_key
190
                  }]
191
          ; set_zkapp_uri : Auth_required.t
×
192
                [@default
193
                  Auth_required.of_account_perm
×
194
                    Mina_base.Permissions.user_default.set_zkapp_uri]
195
          ; edit_action_state : Auth_required.t
×
196
                [@default
197
                  Auth_required.of_account_perm
×
198
                    Mina_base.Permissions.user_default.edit_action_state]
199
          ; set_token_symbol : Auth_required.t
×
200
                [@default
201
                  Auth_required.of_account_perm
×
202
                    Mina_base.Permissions.user_default.set_token_symbol]
203
          ; increment_nonce : Auth_required.t
×
204
                [@default
205
                  Auth_required.of_account_perm
×
206
                    Mina_base.Permissions.user_default.increment_nonce]
207
          ; set_voting_for : Auth_required.t
×
208
                [@default
209
                  Auth_required.of_account_perm
×
210
                    Mina_base.Permissions.user_default.set_voting_for]
211
          ; set_timing : Auth_required.t
×
212
                [@default
213
                  Auth_required.of_account_perm
×
214
                    Mina_base.Permissions.user_default.set_timing]
215
          }
216
        [@@deriving yojson, fields, sexp, bin_io_unversioned]
64✔
217

218
        let fields = Fields.names |> Array.of_list
16✔
219

220
        let of_yojson json = of_yojson_generic ~fields of_yojson json
×
221

222
        let to_yojson t =
223
          `Assoc
1,694✔
224
            [ ("edit_state", Auth_required.to_yojson t.edit_state)
1,694✔
225
            ; ("send", Auth_required.to_yojson t.send)
1,694✔
226
            ; ("receive", Auth_required.to_yojson t.receive)
1,694✔
227
            ; ("access", Auth_required.to_yojson t.access)
1,694✔
228
            ; ("set_delegate", Auth_required.to_yojson t.set_delegate)
1,694✔
229
            ; ("set_permissions", Auth_required.to_yojson t.set_permissions)
1,694✔
230
            ; ( "set_verification_key"
231
              , Verification_key_perm.to_yojson t.set_verification_key )
1,694✔
232
            ; ("set_zkapp_uri", Auth_required.to_yojson t.set_zkapp_uri)
1,694✔
233
            ; ("edit_action_state", Auth_required.to_yojson t.edit_action_state)
1,694✔
234
            ; ("set_token_symbol", Auth_required.to_yojson t.set_token_symbol)
1,694✔
235
            ; ("increment_nonce", Auth_required.to_yojson t.increment_nonce)
1,694✔
236
            ; ("set_voting_for", Auth_required.to_yojson t.set_voting_for)
1,694✔
237
            ; ("set_timing", Auth_required.to_yojson t.set_timing)
1,694✔
238
            ]
239

240
        let of_permissions (perm : Mina_base.Permissions.t) =
241
          { edit_state = Auth_required.of_account_perm perm.edit_action_state
×
242
          ; send = Auth_required.of_account_perm perm.send
×
243
          ; receive = Auth_required.of_account_perm perm.receive
×
244
          ; set_delegate = Auth_required.of_account_perm perm.set_delegate
×
245
          ; set_permissions = Auth_required.of_account_perm perm.set_permissions
×
246
          ; set_verification_key =
247
              (let auth, txn_version = perm.set_verification_key in
248
               { auth = Auth_required.of_account_perm auth; txn_version } )
×
249
          ; set_token_symbol =
250
              Auth_required.of_account_perm perm.set_token_symbol
×
251
          ; access = Auth_required.of_account_perm perm.access
×
252
          ; edit_action_state =
253
              Auth_required.of_account_perm perm.edit_action_state
×
254
          ; set_zkapp_uri = Auth_required.of_account_perm perm.set_zkapp_uri
×
255
          ; increment_nonce = Auth_required.of_account_perm perm.increment_nonce
×
256
          ; set_timing = Auth_required.of_account_perm perm.set_timing
×
257
          ; set_voting_for = Auth_required.of_account_perm perm.set_voting_for
×
258
          }
259
      end
260

261
      module Zkapp_account = struct
262
        module Field = struct
263
          type t = Snark_params.Tick.Field.t
16✔
264
          [@@deriving sexp, bin_io_unversioned]
64✔
265

266
          let to_yojson t = `String (Snark_params.Tick.Field.to_string t)
×
267

268
          let of_yojson = function
UNCOV
269
            | `String s ->
×
UNCOV
270
                Ok (Snark_params.Tick.Field.of_string s)
×
271
            | _ ->
×
272
                Error
273
                  "Invalid JSON in runtime config Zkapp_account.state, \
274
                   expected string"
275
        end
276

277
        module Verification_key = struct
278
          type t = Pickles.Side_loaded.Verification_key.Stable.Latest.t
16✔
279
          [@@deriving sexp, bin_io_unversioned]
64✔
280

281
          let to_yojson t =
282
            `String (Pickles.Side_loaded.Verification_key.to_base64 t)
×
283

284
          let of_yojson = function
285
            | `String s ->
×
286
                let vk_or_err =
287
                  Pickles.Side_loaded.Verification_key.of_base64 s
288
                in
289
                Result.map_error vk_or_err ~f:Error.to_string_hum
×
290
            | _ ->
×
291
                Error
292
                  "Invalid JSON in runtime config \
293
                   Zkapp_account.verification_key, expected string"
294
        end
295

296
        module Zkapp_version = struct
297
          type t = Mina_numbers.Zkapp_version.Stable.Latest.t
16✔
298
          [@@deriving bin_io_unversioned]
64✔
299

300
          include (
301
            Mina_numbers.Zkapp_version :
302
              module type of Mina_numbers.Zkapp_version with type t := t )
303
        end
304

305
        type t =
16✔
306
          { app_state : Field.t list
×
307
          ; verification_key : Verification_key.t option [@default None]
×
308
          ; zkapp_version : Zkapp_version.t
×
309
          ; action_state : Field.t list
×
310
          ; last_action_slot : int
×
311
          ; proved_state : bool
×
312
          ; zkapp_uri : string
×
313
          }
314
        [@@deriving sexp, fields, yojson, bin_io_unversioned]
64✔
315

316
        let fields = Fields.names |> Array.of_list
16✔
317

UNCOV
318
        let of_yojson json = of_yojson_generic ~fields of_yojson json
×
319

320
        let of_zkapp (zkapp : Mina_base.Zkapp_account.t) : t =
321
          let open Mina_base.Zkapp_account in
×
322
          { app_state = Mina_base.Zkapp_state.V.to_list zkapp.app_state
×
323
          ; verification_key =
324
              Option.map zkapp.verification_key ~f:With_hash.data
×
325
          ; zkapp_version = zkapp.zkapp_version
326
          ; action_state =
327
              Pickles_types.Vector.Vector_5.to_list zkapp.action_state
×
328
          ; last_action_slot =
329
              Unsigned.UInt32.to_int
×
330
              @@ Mina_numbers.Global_slot_since_genesis.to_uint32
×
331
                   zkapp.last_action_slot
332
          ; proved_state = zkapp.proved_state
333
          ; zkapp_uri = zkapp.zkapp_uri
334
          }
335
      end
336

337
      type t =
×
338
        { pk : string
×
339
        ; sk : string option [@default None]
14✔
340
        ; balance : Currency.Balance.t
×
341
        ; delegate : string option [@default None]
1,720✔
342
        ; timing : Timed.t option [@default None]
×
343
        ; token : string option [@default None]
1,694✔
344
        ; nonce : Mina_numbers.Account_nonce.t
14✔
345
              [@default Mina_numbers.Account_nonce.zero]
346
        ; receipt_chain_hash : string option [@default None]
1,694✔
347
        ; voting_for : string option [@default None]
1,694✔
UNCOV
348
        ; zkapp : Zkapp_account.t option [@default None]
×
349
        ; permissions : Permissions.t option [@default None]
×
350
        ; token_symbol : string option [@default None]
1,694✔
351
        }
352
      [@@deriving sexp, fields, yojson]
20✔
353

354
      let fields = Fields.names |> Array.of_list
16✔
355

356
      let of_yojson json = of_yojson_generic ~fields of_yojson json
14✔
357

358
      let default : t =
359
        { pk = Signature_lib.Public_key.Compressed.(to_base58_check empty)
16✔
360
        ; sk = None
361
        ; balance = Currency.Balance.zero
362
        ; delegate = None
363
        ; timing = None
364
        ; token = None
365
        ; nonce = Mina_numbers.Account_nonce.zero
366
        ; receipt_chain_hash = None
367
        ; voting_for = None
368
        ; zkapp = None
369
        ; permissions = None
370
        ; token_symbol = None
371
        }
372
    end
373

374
    type t = Single.t list [@@deriving yojson]
×
375
  end
376

377
  module Ledger = struct
378
    module Balance_spec = struct
379
      type t = { number : int; balance : Currency.Balance.t }
×
380
      [@@deriving yojson]
×
381
    end
382

383
    type t =
×
384
      { accounts : Accounts.t option [@default None]
2✔
385
      ; num_accounts : int option [@default None]
2✔
386
      ; balances : Balance_spec.t list [@default []]
×
387
      ; hash : string option [@default None]
7✔
388
      ; s3_data_hash : string option [@default None]
×
389
      ; name : string option [@default None]
5✔
390
      ; add_genesis_winner : bool option [@default None]
7✔
391
      }
392
    [@@deriving yojson, fields]
4✔
393

394
    let fields = Fields.names |> Array.of_list
16✔
395

396
    let of_yojson json = of_yojson_generic ~fields of_yojson json
2✔
397

398
    let default : t =
399
      { accounts = None
400
      ; num_accounts = None
401
      ; balances = []
402
      ; hash = None
403
      ; s3_data_hash = None
404
      ; name = None
405
      ; add_genesis_winner = None
406
      }
407
  end
408

409
  module Proof_keys = struct
410
    module Transaction_capacity = struct
411
      type t =
×
412
        { log_2 : int option [@default None] [@key "2_to_the"]
×
413
        ; txns_per_second_x10 : int option [@default None]
×
414
        }
415
      [@@deriving yojson]
×
416

417
      (* we don't deriving the field names here, because the first one differs from the
418
         field in the record type
419
      *)
420
      let fields = [| "2_to_the"; "txns_per_second_x10" |]
421

422
      let alternates = [| ("two_to_the", "2_to_the"); ("log_2", "2_to_the") |]
423

424
      let of_yojson json =
425
        json
×
426
        |> yojson_rename_fields ~alternates
×
427
        |> yojson_strip_fields ~keep_fields:fields
×
428
        |> of_yojson |> dump_on_error json
×
429
    end
430

431
    type t =
×
432
      { level : string option [@default None]
3✔
433
      ; sub_windows_per_window : int option [@default None]
×
434
      ; ledger_depth : int option [@default None]
×
435
      ; work_delay : int option [@default None]
×
436
      ; block_window_duration_ms : int option [@default None]
×
437
      ; transaction_capacity : Transaction_capacity.t option [@default None]
×
438
      ; coinbase_amount : Currency.Amount.t option [@default None]
×
439
      ; supercharged_coinbase_factor : int option [@default None]
×
440
      ; account_creation_fee : Currency.Fee.t option [@default None]
×
441
      ; fork : Fork_config.t option [@default None]
×
442
      }
443
    [@@deriving yojson, fields]
×
444

445
    let fields = Fields.names |> Array.of_list
16✔
446

447
    let of_yojson json = of_yojson_generic ~fields of_yojson json
×
448
  end
449

450
  module Genesis = struct
451
    type t =
×
452
      { k : int option [@default None]
×
453
      ; delta : int option [@default None]
×
454
      ; slots_per_epoch : int option [@default None]
×
455
      ; slots_per_sub_window : int option [@default None]
×
456
      ; grace_period_slots : int option [@default None]
×
457
      ; genesis_state_timestamp : string option [@default None]
×
458
      }
459
    [@@deriving yojson, fields]
×
460

461
    let fields = Fields.names |> Array.of_list
16✔
462

463
    let of_yojson json = of_yojson_generic ~fields of_yojson json
×
464
  end
465

466
  module Daemon = struct
467
    type t =
×
468
      { txpool_max_size : int option [@default None]
×
469
      ; peer_list_url : string option [@default None]
×
470
      ; zkapp_proof_update_cost : float option [@default None]
×
471
      ; zkapp_signed_single_update_cost : float option [@default None]
×
472
      ; zkapp_signed_pair_update_cost : float option [@default None]
×
473
      ; zkapp_transaction_cost_limit : float option [@default None]
×
474
      ; max_event_elements : int option [@default None]
×
475
      ; max_action_elements : int option [@default None]
×
476
      ; zkapp_cmd_limit_hardcap : int option [@default None]
×
477
      ; slot_tx_end : int option [@default None]
×
478
      ; slot_chain_end : int option [@default None]
×
479
      ; minimum_user_command_fee : Currency.Fee.t option [@default None]
×
480
      ; network_id : string option [@default None]
×
481
      ; client_port : int option [@default None] [@key "client-port"]
×
482
      ; libp2p_port : int option [@default None] [@key "libp2p-port"]
×
483
      ; rest_port : int option [@default None] [@key "rest-port"]
×
484
      ; graphql_port : int option [@default None] [@key "limited-graphql-port"]
×
485
      ; node_status_url : string option [@default None] [@key "node-status-url"]
×
486
      ; block_producer_key : string option
×
487
            [@default None] [@key "block-producer-key"]
488
      ; block_producer_pubkey : string option
×
489
            [@default None] [@key "block-producer-pubkey"]
490
      ; block_producer_password : string option
×
491
            [@default None] [@key "block-producer-password"]
492
      ; coinbase_receiver : string option
×
493
            [@default None] [@key "coinbase-receiver"]
494
      ; run_snark_worker : string option
×
495
            [@default None] [@key "run-snark-worker"]
496
      ; run_snark_coordinator : string option
×
497
            [@default None] [@key "run-snark-coordinator"]
498
      ; snark_worker_fee : int option [@default None] [@key "snark-worker-fee"]
×
499
      ; snark_worker_parallelism : int option
×
500
            [@default None] [@key "snark-worker-parallelism"]
501
      ; work_selection : string option [@default None] [@key "work-selection"]
×
502
      ; work_reassignment_wait : int option
×
503
            [@default None] [@key "work-reassignment-wait"]
504
      ; log_txn_pool_gossip : bool option
×
505
            [@default None] [@key "log-txn-pool-gossip"]
506
      ; log_snark_work_gossip : bool option
×
507
            [@default None] [@key "log-snark-work-gossip"]
508
      ; log_block_creation : bool option
×
509
            [@default None] [@key "log-block-creation"]
510
      ; min_connections : int option [@default None] [@key "min-connections"]
×
511
      ; max_connections : int option [@default None] [@key "max-connections"]
×
512
      ; pubsub_v0 : string option [@default None] [@key "pubsub-v0"]
×
513
      ; validation_queue_size : int option
×
514
            [@default None] [@key "validation-queue-size"]
515
      ; stop_time : int option [@default None] [@key "stop-time"]
×
516
      ; peers : string list option [@default None] [@key "peers"]
×
517
      }
518
    [@@deriving yojson, fields]
×
519

520
    let fields = Fields.names |> Array.of_list
16✔
521

522
    let of_yojson json = of_yojson_generic ~fields of_yojson json
×
523
  end
524

525
  module Epoch_data = struct
526
    module Data = struct
527
      type t =
×
528
        { accounts : Accounts.t option [@default None]
×
529
        ; seed : string
×
530
        ; s3_data_hash : string option [@default None]
×
531
        ; hash : string option [@default None]
×
532
        }
533
      [@@deriving yojson, fields]
×
534

535
      let fields = Fields.names |> Array.of_list
16✔
536

537
      let of_yojson json = of_yojson_generic ~fields of_yojson json
×
538
    end
539

540
    type t =
×
541
      { staking : Data.t
×
542
      ; next : (Data.t option[@default None]) (*If None then next = staking*)
×
543
      }
544
    [@@deriving yojson, fields]
545

546
    let fields = Fields.names |> Array.of_list
16✔
547

548
    let of_yojson json = of_yojson_generic ~fields of_yojson json
×
549
  end
550

551
  type t =
×
552
    { daemon : Daemon.t option [@default None]
×
553
    ; genesis : Genesis.t option [@default None]
×
554
    ; proof : Proof_keys.t option [@default None]
×
555
    ; ledger : Ledger.t option [@default None]
×
556
    ; epoch_data : Epoch_data.t option [@default None]
×
557
    }
558
  [@@deriving yojson, fields]
559

560
  let fields = Fields.names |> Array.of_list
16✔
561

562
  let of_yojson json = of_yojson_generic ~fields of_yojson json
×
563

564
  let default : t =
565
    { daemon = None
566
    ; genesis = None
567
    ; proof = None
568
    ; ledger = None
569
    ; epoch_data = None
570
    }
571
end
572

573
(** JSON representation:
574

575
  { "daemon":
576
      { "txpool_max_size": 1
577
      , "peer_list_url": "https://www.example.com/peer-list.txt" }
578
  , "genesis": { "k": 1, "delta": 1 }
579
  , "proof":
580
      { "level": "check"
581
      , "sub_windows_per_window": 8
582
      , "ledger_depth": 14
583
      , "work_delay": 2
584
      , "block_window_duration_ms": 120000
585
      , "transaction_capacity": {"txns_per_second_x10": 2}
586
      , "coinbase_amount": "200"
587
      , "supercharged_coinbase_factor": 2
588
      , "account_creation_fee": "0.001" }
589
  , "ledger":
590
      { "name": "release"
591
      , "accounts":
592
          [ { "pk": "public_key"
593
            , "sk": "secret_key"
594
            , "balance": "0.000600000"
595
            , "delegate": "public_key" }
596
          , { "pk": "public_key"
597
            , "sk": "secret_key"
598
            , "balance": "0.000000000"
599
            , "delegate": "public_key" } ]
600
      , "hash": "root_hash"
601
      , "num_accounts": 10
602
      , "genesis_state_timestamp": "2000-00-00 12:00:00+0100" } }
603

604
  All fields are optional *except*:
605
  * each account in [ledger.accounts] must have a [balance] field
606
  * if [ledger] is present, it must feature one of [name], [accounts] or [hash].
607

608
*)
609

610
module Accounts = struct
611
  module Single = struct
612
    module Timed = struct
613
      type t = Json_layout.Accounts.Single.Timed.t =
16✔
614
        { initial_minimum_balance : Currency.Balance.Stable.Latest.t
×
615
        ; cliff_time : Mina_numbers.Global_slot_since_genesis.Stable.Latest.t
×
616
        ; cliff_amount : Currency.Amount.Stable.Latest.t
×
617
        ; vesting_period : Mina_numbers.Global_slot_span.Stable.Latest.t
×
618
        ; vesting_increment : Currency.Amount.Stable.Latest.t
×
619
        }
620
      [@@deriving bin_io_unversioned, sexp]
64✔
621
    end
622

623
    module Permissions = Json_layout.Accounts.Single.Permissions
624
    module Zkapp_account = Json_layout.Accounts.Single.Zkapp_account
625

626
    type t = Json_layout.Accounts.Single.t =
16✔
627
      { pk : string
×
628
      ; sk : string option
×
629
      ; balance : Currency.Balance.Stable.Latest.t
×
630
      ; delegate : string option
×
631
      ; timing : Timed.t option
×
632
      ; token : string option
×
633
      ; nonce : Mina_numbers.Account_nonce.Stable.Latest.t
×
634
      ; receipt_chain_hash : string option
×
635
      ; voting_for : string option
×
636
      ; zkapp : Zkapp_account.t option
×
637
      ; permissions : Permissions.t option
×
638
      ; token_symbol : string option
×
639
      }
640
    [@@deriving bin_io_unversioned, sexp]
64✔
641

642
    let to_json_layout : t -> Json_layout.Accounts.Single.t = Fn.id
643

644
    let of_json_layout : Json_layout.Accounts.Single.t -> (t, string) Result.t =
645
      Result.return
646

647
    let to_yojson x = Json_layout.Accounts.Single.to_yojson (to_json_layout x)
×
648

649
    let of_yojson json =
650
      Result.bind ~f:of_json_layout (Json_layout.Accounts.Single.of_yojson json)
×
651

652
    let default = Json_layout.Accounts.Single.default
653

654
    let of_account (a : Mina_base.Account.t) : (t, string) Result.t =
655
      let open Result.Let_syntax in
×
656
      let open Signature_lib in
657
      return
658
        { pk = Public_key.Compressed.to_base58_check a.public_key
×
659
        ; sk = None
660
        ; balance = a.balance
661
        ; delegate =
662
            Option.map a.delegate ~f:(fun pk ->
×
663
                Public_key.Compressed.to_base58_check pk )
×
664
        ; timing =
665
            ( match a.timing with
666
            | Untimed ->
×
667
                None
668
            | Timed t ->
×
669
                let open Timed in
670
                Some
671
                  { initial_minimum_balance = t.initial_minimum_balance
672
                  ; cliff_time = t.cliff_time
673
                  ; cliff_amount = t.cliff_amount
674
                  ; vesting_period = t.vesting_period
675
                  ; vesting_increment = t.vesting_increment
676
                  } )
677
        ; token = Some (Mina_base.Token_id.to_string a.token_id)
×
678
        ; token_symbol = Some a.token_symbol
679
        ; zkapp = Option.map a.zkapp ~f:Zkapp_account.of_zkapp
×
680
        ; nonce = a.nonce
681
        ; receipt_chain_hash =
682
            Some
683
              (Mina_base.Receipt.Chain_hash.to_base58_check a.receipt_chain_hash)
×
684
        ; voting_for = Some (Mina_base.State_hash.to_base58_check a.voting_for)
×
685
        ; permissions = Some (Permissions.of_permissions a.permissions)
×
686
        }
687

688
    let to_account ?(ignore_missing_fields = false) (a : t) :
×
689
        Mina_base.Account.t =
690
      let open Signature_lib in
×
691
      let timing =
692
        let open Mina_base.Account_timing.Poly in
693
        match a.timing with
694
        | None ->
×
695
            Untimed
696
        | Some
×
697
            { initial_minimum_balance
698
            ; cliff_time
699
            ; cliff_amount
700
            ; vesting_period
701
            ; vesting_increment
702
            } ->
703
            Timed
704
              { initial_minimum_balance
705
              ; cliff_time
706
              ; cliff_amount
707
              ; vesting_period
708
              ; vesting_increment
709
              }
710
      in
711
      let to_permissions (perms : Permissions.t) =
712
        Mina_base.Permissions.Poly.
×
713
          { edit_state =
714
              Json_layout.Accounts.Single.Permissions.Auth_required
715
              .to_account_perm perms.edit_state
×
716
          ; access =
717
              Json_layout.Accounts.Single.Permissions.Auth_required
718
              .to_account_perm perms.access
×
719
          ; send =
720
              Json_layout.Accounts.Single.Permissions.Auth_required
721
              .to_account_perm perms.send
×
722
          ; receive =
723
              Json_layout.Accounts.Single.Permissions.Auth_required
724
              .to_account_perm perms.receive
×
725
          ; set_delegate =
726
              Json_layout.Accounts.Single.Permissions.Auth_required
727
              .to_account_perm perms.set_delegate
×
728
          ; set_permissions =
729
              Json_layout.Accounts.Single.Permissions.Auth_required
730
              .to_account_perm perms.set_permissions
×
731
          ; set_verification_key =
732
              ( Json_layout.Accounts.Single.Permissions.Auth_required
733
                .to_account_perm perms.set_verification_key.auth
×
734
              , perms.set_verification_key.txn_version )
735
          ; set_zkapp_uri =
736
              Json_layout.Accounts.Single.Permissions.Auth_required
737
              .to_account_perm perms.set_zkapp_uri
×
738
          ; edit_action_state =
739
              Json_layout.Accounts.Single.Permissions.Auth_required
740
              .to_account_perm perms.edit_action_state
×
741
          ; set_token_symbol =
742
              Json_layout.Accounts.Single.Permissions.Auth_required
743
              .to_account_perm perms.set_token_symbol
×
744
          ; increment_nonce =
745
              Json_layout.Accounts.Single.Permissions.Auth_required
746
              .to_account_perm perms.increment_nonce
×
747
          ; set_voting_for =
748
              Json_layout.Accounts.Single.Permissions.Auth_required
749
              .to_account_perm perms.set_voting_for
×
750
          ; set_timing =
751
              Json_layout.Accounts.Single.Permissions.Auth_required
752
              .to_account_perm perms.set_timing
×
753
          }
754
      in
755
      let permissions =
756
        match (ignore_missing_fields, a.permissions) with
757
        | _, Some perms ->
×
758
            to_permissions perms
×
759
        | false, None ->
×
760
            failwithf "no permissions set for account %s" a.pk ()
×
761
        | true, _ ->
×
762
            Mina_base.Permissions.user_default
763
      in
764
      let mk_zkapp (app : Zkapp_account.t) :
765
          ( Mina_base.Zkapp_state.Value.t
766
          , Mina_base.Verification_key_wire.t option
767
          , Zkapp_account.Zkapp_version.t
768
          , Zkapp_account.Field.t
769
          , Mina_numbers.Global_slot_since_genesis.t
770
          , bool
771
          , string )
772
          Mina_base.Zkapp_account.Poly.t =
773
        let hash_data = Mina_base.Verification_key_wire.digest_vk in
×
774
        Zkapp_account.
775
          { app_state = Mina_base.Zkapp_state.V.of_list_exn app.app_state
×
776
          ; verification_key =
777
              Option.map ~f:With_hash.(of_data ~hash_data) app.verification_key
×
778
          ; zkapp_version = app.zkapp_version
779
          ; action_state =
780
              Pickles_types.Vector.Vector_5.of_list_exn app.action_state
×
781
          ; last_action_slot =
782
              Mina_numbers.Global_slot_since_genesis.of_uint32
×
783
              @@ Unsigned.UInt32.of_int app.last_action_slot
×
784
          ; proved_state = app.proved_state
785
          ; zkapp_uri = app.zkapp_uri
786
          }
787
      in
788
      let receipt_chain_hash =
789
        match (ignore_missing_fields, a.receipt_chain_hash) with
790
        | _, Some rch ->
×
791
            Mina_base.Receipt.Chain_hash.of_base58_check_exn rch
×
792
        | false, None ->
×
793
            failwithf "no receipt_chain_hash set for account %s" a.pk ()
×
794
        | true, _ ->
×
795
            Mina_base.Receipt.Chain_hash.empty
796
      in
797
      let voting_for =
798
        match (ignore_missing_fields, a.voting_for) with
799
        | _, Some voting_for ->
×
800
            Mina_base.State_hash.of_base58_check_exn voting_for
×
801
        | false, None ->
×
802
            failwithf "no voting_for set for account %s" a.pk ()
×
803
        | true, _ ->
×
804
            Mina_base.State_hash.dummy
805
      in
806
      { public_key = Public_key.Compressed.of_base58_check_exn a.pk
×
807
      ; token_id =
808
          Mina_base.Token_id.(Option.value_map ~default ~f:of_string a.token)
×
809
      ; token_symbol = Option.value ~default:"" a.token_symbol
×
810
      ; balance = a.balance
811
      ; nonce = a.nonce
812
      ; receipt_chain_hash
813
      ; delegate =
814
          Option.map ~f:Public_key.Compressed.of_base58_check_exn a.delegate
×
815
      ; voting_for
816
      ; timing
817
      ; permissions
818
      ; zkapp = Option.map ~f:mk_zkapp a.zkapp
×
819
      }
820
  end
821

822
  type single = Single.t =
823
    { pk : string
824
    ; sk : string option
825
    ; balance : Currency.Balance.t
826
    ; delegate : string option
827
    ; timing : Single.Timed.t option
828
    ; token : string option
829
    ; nonce : Mina_numbers.Account_nonce.t
830
    ; receipt_chain_hash : string option
831
    ; voting_for : string option
832
    ; zkapp : Single.Zkapp_account.t option
833
    ; permissions : Single.Permissions.t option
834
    ; token_symbol : string option
835
    }
836

837
  type t = Single.t list [@@deriving bin_io_unversioned]
16✔
838

839
  let to_json_layout : t -> Json_layout.Accounts.t =
840
    List.map ~f:Single.to_json_layout
841

842
  let of_json_layout (t : Json_layout.Accounts.t) : (t, string) Result.t =
843
    let exception Stop of string in
2✔
844
    try
845
      Result.return
2✔
846
      @@ List.map t ~f:(fun x ->
2✔
847
             match Single.of_json_layout x with
14✔
848
             | Ok x ->
14✔
849
                 x
850
             | Error err ->
×
851
                 raise (Stop err) )
852
    with Stop err -> Error err
×
853

854
  let to_yojson x = Json_layout.Accounts.to_yojson (to_json_layout x)
4✔
855

856
  let of_yojson json =
857
    Result.bind ~f:of_json_layout (Json_layout.Accounts.of_yojson json)
×
858
end
859

860
module Ledger = struct
861
  type base =
16✔
862
    | Named of string  (** One of the named ledgers in [Genesis_ledger] *)
×
863
    | Accounts of Accounts.t  (** A ledger generated from the given accounts *)
×
864
    | Hash
×
865
        (** The ledger with the given root hash stored in the containing Ledger.t *)
866
  [@@deriving bin_io_unversioned]
64✔
867

868
  type t =
16✔
869
    { base : base
870
    ; num_accounts : int option
871
    ; balances : (int * Currency.Balance.Stable.Latest.t) list
872
    ; hash : string option
873
    ; s3_data_hash : string option
874
    ; name : string option
875
    ; add_genesis_winner : bool option
876
    }
877
  [@@deriving bin_io_unversioned]
64✔
878

879
  let to_json_layout
880
      { base
881
      ; num_accounts
882
      ; balances
883
      ; hash
884
      ; name
885
      ; add_genesis_winner
886
      ; s3_data_hash
887
      } : Json_layout.Ledger.t =
888
    let balances =
10✔
889
      List.map balances ~f:(fun (number, balance) ->
890
          { Json_layout.Ledger.Balance_spec.number; balance } )
×
891
    in
892
    let without_base : Json_layout.Ledger.t =
10✔
893
      { accounts = None
894
      ; num_accounts
895
      ; balances
896
      ; hash
897
      ; s3_data_hash
898
      ; name
899
      ; add_genesis_winner
900
      }
901
    in
902
    match base with
903
    | Named name ->
3✔
904
        { without_base with name = Some name }
905
    | Accounts accounts ->
7✔
906
        { without_base with accounts = Some (Accounts.to_json_layout accounts) }
7✔
907
    | Hash ->
×
908
        without_base
909

910
  let of_json_layout
911
      ({ accounts
912
       ; num_accounts
913
       ; balances
914
       ; hash
915
       ; s3_data_hash
916
       ; name
917
       ; add_genesis_winner
918
       } :
919
        Json_layout.Ledger.t ) : (t, string) Result.t =
920
    let open Result.Let_syntax in
2✔
921
    let%map base =
922
      match accounts with
923
      | Some accounts ->
2✔
924
          let%map accounts = Accounts.of_json_layout accounts in
2✔
925
          Accounts accounts
2✔
926
      | None -> (
×
927
          match name with
928
          | Some name ->
×
929
              return (Named name)
×
930
          | None -> (
×
931
              match hash with
932
              | Some _ ->
×
933
                  return Hash
×
934
              | None ->
×
935
                  Error
936
                    "Runtime_config.Ledger.of_json_layout: Expected a field \
937
                     'accounts', 'name' or 'hash'" ) )
938
    in
939
    let balances =
2✔
940
      List.map balances
941
        ~f:(fun { Json_layout.Ledger.Balance_spec.number; balance } ->
942
          (number, balance) )
×
943
    in
944
    { base
2✔
945
    ; num_accounts
946
    ; balances
947
    ; hash
948
    ; s3_data_hash
949
    ; name
950
    ; add_genesis_winner
951
    }
952

953
  let to_yojson x = Json_layout.Ledger.to_yojson (to_json_layout x)
7✔
954

955
  let of_yojson json =
956
    Result.bind ~f:of_json_layout (Json_layout.Ledger.of_yojson json)
2✔
957
end
958

959
module Proof_keys = struct
960
  module Level = struct
961
    type t = Full | Check | No_check [@@deriving bin_io_unversioned, equal]
×
962

963
    let to_string = function
964
      | Full ->
×
965
          "full"
966
      | Check ->
×
967
          "check"
968
      | No_check ->
3✔
969
          "none"
970

971
    let of_string str =
972
      match String.lowercase str with
×
973
      | "full" ->
×
974
          Ok Full
975
      | "check" ->
×
976
          Ok Check
977
      | "none" ->
×
978
          Ok No_check
979
      | _ ->
×
980
          Error "Expected one of 'full', 'check', or 'none'"
981

982
    let to_json_layout = to_string
983

984
    let of_json_layout str =
985
      Result.map_error (of_string str) ~f:(fun err ->
×
986
          "Runtime_config.Proof_keys.Level.of_json_layout: Could not decode \
×
987
           field 'level'. " ^ err )
988

989
    let to_yojson x = `String (to_json_layout x)
×
990

991
    let of_yojson = function
992
      | `String str ->
×
993
          of_json_layout str
994
      | _ ->
×
995
          Error
996
            "Runtime_config.Proof_keys.Level.of_json_layout: Expected the \
997
             field 'level' to contain a string"
998
  end
999

1000
  module Transaction_capacity = struct
1001
    type t = Log_2 of int | Txns_per_second_x10 of int
×
1002
    [@@deriving bin_io_unversioned]
64✔
1003

1004
    let to_json_layout : t -> Json_layout.Proof_keys.Transaction_capacity.t =
1005
      function
1006
      | Log_2 i ->
×
1007
          { log_2 = Some i; txns_per_second_x10 = None }
1008
      | Txns_per_second_x10 i ->
×
1009
          { log_2 = None; txns_per_second_x10 = Some i }
1010

1011
    let of_json_layout :
1012
        Json_layout.Proof_keys.Transaction_capacity.t -> (t, string) Result.t =
1013
      function
1014
      | { log_2 = Some i; txns_per_second_x10 = None } ->
×
1015
          Ok (Log_2 i)
1016
      | { txns_per_second_x10 = Some i; log_2 = None } ->
×
1017
          Ok (Txns_per_second_x10 i)
1018
      | _ ->
×
1019
          Error
1020
            "Runtime_config.Proof_keys.Transaction_capacity.of_json_layout: \
1021
             Expected exactly one of the fields '2_to_the' or \
1022
             'txns_per_second_x10'"
1023

1024
    let to_yojson x =
1025
      Json_layout.Proof_keys.Transaction_capacity.to_yojson (to_json_layout x)
×
1026

1027
    let of_yojson json =
1028
      Result.bind ~f:of_json_layout
×
1029
        (Json_layout.Proof_keys.Transaction_capacity.of_yojson json)
×
1030

1031
    let small : t = Log_2 2
1032

1033
    let medium : t = Log_2 3
1034

1035
    let to_transaction_capacity_log_2 ~block_window_duration_ms
1036
        ~transaction_capacity =
1037
      match transaction_capacity with
×
1038
      | Log_2 i ->
×
1039
          i
1040
      | Txns_per_second_x10 tps_goal_x10 ->
×
1041
          let max_coinbases = 2 in
1042
          let max_user_commands_per_block =
1043
            (* block_window_duration is in milliseconds, so divide by 1000 divide
1044
               by 10 again because we have tps * 10
1045
            *)
1046
            tps_goal_x10 * block_window_duration_ms / (1000 * 10)
1047
          in
1048
          (* Log of the capacity of transactions per transition.
1049
              - 1 will only work if we don't have prover fees.
1050
              - 2 will work with prover fees, but not if we want a transaction
1051
                included in every block.
1052
              - At least 3 ensures a transaction per block and the staged-ledger
1053
                unit tests pass.
1054
          *)
1055
          1
1056
          + Core_kernel.Int.ceil_log2
×
1057
              (max_user_commands_per_block + max_coinbases)
1058
  end
1059

1060
  type t =
16✔
1061
    { level : Level.t option
1062
    ; sub_windows_per_window : int option
1063
    ; ledger_depth : int option
1064
    ; work_delay : int option
1065
    ; block_window_duration_ms : int option
1066
    ; transaction_capacity : Transaction_capacity.t option
1067
    ; coinbase_amount : Currency.Amount.Stable.Latest.t option
1068
    ; supercharged_coinbase_factor : int option
1069
    ; account_creation_fee : Currency.Fee.Stable.Latest.t option
1070
    ; fork : Fork_config.t option
1071
    }
1072
  [@@deriving bin_io_unversioned]
64✔
1073

1074
  let make ?level ?sub_windows_per_window ?ledger_depth ?work_delay
1075
      ?block_window_duration_ms ?transaction_capacity ?coinbase_amount
1076
      ?supercharged_coinbase_factor ?account_creation_fee ?fork () =
1077
    { level
×
1078
    ; sub_windows_per_window
1079
    ; ledger_depth
1080
    ; work_delay
1081
    ; block_window_duration_ms
1082
    ; transaction_capacity
1083
    ; coinbase_amount
1084
    ; supercharged_coinbase_factor
1085
    ; account_creation_fee
1086
    ; fork
1087
    }
1088

1089
  let default =
1090
    { level = None
1091
    ; sub_windows_per_window = None
1092
    ; ledger_depth = None
1093
    ; work_delay = None
1094
    ; block_window_duration_ms = None
1095
    ; transaction_capacity = None
1096
    ; coinbase_amount = None
1097
    ; supercharged_coinbase_factor = None
1098
    ; account_creation_fee = None
1099
    ; fork = None
1100
    }
1101

1102
  let to_json_layout
1103
      { level
1104
      ; sub_windows_per_window
1105
      ; ledger_depth
1106
      ; work_delay
1107
      ; block_window_duration_ms
1108
      ; transaction_capacity
1109
      ; coinbase_amount
1110
      ; supercharged_coinbase_factor
1111
      ; account_creation_fee
1112
      ; fork
1113
      } =
1114
    { Json_layout.Proof_keys.level = Option.map ~f:Level.to_json_layout level
3✔
1115
    ; sub_windows_per_window
1116
    ; ledger_depth
1117
    ; work_delay
1118
    ; block_window_duration_ms
1119
    ; transaction_capacity =
1120
        Option.map ~f:Transaction_capacity.to_json_layout transaction_capacity
3✔
1121
    ; coinbase_amount
1122
    ; supercharged_coinbase_factor
1123
    ; account_creation_fee
1124
    ; fork
1125
    }
1126

1127
  let of_json_layout
1128
      { Json_layout.Proof_keys.level
1129
      ; sub_windows_per_window
1130
      ; ledger_depth
1131
      ; work_delay
1132
      ; block_window_duration_ms
1133
      ; transaction_capacity
1134
      ; coinbase_amount
1135
      ; supercharged_coinbase_factor
1136
      ; account_creation_fee
1137
      ; fork
1138
      } =
1139
    let open Result.Let_syntax in
×
1140
    let%map level = result_opt ~f:Level.of_json_layout level
×
1141
    and transaction_capacity =
1142
      result_opt ~f:Transaction_capacity.of_json_layout transaction_capacity
×
1143
    in
1144
    { level
×
1145
    ; sub_windows_per_window
1146
    ; ledger_depth
1147
    ; work_delay
1148
    ; block_window_duration_ms
1149
    ; transaction_capacity
1150
    ; coinbase_amount
1151
    ; supercharged_coinbase_factor
1152
    ; account_creation_fee
1153
    ; fork
1154
    }
1155

1156
  let to_yojson x = Json_layout.Proof_keys.to_yojson (to_json_layout x)
×
1157

1158
  let of_yojson json =
1159
    Result.bind ~f:of_json_layout (Json_layout.Proof_keys.of_yojson json)
×
1160

1161
  let combine t1 t2 =
1162
    { level = opt_fallthrough ~default:t1.level t2.level
×
1163
    ; sub_windows_per_window =
1164
        opt_fallthrough ~default:t1.sub_windows_per_window
×
1165
          t2.sub_windows_per_window
1166
    ; ledger_depth = opt_fallthrough ~default:t1.ledger_depth t2.ledger_depth
×
1167
    ; work_delay = opt_fallthrough ~default:t1.work_delay t2.work_delay
×
1168
    ; block_window_duration_ms =
1169
        opt_fallthrough ~default:t1.block_window_duration_ms
×
1170
          t2.block_window_duration_ms
1171
    ; transaction_capacity =
1172
        opt_fallthrough ~default:t1.transaction_capacity t2.transaction_capacity
×
1173
    ; coinbase_amount =
1174
        opt_fallthrough ~default:t1.coinbase_amount t2.coinbase_amount
×
1175
    ; supercharged_coinbase_factor =
1176
        opt_fallthrough ~default:t1.supercharged_coinbase_factor
×
1177
          t2.supercharged_coinbase_factor
1178
    ; account_creation_fee =
1179
        opt_fallthrough ~default:t1.account_creation_fee t2.account_creation_fee
×
1180
    ; fork = opt_fallthrough ~default:t1.fork t2.fork
×
1181
    }
1182
end
1183

1184
module Genesis = struct
1185
  type t = Json_layout.Genesis.t =
16✔
1186
    { k : int option (* the depth of finality constant (in slots) *)
1187
    ; delta : int option (* max permissible delay of packets (in slots) *)
1188
    ; slots_per_epoch : int option
1189
    ; slots_per_sub_window : int option
1190
    ; grace_period_slots : int option
1191
    ; genesis_state_timestamp : string option
1192
    }
1193
  [@@deriving bin_io_unversioned]
64✔
1194

1195
  let to_json_layout : t -> Json_layout.Genesis.t = Fn.id
1196

1197
  let of_json_layout : Json_layout.Genesis.t -> (t, string) Result.t =
1198
    Result.return
1199

1200
  let to_yojson x = Json_layout.Genesis.to_yojson (to_json_layout x)
×
1201

1202
  let of_yojson json =
1203
    Result.bind ~f:of_json_layout (Json_layout.Genesis.of_yojson json)
×
1204

1205
  let combine t1 t2 =
1206
    { k = opt_fallthrough ~default:t1.k t2.k
×
1207
    ; delta = opt_fallthrough ~default:t1.delta t2.delta
×
1208
    ; slots_per_epoch =
1209
        opt_fallthrough ~default:t1.slots_per_epoch t2.slots_per_epoch
×
1210
    ; slots_per_sub_window =
1211
        opt_fallthrough ~default:t1.slots_per_sub_window t2.slots_per_sub_window
×
1212
    ; grace_period_slots =
1213
        opt_fallthrough ~default:t1.grace_period_slots t2.grace_period_slots
×
1214
    ; genesis_state_timestamp =
1215
        opt_fallthrough ~default:t1.genesis_state_timestamp
×
1216
          t2.genesis_state_timestamp
1217
    }
1218
end
1219

1220
module Daemon = struct
1221
  (* Peer list URL should usually be None. This option is better provided with
1222
     a command line argument. Putting it in the config makes the network explicitly
1223
     rely on a certain number of nodes, reducing decentralisation. See #14766 *)
1224
  type t = Json_layout.Daemon.t =
16✔
1225
    { txpool_max_size : int option
×
1226
    ; peer_list_url : string option
×
1227
    ; zkapp_proof_update_cost : float option [@default None]
×
1228
    ; zkapp_signed_single_update_cost : float option [@default None]
×
1229
    ; zkapp_signed_pair_update_cost : float option [@default None]
×
1230
    ; zkapp_transaction_cost_limit : float option [@default None]
×
1231
    ; max_event_elements : int option [@default None]
×
1232
    ; max_action_elements : int option [@default None]
×
1233
    ; zkapp_cmd_limit_hardcap : int option [@default None]
×
1234
    ; slot_tx_end : int option [@default None]
×
1235
    ; slot_chain_end : int option [@default None]
×
1236
    ; minimum_user_command_fee : Currency.Fee.Stable.Latest.t option
×
1237
          [@default None]
1238
    ; network_id : string option [@default None]
×
1239
    ; client_port : int option [@default None]
×
1240
    ; libp2p_port : int option [@default None]
×
1241
    ; rest_port : int option [@default None]
×
1242
    ; graphql_port : int option [@default None]
×
1243
    ; node_status_url : string option [@default None]
×
1244
    ; block_producer_key : string option [@default None]
×
1245
    ; block_producer_pubkey : string option [@default None]
×
1246
    ; block_producer_password : string option [@default None]
×
1247
    ; coinbase_receiver : string option [@default None]
×
1248
    ; run_snark_worker : string option [@default None]
×
1249
    ; run_snark_coordinator : string option [@default None]
×
1250
    ; snark_worker_fee : int option [@default None]
×
1251
    ; snark_worker_parallelism : int option [@default None]
×
1252
    ; work_selection : string option [@default None]
×
1253
    ; work_reassignment_wait : int option [@default None]
×
1254
    ; log_txn_pool_gossip : bool option [@default None]
×
1255
    ; log_snark_work_gossip : bool option [@default None]
×
1256
    ; log_block_creation : bool option [@default None]
×
1257
    ; min_connections : int option [@default None]
×
1258
    ; max_connections : int option [@default None]
×
1259
    ; pubsub_v0 : string option [@default None]
×
1260
    ; validation_queue_size : int option [@default None]
×
1261
    ; stop_time : int option [@default None]
×
1262
    ; peers : string list option [@default None]
×
1263
    }
1264
  [@@deriving bin_io_unversioned, fields]
64✔
1265

1266
  let default : t =
1267
    { txpool_max_size = None
1268
    ; peer_list_url = None
1269
    ; zkapp_proof_update_cost = None
1270
    ; zkapp_signed_single_update_cost = None
1271
    ; zkapp_signed_pair_update_cost = None
1272
    ; zkapp_transaction_cost_limit = None
1273
    ; max_event_elements = None
1274
    ; max_action_elements = None
1275
    ; zkapp_cmd_limit_hardcap = None
1276
    ; slot_tx_end = None
1277
    ; slot_chain_end = None
1278
    ; minimum_user_command_fee = None
1279
    ; network_id = None
1280
    ; client_port = None
1281
    ; libp2p_port = None
1282
    ; rest_port = None
1283
    ; graphql_port = None
1284
    ; node_status_url = None
1285
    ; block_producer_key = None
1286
    ; block_producer_pubkey = None
1287
    ; block_producer_password = None
1288
    ; coinbase_receiver = None
1289
    ; run_snark_worker = None
1290
    ; run_snark_coordinator = None
1291
    ; snark_worker_fee = None
1292
    ; snark_worker_parallelism = None
1293
    ; work_selection = None
1294
    ; work_reassignment_wait = None
1295
    ; log_txn_pool_gossip = None
1296
    ; log_snark_work_gossip = None
1297
    ; log_block_creation = None
1298
    ; min_connections = None
1299
    ; max_connections = None
1300
    ; pubsub_v0 = None
1301
    ; validation_queue_size = None
1302
    ; stop_time = None
1303
    ; peers = None
1304
    }
1305

1306
  let to_json_layout : t -> Json_layout.Daemon.t = Fn.id
1307

1308
  let of_json_layout : Json_layout.Daemon.t -> (t, string) Result.t =
1309
    Result.return
1310

1311
  let to_yojson x = Json_layout.Daemon.to_yojson (to_json_layout x)
×
1312

1313
  let of_yojson json =
1314
    Result.bind ~f:of_json_layout (Json_layout.Daemon.of_yojson json)
×
1315

1316
  let combine t1 t2 =
1317
    { txpool_max_size =
×
1318
        opt_fallthrough ~default:t1.txpool_max_size t2.txpool_max_size
×
1319
    ; peer_list_url = opt_fallthrough ~default:t1.peer_list_url t2.peer_list_url
×
1320
    ; zkapp_proof_update_cost =
1321
        opt_fallthrough ~default:t1.zkapp_proof_update_cost
×
1322
          t2.zkapp_proof_update_cost
1323
    ; zkapp_signed_single_update_cost =
1324
        opt_fallthrough ~default:t1.zkapp_signed_single_update_cost
×
1325
          t2.zkapp_signed_single_update_cost
1326
    ; zkapp_signed_pair_update_cost =
1327
        opt_fallthrough ~default:t1.zkapp_signed_pair_update_cost
×
1328
          t2.zkapp_signed_pair_update_cost
1329
    ; zkapp_transaction_cost_limit =
1330
        opt_fallthrough ~default:t1.zkapp_transaction_cost_limit
×
1331
          t2.zkapp_transaction_cost_limit
1332
    ; max_event_elements =
1333
        opt_fallthrough ~default:t1.max_event_elements t2.max_event_elements
×
1334
    ; max_action_elements =
1335
        opt_fallthrough ~default:t1.max_action_elements t2.max_action_elements
×
1336
    ; zkapp_cmd_limit_hardcap =
1337
        opt_fallthrough ~default:t1.zkapp_cmd_limit_hardcap
×
1338
          t2.zkapp_cmd_limit_hardcap
1339
    ; slot_tx_end = opt_fallthrough ~default:t1.slot_tx_end t2.slot_tx_end
×
1340
    ; slot_chain_end =
1341
        opt_fallthrough ~default:t1.slot_chain_end t2.slot_chain_end
×
1342
    ; minimum_user_command_fee =
1343
        opt_fallthrough ~default:t1.minimum_user_command_fee
×
1344
          t2.minimum_user_command_fee
1345
    ; network_id = opt_fallthrough ~default:t1.network_id t2.network_id
×
1346
    ; client_port = opt_fallthrough ~default:t1.client_port t2.client_port
×
1347
    ; libp2p_port = opt_fallthrough ~default:t1.libp2p_port t2.libp2p_port
×
1348
    ; rest_port = opt_fallthrough ~default:t1.rest_port t2.rest_port
×
1349
    ; graphql_port = opt_fallthrough ~default:t1.graphql_port t2.graphql_port
×
1350
    ; node_status_url =
1351
        opt_fallthrough ~default:t1.node_status_url t2.node_status_url
×
1352
    ; block_producer_key =
1353
        opt_fallthrough ~default:t1.block_producer_key t2.block_producer_key
×
1354
    ; block_producer_pubkey =
1355
        opt_fallthrough ~default:t1.block_producer_pubkey
×
1356
          t2.block_producer_pubkey
1357
    ; block_producer_password =
1358
        opt_fallthrough ~default:t1.block_producer_password
×
1359
          t2.block_producer_password
1360
    ; coinbase_receiver =
1361
        opt_fallthrough ~default:t1.coinbase_receiver t2.coinbase_receiver
×
1362
    ; run_snark_worker =
1363
        opt_fallthrough ~default:t1.run_snark_worker t2.run_snark_worker
×
1364
    ; run_snark_coordinator =
1365
        opt_fallthrough ~default:t1.run_snark_coordinator
×
1366
          t2.run_snark_coordinator
1367
    ; snark_worker_fee =
1368
        opt_fallthrough ~default:t1.snark_worker_fee t2.snark_worker_fee
×
1369
    ; snark_worker_parallelism =
1370
        opt_fallthrough ~default:t1.snark_worker_parallelism
×
1371
          t2.snark_worker_parallelism
1372
    ; work_selection =
1373
        opt_fallthrough ~default:t1.work_selection t2.work_selection
×
1374
    ; work_reassignment_wait =
1375
        opt_fallthrough ~default:t1.work_reassignment_wait
×
1376
          t2.work_reassignment_wait
1377
    ; log_txn_pool_gossip =
1378
        opt_fallthrough ~default:t1.log_txn_pool_gossip t2.log_txn_pool_gossip
×
1379
    ; log_snark_work_gossip =
1380
        opt_fallthrough ~default:t1.log_snark_work_gossip
×
1381
          t2.log_snark_work_gossip
1382
    ; log_block_creation =
1383
        opt_fallthrough ~default:t1.log_block_creation t2.log_block_creation
×
1384
    ; min_connections =
1385
        opt_fallthrough ~default:t1.min_connections t2.min_connections
×
1386
    ; max_connections =
1387
        opt_fallthrough ~default:t1.max_connections t2.max_connections
×
1388
    ; pubsub_v0 = opt_fallthrough ~default:t1.pubsub_v0 t2.pubsub_v0
×
1389
    ; validation_queue_size =
1390
        opt_fallthrough ~default:t1.validation_queue_size
×
1391
          t2.validation_queue_size
1392
    ; stop_time = opt_fallthrough ~default:t1.stop_time t2.stop_time
×
1393
    ; peers = opt_fallthrough ~default:t1.peers t2.peers
×
1394
    }
1395
end
1396

1397
module Epoch_data = struct
1398
  module Data = struct
1399
    type t = { ledger : Ledger.t; seed : string }
×
1400
    [@@deriving bin_io_unversioned, yojson]
64✔
1401
  end
1402

1403
  type t =
16✔
1404
    { staking : Data.t; next : Data.t option (*If None, then next = staking*) }
×
1405
  [@@deriving bin_io_unversioned, yojson]
64✔
1406

1407
  let to_json_layout : t -> Json_layout.Epoch_data.t =
1408
   fun { staking; next } ->
1409
    let accounts (ledger : Ledger.t) =
×
1410
      match ledger.base with Accounts acc -> Some acc | _ -> None
×
1411
    in
1412
    let staking =
1413
      { Json_layout.Epoch_data.Data.accounts = accounts staking.ledger
×
1414
      ; seed = staking.seed
1415
      ; hash = staking.ledger.hash
1416
      ; s3_data_hash = staking.ledger.s3_data_hash
1417
      }
1418
    in
1419
    let next =
1420
      Option.map next ~f:(fun n ->
1421
          { Json_layout.Epoch_data.Data.accounts = accounts n.ledger
×
1422
          ; seed = n.seed
1423
          ; hash = n.ledger.hash
1424
          ; s3_data_hash = n.ledger.s3_data_hash
1425
          } )
1426
    in
1427
    { Json_layout.Epoch_data.staking; next }
×
1428

1429
  let of_json_layout : Json_layout.Epoch_data.t -> (t, string) Result.t =
1430
   fun { staking; next } ->
1431
    let open Result.Let_syntax in
×
1432
    let data (t : [ `Staking | `Next ])
1433
        { Json_layout.Epoch_data.Data.accounts; seed; hash; s3_data_hash } =
1434
      let%map base =
1435
        match accounts with
1436
        | Some accounts ->
×
1437
            return @@ Ledger.Accounts accounts
×
1438
        | None -> (
×
1439
            match hash with
1440
            | Some _ ->
×
1441
                return @@ Ledger.Hash
×
1442
            | None ->
×
1443
                let ledger_name =
1444
                  match t with `Staking -> "staking" | `Next -> "next"
×
1445
                in
1446
                Error
1447
                  (sprintf
×
1448
                     "Runtime_config.Epoch_data.of_json_layout: Expected a \
1449
                      field 'accounts', or 'hash' in '%s' ledger"
1450
                     ledger_name ) )
1451
      in
1452
      let ledger =
×
1453
        { Ledger.base
1454
        ; num_accounts = None
1455
        ; balances = []
1456
        ; hash
1457
        ; s3_data_hash
1458
        ; name = None
1459
        ; add_genesis_winner = Some false
1460
        }
1461
      in
1462
      { Data.ledger; seed }
1463
    in
1464
    let%bind staking = data `Staking staking in
×
1465
    let%map next =
1466
      Option.value_map next ~default:(Ok None) ~f:(fun next ->
×
1467
          Result.map ~f:Option.some @@ data `Next next )
×
1468
    in
1469
    { staking; next }
×
1470

1471
  let to_yojson x = Json_layout.Epoch_data.to_yojson (to_json_layout x)
×
1472

1473
  let of_yojson json =
1474
    Result.bind ~f:of_json_layout (Json_layout.Epoch_data.of_yojson json)
×
1475
end
1476

1477
type t =
16✔
1478
  { daemon : Daemon.t option
×
1479
  ; genesis : Genesis.t option
×
1480
  ; proof : Proof_keys.t option
×
1481
  ; ledger : Ledger.t option
×
1482
  ; epoch_data : Epoch_data.t option
×
1483
  }
1484
[@@deriving bin_io_unversioned, fields]
64✔
1485

1486
let make ?daemon ?genesis ?proof ?ledger ?epoch_data () =
1487
  { daemon; genesis; proof; ledger; epoch_data }
×
1488

1489
let to_json_layout { daemon; genesis; proof; ledger; epoch_data } =
1490
  { Json_layout.daemon = Option.map ~f:Daemon.to_json_layout daemon
3✔
1491
  ; genesis = Option.map ~f:Genesis.to_json_layout genesis
3✔
1492
  ; proof = Option.map ~f:Proof_keys.to_json_layout proof
3✔
1493
  ; ledger = Option.map ~f:Ledger.to_json_layout ledger
3✔
1494
  ; epoch_data = Option.map ~f:Epoch_data.to_json_layout epoch_data
3✔
1495
  }
1496

1497
let of_json_layout { Json_layout.daemon; genesis; proof; ledger; epoch_data } =
1498
  let open Result.Let_syntax in
×
1499
  let%map daemon = result_opt ~f:Daemon.of_json_layout daemon
×
1500
  and genesis = result_opt ~f:Genesis.of_json_layout genesis
×
1501
  and proof = result_opt ~f:Proof_keys.of_json_layout proof
×
1502
  and ledger = result_opt ~f:Ledger.of_json_layout ledger
×
1503
  and epoch_data = result_opt ~f:Epoch_data.of_json_layout epoch_data in
×
1504
  { daemon; genesis; proof; ledger; epoch_data }
×
1505

1506
let to_yojson x = Json_layout.to_yojson (to_json_layout x)
×
1507

1508
let to_yojson_without_accounts x =
1509
  let layout = to_json_layout x in
3✔
1510
  let genesis_accounts =
3✔
1511
    let%bind.Option { accounts; _ } = layout.ledger in
1512
    Option.map ~f:List.length accounts
3✔
1513
  in
1514
  let staking_accounts =
3✔
1515
    let%bind.Option { staking; _ } = layout.epoch_data in
1516
    Option.map ~f:List.length staking.accounts
×
1517
  in
1518
  let next_accounts =
3✔
1519
    let%bind.Option { next; _ } = layout.epoch_data in
1520
    let%bind.Option { accounts; _ } = next in
1521
    Option.map ~f:List.length accounts
×
1522
  in
1523
  let layout =
3✔
1524
    let f ledger = { ledger with Json_layout.Ledger.accounts = None } in
3✔
1525
    { layout with
1526
      ledger = Option.map ~f layout.ledger
3✔
1527
    ; epoch_data =
1528
        Option.map layout.epoch_data ~f:(fun { staking; next } ->
3✔
1529
            { Json_layout.Epoch_data.staking = { staking with accounts = None }
×
1530
            ; next = Option.map next ~f:(fun n -> { n with accounts = None })
×
1531
            } )
1532
    }
1533
  in
1534
  ( Json_layout.to_yojson layout
3✔
1535
  , `Accounts_omitted
1536
      (`Genesis genesis_accounts, `Staking staking_accounts, `Next next_accounts)
1537
  )
1538

1539
let of_yojson json = Result.bind ~f:of_json_layout (Json_layout.of_yojson json)
×
1540

1541
let default =
1542
  { daemon = None
1543
  ; genesis = None
1544
  ; proof = None
1545
  ; ledger = None
1546
  ; epoch_data = None
1547
  }
1548

1549
let combine t1 t2 =
1550
  let merge ~combine t1 t2 =
×
1551
    match (t1, t2) with
×
1552
    | Some t1, Some t2 ->
×
1553
        Some (combine t1 t2)
×
1554
    | Some t, None | None, Some t ->
×
1555
        Some t
1556
    | None, None ->
×
1557
        None
1558
  in
1559
  { daemon = merge ~combine:Daemon.combine t1.daemon t2.daemon
×
1560
  ; genesis = merge ~combine:Genesis.combine t1.genesis t2.genesis
×
1561
  ; proof = merge ~combine:Proof_keys.combine t1.proof t2.proof
×
1562
  ; ledger = opt_fallthrough ~default:t1.ledger t2.ledger
×
1563
  ; epoch_data = opt_fallthrough ~default:t1.epoch_data t2.epoch_data
×
1564
  }
1565

1566
let ledger_accounts (ledger : Mina_ledger.Ledger.Any_ledger.witness) =
1567
  let open Async.Deferred.Result.Let_syntax in
×
1568
  let yield = Async_unix.Scheduler.yield_every ~n:100 |> Staged.unstage in
1569
  let%bind accounts =
1570
    Mina_ledger.Ledger.Any_ledger.M.to_list ledger
×
1571
    |> Async.Deferred.map ~f:Result.return
×
1572
  in
1573
  let%map accounts =
1574
    deferred_list_fold ~init:[]
×
1575
      ~f:(fun acc el ->
1576
        let open Async.Deferred.Infix in
×
1577
        let%bind () = yield () >>| Result.return in
×
1578
        let%map elt = Accounts.Single.of_account el |> Async.Deferred.return in
×
1579
        elt :: acc )
×
1580
      accounts
1581
  in
1582
  List.rev accounts
×
1583

1584
let ledger_of_accounts accounts =
1585
  Ledger.
×
1586
    { base = Accounts accounts
1587
    ; num_accounts = None
1588
    ; balances = []
1589
    ; hash = None
1590
    ; s3_data_hash = None
1591
    ; name = None
1592
    ; add_genesis_winner = Some false
1593
    }
1594

1595
let make_fork_config ~staged_ledger ~global_slot_since_genesis ~state_hash
1596
    ~blockchain_length ~staking_ledger ~staking_epoch_seed ~next_epoch_ledger
1597
    ~next_epoch_seed =
1598
  let open Async.Deferred.Result.Let_syntax in
×
1599
  let global_slot_since_genesis =
1600
    Mina_numbers.Global_slot_since_genesis.to_int global_slot_since_genesis
1601
  in
1602
  let blockchain_length = Unsigned.UInt32.to_int blockchain_length in
×
1603
  let yield () =
×
1604
    let open Async.Deferred.Infix in
×
1605
    Async_unix.Scheduler.yield () >>| Result.return
×
1606
  in
1607
  let%bind () = yield () in
×
1608
  let%bind accounts =
1609
    Mina_ledger.Ledger.Any_ledger.cast (module Mina_ledger.Ledger) staged_ledger
×
1610
    |> ledger_accounts
×
1611
  in
1612
  let hash =
×
1613
    Option.some @@ Mina_base.Ledger_hash.to_base58_check
×
1614
    @@ Mina_ledger.Ledger.merkle_root staged_ledger
×
1615
  in
1616
  let fork =
×
1617
    Fork_config.
1618
      { state_hash = Mina_base.State_hash.to_base58_check state_hash
×
1619
      ; blockchain_length
1620
      ; global_slot_since_genesis
1621
      }
1622
  in
1623
  let%bind () = yield () in
×
1624
  let%bind staking_ledger_accounts = ledger_accounts staking_ledger in
×
1625
  let%bind () = yield () in
×
1626
  let%map next_epoch_ledger_accounts =
1627
    match next_epoch_ledger with
1628
    | None ->
×
1629
        return None
×
1630
    | Some l ->
×
1631
        ledger_accounts l >>| Option.return
×
1632
  in
1633
  let epoch_data =
×
1634
    let open Epoch_data in
1635
    let open Data in
1636
    { staking =
1637
        { ledger = ledger_of_accounts staking_ledger_accounts
×
1638
        ; seed = staking_epoch_seed
1639
        }
1640
    ; next =
1641
        Option.map next_epoch_ledger_accounts ~f:(fun accounts ->
×
1642
            { ledger = ledger_of_accounts accounts; seed = next_epoch_seed } )
×
1643
    }
1644
  in
1645
  make
1646
  (* add_genesis_winner must be set to false, because this
1647
     config effectively creates a continuation of the current
1648
     blockchain state and therefore the genesis ledger already
1649
     contains the winner of the previous block. No need to
1650
     artificially add it. In fact, it wouldn't work at all,
1651
     because the new node would try to create this account at
1652
     startup, even though it already exists, leading to an error.*)
1653
    ~epoch_data
1654
    ~ledger:
1655
      { base = Accounts accounts
1656
      ; num_accounts = None
1657
      ; balances = []
1658
      ; hash
1659
      ; s3_data_hash = None
1660
      ; name = None
1661
      ; add_genesis_winner = Some false
1662
      }
1663
    ~proof:(Proof_keys.make ~fork ()) ()
×
1664

1665
let slot_tx_end, slot_chain_end =
1666
  let f get_runtime t =
UNCOV
1667
    let open Option.Let_syntax in
×
UNCOV
1668
    t.daemon >>= get_runtime >>| Mina_numbers.Global_slot_since_hard_fork.of_int
×
1669
  in
1670
  (f (fun d -> d.slot_tx_end), f (fun d -> d.slot_chain_end))
×
1671

1672
module type Json_loader_intf = sig
1673
  val load_config_files :
1674
       ?conf_dir:string
1675
    -> ?commit_id_short:string
1676
    -> logger:Logger.t
1677
    -> string list
1678
    -> t Deferred.Or_error.t
1679
end
1680

1681
module Json_loader : Json_loader_intf = struct
1682
  let load_config_file filename =
1683
    Monitor.try_with_or_error ~here:[%here] (fun () ->
×
1684
        let%map json = Reader.file_contents filename in
×
1685
        Yojson.Safe.from_string json )
×
1686

1687
  let get_magic_config_files ?conf_dir
UNCOV
1688
      ?(commit_id_short = Mina_version.commit_id_short) () =
×
UNCOV
1689
    let config_file_installed =
×
1690
      (* Search for config files installed as part of a deb/brew package.
1691
         These files are commit-dependent, to ensure that we don't clobber
1692
         configuration for dev builds or use incompatible configs.
1693
      *)
1694
      let config_file_installed =
1695
        let json = "config_" ^ commit_id_short ^ ".json" in
UNCOV
1696
        List.fold_until ~init:None
×
UNCOV
1697
          (Cache_dir.possible_paths json)
×
1698
          ~f:(fun _acc f ->
UNCOV
1699
            match Core.Sys.file_exists f with
×
1700
            | `Yes ->
×
1701
                Stop (Some f)
UNCOV
1702
            | _ ->
×
1703
                Continue None )
1704
          ~finish:Fn.id
1705
      in
1706
      match config_file_installed with
1707
      | Some config_file ->
×
1708
          Some (config_file, `Must_exist)
UNCOV
1709
      | None ->
×
1710
          None
1711
    in
1712

1713
    let config_file_configdir =
1714
      Option.map conf_dir ~f:(fun dir ->
1715
          (dir ^ "/" ^ "daemon.json", `May_be_missing) )
×
1716
    in
UNCOV
1717
    let config_file_envvar =
×
1718
      match Sys.getenv "MINA_CONFIG_FILE" with
1719
      | Some config_file ->
×
1720
          Some (config_file, `Must_exist)
UNCOV
1721
      | None ->
×
1722
          None
1723
    in
1724
    List.filter_opt
1725
      [ config_file_installed; config_file_configdir; config_file_envvar ]
1726

1727
  let load_config_files ?conf_dir ?commit_id_short ~logger config_files =
UNCOV
1728
    let open Deferred.Or_error.Let_syntax in
×
1729
    let config_files = List.map ~f:(fun a -> (a, `Must_exist)) config_files in
×
UNCOV
1730
    let config_files =
×
UNCOV
1731
      get_magic_config_files ?conf_dir ?commit_id_short () @ config_files
×
1732
    in
1733
    let%map config_jsons =
1734
      let config_files_paths =
1735
        List.map config_files ~f:(fun (config_file, _) -> `String config_file)
×
1736
      in
UNCOV
1737
      [%log info] "Reading configuration files $config_files"
×
1738
        ~metadata:[ ("config_files", `List config_files_paths) ] ;
UNCOV
1739
      Deferred.Or_error.List.filter_map config_files
×
1740
        ~f:(fun (config_file, handle_missing) ->
1741
          match%bind.Deferred load_config_file config_file with
×
1742
          | Ok config_json ->
×
1743
              Deferred.Or_error.return @@ Some (config_file, config_json)
1744
          | Error err -> (
×
1745
              match handle_missing with
1746
              | `Must_exist ->
×
1747
                  Mina_user_error.raisef ~where:"reading configuration file"
1748
                    "The configuration file %s could not be read:\n%s"
1749
                    config_file (Error.to_string_hum err)
×
1750
              | `May_be_missing ->
×
1751
                  [%log warn] "Could not read configuration from $config_file"
×
1752
                    ~metadata:
1753
                      [ ("config_file", `String config_file)
1754
                      ; ("error", Error_json.error_to_yojson err)
×
1755
                      ] ;
1756
                  return None ) )
×
1757
    in
UNCOV
1758
    List.fold ~init:default config_jsons
×
1759
      ~f:(fun config (config_file, config_json) ->
1760
        match of_yojson config_json with
×
1761
        | Ok loaded_config ->
×
1762
            combine config loaded_config
1763
        | Error err ->
×
1764
            [%log fatal]
×
1765
              "Could not parse configuration from $config_file: $error"
1766
              ~metadata:
1767
                [ ("config_file", `String config_file)
1768
                ; ("config_json", config_json)
1769
                ; ("error", `String err)
1770
                ] ;
1771
            failwithf "Could not parse configuration file: %s" err () )
×
1772
end
1773

1774
module type Constants_intf = sig
1775
  type constants
1776

1777
  val load_constants :
1778
       ?conf_dir:string
1779
    -> ?commit_id_short:string
1780
    -> ?itn_features:bool
1781
    -> ?cli_proof_level:Genesis_constants.Proof_level.t
1782
    -> logger:Logger.t
1783
    -> string list
1784
    -> constants Deferred.t
1785

1786
  val load_constants' :
1787
       ?itn_features:bool
1788
    -> ?cli_proof_level:Genesis_constants.Proof_level.t
1789
    -> t
1790
    -> constants
1791

1792
  val genesis_constants : constants -> Genesis_constants.t
1793

1794
  val constraint_constants :
1795
    constants -> Genesis_constants.Constraint_constants.t
1796

1797
  val proof_level : constants -> Genesis_constants.Proof_level.t
1798

1799
  val compile_config : constants -> Mina_compile_config.t
1800

1801
  val magic_for_unit_tests : t -> constants
1802
end
1803

1804
module Constants : Constants_intf = struct
1805
  type constants =
1806
    { genesis_constants : Genesis_constants.t
1807
    ; constraint_constants : Genesis_constants.Constraint_constants.t
1808
    ; proof_level : Genesis_constants.Proof_level.t
1809
    ; compile_config : Mina_compile_config.t
1810
    }
1811

1812
  let genesis_constants t = t.genesis_constants
3✔
1813

1814
  let constraint_constants t = t.constraint_constants
3✔
1815

1816
  let proof_level t = t.proof_level
3✔
1817

1818
  let compile_config t = t.compile_config
3✔
1819

1820
  let combine (a : constants) (b : t) : constants =
1821
    let genesis_constants =
3✔
1822
      { Genesis_constants.protocol =
1823
          { k =
1824
              Option.value ~default:a.genesis_constants.protocol.k
3✔
1825
                Option.(b.genesis >>= fun g -> g.k)
×
1826
          ; delta =
1827
              Option.value ~default:a.genesis_constants.protocol.delta
3✔
1828
                Option.(b.genesis >>= fun g -> g.delta)
×
1829
          ; slots_per_epoch =
1830
              Option.value ~default:a.genesis_constants.protocol.slots_per_epoch
3✔
1831
                Option.(b.genesis >>= fun g -> g.slots_per_epoch)
×
1832
          ; slots_per_sub_window =
1833
              Option.value
3✔
1834
                ~default:a.genesis_constants.protocol.slots_per_sub_window
1835
                Option.(b.genesis >>= fun g -> g.slots_per_sub_window)
×
1836
          ; grace_period_slots =
1837
              Option.value
3✔
1838
                ~default:a.genesis_constants.protocol.grace_period_slots
1839
                Option.(b.genesis >>= fun g -> g.grace_period_slots)
×
1840
          ; genesis_state_timestamp =
1841
              Option.value
3✔
1842
                ~default:a.genesis_constants.protocol.genesis_state_timestamp
1843
                Option.(
1844
                  b.genesis
1845
                  >>= fun g ->
3✔
1846
                  g.genesis_state_timestamp
×
1847
                  >>| Genesis_constants.genesis_timestamp_of_string
×
1848
                  >>| Genesis_constants.of_time)
1849
          }
1850
      ; txpool_max_size =
1851
          Option.value ~default:a.genesis_constants.txpool_max_size
3✔
1852
            Option.(b.daemon >>= fun d -> d.txpool_max_size)
×
1853
      ; num_accounts =
1854
          Option.first_some
3✔
1855
            Option.(b.ledger >>= fun l -> l.num_accounts)
3✔
1856
            a.genesis_constants.num_accounts
1857
      ; zkapp_proof_update_cost =
1858
          Option.value ~default:a.genesis_constants.zkapp_proof_update_cost
3✔
1859
            Option.(b.daemon >>= fun d -> d.zkapp_proof_update_cost)
×
1860
      ; zkapp_signed_single_update_cost =
1861
          Option.value
3✔
1862
            ~default:a.genesis_constants.zkapp_signed_single_update_cost
1863
            Option.(b.daemon >>= fun d -> d.zkapp_signed_single_update_cost)
×
1864
      ; zkapp_signed_pair_update_cost =
1865
          Option.value
3✔
1866
            ~default:a.genesis_constants.zkapp_signed_pair_update_cost
1867
            Option.(b.daemon >>= fun d -> d.zkapp_signed_pair_update_cost)
×
1868
      ; zkapp_transaction_cost_limit =
1869
          Option.value ~default:a.genesis_constants.zkapp_transaction_cost_limit
3✔
1870
            Option.(b.daemon >>= fun d -> d.zkapp_transaction_cost_limit)
×
1871
      ; max_event_elements =
1872
          Option.value ~default:a.genesis_constants.max_event_elements
3✔
1873
            Option.(b.daemon >>= fun d -> d.max_event_elements)
×
1874
      ; max_action_elements =
1875
          Option.value ~default:a.genesis_constants.max_action_elements
3✔
1876
            Option.(b.daemon >>= fun d -> d.max_action_elements)
×
1877
      ; zkapp_cmd_limit_hardcap =
1878
          Option.value ~default:a.genesis_constants.zkapp_cmd_limit_hardcap
3✔
1879
            Option.(b.daemon >>= fun d -> d.zkapp_cmd_limit_hardcap)
×
1880
      ; minimum_user_command_fee =
1881
          Option.value ~default:a.genesis_constants.minimum_user_command_fee
3✔
1882
            Option.(b.daemon >>= fun d -> d.minimum_user_command_fee)
×
1883
      }
1884
    in
1885
    let constraint_constants =
1886
      let fork =
1887
        let a = a.constraint_constants.fork in
1888
        let b =
1889
          let%map.Option f = Option.(b.proof >>= fun x -> x.fork) in
3✔
1890
          { Genesis_constants.Fork_constants.state_hash =
×
1891
              Mina_base.State_hash.of_base58_check_exn f.state_hash
×
1892
          ; blockchain_length = Mina_numbers.Length.of_int f.blockchain_length
×
1893
          ; global_slot_since_genesis =
1894
              Mina_numbers.Global_slot_since_genesis.of_int
×
1895
                f.global_slot_since_genesis
1896
          }
1897
        in
1898
        Option.first_some b a
3✔
1899
      in
1900
      let block_window_duration_ms =
1901
        Option.value ~default:a.constraint_constants.block_window_duration_ms
1902
          Option.(b.proof >>= fun p -> p.block_window_duration_ms)
3✔
1903
      in
1904
      { a.constraint_constants with
3✔
1905
        sub_windows_per_window =
1906
          Option.value ~default:a.constraint_constants.sub_windows_per_window
3✔
1907
            Option.(b.proof >>= fun p -> p.sub_windows_per_window)
3✔
1908
      ; ledger_depth =
1909
          Option.value ~default:a.constraint_constants.ledger_depth
3✔
1910
            Option.(b.proof >>= fun p -> p.ledger_depth)
3✔
1911
      ; work_delay =
1912
          Option.value ~default:a.constraint_constants.work_delay
3✔
1913
            Option.(b.proof >>= fun p -> p.work_delay)
3✔
1914
      ; block_window_duration_ms
1915
      ; transaction_capacity_log_2 =
1916
          Option.value
3✔
1917
            ~default:a.constraint_constants.transaction_capacity_log_2
1918
            Option.(
1919
              b.proof
1920
              >>= fun p ->
3✔
1921
              p.transaction_capacity
3✔
1922
              >>| fun transaction_capacity ->
1923
              Proof_keys.Transaction_capacity.to_transaction_capacity_log_2
×
1924
                ~block_window_duration_ms ~transaction_capacity)
1925
      ; coinbase_amount =
1926
          Option.value ~default:a.constraint_constants.coinbase_amount
3✔
1927
            Option.(b.proof >>= fun p -> p.coinbase_amount)
3✔
1928
      ; supercharged_coinbase_factor =
1929
          Option.value
3✔
1930
            ~default:a.constraint_constants.supercharged_coinbase_factor
1931
            Option.(b.proof >>= fun p -> p.supercharged_coinbase_factor)
3✔
1932
      ; account_creation_fee =
1933
          Option.value ~default:a.constraint_constants.account_creation_fee
3✔
1934
            Option.(b.proof >>= fun p -> p.account_creation_fee)
3✔
1935
      ; fork
1936
      }
1937
    in
1938
    let proof_level =
1939
      let coerce_proof_level = function
1940
        | Proof_keys.Level.Full ->
×
1941
            Genesis_constants.Proof_level.Full
1942
        | Check ->
×
1943
            Genesis_constants.Proof_level.Check
1944
        | No_check ->
3✔
1945
            Genesis_constants.Proof_level.No_check
1946
      in
1947
      Option.value ~default:a.proof_level
3✔
1948
        Option.(b.proof >>= fun p -> p.level >>| coerce_proof_level)
3✔
1949
    in
1950
    let compile_config =
1951
      { a.compile_config with
1952
        network_id =
1953
          Option.value ~default:a.compile_config.network_id
3✔
1954
            Option.(b.daemon >>= fun d -> d.network_id)
×
1955
      }
1956
    in
1957
    { genesis_constants; constraint_constants; proof_level; compile_config }
1958

1959
  let load_constants' ?itn_features ?cli_proof_level runtime_config =
UNCOV
1960
    let compile_constants =
×
1961
      { genesis_constants = Genesis_constants.Compiled.genesis_constants
1962
      ; constraint_constants = Genesis_constants.Compiled.constraint_constants
1963
      ; proof_level = Genesis_constants.Compiled.proof_level
1964
      ; compile_config = Mina_compile_config.Compiled.t
1965
      }
1966
    in
1967
    let cs = combine compile_constants runtime_config in
UNCOV
1968
    { cs with
×
UNCOV
1969
      proof_level = Option.value ~default:cs.proof_level cli_proof_level
×
1970
    ; compile_config =
1971
        { cs.compile_config with
1972
          itn_features =
UNCOV
1973
            Option.value ~default:cs.compile_config.itn_features itn_features
×
1974
        }
1975
    }
1976

1977
  (* Use this function if you don't need/want the ledger configuration *)
1978
  let load_constants ?conf_dir ?commit_id_short ?itn_features ?cli_proof_level
1979
      ~logger config_files =
UNCOV
1980
    Deferred.Or_error.ok_exn
×
1981
    @@
1982
    let open Deferred.Or_error.Let_syntax in
1983
    let%map runtime_config =
UNCOV
1984
      Json_loader.load_config_files ?conf_dir ?commit_id_short ~logger
×
1985
        config_files
1986
    in
UNCOV
1987
    load_constants' ?itn_features ?cli_proof_level runtime_config
×
1988

1989
  let magic_for_unit_tests t =
1990
    let compile_constants =
3✔
1991
      { genesis_constants = Genesis_constants.For_unit_tests.t
1992
      ; constraint_constants =
1993
          Genesis_constants.For_unit_tests.Constraint_constants.t
1994
      ; proof_level = Genesis_constants.For_unit_tests.Proof_level.t
1995
      ; compile_config = Mina_compile_config.For_unit_tests.t
1996
      }
1997
    in
1998
    combine compile_constants t
1999
end
32✔
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