Longfellow ZK 0290cb32

Loading...
Searching...
No Matches
bit_adder.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_BIT_ADDER_H_
16#define PRIVACY_PROOFS_ZK_LIB_CIRCUITS_LOGIC_BIT_ADDER_H_
17
18#include <stddef.h>
19
20#include <cstdint>
21#include <vector>
22
23// Circuit element that maps bitvec<N> V to a field element E
24// in such a way that:
25//
26// 1) addition can be performed efficiently, e.g. as field
27// addition or field multiplication
28// 2) given and E that is the sum of K bitvecs, a simple circuit
29// asserts that E = A mod 2^N
30 namespace proofs {
31
32 template <class Logic, size_t N, bool kCharacteristicTwo>
33 class BitAdderAux;
34
35// Use the additive group in fields with large characteristic
36 template <class Logic, size_t N>
37 class BitAdderAux<Logic, N, /*kCharacteristicTwo=*/false> {
38 public:
39 using Field = typename Logic::Field;
40 using BitW = typename Logic::BitW;
41 using EltW = typename Logic::EltW;
42 using Elt = typename Field::Elt;
43 using BV = typename Logic::template bitvec<N>;
44 const Logic& l_;
45
46 explicit BitAdderAux(const Logic& l) : l_(l) {}
47
48 EltW as_field_element(const BV& v) const {
49 const Logic& L = l_; // shorthand
50 constexpr uint64_t uno = 1;
51 EltW r = L.konst(L.zero());
52 for (size_t i = 0; i < N; ++i) {
53 auto vi = L.eval(v[i]);
54 r = L.axpy(&r, L.elt(uno << i), vi);
55 }
56 return r;
57 }
58
59 EltW add(const EltW* a, const EltW& b) const { return l_.add(a, b); }
60 EltW add(const BV& a, const BV& b) const {
61 auto a_fe = as_field_element(a);
62 auto b_fe = as_field_element(b);
63 return add(&a_fe, b_fe);
64 }
65 EltW add(const std::vector<BV>& a) const {
66 return l_.add(0, a.size(),
67 [&](size_t i) { return as_field_element(a[i]); });
68 }
69
70 // assert that B = A + i*2^N for 0 <= i < k
71 void assert_eqmod(const BV& a, const EltW& b, size_t k) const {
72 const Logic& L = l_; // shorthand
73 constexpr uint64_t uno = 1;
74 EltW z = L.sub(&b, as_field_element(a));
75 EltW zz = L.mul(0, k, [&](size_t i) {
76 return L.sub(&z, L.konst((uno << N) * i));
77 });
78 L.assert0(zz);
79 }
80};
81
82// Use the multiplicative group in GF(2^k)
83 template <class Logic, size_t N>
84 class BitAdderAux<Logic, N, /*kCharacteristicTwo=*/true> {
85 public:
86 using Field = typename Logic::Field;
87 using BitW = typename Logic::BitW;
88 using EltW = typename Logic::EltW;
89 using Elt = typename Field::Elt;
90 using BV = typename Logic::template bitvec<N>;
91 const Logic& l_;
92
93 explicit BitAdderAux(const Logic& l) : l_(l) {
94 const Logic& L = l_; // shorthand
95 const Field& F = l_.f_; // shorthand
96
97 // assume that X is a root of unity of order large enough.
98 Elt alpha = F.x();
99
100 for (size_t i = 0; i < N; ++i) {
101 alpha_2_i_[i] = alpha;
102 alpha = L.mulf(alpha, alpha);
103 }
104 alpha_2_N_ = alpha;
105 }
106
107 EltW as_field_element(const BV& v) const {
108 const Logic& L = l_; // shorthand
109 return L.mul(0, N, [&](size_t i) {
110 auto a2i = L.konst(alpha_2_i_[i]);
111 return L.mux(&v[i], &a2i, L.konst(L.one()));
112 });
113 }
114
115 EltW add(const EltW* a, const EltW& b) const { return l_.mul(a, b); }
116 EltW add(const BV& a, const BV& b) const {
117 auto a_fe = as_field_element(a);
118 auto b_fe = as_field_element(b);
119 return add(&a_fe, b_fe);
120 }
121 EltW add(const std::vector<BV>& a) const {
122 return l_.mul(0, a.size(),
123 [&](size_t i) { return as_field_element(a[i]); });
124 }
125
126 // assert that B = A + alpha^(i*2^N) for 0 <= i < k
127 void assert_eqmod(const BV& a, const EltW& b, size_t k) const {
128 const Logic& L = l_; // shorthand
129 const Field& F = l_.f_; // shorthand
130
131 std::vector<Elt> p(k);
132 p[0] = F.one();
133 for (size_t i = 1; i < k; ++i) {
134 p[i] = F.mulf(alpha_2_N_, p[i - 1]);
135 }
136 EltW aa = as_field_element(a);
137 EltW prod = L.mul(0, k, [&](size_t i) {
138 auto pi = L.konst(p[i]);
139 return L.sub(&b, L.mul(&pi, aa));
140 });
141 L.assert0(prod);
142 }
143
144 private:
145 Elt alpha_2_i_[N + 1];
146 Elt alpha_2_N_;
147};
148
149 template <class Logic, size_t N>
150 using BitAdder = BitAdderAux<Logic, N, Logic::Field::kCharacteristicTwo>;
151} // namespace proofs
152
153#endif // PRIVACY_PROOFS_ZK_LIB_CIRCUITS_LOGIC_BIT_ADDER_H_
proofs::BitAdderAux
Definition bit_adder.h:33
proofs::Logic
Definition logic.h:38
proofs::GF2_128::Elt
Definition gf2_128.h:63
proofs::Logic::BitW
Definition logic.h:130