Longfellow ZK 0290cb32

Loading...
Searching...
No Matches
counter.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_CIRCUITS_LOGIC_COUNTER_H_
16#define PRIVACY_PROOFS_ZK_LIB_CIRCUITS_LOGIC_COUNTER_H_
17
18#include <stddef.h>
19
20#include <cstdint>
21
22// Embedding of small unsigned integers into an additive group of
23// unspecified size, but assumed to be able to encode 16 bits or so.
24// For prime fields inject the integer mod p, and for
25// binary fields use the multiplicative group.
26 namespace proofs {
27
28 template <class Logic, bool kCharacteristicTwo>
29 class CounterAux;
30
31// Use the additive group in fields with large characteristic
32 template <class Logic_>
33 class CounterAux<Logic_, /*kCharacteristicTwo=*/false> {
34 public:
35 using Logic = Logic_;
36 using Field = typename Logic::Field;
37 using EltW = typename Logic::EltW;
38 using BitW = typename Logic::BitW;
39 using CElt = typename Field::CElt;
40
41 // Even though everything is ultimately represented
42 // as EltW, keeps the types distinct to avoid
43 // confusion.
44
45 struct CEltW {
46 EltW e;
47 };
48
49 explicit CounterAux(const Logic& l) : l_(l) {}
50
51 const Logic& logic() const { return l_; }
52
53 // Convert a counter into *some* field element such that the counter is
54 // nonzero (as a counter) iff the field element is nonzero.
55 EltW znz_indicator(const CEltW& celt) const { return celt.e; }
56
57 CEltW mone() const { return CEltW{l_.konst(l_.mone())}; }
58 CEltW as_counter(uint64_t n) const { return CEltW{l_.konst(n)}; }
59 CEltW as_counter(const CElt& x) const { return CEltW{l_.konst(x.e)}; }
60
61 CEltW as_counter(const BitW& b) const { return CEltW{l_.eval(b)}; }
62
63 template <size_t N>
64 CEltW as_counter(const typename Logic::template bitvec<N>& v) const {
65 // counters have the same representation as scalars
66 return CEltW{l_.as_scalar(v)};
67 }
68
69 CEltW add(const CEltW* a, const CEltW& b) const {
70 return CEltW{l_.add(&a->e, b.e)};
71 }
72
73 // a ? b : 0
74 CEltW ite0(const BitW* a, const CEltW& b) const {
75 EltW ae = l_.eval(*a);
76 return CEltW{l_.mul(&ae, b.e)};
77 }
78
79 // a ? b : c
80 CEltW mux(const BitW* a, const CEltW* b, const CEltW& c) const {
81 return add(&c, ite0(a, sub(b, c)));
82 }
83 void assert0(const CEltW& a) const { l_.assert0(a.e); }
84 void assert_eq(const CEltW* a, const CEltW& b) const {
85 l_.assert_eq(&a->e, b.e);
86 }
87
88 CEltW input() const { return CEltW{l_.eltw_input()}; }
89
90 private:
91 const Logic& l_;
92
93 // used only internally, do not export since we don't
94 // want to invert in the multiplicative group
95 CEltW sub(const CEltW* a, const CEltW& b) const {
96 return CEltW{l_.sub(&a->e, b.e)};
97 }
98};
99
100// use the multiplicative group in characteristic 2
101 template <class Logic_>
102 class CounterAux<Logic_, /*kCharacteristicTwo=*/true> {
103 public:
104 using Logic = Logic_;
105 using Field = typename Logic::Field;
106 using EltW = typename Logic::EltW;
107 using BitW = typename Logic::BitW;
108 using CElt = typename Field::CElt;
109
110 struct CEltW {
111 EltW e;
112 };
113
114 explicit CounterAux(const Logic& l) : l_(l) {}
115
116 const Logic& logic() const { return l_; }
117
118 // Convert a counter into *some* field element such that the counter is
119 // nonzero (as a counter) iff the field element is nonzero.
120 EltW znz_indicator(const CEltW& celt) const {
121 return l_.sub(&celt.e, l_.konst(l_.one()));
122 }
123
124 CEltW mone() const { return CEltW{l_.konst(l_.f_.invg())}; }
125 CEltW as_counter(uint64_t n) const {
126 return CEltW{l_.konst(l_.f_.as_counter(n).e)};
127 }
128 CEltW as_counter(const CElt& x) const { return CEltW{l_.konst(x.e)}; }
129
130 CEltW as_counter(const BitW& b) const {
131 CEltW iftrue = CEltW{l_.konst(l_.f_.g())};
132 return ite0(&b, iftrue);
133 }
134
135 template <size_t N>
136 CEltW as_counter(const typename Logic::template bitvec<N>& v) const {
137 const Logic& L = l_; // shorthand
138
139 // do the multiplication in Logic since we don't have
140 // a range addition in Counter
141 EltW p = L.mul(0, N, [&](size_t i) {
142 auto g2i = L.konst(L.f_.counter_beta(i));
143 return L.mux(&v[i], &g2i, L.konst(L.one()));
144 });
145
146 return CEltW{p};
147 }
148
149 CEltW add(const CEltW* a, const CEltW& b) const {
150 return CEltW{l_.mul(&a->e, b.e)};
151 }
152
153 // a ? b : 0
154 CEltW ite0(const BitW* a, const CEltW& b) const {
155 return CEltW{l_.mux(a, &b.e, l_.konst(l_.one()))};
156 }
157
158 // a ? b : c
159 CEltW mux(const BitW* a, const CEltW* b, const CEltW& c) const {
160 return CEltW{l_.mux(a, &b->e, c.e)};
161 }
162 void assert0(const CEltW& a) const { l_.assert_eq(&a.e, l_.konst(l_.one())); }
163 void assert_eq(const CEltW* a, const CEltW& b) const {
164 l_.assert_eq(&a->e, b.e);
165 }
166
167 CEltW input() const { return CEltW{l_.eltw_input()}; }
168
169 private:
170 const Logic& l_;
171};
172
173 template <class Logic>
174 using Counter = CounterAux<Logic, Logic::Field::kCharacteristicTwo>;
175} // namespace proofs
176
177#endif // PRIVACY_PROOFS_ZK_LIB_CIRCUITS_LOGIC_COUNTER_H_
proofs::CounterAux
Definition counter.h:29
proofs::Logic
Definition logic.h:38
proofs::CounterAux< Logic_, false >::CEltW
Definition counter.h:45
proofs::CounterAux< Logic_, true >::CEltW
Definition counter.h:110
proofs::GF2_128::CElt
Definition gf2_128.h:285
proofs::Logic::BitW
Definition logic.h:130