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
module Make
(PC : Kzg.Polynomial_commitment_sig
with type Commitment.t = Bls12_381.G1.t SMap.t)
(Pack : Pack.Aggregator) =
struct
module Scalar = PC.Scalar
module Polynomial = PC.Polynomial
module Domain = Polynomial.Domain
module Poly = PC.Polynomial.Polynomial
module Scalar_map = PC.Scalar_map
module Fr_generation = PC.Fr_generation
type secret = Poly.t SMap.t
type query = Scalar.t SMap.t
type answer = Scalar.t SMap.t SMap.t
let answer_encoding : answer Data_encoding.t =
SMap.encoding @@ SMap.encoding Encodings.fr_encoding
let bytes_of_query =
Data_encoding.Binary.to_bytes_exn @@ SMap.encoding Encodings.fr_encoding
let bytes_of_answer = Data_encoding.Binary.to_bytes_exn answer_encoding
type transcript = Bytes.t
module Public_parameters = struct
type prover = {
pp_pc_prover : PC.Public_parameters.prover;
pp_pack_prover : Pack.prover_public_parameters;
}
type verifier = {
pp_pc_verifier : PC.Public_parameters.verifier;
pp_pack_verifier : Pack.verifier_public_parameters;
}
let verifier_encoding : verifier Data_encoding.t =
Data_encoding.(
conv
(fun { pp_pc_verifier; pp_pack_verifier } ->
(pp_pc_verifier, pp_pack_verifier))
(fun (pp_pc_verifier, pp_pack_verifier) ->
{ pp_pc_verifier; pp_pack_verifier })
(obj2
(req "pp_pc_verifier" PC.Public_parameters.verifier_encoding)
(req "pp_pack_prover" Pack.verifier_public_parameters_encoding)))
type setup_params = int * int
let setup ?state setup_params =
let pp_pc_prover, pp_pc_verifier =
PC.Public_parameters.setup ?state setup_params
in
let pp_pack_prover, pp_pack_verifier =
Pack.setup ?state (snd setup_params)
in
let pp_prover = { pp_pc_prover; pp_pack_prover } in
let pp_verifier = { pp_pc_verifier; pp_pack_verifier } in
(pp_prover, pp_verifier)
let get_d (public_parameters : prover) =
PC.Public_parameters.get_d public_parameters.pp_pc_prover
let import setup_params srsfiles =
let pp_pc_prover, pp_pc_verifier =
PC.Public_parameters.import setup_params srsfiles
in
let pp_pack_prover, pp_pack_verifier =
Pack.import (snd setup_params) srsfiles
in
let pp_prover = { pp_pc_prover; pp_pack_prover } in
let pp_verifier = { pp_pc_verifier; pp_pack_verifier } in
(pp_prover, pp_verifier)
let to_bytes ({ pp_pc_prover; pp_pack_prover } : prover) =
Utils.Hash.hash_bytes
[
PC.Public_parameters.to_bytes pp_pc_prover;
Pack.public_parameters_to_bytes pp_pack_prover;
]
end
module Commitment = struct
type t = Pack.commitment
let encoding : t Data_encoding.t = Pack.commitment_encoding
type prover_aux = PC.Commitment.t * PC.Commitment.prover_aux
let expand_transcript =
Utils.expand_transcript
~to_bytes:(Data_encoding.Binary.to_bytes_exn encoding)
let commit (pp : Public_parameters.prover) f_map =
let prover_aux = PC.Commitment.commit pp.pp_pc_prover f_map in
let cm_list = List.map snd @@ SMap.bindings (fst prover_aux) in
let pack_cmt = Pack.commit pp.pp_pack_prover cm_list in
(pack_cmt, prover_aux)
let cardinal = Pack.commitment_cardinal
end
type proof = {
pc_proof : PC.proof;
packed_values : Pack.packed list;
pack_proof : Pack.proof;
}
let proof_encoding : proof Data_encoding.t =
Data_encoding.(
conv
(fun { pc_proof; packed_values; pack_proof } ->
(pc_proof, packed_values, pack_proof))
(fun (pc_proof, packed_values, pack_proof) ->
{ pc_proof; packed_values; pack_proof })
(obj3
(req "pc_proof" PC.proof_encoding)
(req "packed_values" @@ list Pack.packed_encoding)
(req "pack_proof" Pack.proof_encoding)))
let expand_with_proof =
Utils.expand_transcript
~to_bytes:(Data_encoding.Binary.to_bytes_exn proof_encoding)
let expand_with_query = Utils.list_expand_transcript ~to_bytes:bytes_of_query
let expand_with_answer =
Utils.list_expand_transcript ~to_bytes:bytes_of_answer
let batch ~zero ~add ~mul r map =
SMap.fold
(fun _ x (acc, rk) -> (add acc (mul rk x), Scalar.mul r rk))
map (zero, Scalar.one)
|> fst
let batch_polys r map =
let polys = SMap.bindings map |> List.map snd in
let r_coeffs = Fr_generation.powers (List.length polys) r in
Poly.linear polys @@ Array.to_list r_coeffs
let batch_answers r = SMap.map Scalar.(batch ~zero ~add ~mul r)
let evaluate = PC.evaluate
let prove (pp : Public_parameters.prover) transcript f_map_list
(prover_aux_list : Commitment.prover_aux list) query_list answer_list =
let transcript = expand_with_query transcript query_list in
let transcript = expand_with_answer transcript answer_list in
let r, transcript = Fr_generation.random_fr transcript in
let f_list = List.map (batch_polys r) f_map_list in
let s_list = List.map (batch_answers r) answer_list in
let cmts_list =
List.map
(fun (cmts, _prover_aux) -> List.map snd @@ SMap.bindings cmts)
prover_aux_list
in
let (packed_values, pack_proof), transcript =
Pack.prove pp.pp_pack_prover transcript r cmts_list
in
let f_map_list =
List.mapi (fun i l -> SMap.singleton (string_of_int i) l) f_list
in
let s_map_list =
List.mapi
(fun i m -> SMap.map (fun s -> SMap.singleton (string_of_int i) s) m)
s_list
in
let prover_aux_list = List.map snd prover_aux_list in
let pc_proof, transcript =
PC.prove pp.pp_pc_prover transcript f_map_list prover_aux_list query_list
s_map_list
in
let proof = { pc_proof; packed_values; pack_proof } in
(proof, expand_with_proof transcript proof)
let verify (pp : Public_parameters.verifier) transcript cmt_list query_list
s_map_list proof =
let transcript = expand_with_query transcript query_list in
let transcript = expand_with_answer transcript s_map_list in
let r, transcript = Fr_generation.random_fr transcript in
let pack_ok, transcript =
Pack.verify pp.pp_pack_verifier transcript cmt_list r
(proof.packed_values, proof.pack_proof)
in
let s_list = List.map (batch_answers r) s_map_list in
let s_map_list =
List.mapi
(fun i m -> SMap.map (fun s -> SMap.singleton (string_of_int i) s) m)
s_list
in
let cmt_map_list =
List.mapi
(fun i l -> SMap.singleton (string_of_int i) l)
proof.packed_values
in
let pc_ok, transcript =
PC.verify pp.pp_pc_verifier transcript cmt_map_list query_list s_map_list
proof.pc_proof
in
(pack_ok && pc_ok, expand_with_proof transcript proof)
end
include (Make (Kzg) (Pack) : Kzg.Polynomial_commitment_sig)