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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
module Hash : sig
type state
val init : unit -> state
val update : state -> bytes -> unit
val finish : state -> bytes
val hash_bytes : bytes list -> bytes
val bytes_to_seed : bytes -> int array * bytes
end = struct
type state = Hacl_star.EverCrypt.Hash.t
let init () =
Hacl_star.EverCrypt.Hash.init ~alg:Hacl_star.SharedDefs.HashDefs.BLAKE2b
let update st msg = Hacl_star.EverCrypt.Hash.update ~st ~msg
let finish st = Hacl_star.EverCrypt.Hash.finish ~st
let hash_bytes bytes =
let blake2b msg =
let digest_size = 32 in
let open Hacl_star in
if AutoConfig2.(has_feature VEC256) then
Hacl.Blake2b_256.hash msg digest_size
else Hacl.Blake2b_32.hash msg digest_size
in
blake2b (Bytes.concat Bytes.empty bytes)
let bytes_to_seed b =
let hashed_b = hash_bytes [b] in
assert (Bytes.length hashed_b = 32) ;
let sys_int_size = Sys.int_size - 1 in
let modulo = Z.pow (Z.of_int 2) sys_int_size in
let n0_raw = Z.of_bits (Bytes.sub_string hashed_b 0 8) in
let n0 = Z.to_int (Z.erem n0_raw modulo) in
let n1_raw = Z.of_bits (Bytes.sub_string hashed_b 8 8) in
let n1 = Z.to_int (Z.erem n1_raw modulo) in
let n2_raw = Z.of_bits (Bytes.sub_string hashed_b 16 8) in
let n2 = Z.to_int (Z.erem n2_raw modulo) in
let n3_raw = Z.of_bits (Bytes.sub_string hashed_b 24 8) in
let n3 = Z.to_int (Z.erem n3_raw modulo) in
([|n0; n1; n2; n3|], hashed_b)
end
module Transcript = struct
let list_expand repr list transcript =
let open Hash in
let st = init () in
update st transcript ;
List.iter (fun a -> update st (Plompiler.Utils.to_bytes repr a)) list ;
finish st
let expand : 'a Repr.t -> 'a -> bytes -> bytes =
fun repr x transcript -> list_expand repr [x] transcript
end
module Array = struct
include Array
let pad array final_size =
let size = Array.length array in
Array.init final_size (fun i ->
if i < size then array.(i) else array.(size - 1))
let resize array final_size =
let size = Array.length array in
if size = final_size then array
else if size > final_size then Array.sub array 0 final_size
else pad array final_size
let build init next len =
let xi = ref init in
Array.init len (fun _ ->
let i = !xi in
xi := next !xi ;
i)
end
let pad_answers nb_max_proofs nb_rc_wires nb_proofs
(answers : S.t SMap.t SMap.t list) =
let answers = List.map (SMap.map SMap.values) answers in
let answers_padded =
List.map_end
(SMap.map (fun w_list ->
w_list
@ List.init
((nb_max_proofs - nb_proofs)
* (Plompiler.Csir.nb_wires_arch + nb_rc_wires))
(Fun.const S.zero)))
answers
in
answers_padded |> List.concat_map SMap.values |> List.flatten
module Fr_generation : sig
val powers : int -> Bls.Scalar.t -> Bls.Scalar.t array
val batch : Bls.Scalar.t -> Bls.Scalar.t list -> Bls.Scalar.t
val build_quadratic_non_residues : int -> Bls.Scalar.t array
val random_fr_list : Bytes.t -> int -> Bls.Scalar.t list * Bytes.t
val random_fr : Bytes.t -> Bls.Scalar.t * Bytes.t
val evaluate_l1 :
domain_size:int -> generator:Bls.Scalar.t -> Bls.Scalar.t -> Bls.Scalar.t
val evaluate_l0 : domain_size:int -> Bls.Scalar.t -> Bls.Scalar.t
end = struct
open Bls
let powers d x = Array.build Scalar.one Scalar.(mul x) d
let batch x l =
List.fold_left
(fun acc y -> Scalar.((x * acc) + y))
Scalar.zero
(List.rev l)
let build_quadratic_non_residues len =
let is_nonresidue n = Z.(equal (Scalar.legendre_symbol n) Z.(-one)) in
let rec next n =
Scalar.(n + one) |> fun n -> if is_nonresidue n then n else next n
in
Array.build Scalar.one next len
let rec hash_to_Fr a =
let b = Z.to_bits a |> Bytes.of_string in
let hashed_b = Hash.hash_bytes [b] in
assert (Bytes.length hashed_b = 32) ;
let x_fr = Scalar.of_bytes_opt hashed_b in
match x_fr with
| Some a -> a
| None -> hash_to_Fr (Z.succ a)
let generate_random_fr ?state () =
(match state with None -> () | Some s -> Random.set_state s) ;
let n0 = Z.of_int64 @@ Random.int64 Int64.max_int in
let n1 = Z.of_int64 @@ Random.int64 Int64.max_int in
let n2 = Z.of_int64 @@ Random.int64 Int64.max_int in
let n3 = Z.of_int64 @@ Random.int64 Int64.max_int in
let n1_64 = Z.(n1 lsl 64) in
let n2_128 = Z.(n2 lsl 128) in
let n3_192 = Z.(n3 lsl 192) in
let gamma_z = Z.(n0 + n1_64 + n2_128 + n3_192) in
let gamma_fr = hash_to_Fr gamma_z in
gamma_fr
let random_fr_list transcript nb_values =
let transcript_array, hashed_transcript = Hash.bytes_to_seed transcript in
Random.full_init transcript_array ;
(List.init nb_values (fun _ -> generate_random_fr ()), hashed_transcript)
let random_fr transcript =
let l, hashed_transcript = random_fr_list transcript 1 in
(List.hd l, hashed_transcript)
let evaluate_l1 ~domain_size ~generator x =
let n = Z.of_int domain_size in
let l1_num = Scalar.(generator * sub (pow x n) one) in
let l1_den = Scalar.(of_z n * sub x generator) in
Scalar.div_exn l1_num l1_den
let evaluate_l0 ~domain_size x =
let n = Z.of_int domain_size in
let l0_num = Scalar.(sub (pow x n) one) in
let l0_den = Scalar.(of_z n * sub x one) in
Scalar.div_exn l0_num l0_den
end
exception SRS_too_short of string
open Bls
let pippenger pippenger ps ss =
try pippenger ?start:None ?len:None ps ss
with Invalid_argument s ->
raise (Invalid_argument ("Utils.pippenger : " ^ s))
let pippenger1_with_affine_array g =
pippenger G1.pippenger_with_affine_array (G1.to_affine_array g)
let commit_single pippenger zero srs_size srs p =
let p_size = 1 + Poly.degree p in
if p_size = 0 then zero
else if p_size > srs_size then
raise
(SRS_too_short
(Printf.sprintf
"commit : Polynomial degree, %i, exceeds srs length, %i."
p_size
srs_size))
else pippenger srs p
let commit1 srs p =
commit_single Srs_g1.pippenger G1.zero (Srs_g1.size srs) srs p
let commit2 srs p =
commit_single Srs_g2.pippenger G2.zero (Srs_g2.size srs) srs p