Longfellow ZK 0290cb32

Loading...
Searching...
No Matches
circuit.h
1// Copyright 2025 Google LLC.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef PRIVACY_PROOFS_ZK_LIB_SUMCHECK_CIRCUIT_H_
16#define PRIVACY_PROOFS_ZK_LIB_SUMCHECK_CIRCUIT_H_
17
18#include <stddef.h>
19
20#include <cstdint>
21#include <memory>
22#include <vector>
23
24#include "algebra/poly.h"
25#include "arrays/affine.h"
26#include "sumcheck/quad.h"
27
28 namespace proofs {
29 template <class Field>
30 struct Layer {
31 corner_t nw; // number of inputs
32 size_t logw; // number of binding rounds for the hand variables
33 std::unique_ptr<const Quad<Field>> quad;
34
35 bool operator==(const Layer& y) const {
36 // This operator relies on the layer being properly constructed, so that
37 // the quad reference is never a nullptr.
38 return nw == y.nw && logw == y.logw && *quad == *y.quad;
39 }
40
41 size_t nterms() const { return quad->n_; }
42};
43
44 template <class Field>
45 struct Circuit {
46 corner_t nv; // number of outputs for one copy
47 size_t logv; // number of G variables in V[G,C] in the final output
48 corner_t nc; // number of copies
49 size_t logc; // number of sumcheck rounds for the C variables
50 size_t nl; // number of layers
51
52 size_t ninputs; // number of inputs
53 size_t npub_in; // number of public inputs, index of first private input
54 size_t subfield_boundary; // Least input wire not known to be in the
55 // subfield
56
57 std::vector<Layer<Field>> l; // layers
58
59 uint8_t id[32]; // unique id for the circuit, created by the compiler
60
61 bool operator==(const Circuit& y) const {
62 return nv == y.nv && logv == y.logv && nc == y.nc && logc == y.logc &&
63 nl == y.nl && l == y.l;
64 }
65 size_t nterms() const {
66 size_t n = 0;
67 for (const auto& layer : l) {
68 n += layer.nterms();
69 }
70 return n;
71 }
72};
73
74 template <class Field>
75 struct LayerProof {
76 using Elt = typename Field::Elt;
77 // For efficiency, we distinguish polynomials needed to bind copy
78 // variables (CPoly, degree 3) from polynomials needed to bind
79 // wire variables (WPoly, degree 2).
80 using CPoly = SumcheckPoly<4, Field>;
81 using WPoly = SumcheckPoly<3, Field>;
82 using FWPoly = Poly<3, Field>;
83 using FCPoly = Poly<4, Field>;
84
85 // Maximum 2^40 gates/wires/copies per layer.
86 static constexpr size_t kMaxBindings = 40;
87
88 CPoly cp[kMaxBindings]; // polys for the C variables
89
90 // The binding order we use is "for (round) { for (hand) ... }", and
91 // thus one can organize this array as [kMaxBindings][2] for better
92 // memory locality.
93 // However, the corresponding challenges are organized as [2][kMaxBindings]
94 // to allow easier binding by hand, and so it makes sense to keep this
95 // array in the same order as the challenges.
96 WPoly hp[2][kMaxBindings]; // polys for each hand \in {right,left}
97
98 // prover provides W[R,C] and W[L,C], which serve as claims
99 // for the next layer
100 Elt wc[2];
101};
102
103 template <class Field>
104 struct LayerChallenge {
105 using Elt = typename Field::Elt;
106 static constexpr size_t kMaxBindings = LayerProof<Field>::kMaxBindings;
107
108 // verifier: coefficient for the random linear combination
109 // claim[0] + alpha * claim[1] of the two input claims.
110 Elt alpha;
111 Elt beta; // random coefficient for assert-zero
112 Elt cb[kMaxBindings]; // bindings for the C variables
113 Elt hb[2][kMaxBindings]; // bindings for each hand
114};
115
116 template <class Field>
117 struct Challenge {
118 using Elt = typename Field::Elt;
119 static constexpr size_t kMaxBindings = LayerProof<Field>::kMaxBindings;
120
121 // verifier picks Q for EQ[Q|c]
122 Elt q[kMaxBindings]; // [logC]
123
124 // verifier picks G for V[G,c]
125 Elt g[kMaxBindings]; // [logV]
126 std::vector<LayerChallenge<Field>> l;
127 explicit Challenge(size_t nl) : l(nl) {}
128};
129
130// Full proof:
131 template <class Field>
132 struct Proof {
133 typedef typename LayerProof<Field>::CPoly CPoly;
134 typedef typename LayerProof<Field>::WPoly WPoly;
135
136 using Elt = typename Field::Elt;
137 static constexpr size_t kMaxBindings = LayerProof<Field>::kMaxBindings;
138
139 // then engage in sumcheck one per layer
140 std::vector<LayerProof<Field>> l;
141
142 explicit Proof(size_t nl) : l(nl) {}
143 size_t size() const {
144 return l.size() * (kMaxBindings * 4 + kMaxBindings * 3 * 2 + 2);
145 }
146};
147
148// Auxiliary information generated by the prover to be
149// used by the ZK prover
150 template <class Field>
151 struct ProofAux {
152 using Elt = typename Field::Elt;
153 std::vector<Elt> bound_quad;
154 explicit ProofAux(size_t nl) : bound_quad(nl) {}
155};
156} // namespace proofs
157
158#endif // PRIVACY_PROOFS_ZK_LIB_SUMCHECK_CIRCUIT_H_
proofs::Poly
Definition poly.h:30
proofs::SumcheckPoly
Definition poly.h:178
proofs::Circuit
Definition circuit.h:45
proofs::GF2_128::Elt
Definition gf2_128.h:63
proofs::LayerChallenge
Definition circuit.h:104
proofs::Layer
Definition circuit.h:30
proofs::LayerProof
Definition circuit.h:75