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, "16");
18make_uint!(UInt32, 32, u32, uint32, "32");
19make_uint!(UInt64, 64, u64, uint64, "64");
20
21/// Specifies constraints for conversion to a little-endian bit representation
22/// of `self`.
23pub trait ToBitsGadget<F: Field> {
24 /// Outputs the canonical little-endian bit-wise representation of `self`.
25 ///
26 /// This is the correct default for 99% of use cases.
27 fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError>;
28
29 /// Outputs a possibly non-unique little-endian bit-wise representation of
30 /// `self`.
31 ///
32 /// If you're not absolutely certain that your usecase can get away with a
33 /// non-canonical representation, please use `self.to_bits()` instead.
34 fn to_non_unique_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
35 self.to_bits_le()
36 }
37
38 /// Outputs the canonical big-endian bit-wise representation of `self`.
39 fn to_bits_be(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
40 let mut res = self.to_bits_le()?;
41 res.reverse();
42 Ok(res)
43 }
44
45 /// Outputs a possibly non-unique big-endian bit-wise representation of
46 /// `self`.
47 fn to_non_unique_bits_be(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
48 let mut res = self.to_non_unique_bits_le()?;
49 res.reverse();
50 Ok(res)
51 }
52}
53
54impl<F: Field> ToBitsGadget<F> for Boolean<F> {
55 fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
56 Ok(vec![self.clone()])
57 }
58}
59
60impl<F: Field> ToBitsGadget<F> for [Boolean<F>] {
61 /// Outputs `self`.
62 fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
63 Ok(self.to_vec())
64 }
65}
66
67impl<F: Field> ToBitsGadget<F> for UInt8<F> {
68 fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
69 Ok(self.bits.to_vec())
70 }
71}
72
73impl<F: Field> ToBitsGadget<F> for [UInt8<F>] {
74 /// Interprets `self` as an integer, and outputs the little-endian
75 /// bit-wise decomposition of that integer.
76 fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
77 let bits = self.iter().flat_map(|b| &b.bits).cloned().collect();
78 Ok(bits)
79 }
80}
81
82impl<F: Field, T> ToBitsGadget<F> for Vec<T>
83where
84 [T]: ToBitsGadget<F>,
85{
86 fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
87 self.as_slice().to_bits_le().map(|v| v.to_vec())
88 }
89
90 fn to_non_unique_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
91 self.as_slice().to_non_unique_bits_le().map(|v| v.to_vec())
92 }
93}
94
95/// Specifies constraints for conversion to a little-endian byte representation
96/// of `self`.
97pub trait ToBytesGadget<F: Field> {
98 /// Outputs a canonical, little-endian, byte decomposition of `self`.
99 ///
100 /// This is the correct default for 99% of use cases.
101 fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError>;
102
103 /// Outputs a possibly non-unique byte decomposition of `self`.
104 ///
105 /// If you're not absolutely certain that your usecase can get away with a
106 /// non-canonical representation, please use `self.to_bytes(cs)` instead.
107 fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
108 self.to_bytes()
109 }
110}
111
112impl<F: Field> ToBytesGadget<F> for [UInt8<F>] {
113 fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
114 Ok(self.to_vec())
115 }
116}
117
118impl<'a, F: Field, T: 'a + ToBytesGadget<F>> ToBytesGadget<F> for &'a T {
119 fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
120 (*self).to_bytes()
121 }
122}
123
124impl<'a, F: Field> ToBytesGadget<F> for &'a [UInt8<F>] {
125 fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
126 Ok(self.to_vec())
127 }
128}