ark-r1cs-std/r1cs-std/src/bits/mod.rs
r1cs-std/src/bits/mod.rsRaw
1use crate::{
2 bits::{boolean::Boolean, uint8::UInt8},
3 Vec,
4};
5use algebra::Field;
6use r1cs_core::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 equivalents of
13/// `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 of `self`.
22pub trait ToBitsGadget<F: Field> {
23 /// Outputs the canonical little-endian bit-wise representation of `self`.
24 ///
25 /// This is the correct default for 99% of use cases.
26 fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError>;
27
28 /// Outputs a possibly non-unique bit-wise representation of `self`.
29 ///
30 /// If you're not absolutely certain that your usecase can get away with a
31 /// non-canonical representation, please use `self.to_bits(cs)` instead.
32 fn to_non_unique_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
33 self.to_bits_le()
34 }
35}
36
37impl<F: Field> ToBitsGadget<F> for Boolean<F> {
38 fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
39 Ok(vec![self.clone()])
40 }
41}
42
43impl<F: Field> ToBitsGadget<F> for [Boolean<F>] {
44 /// Outputs `self`.
45 fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
46 Ok(self.to_vec())
47 }
48}
49
50impl<F: Field> ToBitsGadget<F> for UInt8<F> {
51 fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
52 Ok(self.bits.to_vec())
53 }
54}
55
56impl<F: Field> ToBitsGadget<F> for [UInt8<F>] {
57 /// Interprets `self` as an integer, and outputs the little-endian
58 /// bit-wise decomposition of that integer.
59 fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
60 let bits = self.iter().flat_map(|b| &b.bits).cloned().collect();
61 Ok(bits)
62 }
63}
64
65impl<F: Field, T> ToBitsGadget<F> for Vec<T>
66where
67 [T]: ToBitsGadget<F>,
68{
69 fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
70 self.as_slice().to_bits_le().map(|v| v.to_vec())
71 }
72
73 fn to_non_unique_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
74 self.as_slice().to_non_unique_bits_le().map(|v| v.to_vec())
75 }
76}
77
78/// Specifies constraints for conversion to a little-endian byte representation of `self`.
79pub trait ToBytesGadget<F: Field> {
80 /// Outputs a canonical, little-endian, byte decomposition of `self`.
81 ///
82 /// This is the correct default for 99% of use cases.
83 fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError>;
84
85 /// Outputs a possibly non-unique byte decomposition of `self`.
86 ///
87 /// If you're not absolutely certain that your usecase can get away with a
88 /// non-canonical representation, please use `self.to_bytes(cs)` instead.
89 fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
90 self.to_bytes()
91 }
92}
93
94impl<F: Field> ToBytesGadget<F> for [UInt8<F>] {
95 fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
96 Ok(self.to_vec())
97 }
98}
99
100impl<'a, F: Field, T: 'a + ToBytesGadget<F>> ToBytesGadget<F> for &'a T {
101 fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
102 (*self).to_bytes()
103 }
104}
105
106impl<'a, F: Field> ToBytesGadget<F> for &'a [UInt8<F>] {
107 fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
108 Ok(self.to_vec())
109 }
110}