Skip to content

Commit 56496e6

Browse files
authored
VK summary (#1391)
This PR adds verification key 'summaries' to the snarky verifiers. Basically we construct a (non-deterministic, non-total) function `summary : G1.t list * G2.t list * Fqk.Unitary.t list -> bool list` which is injective (if it doesn't throw). By `Fqk.Unitary.t` I mean Fqk elements which are unitary. `a + b beta : Fqk.t` is unitary if `(a + b beta)(a - b beta) = 1`. The summary works element-wise as follows: - G1 elements are mapped to their x coordinate and the parity of their y coordinate - G2 elements are mapped to their x coordinate and the parity of the 'real part' of their y coordinate, assuming the real part is non-zero - Fqk.t elements `a + b beta` are mapped to `a` and the parity of the 'real part' of `b`, assuming the real part is non-zero. `b` is determined up to sign by `a` by unitary-ness. The point of this is for making hashing more efficient. `summary` shrinks the size of its input, so you can get away with hashing fewer bits.
1 parent fffe14d commit 56496e6

File tree

4 files changed

+98
-1
lines changed

4 files changed

+98
-1
lines changed

src/lib/snarky_verifier/groth.ml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,19 @@ open Core
44
module Make (Inputs : Inputs.S) = struct
55
open Inputs
66
open Impl
7+
open Let_syntax
78

89
module Verification_key = struct
910
type ('g1, 'g2, 'fqk) t_ =
1011
{query_base: 'g1; query: 'g1 list; delta: 'g2; alpha_beta_inv: 'fqk}
1112

13+
include Summary.Make (Inputs)
14+
15+
let summary_input {query_base; query; delta; alpha_beta_inv} =
16+
{ Summary.Input.g1s= query_base :: query
17+
; g2s= [delta]
18+
; gts= [alpha_beta_inv] }
19+
1220
type ('a, 'b, 'c) vk = ('a, 'b, 'c) t_
1321

1422
module Precomputation = struct
@@ -40,7 +48,6 @@ module Make (Inputs : Inputs.S) = struct
4048

4149
let verify (vk : (_, _, _) Verification_key.t_)
4250
(vk_precomp : Verification_key.Precomputation.t) inputs {Proof.a; b; c} =
43-
let open Let_syntax in
4451
let%bind acc =
4552
let%bind (module Shifted) = G1.Shifted.create () in
4653
let%bind init = Shifted.(add zero vk.query_base) in

src/lib/snarky_verifier/groth_maller.ml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,21 @@ module Make (Inputs : Inputs.S) = struct
1717
; h_gamma: 'g2
1818
; g_alpha_h_beta: 'fqk }
1919

20+
include Summary.Make (Inputs)
21+
22+
let summary_input
23+
{ g_alpha
24+
; g_gamma
25+
; query_base
26+
; query
27+
; h
28+
; h_beta
29+
; h_gamma
30+
; g_alpha_h_beta } =
31+
{ Summary.Input.g1s= g_alpha :: g_gamma :: query_base :: query
32+
; g2s= [h; h_beta; h_gamma]
33+
; gts= [g_alpha_h_beta] }
34+
2035
type ('a, 'b, 'c) vk = ('a, 'b, 'c) t_
2136

2237
module Precomputation = struct

src/lib/snarky_verifier/inputs.ml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,14 @@ module type S = sig
7474
val one : t
7575
end
7676

77+
module Fqe : sig
78+
type _ t_
79+
80+
val real_part : 'a t_ -> 'a
81+
82+
val parts : 'a t_ -> 'a list
83+
end
84+
7785
val group_miller_loop :
7886
(Sgn.t * G1_precomputation.t * G2_precomputation.t) list
7987
-> (Fqk.t, _) Checked.t

src/lib/snarky_verifier/summary.ml

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
open Core_kernel
2+
3+
module type Inputs_intf = sig
4+
module Impl : Snarky.Snark_intf.S
5+
6+
module Fqe : sig
7+
type _ t_
8+
9+
val real_part : 'a t_ -> 'a
10+
11+
val parts : 'a t_ -> 'a list
12+
end
13+
end
14+
15+
module Input = struct
16+
type ('g1, 'g2, 'gt) t = {g1s: 'g1 list; g2s: 'g2 list; gts: 'gt list}
17+
end
18+
19+
module Make (Inputs : Inputs_intf) = struct
20+
open Inputs
21+
open Impl
22+
open Let_syntax
23+
24+
let summary {Input.g1s; g2s; gts} =
25+
let%map elts =
26+
List.map g1s ~f:(fun (x, _) -> x)
27+
@ List.concat_map g2s ~f:(fun (x, _) -> Fqe.parts x)
28+
@ List.concat_map gts ~f:(fun (a, _) -> Fqe.parts a)
29+
|> Checked.List.map ~f:(fun x ->
30+
Field.Checked.choose_preimage_var x ~length:Field.size_in_bits
31+
>>| List.hd_exn )
32+
and signs =
33+
let parity x =
34+
let%map bs = Field.Checked.unpack_full x in
35+
List.hd_exn (bs :> Boolean.var list)
36+
in
37+
let real_part_parity a =
38+
let x = Fqe.real_part a in
39+
let%bind () = Field.Checked.Assert.non_zero x in
40+
parity x
41+
in
42+
let%map g1s = Checked.List.map g1s ~f:(fun (_, y) -> parity y)
43+
and g2s = Checked.List.map g2s ~f:(fun (_, y) -> real_part_parity y)
44+
and gts = Checked.List.map gts ~f:(fun (_, b) -> real_part_parity b) in
45+
g1s @ g2s @ gts
46+
in
47+
elts @ signs
48+
49+
let summary_unchecked {Input.g1s; g2s; gts} =
50+
let parity x = Bigint.(test_bit (of_field x) 0) in
51+
let elts =
52+
List.map g1s ~f:(fun (x, _) -> x)
53+
@ List.concat_map g2s ~f:(fun (x, _) -> Fqe.parts x)
54+
@ List.concat_map gts ~f:(fun (a, _) -> Fqe.parts a)
55+
|> List.map ~f:parity
56+
and signs =
57+
let real_part_parity a =
58+
let x = Fqe.real_part a in
59+
assert (not (Field.equal Field.zero x)) ;
60+
parity x
61+
in
62+
List.map g1s ~f:(fun (_, y) -> parity y)
63+
@ List.map g2s ~f:(fun (_, y) -> real_part_parity y)
64+
@ List.map gts ~f:(fun (_, b) -> real_part_parity b)
65+
in
66+
elts @ signs
67+
end

0 commit comments

Comments
 (0)