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

MinaProtocol / mina / 236

21 May 2025 10:28PM UTC coverage: 63.682% (+26.9%) from 36.813%
236

push

buildkite

web-flow
Merge pull request #17252 from MinaProtocol/georgeee/merge-compatible-to-develop-2025-05-21

Merge compatible to develop (21 May 2025)

173 of 380 new or added lines in 30 files covered. (45.53%)

1311 existing lines in 29 files now uncovered.

48603 of 76321 relevant lines covered (63.68%)

509672.48 hits per line

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

53.68
/src/lib/staged_ledger_diff/diff.ml
1
open Core_kernel
73✔
2
open Mina_base
3

4
module At_most_two = struct
5
  [%%versioned
6
  module Stable = struct
7
    [@@@no_toplevel_latest_type]
8

9
    module V1 = struct
NEW
10
      type 'a t = Zero | One of 'a option | Two of ('a * 'a option) option
×
11
      [@@deriving equal, compare, sexp, yojson]
219✔
12
    end
13
  end]
14

15
  type 'a t = 'a Stable.Latest.t =
38,888✔
NEW
16
    | Zero
×
NEW
17
    | One of 'a option
×
NEW
18
    | Two of ('a * 'a option) option
×
NEW
19
  [@@deriving equal, compare, sexp, yojson]
×
20

21
  let increase t ws =
NEW
22
    match (t, ws) with
×
NEW
23
    | Zero, [] ->
×
24
        Ok (One None)
NEW
25
    | Zero, [ a ] ->
×
26
        Ok (One (Some a))
NEW
27
    | One _, [] ->
×
28
        Ok (Two None)
NEW
29
    | One _, [ a ] ->
×
30
        Ok (Two (Some (a, None)))
