Source file vdf_self_contained.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
(*****************************************************************************)
(*                                                                           *)
(* MIT License                                                               *)
(* Copyright (c) 2022 Nomadic Labs <contact@nomadic-labs.com>                *)
(*                                                                           *)
(* Permission is hereby granted, free of charge, to any person obtaining a   *)
(* copy of this software and associated documentation files (the "Software"),*)
(* to deal in the Software without restriction, including without limitation *)
(* the rights to use, copy, modify, merge, publish, distribute, sublicense,  *)
(* and/or sell copies of the Software, and to permit persons to whom the     *)
(* Software is furnished to do so, subject to the following conditions:      *)
(*                                                                           *)
(* The above copyright notice and this permission notice shall be included   *)
(* in all copies or substantial portions of the Software.                    *)
(*                                                                           *)
(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)
(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  *)
(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL   *)
(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)
(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING   *)
(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER       *)
(* DEALINGS IN THE SOFTWARE.                                                 *)
(*                                                                           *)
(*****************************************************************************)

module Random = Random4

let discriminant_size_bytes = 128

let form_size_bytes = 100

type form = Bytes.t

type discriminant = Bytes.t

type challenge = form

type result = form

type proof = form

type difficulty = int64

let discriminant_to_bytes x = x

let discriminant_of_bytes_opt x =
  if Bytes.length x = discriminant_size_bytes then Some x else None

let challenge_to_bytes x = x

let challenge_of_bytes_opt x =
  if Bytes.length x = form_size_bytes then Some x else None

let result_to_bytes x = x

let result_of_bytes_opt x =
  if Bytes.length x = form_size_bytes then Some x else None

let proof_to_bytes x = x

let proof_of_bytes_opt x =
  if Bytes.length x = form_size_bytes then Some x else None

let invalid_discriminant_size =
  Invalid_argument
    (Printf.sprintf
       "Invalid discriminant: discriminant must be %d byte long."
       discriminant_size_bytes)

let check_discriminant_size size =
  if size != discriminant_size_bytes then raise invalid_discriminant_size

let generate_discriminant ?(seed = Bytes.empty) form_size_bytes =
  check_discriminant_size form_size_bytes ;
  let result = Bytes.create form_size_bytes in
  Utils.Stubs.create_discriminant
    seed
    (Bytes.length seed)
    form_size_bytes
    result ;
  result

let random discriminant seed =
  let () =
    let state_seed = Array.(map int_of_char (of_seq (Bytes.to_seq seed))) in
    Random.(State.make state_seed |> set_state)
  in
  let discriminant_size_int = Bytes.length discriminant in
  let discriminant_size = discriminant_size_int |> Unsigned.Size_t.of_int in
  let mul_bytes form exp_bits exp_len =
    let buffer = Bytes.create form_size_bytes in
    let status =
      Class_group.Stubs.mul
        discriminant
        discriminant_size
        form
        exp_bits
        exp_len
        buffer
    in
    match status with
    | x when x = 0 -> buffer
    | x when x = 2 -> raise Utils.invalid_group_element
    | _ -> raise Utils.unknown_error
  in
  let one =
    let buffer = Bytes.create form_size_bytes in
    Class_group.Stubs.one discriminant discriminant_size buffer ;
    buffer
  in
  let len_exp = discriminant_size_int / 2 in
  let random_exp =
    Bytes.init len_exp (fun _ -> Random.int 256 |> char_of_int)
  in
  mul_bytes one random_exp len_exp

let generate_challenge = random

let prove discriminant challenge difficulty =
  let discriminant_size_int = Bytes.length discriminant in
  check_discriminant_size discriminant_size_int ;
  let discriminant_size = discriminant_size_int |> Unsigned.Size_t.of_int in
  let difficulty_uint = Unsigned.UInt64.of_int64 difficulty in
  let result = Bytes.create form_size_bytes in
  let proof = Bytes.create form_size_bytes in
  let status =
    Vdf.Stubs.prove
      discriminant
      discriminant_size
      challenge
      difficulty_uint
      result
      proof
  in
  match status with
  | x when x = 0 -> (result, proof)
  | x when x = 2 -> raise Utils.invalid_group_element
  | _ -> raise Utils.unknown_error

let verify discriminant challenge difficulty result proof =
  let discriminant_size_int = Bytes.length discriminant in
  check_discriminant_size discriminant_size_int ;
  let status =
    Vdf.Stubs.verify
      discriminant
      (Unsigned.Size_t.of_int discriminant_size_int)
      challenge
      result
      proof
      (Unsigned.UInt64.of_int64 difficulty)
  in
  match status with
  | x when x = 0 -> false
  | x when x = 1 -> true
  | x when x = 2 -> raise Utils.invalid_group_element
  | _ -> raise Utils.unknown_error