bellperson_nonnative/util/
bit.rs1use bellperson::gadgets::boolean::Boolean;
3use bellperson::{ConstraintSystem, LinearCombination, SynthesisError};
4use ff::PrimeField;
5
6use std::fmt::{self, Display, Formatter};
7
8use crate::OptionExt;
9
10#[derive(Clone)]
11pub struct Bit<Scalar: PrimeField> {
13 pub bit: LinearCombination<Scalar>,
15 pub value: Option<bool>,
17}
18
19#[derive(Clone)]
20pub struct Bitvector<Scalar: PrimeField> {
22 pub bits: Vec<LinearCombination<Scalar>>,
24 pub values: Option<Vec<bool>>,
26 pub allocations: Vec<Bit<Scalar>>,
28}
29
30impl<Scalar: PrimeField> Bitvector<Scalar> {
31 pub fn reversed(mut self) -> Self {
33 self.values.as_mut().map(|v| v.reverse());
34 self.bits.reverse();
35 self
36 }
37 pub fn truncate(mut self, n: usize) -> Self {
39 self.values.as_mut().map(|v| v.truncate(n));
40 self.bits.truncate(n);
41 self
42 }
43
44 pub fn get(&self, i: usize) -> Option<Bit<Scalar>> {
45 self.bits.get(i).map(|lc| Bit {
46 bit: lc.clone(),
47 value: self.values.as_ref().map(|vs| vs[i].clone()),
48 })
49 }
50
51 pub fn shr(mut self, i: usize) -> Self {
52 self.values.as_mut().map(|v| {
53 v.drain(0..i);
54 });
55 self.bits.drain(0..i);
56 self
57 }
58
59 pub fn shl(mut self, i: usize) -> Self {
60 self.values.as_mut().map(|v| {
61 v.splice(0..0, std::iter::repeat(false).take(i));
62 });
63 self.bits
64 .splice(0..0, std::iter::repeat(LinearCombination::zero()).take(i));
65 self
66 }
67
68 pub fn pop(&mut self) -> Option<Bit<Scalar>> {
69 if self.bits.len() > 0 {
70 Some(Bit::new(
71 self.bits.pop().unwrap(),
72 self.values.as_mut().map(|vs| vs.pop().unwrap()),
73 ))
74 } else {
75 None
76 }
77 }
78
79 pub fn push(&mut self, mut b: Bit<Scalar>) {
80 self.values
81 .as_mut()
82 .map(|vs| b.value.take().map(|v| vs.push(v)));
83 self.bits.push(b.bit);
84 }
85
86 pub fn insert(&mut self, i: usize, mut b: Bit<Scalar>) {
87 self.values
88 .as_mut()
89 .map(|vs| b.value.take().map(|v| vs.insert(i, v)));
90 self.bits.insert(i, b.bit);
91 }
92
93 pub fn append(&mut self, mut other: Self) {
94 let ovs = other.values.take();
95 self.bits.extend(other.bits.into_iter());
96 self.values
97 .as_mut()
98 .map(|vs| ovs.map(|ovs| vs.extend(ovs.into_iter())));
99 }
100
101 pub fn into_bits(mut self) -> Vec<Bit<Scalar>> {
102 let vs = self.values.take();
103 self.bits
104 .into_iter()
105 .enumerate()
106 .map(|(i, b)| Bit {
107 bit: b,
108 value: vs.as_ref().map(|vs| vs[i]),
109 })
110 .collect()
111 }
112
113 pub fn from_bits(bs: Vec<Bit<Scalar>>) -> Self {
114 let mut bits = Vec::new();
115 let mut values = Some(Vec::new());
116 for mut b in bs.clone() {
117 let v = b.value.take();
118 bits.push(b.bit);
119 values = values.take().and_then(|mut vs| {
120 v.map(|v| {
121 vs.push(v);
122 vs
123 })
124 });
125 }
126 Self {
127 bits,
128 values,
129 allocations: bs,
130 }
131 }
132}
133
134impl<Scalar: PrimeField> Bit<Scalar> {
135 pub fn alloc<CS>(mut cs: CS, value: Option<bool>) -> Result<Self, SynthesisError>
138 where
139 CS: ConstraintSystem<Scalar>,
140 {
141 let var = cs.alloc(
142 || "boolean",
143 || {
144 if *value.grab()? {
145 Ok(Scalar::one())
146 } else {
147 Ok(Scalar::zero())
148 }
149 },
150 )?;
151
152 cs.enforce(
155 || "boolean constraint",
156 |lc| lc + CS::one() - var,
157 |lc| lc + var,
158 |lc| lc,
159 );
160
161 Ok(Self {
162 bit: LinearCombination::zero() + var,
163 value,
164 })
165 }
166
167 pub fn constrain_value<CS>(&self, mut cs: CS, value: bool)
168 where
169 CS: ConstraintSystem<Scalar>,
170 {
171 cs.enforce(
172 || format!("is {}", value),
173 |lc| lc,
174 |lc| lc,
175 |lc| {
176 if value {
177 lc + &self.bit - CS::one()
178 } else {
179 lc + &self.bit
180 }
181 },
182 );
183 }
184
185 pub fn new(bit: LinearCombination<Scalar>, value: Option<bool>) -> Self {
186 Self { bit, value }
187 }
188
189 pub fn from_sapling<CS: ConstraintSystem<Scalar>>(b: Boolean) -> Self {
190 Self::new(b.lc(CS::one(), Scalar::one()), b.get_value())
191 }
192
193 pub fn not<CS: ConstraintSystem<Scalar>>(&self) -> Self {
194 Self::new(
195 LinearCombination::zero() + CS::one() - &self.bit,
196 self.value.clone().map(|b| !b),
197 )
198 }
199
200 pub fn new_false<CS: ConstraintSystem<Scalar>>() -> Self {
201 Self::new(LinearCombination::zero(), Some(false))
202 }
203
204 pub fn new_true<CS: ConstraintSystem<Scalar>>() -> Self {
205 Self::new(LinearCombination::zero() + CS::one(), Some(true))
206 }
207
208 pub fn new_value<CS: ConstraintSystem<Scalar>>(v: bool) -> Self {
209 if v {
210 Self::new_true::<CS>()
211 } else {
212 Self::new_false::<CS>()
213 }
214 }
215}
216
217impl<Scalar: PrimeField> Display for Bitvector<Scalar> {
218 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
219 match self.values.as_ref() {
220 Some(vs) => write!(
221 f,
222 "Bitvector({})",
223 vs.into_iter()
224 .map(|b| if *b { "1" } else { "0" })
225 .collect::<Vec<_>>()
226 .concat()
227 ),
228 None => write!(f, "Bitvector(len {})", self.bits.len()),
229 }
230 }
231}