package class_group_vdf

  1. Overview
  2. Docs

Source file class_group.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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
open Utils

module Stubs = struct
  external caml_check_bytes_stubs :
    Bytes.t -> Unsigned.Size_t.t -> Bytes.t -> bool = "caml_check_bytes_stubs"

  external zero : Bytes.t -> Unsigned.Size_t.t -> Bytes.t -> unit
    = "caml_zero_stubs"

  external one : Bytes.t -> Unsigned.Size_t.t -> Bytes.t -> unit
    = "caml_one_stubs"

  external eq : Bytes.t -> Unsigned.Size_t.t -> Bytes.t -> Bytes.t -> int
    = "caml_eq_stubs"

  external neg : Bytes.t -> Unsigned.Size_t.t -> Bytes.t -> Bytes.t -> int
    = "caml_neg_stubs"

  external add :
    Bytes.t -> Unsigned.Size_t.t -> Bytes.t -> Bytes.t -> Bytes.t -> int
    = "caml_add_stubs"

  external double : Bytes.t -> Unsigned.Size_t.t -> Bytes.t -> Bytes.t -> int
    = "caml_double_stubs"

  external mul :
    Bytes.t -> Unsigned.Size_t.t -> Bytes.t -> Bytes.t -> int -> Bytes.t -> int
    = "caml_mul_bytecode_stubs" "caml_mul_stubs"
end

module type Class_group_sig = sig
  (* BE CAREFUL : GET THE CANONICAL REPRESENTATION !!! *)
  include S.GROUP

  val discriminant : Integer.t

  val discriminant_size : Unsigned.Size_t.t
  (* val of_coefficients : Integer.t * Integer.t * Integer.t -> t

     val get_coefficients : t -> Integer.t * Integer.t * Integer.t

     val get_discriminant : t -> Integer.t *)
end

module Make (D : sig
  val discriminant : Integer.t
end) : Class_group_sig = struct
  type t = Bytes.t

  let invalid_discriminant_size =
    Invalid_argument
      "Invalid discriminant: current code only support discriminant of size 128"

  let discriminant_size_int = Integer.size_in_bytes D.discriminant

  let discriminant =
    (* Constraint from Chia's cpp code *)
    if discriminant_size_int = 128 then D.discriminant
    else raise invalid_discriminant_size

  let discriminant_size = Unsigned.Size_t.of_int discriminant_size_int

  let discriminant_bytes = Integer.to_bytes D.discriminant

  (* Constraint from Chia's cpp code *)
  let size_in_bytes = 100

  let check_bytes input =
    Stubs.caml_check_bytes_stubs discriminant_bytes discriminant_size input

  let of_bytes_exn input =
    if check_bytes input then input else failwith "Form not in group"

  let of_bytes_opt input = if check_bytes input then Some input else None

  let to_bytes f = f

  (* let of_coefficients _a _b _c = let id = Bytes.create size_in_bytes in
     Stubs.identity disc discriminant_size id ; id

     (* TODO *) let get_coefficients _f = let zero = Integer.of_bytes
     (Bytes.create 0) in (zero, zero, zero)

     (* TODO *) let get_discriminant _f = Integer.of_bytes (Bytes.create 0) *)

  let size_in_memory = 100

  let zero =
    let buffer = Bytes.create size_in_bytes in
    Stubs.zero discriminant_bytes discriminant_size buffer ;
    buffer

  let one =
    let buffer = Bytes.create size_in_bytes in
    Stubs.one discriminant_bytes discriminant_size buffer ;
    buffer

  let eq f1 f2 =
    let status = Stubs.eq discriminant_bytes discriminant_size f1 f2 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

  let is_zero f = eq f zero

  let is_one f = eq f one

  let neg f =
    let buffer = Bytes.create size_in_bytes in
    let status = Stubs.neg discriminant_bytes discriminant_size f buffer in
    match status with
    | x when x = 0 -> buffer
    | x when x = 2 -> raise Utils.invalid_group_element
    | _ -> raise Utils.unknown_error

  let add f1 f2 =
    let buffer = Bytes.create size_in_bytes in
    let status = Stubs.add discriminant_bytes discriminant_size f1 f2 buffer in
    match status with
    | x when x = 0 -> buffer
    | x when x = 2 -> raise Utils.invalid_group_element
    | _ -> raise Utils.unknown_error

  let double f =
    let buffer = Bytes.create size_in_bytes in
    let status = Stubs.double discriminant_bytes discriminant_size f buffer in
    match status with
    | x when x = 0 -> buffer
    | x when x = 2 -> raise Utils.invalid_group_element
    | _ -> raise Utils.unknown_error

  let mul form exponent =
    let rec aux f n =
      if Z.(equal n zero) then zero
      else if Z.(equal n one) then f
      else if Z.(lt n zero) then aux (neg f) Z.(neg n)
      else
        let buffer = Bytes.create size_in_bytes in
        let exp_bits = Z.to_bits n |> Bytes.unsafe_of_string in
        let exp_len = Z.numbits n in
        let status =
          Stubs.mul
            discriminant_bytes
            discriminant_size
            f
            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
    aux form exponent

  let random ?state () =
    let () =
      match state with
      | None -> Random.self_init ()
      | Some s -> Random.set_state s
    in
    let mul_bytes form exp_bits exp_len =
      let buffer = Bytes.create size_in_bytes in
      let status =
        Stubs.mul
          discriminant_bytes
          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 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
end