NEW
31
    | One _, [ a; a' ] ->
×
32
        Ok (Two (Some (a', Some a)))
NEW
33
    | _ ->
×
34
        Or_error.error_string "Error incrementing coinbase parts"
35
end
36

37
module At_most_one = struct
38
  [%%versioned
39
  module Stable = struct
40
    [@@@no_toplevel_latest_type]
41

42
    module V1 = struct
NEW
43
      type 'a t = Zero | One of 'a option
×
44
      [@@deriving equal, compare, sexp, yojson]
219✔
45
    end
46
  end]
47

NEW
48
  type 'a t = 'a Stable.Latest.t = Zero | One of 'a option
×
49
  [@@deriving equal, compare, sexp, yojson]
50

51
  let increase t ws =
NEW
52
    match (t, ws) with
×
NEW
53
    | Zero, [] ->
×
54
        Ok (One None)
NEW
55
    | Zero, [ a ] ->
×
56
        Ok (One (Some a))
NEW
57
    | _ ->
×
58
        Or_error.error_string "Error incrementing coinbase parts"
59
end
60

61
module Ft = struct
62
  [%%versioned
63
  module Stable = struct
64
    [@@@no_toplevel_latest_type]
65

66
    module V1 = struct
67
      type t = Coinbase.Fee_transfer.Stable.V1.t
5✔
68
      [@@deriving equal, compare, sexp, yojson]
365✔
69

70
      let to_latest = Fn.id
71
    end
72
  end]
73

NEW
74
  type t = Stable.Latest.t [@@deriving equal, compare, sexp, yojson]
×
75
end
76

77
module Pre_diff_two = struct
78
  [%%versioned
79
  module Stable = struct
80
    [@@@no_toplevel_latest_type]
81

82
    module V2 = struct
83
      type ('a, 'b) t =
365✔
NEW
84
        { completed_works : 'a list
×
NEW
85
        ; commands : 'b list
×
NEW
86
        ; coinbase : Ft.Stable.V1.t At_most_two.Stable.V1.t
×
NEW
87
        ; internal_command_statuses : Transaction_status.Stable.V2.t list
×
88
        }
89
      [@@deriving equal, compare, sexp, yojson]
329✔
90
    end
91
  end]
92

NEW
93
  type ('a, 'b) t = ('a, 'b) Stable.Latest.t =
×
NEW
94
    { completed_works : 'a list
×
NEW
95
    ; commands : 'b list
×
NEW
96
    ; coinbase : Ft.t At_most_two.t
×
NEW
97
    ; internal_command_statuses : Transaction_status.t list
×
98
    }
NEW
99
  [@@deriving equal, compare, sexp, yojson]
×
100

101
  let map t ~f1 ~f2 =
102
    { completed_works = List.map t.completed_works ~f:f1
2,186✔
103
    ; commands = List.map t.commands ~f:f2
2,186✔
104
    ; coinbase = t.coinbase
105
    ; internal_command_statuses = t.internal_command_statuses
106
    }
107
end
108

109
module Pre_diff_one = struct
110
  [%%versioned
111
  module Stable = struct
112
    [@@@no_toplevel_latest_type]
113

114
    module V2 = struct
115
      type ('a, 'b) t =
153✔
NEW
116
        { completed_works : 'a list
×
NEW
117
        ; commands : 'b list
×
NEW
118
        ; coinbase : Ft.Stable.V1.t At_most_one.Stable.V1.t
×
NEW
119
        ; internal_command_statuses : Transaction_status.Stable.V2.t list
×
120
        }
121
      [@@deriving equal, compare, sexp, yojson]
316✔
122
    end
123
  end]
124

NEW
125
  type ('a, 'b) t = ('a, 'b) Stable.Latest.t =
×
NEW
126
    { completed_works : 'a list
×
NEW
127
    ; commands : 'b list
×
NEW
128
    ; coinbase : Ft.t At_most_one.t
×
NEW
129
    ; internal_command_statuses : Transaction_status.t list
×
130
    }
NEW
131
  [@@deriving equal, compare, sexp, yojson]
×
132

133
  let map t ~f1 ~f2 =
NEW
134
    { completed_works = List.map t.completed_works ~f:f1
×
NEW
135
    ; commands = List.map t.commands ~f:f2
×
136
    ; coinbase = t.coinbase
137
    ; internal_command_statuses = t.internal_command_statuses
138
    }
139
end
140

141
module Pre_diff_with_at_most_two_coinbase = struct
142
  [%%versioned
143
  module Stable = struct
144
    [@@@no_toplevel_latest_type]
145

146
    module V2 = struct
147
      type t =
73✔
NEW
148
        ( Transaction_snark_work.Stable.V2.t
×
149
        , User_command.Stable.V2.t With_status.Stable.V2.t )
42✔
150
        Pre_diff_two.Stable.V2.t
6✔
151
      [@@deriving equal, sexp, yojson]
365✔
152

153
      let to_latest = Fn.id
154
    end
155
  end]
156

157
  type t =
158
    (Transaction_snark_work.t, User_command.t With_status.t) Pre_diff_two.t
159

160
  let write_all_proofs_to_disk ~proof_cache_db : Stable.Latest.t -> t =
161
    Pre_diff_two.map
280✔
162
      ~f1:(Transaction_snark_work.write_all_proofs_to_disk ~proof_cache_db)
163
      ~f2:
164
        (With_status.map
165
           ~f:(User_command.write_all_proofs_to_disk ~proof_cache_db) )
166

167
  let read_all_proofs_from_disk : t -> Stable.Latest.t =
168
    Pre_diff_two.map ~f1:Transaction_snark_work.read_all_proofs_from_disk
169
      ~f2:(With_status.map ~f:User_command.read_all_proofs_from_disk)
170
end
171

172
module Pre_diff_with_at_most_one_coinbase = struct
173
  [%%versioned
174
  module Stable = struct
175
    [@@@no_toplevel_latest_type]
176

177
    module V2 = struct
178
      type t =
73✔
NEW
179
        ( Transaction_snark_work.Stable.V2.t
×
NEW
180
        , User_command.Stable.V2.t With_status.Stable.V2.t )
×
NEW
181
        Pre_diff_one.Stable.V2.t
×
182
      [@@deriving equal, sexp, yojson]
365✔
183

184
      let to_latest = Fn.id
185
    end
186
  end]
187

188
  type t =
189
    (Transaction_snark_work.t, User_command.t With_status.t) Pre_diff_one.t
190

191
  let write_all_proofs_to_disk ~proof_cache_db : Stable.Latest.t -> t =
192
    Pre_diff_one.map
280✔
193
      ~f1:(Transaction_snark_work.write_all_proofs_to_disk ~proof_cache_db)
194
      ~f2:
195
        (With_status.map
196
           ~f:(User_command.write_all_proofs_to_disk ~proof_cache_db) )
197

198
  let read_all_proofs_from_disk : t -> Stable.Latest.t =
199
    Pre_diff_one.map ~f1:Transaction_snark_work.read_all_proofs_from_disk
200
      ~f2:(With_status.map ~f:User_command.read_all_proofs_from_disk)
201
end
202

203
module Diff = struct
204
  let coinbase_amount
205
      ~(constraint_constants : Genesis_constants.Constraint_constants.t)
206
      ~supercharge_coinbase =
207
    if supercharge_coinbase then
5,448✔
208
      Currency.Amount.scale constraint_constants.coinbase_amount
4,480✔
209
        constraint_constants.supercharged_coinbase_factor
210
    else Some constraint_constants.coinbase_amount
968✔
211

212
  let coinbase
213
      ~(constraint_constants : Genesis_constants.Constraint_constants.t)
214
      ~supercharge_coinbase (first_pre_diff, second_pre_diff_opt) =
215
    let coinbase_amount =
381✔
216
      coinbase_amount ~constraint_constants ~supercharge_coinbase
217
    in
218
    match
219
      ( first_pre_diff.Pre_diff_two.coinbase
220
      , Option.value_map second_pre_diff_opt ~default:At_most_one.Zero
381✔
NEW
221
          ~f:(fun d -> d.Pre_diff_one.coinbase) )
×
222
    with
223
    | At_most_two.Zero, At_most_one.Zero ->
221✔
224
        Some Currency.Amount.zero
225
    | _ ->
160✔
226
        coinbase_amount
227

228
  [%%versioned
229
  module Stable = struct
230
    [@@@no_toplevel_latest_type]
231

232
    module V2 = struct
233
      type t =
73✔
NEW
234
        Pre_diff_with_at_most_two_coinbase.Stable.V2.t
×
NEW
235
        * Pre_diff_with_at_most_one_coinbase.Stable.V2.t option
×
236
      [@@deriving equal, sexp, yojson]
365✔
237

238
      let to_latest = Fn.id
239

240
      let coinbase = coinbase
241
    end
242
  end]
243

244
  type t =
245
    Pre_diff_with_at_most_two_coinbase.t
246
    * Pre_diff_with_at_most_one_coinbase.t option
247

248
  let write_all_proofs_to_disk ~proof_cache_db
249
      (( pre_diff_with_at_most_two_coinbase
250
       , pre_diff_with_at_most_one_coinbase_opt ) :
251
        Stable.Latest.t ) : t =
252
    ( Pre_diff_with_at_most_two_coinbase.write_all_proofs_to_disk
280✔
253
        ~proof_cache_db pre_diff_with_at_most_two_coinbase
254
    , Option.map pre_diff_with_at_most_one_coinbase_opt
280✔
255
        ~f:
256
          (Pre_diff_with_at_most_one_coinbase.write_all_proofs_to_disk
257
             ~proof_cache_db ) )
258

259
  let read_all_proofs_from_disk
260
      (( pre_diff_with_at_most_two_coinbase
261
       , pre_diff_with_at_most_one_coinbase_opt ) :
262
        t ) : Stable.Latest.t =
263
    ( Pre_diff_with_at_most_two_coinbase.read_all_proofs_from_disk
1,906✔
264
        pre_diff_with_at_most_two_coinbase
265
    , Option.map pre_diff_with_at_most_one_coinbase_opt
1,906✔
266
        ~f:Pre_diff_with_at_most_one_coinbase.read_all_proofs_from_disk )
267
end
268

269
[%%versioned
270
module Stable = struct
271
  [@@@no_toplevel_latest_type]
272

273
  module V2 = struct
NEW
274
    type t = { diff : Diff.Stable.V2.t } [@@deriving equal, sexp, yojson]
×
275

276
    let to_latest = Fn.id
277

278
    let empty_diff : t =
279
      { diff =
280
          ( { completed_works = []
281
            ; commands = []
282
            ; coinbase = At_most_two.Zero
283
            ; internal_command_statuses = []
284
            }
285
          , None )
286
      }
287

288
    let completed_works (t : t) =
289
      (fst t.diff).completed_works
1✔
290
      @ Option.value_map (snd t.diff) ~default:[] ~f:(fun d ->
1✔
291
            d.completed_works )
1✔
292
  end
293
end]
294

NEW
295
type t = { diff : Diff.t } [@@deriving fields]
×
296

297
let write_all_proofs_to_disk ~proof_cache_db t =
298
  { diff = Diff.write_all_proofs_to_disk ~proof_cache_db t.Stable.Latest.diff }
280✔
299

300
let read_all_proofs_from_disk t =
301
  { Stable.Latest.diff = Diff.read_all_proofs_from_disk t.diff }
1,906✔
302

303
module With_valid_signatures_and_proofs = struct
304
  type pre_diff_with_at_most_two_coinbase =
305
    ( Transaction_snark_work.Checked.t
306
    , User_command.Valid.t With_status.t )
307
    Pre_diff_two.t
308

309
  type pre_diff_with_at_most_one_coinbase =
310
    ( Transaction_snark_work.Checked.t
311
    , User_command.Valid.t With_status.t )
312
    Pre_diff_one.t
313

314
  type diff =
315
    pre_diff_with_at_most_two_coinbase
316
    * pre_diff_with_at_most_one_coinbase option
317

318
  type t = { diff : diff }
319

320
  let empty_diff : t =
321
    { diff =
322
        ( { completed_works = []
323
          ; commands = []
324
          ; coinbase = At_most_two.Zero
325
          ; internal_command_statuses = []
326
          }
327
        , None )
328
    }
329

330
  let commands t =
331
    (fst t.diff).commands
23✔
UNCOV
332
    @ Option.value_map (snd t.diff) ~default:[] ~f:(fun d -> d.commands)
×
333
end
334

335
let forget_cw cw_list = List.map ~f:Transaction_snark_work.forget cw_list
5,586✔
336

337
module With_valid_signatures = struct
338
  type pre_diff_with_at_most_two_coinbase =
339
    ( Transaction_snark_work.t
340
    , User_command.Valid.t With_status.t )
341
    Pre_diff_two.t
342

343
  type pre_diff_with_at_most_one_coinbase =
344
    ( Transaction_snark_work.t
345
    , User_command.Valid.t With_status.t )
346
    Pre_diff_one.t
347

348
  type diff =
349
    pre_diff_with_at_most_two_coinbase
350
    * pre_diff_with_at_most_one_coinbase option
351

352
  type t = { diff : diff }
353

354
  let coinbase
355
      ~(constraint_constants : Genesis_constants.Constraint_constants.t)
356
      ~supercharge_coinbase (t : t) =
357
    let first_pre_diff, second_pre_diff_opt = t.diff in
5,067✔
358
    let coinbase_amount =
359
      Diff.coinbase_amount ~constraint_constants ~supercharge_coinbase
360
    in
361
    match
362
      ( first_pre_diff.coinbase
363
      , Option.value_map second_pre_diff_opt ~default:At_most_one.Zero
5,067✔
364
          ~f:(fun d -> d.coinbase) )
579✔
365
    with
366
    | At_most_two.Zero, At_most_one.Zero ->
956✔
367
        Some Currency.Amount.zero
368
    | _ ->
4,111✔
369
        coinbase_amount
370
end
371

372
let validate_commands (t : t)
373
    ~(check :
374
          User_command.t With_status.t list
375
       -> (User_command.Valid.t list, 'e) Result.t Async.Deferred.Or_error.t ) :
376
    (With_valid_signatures.t, 'e) Result.t Async.Deferred.Or_error.t =
377
  let map t ~f = Async.Deferred.Or_error.map t ~f:(Result.map ~f) in
4,423✔
378
  let validate cs =
379
    map (check cs)
4,423✔
380
      ~f:
381
        (List.map2_exn cs ~f:(fun c data ->
4,423✔
382
             { With_status.data; status = c.status } ) )
9,700✔
383
  in
384
  let d1, d2 = t.diff in
385
  map
386
    (validate
4,423✔
387
       (d1.commands @ Option.value_map d2 ~default:[] ~f:(fun d2 -> d2.commands)) )
579✔
388
    ~f:(fun commands_all ->
389
      let commands1, commands2 =
4,422✔
390
        List.split_n commands_all (List.length d1.commands)
4,422✔
391
      in
392
      let p1 : With_valid_signatures.pre_diff_with_at_most_two_coinbase =
4,422✔
393
        { completed_works = d1.completed_works
394
        ; commands = commands1
395
        ; coinbase = d1.coinbase
396
        ; internal_command_statuses = d1.internal_command_statuses
397
        }
398
      in
399
      let p2 =
400
        Option.value_map ~default:None d2 ~f:(fun d2 ->
401
            Some
579✔
402
              { Pre_diff_one.completed_works = d2.completed_works
403
              ; commands = commands2
404
              ; coinbase = d2.coinbase
405
              ; internal_command_statuses = d2.internal_command_statuses
406
              } )
407
      in
408
      ({ diff = (p1, p2) } : With_valid_signatures.t) )
4,422✔
409

410
let forget_proof_checks (d : With_valid_signatures_and_proofs.t) :
411
    With_valid_signatures.t =
412
  let d1 = fst d.diff in
645✔
413
  let p1 : With_valid_signatures.pre_diff_with_at_most_two_coinbase =
645✔
414
    { completed_works = forget_cw d1.completed_works
645✔
415
    ; commands = d1.commands
416
    ; coinbase = d1.coinbase
417
    ; internal_command_statuses = d1.internal_command_statuses
418
    }
419
  in
420
  let p2 =
421
    Option.map (snd d.diff)
645✔
422
      ~f:(fun d2 : With_valid_signatures.pre_diff_with_at_most_one_coinbase ->
NEW
423
        { completed_works = forget_cw d2.completed_works
×
424
        ; commands = d2.commands
425
        ; coinbase = d2.coinbase
426
        ; internal_command_statuses = d2.internal_command_statuses
427
        } )
428
  in
429
  { diff = (p1, p2) }
645✔
430

431
let forget_pre_diff_with_at_most_two
432
    (pre_diff :
433
      With_valid_signatures_and_proofs.pre_diff_with_at_most_two_coinbase ) :
434
    Pre_diff_with_at_most_two_coinbase.t =
435
  { completed_works = forget_cw pre_diff.completed_works
4,362✔
436
  ; commands =
437
      List.map
4,362✔
438
        ~f:(With_status.map ~f:User_command.forget_check)
439
        pre_diff.commands
440
  ; coinbase = pre_diff.coinbase
441
  ; internal_command_statuses = pre_diff.internal_command_statuses
442
  }
443

444
let forget_pre_diff_with_at_most_one
445
    (pre_diff :
446
      With_valid_signatures_and_proofs.pre_diff_with_at_most_one_coinbase ) =
447
  { Pre_diff_one.completed_works = forget_cw pre_diff.completed_works
579✔
448
  ; commands =
449
      List.map
579✔
450
        ~f:(With_status.map ~f:User_command.forget_check)
451
        pre_diff.commands
452
  ; coinbase = pre_diff.coinbase
453
  ; internal_command_statuses = pre_diff.internal_command_statuses
454
  }
455

456
let forget (t : With_valid_signatures_and_proofs.t) =
457
  { diff =
4,362✔
458
      ( forget_pre_diff_with_at_most_two (fst t.diff)
4,362✔
459
      , Option.map (snd t.diff) ~f:forget_pre_diff_with_at_most_one )
4,362✔
460
  }
461

462
let commands (t : t) =
463
  (fst t.diff).commands
16,844✔
464
  @ Option.value_map (snd t.diff) ~default:[] ~f:(fun d -> d.commands)
2,161✔
465

466
let completed_works (t : t) =
467
  (fst t.diff).completed_works
8,854✔
468
  @ Option.value_map (snd t.diff) ~default:[] ~f:(fun d -> d.completed_works)
1,158✔
469

470
let net_return
471
    ~(constraint_constants : Genesis_constants.Constraint_constants.t)
472
    ~supercharge_coinbase (t : t) =
NEW
473
  let open Currency in
×
474
  let open Option.Let_syntax in
475
  let%bind coinbase =
NEW
476
    Diff.coinbase ~constraint_constants ~supercharge_coinbase t.diff
×
477
  in
478
  let%bind total_reward =
NEW
479
    List.fold
×
NEW
480
      ~init:(Some (Amount.to_fee coinbase))
×
NEW
481
      (commands t)
×
482
      ~f:(fun sum cmd ->
483
        let%bind sum = sum in
NEW
484
        Fee.( + ) sum (User_command.fee (With_status.data cmd)) )
×
485
  in
486
  let%bind completed_works_fees =
NEW
487
    List.fold ~init:(Some Fee.zero) (completed_works t) ~f:(fun sum work ->
×
488
        let%bind sum = sum in
NEW
489
        Fee.(sum + Transaction_snark_work.fee work) )
×
490
  in
NEW
491
  Amount.(of_fee total_reward - of_fee completed_works_fees)
×
492

493
let empty_diff : t =
494
  { diff =
495
      ( { completed_works = []
496
        ; commands = []
497
        ; coinbase = At_most_two.Zero
498
        ; internal_command_statuses = []
499
        }
500
      , None )
501
  }
502

503
let is_empty = function
NEW
504
  | { diff =
×
505
        ( { completed_works = []
506
          ; commands = []
507
          ; coinbase = At_most_two.Zero
508
          ; internal_command_statuses = []
509
          }
510
        , None )
511
    } ->
512
      true
NEW
513
  | _ ->
×
514
      false
146✔
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