ark-r1cs-std/src/bits/mod.rs
src/bits/mod.rsRaw
1use crate::{
2 bits::{boolean::Boolean, uint8::UInt8},
3 Vec,
4};
5use ark_ff::Field;
6use ark_relations::r1cs::SynthesisError;
7
8/// This module contains `Boolean`, a R1CS equivalent of the `bool` type.
9pub mod boolean;
10/// This module contains `UInt8`, a R1CS equivalent of the `u8` type.
11pub mod uint8;
12/// This module contains a macro for generating `UIntN` types, which are R1CS
13/// equivalents of `N`-bit unsigned integers.
14#[macro_use]
15pub mod uint;
16
17make_uint!(UInt16, 16, u16, uint16, "`U16`", "`u16`", "16");
18make_uint!(UInt32, 32, u32, uint32, "`U32`", "`u32`", "32");
19make_uint!(UInt64, 64, u64, uint64, "`U64`", "`u64`", "64");
20make_uint!(UInt128, 128, u128, uint128, "`U128`", "`u128`", "128");
21
22/// Specifies constraints for conversion to a little-endian bit representation
23/// of `self`.
24pub trait ToBitsGadget<F: Field> {
25 /// Outputs the canonical little-endian bit-wise representation of `self`.
26 ///
27 /// This is the correct default for 99% of use cases.
28 fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError>;
29
30 /// Outputs a possibly non-unique little-endian bit-wise representation of
31 /// `self`.
32 ///
33 /// If you're not absolutely certain that your usecase can get away with a
34 /// non-canonical representation, please use `self.to_bits()` instead.
35 fn to_non_unique_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
36 self.to_bits_le()
37 }
38
39 /// Outputs the canonical big-endian bit-wise representation of `self`.
40 fn to_bits_be(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
41 let mut res = self.to_bits_le()?;
42 res.reverse();
43 Ok(res)
44 }
45
46 /// Outputs a possibly non-unique big-endian bit-wise representation of
47 /// `self`.
48 fn to_non_unique_bits_be(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
49 let mut res = self.to_non_unique_bits_le()?;
50 res.reverse();
51 Ok(res)
52 }
53}
54
55impl<F: Field> ToBitsGadget<F> for Boolean<F> {
56 fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
57 Ok(vec![self.clone()])
58 }
59}
60
61impl<F: Field> ToBitsGadget<F> for [Boolean<F>] {
62 /// Outputs `self`.
63 fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
64 Ok(self.to_vec())
65 }
66}
67
68impl<F: Field> ToBitsGadget<F> for UInt8<F> {
69 fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
70 Ok(self.bits.to_vec())
71 }
72}
73
74impl<F: Field> ToBitsGadget<F> for [UInt8<F>] {
75 /// Interprets `self` as an integer, and outputs the little-endian
76 /// bit-wise decomposition of that integer.
77 fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
78 let bits = self.iter().flat_map(|b| &b.bits).cloned().collect();
79 Ok(bits)
80 }
81}
82
83impl<F: Field, T> ToBitsGadget<F> for Vec<T>
84where
85 [T]: ToBitsGadget<F>,
86{
87 fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
88 self.as_slice().to_bits_le().map(|v| v.to_vec())
89 }
90
91 fn to_non_unique_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
92 self.as_slice().to_non_unique_bits_le().map(|v| v.to_vec())
93 }
94}
95
96/// Specifies constraints for conversion to a little-endian byte representation
97/// of `self`.
98pub trait ToBytesGadget<F: Field> {
99 /// Outputs a canonical, little-endian, byte decomposition of `self`.
100 ///
101 /// This is the correct default for 99% of use cases.
102 fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError>;
103
104 /// Outputs a possibly non-unique byte decomposition of `self`.
105 ///
106 /// If you're not absolutely certain that your usecase can get away with a
107 /// non-canonical representation, please use `self.to_bytes(cs)` instead.
108 fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
109 self.to_bytes()
110 }
111}
112
113impl<F: Field> ToBytesGadget<F> for [UInt8<F>] {
114 fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
115 Ok(self.to_vec())
116 }
117}
118
119impl<'a, F: Field, T: 'a + ToBytesGadget<F>> ToBytesGadget<F> for &'a T {
120 fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
121 (*self).to_bytes()
122 }
123}
124
125impl<'a, F: Field> ToBytesGadget<F> for &'a [UInt8<F>] {
126 fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
127 Ok(self.to_vec())
128 }
129}