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
open Plonk.Bls
open Plonk.Utils
module SMap = Plonk.SMap
module type Super_PC_sig = sig
include Kzg.PC_for_distribution_sig
type prover_aux = {r : Scalar.t; s_list : Scalar.t SMap.t list}
val prove_super_aggregation :
Public_parameters.prover ->
transcript ->
Poly.t SMap.t list ->
Commitment.prover_aux list ->
query list ->
Scalar.t SMap.t SMap.t list ->
(proof * prover_aux) * transcript
val verify_super_aggregation :
Public_parameters.verifier ->
transcript ->
Commitment.t list ->
query list ->
Scalar.t SMap.t list ->
proof ->
bool * Scalar.t * transcript
end
(** Extension of the KZG_pack implementation with additional
types and functions used in by Distributed_prover *)
module Kzg_pack_impl = struct
module Pack = Aggregation.Pack
module PC = Kzg.Kzg_impl
module BasePC = Aggregation.Polynomial_commitment.Make_impl (PC)
module Commitment = struct
include BasePC.Commitment
let recombine l = List.fold_left Pack.combine (List.hd l) (List.tl l)
let recombine_prover_aux l =
let cm = PC.Commitment.recombine (List.map fst l) in
let p_a = PC.Commitment.recombine_prover_aux (List.map snd l) in
(cm, p_a)
let empty = Pack.empty_commitment
let empty_prover_aux = (PC.Commitment.empty, PC.Commitment.empty_prover_aux)
end
include (BasePC : module type of BasePC with module Commitment := Commitment)
type worker_msg = Scalar.t * string list list [@@deriving repr]
type main_prover_msg = Poly.t list * Commitment.prover_aux list
[@@deriving repr]
type main_prover_state =
Public_parameters.prover
* transcript
* Scalar.t
* query list
* Scalar.t SMap.t list
* main_prover_msg
type partial_prover_aux = {r : Scalar.t; s_list : Scalar.t SMap.t list}
let merge_answers : answer list -> answer =
let open SMap in
List.fold_left (union (fun _k m1 m2 -> Some (union_disjoint m1 m2))) empty
let distributed_prove_worker f_map_list prover_aux_list (r, poly_keys_list) =
let gen_powers r l =
List.mapi (fun i x -> (x, Scalar.pow r @@ Z.of_int i)) l |> SMap.of_list
in
let r_powers_list = List.map (gen_powers r) poly_keys_list in
let f_list =
List.map2
(fun f_map r_map ->
let polys = SMap.bindings f_map in
let coeffs = List.map (fun (name, _) -> SMap.find name r_map) polys in
Poly.linear (List.map snd polys) coeffs)
f_map_list
r_powers_list
in
(f_list, prover_aux_list)
let distributed_expand_transcript transcript query_list answer_list =
let transcript = Transcript.list_expand query_t query_list transcript in
Transcript.list_expand answer_t answer_list transcript
let distributed_prove_main1 (pp : Public_parameters.prover) transcript
query_list answer_list secret_list prover_aux_list :
worker_msg * main_prover_state =
let r, transcript = Fr_generation.random_fr transcript in
let s_list = List.map (batch_answers r) answer_list in
let get_keys map_map =
SMap.fold
(fun _ m acc -> SMap.union (fun _ _ x -> Some x) m acc)
map_map
SMap.empty
|> SMap.bindings |> List.map fst
in
let poly_keys_list = List.map get_keys answer_list in
let worker_message = (r, poly_keys_list) in
let main_msg =
distributed_prove_worker secret_list prover_aux_list worker_message
in
let state = (pp, transcript, r, query_list, s_list, main_msg) in
(worker_message, state)
let distributed_prove_main2
((pp, transcript, r, query_list, s_list, main_msg) : main_prover_state)
worker_msg_list =
let worker_msg_list = main_msg :: worker_msg_list in
let f_list_list = List.map fst worker_msg_list in
let f_list =
Plonk.List.mapn (List.fold_left Poly.add Poly.zero) f_list_list
in
let prover_aux_list_list = List.map snd worker_msg_list in
let prover_aux_list =
Plonk.List.mapn Commitment.recombine_prover_aux prover_aux_list_list
in
let cmts_list =
List.map
(fun (cmts, _prover_aux) ->
List.map snd @@ SMap.bindings cmts |> Array.of_list)
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
let transcript = Transcript.expand proof_t proof transcript in
(proof, transcript, {s_list; r})
end