Browse Source

Change default `to_bits` and `to_bytes` functions to the safe versions

master
Pratyush Mishra 4 years ago
parent
commit
b1913a9ca7
17 changed files with 118 additions and 176 deletions
  1. +0
    -7
      crypto-primitives/src/nizk/gm17/constraints.rs
  2. +0
    -7
      crypto-primitives/src/nizk/groth16/constraints.rs
  3. +0
    -8
      crypto-primitives/src/prf/blake2s/constraints.rs
  4. +0
    -8
      crypto-primitives/src/signature/schnorr/constraints.rs
  5. +1
    -8
      r1cs-std/src/bits/boolean.rs
  6. +23
    -55
      r1cs-std/src/bits/mod.rs
  7. +0
    -7
      r1cs-std/src/bits/uint32.rs
  8. +0
    -7
      r1cs-std/src/bits/uint64.rs
  9. +29
    -28
      r1cs-std/src/fields/fp.rs
  10. +6
    -6
      r1cs-std/src/fields/fp12.rs
  11. +6
    -6
      r1cs-std/src/fields/fp2.rs
  12. +14
    -7
      r1cs-std/src/fields/fp6_3over2.rs
  13. +3
    -1
      r1cs-std/src/fields/mod.rs
  14. +13
    -6
      r1cs-std/src/groups/curves/short_weierstrass/bls12/mod.rs
  15. +9
    -7
      r1cs-std/src/groups/curves/short_weierstrass/mod.rs
  16. +10
    -6
      r1cs-std/src/groups/curves/twisted_edwards/mod.rs
  17. +4
    -2
      r1cs-std/src/groups/mod.rs

+ 0
- 7
crypto-primitives/src/nizk/gm17/constraints.rs

@ -388,13 +388,6 @@ where
}
Ok(bytes)
}
fn to_bytes_strict<CS: ConstraintSystem<ConstraintF>>(
&self,
cs: CS,
) -> Result<Vec<UInt8>, SynthesisError> {
self.to_bytes(cs)
}
}
#[cfg(test)]

+ 0
- 7
crypto-primitives/src/nizk/groth16/constraints.rs

@ -335,13 +335,6 @@ where
}
Ok(bytes)
}
fn to_bytes_strict<CS: ConstraintSystem<ConstraintF>>(
&self,
cs: CS,
) -> Result<Vec<UInt8>, SynthesisError> {
self.to_bytes(cs)
}
}
#[cfg(test)]

+ 0
- 8
crypto-primitives/src/prf/blake2s/constraints.rs

@ -447,14 +447,6 @@ impl ToBytesGadget for Blake2sOutputGadget
) -> Result<Vec<UInt8>, SynthesisError> {
Ok(self.0.clone())
}
#[inline]
fn to_bytes_strict<CS: ConstraintSystem<ConstraintF>>(
&self,
cs: CS,
) -> Result<Vec<UInt8>, SynthesisError> {
self.to_bytes(cs)
}
}
impl<ConstraintF: PrimeField> AllocGadget<[u8; 32], ConstraintF> for Blake2sOutputGadget {

+ 0
- 8
crypto-primitives/src/signature/schnorr/constraints.rs

@ -208,12 +208,4 @@ where
) -> Result<Vec<UInt8>, SynthesisError> {
self.pub_key.to_bytes(&mut cs.ns(|| "PubKey To Bytes"))
}
fn to_bytes_strict<CS: ConstraintSystem<ConstraintF>>(
&self,
mut cs: CS,
) -> Result<Vec<UInt8>, SynthesisError> {
self.pub_key
.to_bytes_strict(&mut cs.ns(|| "PubKey To Bytes"))
}
}

+ 1
- 8
r1cs-std/src/bits/boolean.rs

@ -802,6 +802,7 @@ impl ConditionalEqGadget for Boolean {
}
impl<ConstraintF: Field> ToBytesGadget<ConstraintF> for Boolean {
/// Outputs `1u8` if `self` is true, and `0u8` otherwise.
fn to_bytes<CS: ConstraintSystem<ConstraintF>>(
&self,
_cs: CS,
@ -813,14 +814,6 @@ impl ToBytesGadget for Boolean {
let byte = UInt8 { bits, value };
Ok(vec![byte])
}
/// Additionally checks if the produced list of booleans is 'valid'.
fn to_bytes_strict<CS: ConstraintSystem<ConstraintF>>(
&self,
cs: CS,
) -> Result<Vec<UInt8>, SynthesisError> {
self.to_bytes(cs)
}
}
impl<ConstraintF: PrimeField> CondSelectGadget<ConstraintF> for Boolean {

+ 23
- 55
r1cs-std/src/bits/mod.rs

@ -11,16 +11,24 @@ pub mod uint64;
pub mod uint8;
pub trait ToBitsGadget<ConstraintF: Field> {
/// Outputs the canonical bit-wise representation of `self`.
///
/// This is the correct default for 99% of use cases.
fn to_bits<CS: ConstraintSystem<ConstraintF>>(
&self,
cs: CS,
) -> Result<Vec<Boolean>, SynthesisError>;
/// Additionally checks if the produced list of booleans is 'valid'.
fn to_bits_strict<CS: ConstraintSystem<ConstraintF>>(
/// Outputs a possibly non-unique bit-wise representation of `self`.
///
/// If you're not absolutely certain that your usecase can get away with a
/// non-canonical representation, please use `self.to_bits(cs)` instead.
fn to_non_unique_bits<CS: ConstraintSystem<ConstraintF>>(
&self,
cs: CS,
) -> Result<Vec<Boolean>, SynthesisError>;
) -> Result<Vec<Boolean>, SynthesisError> {
self.to_bits(cs)
}
}
impl<ConstraintF: Field> ToBitsGadget<ConstraintF> for Boolean {
@ -30,13 +38,6 @@ impl ToBitsGadget for Boolean {
) -> Result<Vec<Boolean>, SynthesisError> {
Ok(vec![self.clone()])
}
fn to_bits_strict<CS: ConstraintSystem<ConstraintF>>(
&self,
_: CS,
) -> Result<Vec<Boolean>, SynthesisError> {
Ok(vec![self.clone()])
}
}
impl<ConstraintF: Field> ToBitsGadget<ConstraintF> for [Boolean] {
@ -46,14 +47,8 @@ impl ToBitsGadget for [Boolean] {
) -> Result<Vec<Boolean>, SynthesisError> {
Ok(self.to_vec())
}
fn to_bits_strict<CS: ConstraintSystem<ConstraintF>>(
&self,
_cs: CS,
) -> Result<Vec<Boolean>, SynthesisError> {
Ok(self.to_vec())
}
}
impl<ConstraintF: Field> ToBitsGadget<ConstraintF> for Vec<Boolean> {
fn to_bits<CS: ConstraintSystem<ConstraintF>>(
&self,
@ -61,13 +56,6 @@ impl ToBitsGadget for Vec {
) -> Result<Vec<Boolean>, SynthesisError> {
Ok(self.clone())
}
fn to_bits_strict<CS: ConstraintSystem<ConstraintF>>(
&self,
_cs: CS,
) -> Result<Vec<Boolean>, SynthesisError> {
Ok(self.clone())
}
}
impl<ConstraintF: Field> ToBitsGadget<ConstraintF> for [UInt8] {
@ -81,26 +69,27 @@ impl ToBitsGadget for [UInt8] {
}
Ok(result)
}
fn to_bits_strict<CS: ConstraintSystem<ConstraintF>>(
&self,
cs: CS,
) -> Result<Vec<Boolean>, SynthesisError> {
self.to_bits(cs)
}
}
pub trait ToBytesGadget<ConstraintF: Field> {
/// Outputs a canonical byte-wise representation of `self`.
///
/// This is the correct default for 99% of use cases.
fn to_bytes<CS: ConstraintSystem<ConstraintF>>(
&self,
cs: CS,
) -> Result<Vec<UInt8>, SynthesisError>;
/// Additionally checks if the produced list of booleans is 'valid'.
fn to_bytes_strict<CS: ConstraintSystem<ConstraintF>>(
/// Outputs a possibly non-unique byte decomposition of `self`.
///
/// If you're not absolutely certain that your usecase can get away with a
/// non-canonical representation, please use `self.to_bytes(cs)` instead.
fn to_non_unique_bytes<CS: ConstraintSystem<ConstraintF>>(
&self,
cs: CS,
) -> Result<Vec<UInt8>, SynthesisError>;
) -> Result<Vec<UInt8>, SynthesisError> {
self.to_bytes(cs)
}
}
impl<ConstraintF: Field> ToBytesGadget<ConstraintF> for [UInt8] {
@ -110,13 +99,6 @@ impl ToBytesGadget for [UInt8] {
) -> Result<Vec<UInt8>, SynthesisError> {
Ok(self.to_vec())
}
fn to_bytes_strict<CS: ConstraintSystem<ConstraintF>>(
&self,
cs: CS,
) -> Result<Vec<UInt8>, SynthesisError> {
self.to_bytes(cs)
}
}
impl<'a, ConstraintF: Field, T: 'a + ToBytesGadget<ConstraintF>> ToBytesGadget<ConstraintF>
@ -128,13 +110,6 @@ impl<'a, ConstraintF: Field, T: 'a + ToBytesGadget> ToBytesGadget
) -> Result<Vec<UInt8>, SynthesisError> {
(*self).to_bytes(cs)
}
fn to_bytes_strict<CS: ConstraintSystem<ConstraintF>>(
&self,
cs: CS,
) -> Result<Vec<UInt8>, SynthesisError> {
self.to_bytes(cs)
}
}
impl<'a, ConstraintF: Field> ToBytesGadget<ConstraintF> for &'a [UInt8] {
@ -144,11 +119,4 @@ impl<'a, ConstraintF: Field> ToBytesGadget for &'a [UInt8] {
) -> Result<Vec<UInt8>, SynthesisError> {
Ok(self.to_vec())
}
fn to_bytes_strict<CS: ConstraintSystem<ConstraintF>>(
&self,
cs: CS,
) -> Result<Vec<UInt8>, SynthesisError> {
self.to_bytes(cs)
}
}

+ 0
- 7
r1cs-std/src/bits/uint32.rs

@ -306,13 +306,6 @@ impl ToBytesGadget for UInt32 {
Ok(bytes)
}
fn to_bytes_strict<CS: ConstraintSystem<ConstraintF>>(
&self,
cs: CS,
) -> Result<Vec<UInt8>, SynthesisError> {
self.to_bytes(cs)
}
}
impl PartialEq for UInt32 {

+ 0
- 7
r1cs-std/src/bits/uint64.rs

@ -310,13 +310,6 @@ impl ToBytesGadget for UInt64 {
Ok(bytes)
}
fn to_bytes_strict<CS: ConstraintSystem<ConstraintF>>(
&self,
cs: CS,
) -> Result<Vec<UInt8>, SynthesisError> {
self.to_bytes(cs)
}
}
impl PartialEq for UInt64 {

+ 29
- 28
r1cs-std/src/fields/fp.rs

@ -326,9 +326,18 @@ impl NEqGadget for FpGadget {
}
impl<F: PrimeField> ToBitsGadget<F> for FpGadget<F> {
/// Outputs the binary representation of the value in `self` in *big-endian*
/// Outputs the unique bit-wise decomposition of `self` in *big-endian*
/// form.
fn to_bits<CS: ConstraintSystem<F>>(&self, mut cs: CS) -> Result<Vec<Boolean>, SynthesisError> {
let bits = self.to_non_unique_bits(&mut cs)?;
Boolean::enforce_in_field::<_, _, F>(&mut cs, &bits)?;
Ok(bits)
}
fn to_non_unique_bits<CS: ConstraintSystem<F>>(
&self,
mut cs: CS,
) -> Result<Vec<Boolean>, SynthesisError> {
let num_bits = F::Params::MODULUS_BITS;
use algebra::BitIterator;
let bit_values = match self.value {
@ -375,20 +384,29 @@ impl ToBitsGadget for FpGadget {
Ok(bits.into_iter().map(Boolean::from).collect())
}
fn to_bits_strict<CS: ConstraintSystem<F>>(
&self,
mut cs: CS,
) -> Result<Vec<Boolean>, SynthesisError> {
let bits = self.to_bits(&mut cs)?;
Boolean::enforce_in_field::<_, _, F>(&mut cs, &bits)?;
Ok(bits)
}
}
impl<F: PrimeField> ToBytesGadget<F> for FpGadget<F> {
/// Outputs the unique byte decomposition of `self` in *little-endian*
/// form.
fn to_bytes<CS: ConstraintSystem<F>>(&self, mut cs: CS) -> Result<Vec<UInt8>, SynthesisError> {
let bytes = self.to_non_unique_bytes(&mut cs)?;
Boolean::enforce_in_field::<_, _, F>(
&mut cs,
&bytes.iter()
.flat_map(|byte_gadget| byte_gadget.into_bits_le())
// This reverse maps the bits into big-endian form, as required by `enforce_in_field`.
.rev()
.collect::<Vec<_>>(),
)?;
Ok(bytes)
}
fn to_non_unique_bytes<CS: ConstraintSystem<F>>(
&self,
mut cs: CS,
) -> Result<Vec<UInt8>, SynthesisError> {
let byte_values = match self.value {
Some(value) => to_bytes![&value.into_repr()]?
.into_iter()
@ -425,23 +443,6 @@ impl ToBytesGadget for FpGadget {
Ok(bytes)
}
fn to_bytes_strict<CS: ConstraintSystem<F>>(
&self,
mut cs: CS,
) -> Result<Vec<UInt8>, SynthesisError> {
let bytes = self.to_bytes(&mut cs)?;
Boolean::enforce_in_field::<_, _, F>(
&mut cs,
&bytes.iter()
.flat_map(|byte_gadget| byte_gadget.into_bits_le())
// This reverse maps the bits into big-endian form, as required by `enforce_in_field`.
.rev()
.collect::<Vec<_>>(),
)?;
Ok(bytes)
}
}
impl<F: PrimeField> CondSelectGadget<F> for FpGadget<F> {

+ 6
- 6
r1cs-std/src/fields/fp12.rs

@ -731,12 +731,12 @@ where
Ok(c0)
}
fn to_bits_strict<CS: ConstraintSystem<ConstraintF>>(
fn to_non_unique_bits<CS: ConstraintSystem<ConstraintF>>(
&self,
mut cs: CS,
) -> Result<Vec<Boolean>, SynthesisError> {
let mut c0 = self.c0.to_bits_strict(cs.ns(|| "c0"))?;
let mut c1 = self.c1.to_bits_strict(cs.ns(|| "c1"))?;
let mut c0 = self.c0.to_non_unique_bits(cs.ns(|| "c0"))?;
let mut c1 = self.c1.to_non_unique_bits(cs.ns(|| "c1"))?;
c0.append(&mut c1);
Ok(c0)
}
@ -757,12 +757,12 @@ where
Ok(c0)
}
fn to_bytes_strict<CS: ConstraintSystem<ConstraintF>>(
fn to_non_unique_bytes<CS: ConstraintSystem<ConstraintF>>(
&self,
mut cs: CS,
) -> Result<Vec<UInt8>, SynthesisError> {
let mut c0 = self.c0.to_bytes_strict(cs.ns(|| "c0"))?;
let mut c1 = self.c1.to_bytes_strict(cs.ns(|| "c1"))?;
let mut c0 = self.c0.to_non_unique_bytes(cs.ns(|| "c0"))?;
let mut c1 = self.c1.to_non_unique_bytes(cs.ns(|| "c1"))?;
c0.append(&mut c1);
Ok(c0)
}

+ 6
- 6
r1cs-std/src/fields/fp2.rs

@ -527,12 +527,12 @@ impl, ConstraintF: PrimeField> ToBitsGadget
Ok(c0)
}
fn to_bits_strict<CS: ConstraintSystem<ConstraintF>>(
fn to_non_unique_bits<CS: ConstraintSystem<ConstraintF>>(
&self,
mut cs: CS,
) -> Result<Vec<Boolean>, SynthesisError> {
let mut c0 = self.c0.to_bits_strict(cs.ns(|| "c0"))?;
let mut c1 = self.c1.to_bits_strict(cs.ns(|| "c1"))?;
let mut c0 = self.c0.to_non_unique_bits(cs.ns(|| "c0"))?;
let mut c1 = self.c1.to_non_unique_bits(cs.ns(|| "c1"))?;
c0.append(&mut c1);
Ok(c0)
}
@ -551,12 +551,12 @@ impl, ConstraintF: PrimeField> ToBytesGadget<
Ok(c0)
}
fn to_bytes_strict<CS: ConstraintSystem<ConstraintF>>(
fn to_non_unique_bytes<CS: ConstraintSystem<ConstraintF>>(
&self,
mut cs: CS,
) -> Result<Vec<UInt8>, SynthesisError> {
let mut c0 = self.c0.to_bytes_strict(cs.ns(|| "c0"))?;
let mut c1 = self.c1.to_bytes_strict(cs.ns(|| "c1"))?;
let mut c0 = self.c0.to_non_unique_bytes(cs.ns(|| "c0"))?;
let mut c1 = self.c1.to_non_unique_bytes(cs.ns(|| "c1"))?;
c0.append(&mut c1);
Ok(c0)
}

+ 14
- 7
r1cs-std/src/fields/fp6_3over2.rs

@ -800,13 +800,13 @@ where
Ok(c0)
}
fn to_bits_strict<CS: ConstraintSystem<ConstraintF>>(
fn to_non_unique_bits<CS: ConstraintSystem<ConstraintF>>(
&self,
mut cs: CS,
) -> Result<Vec<Boolean>, SynthesisError> {
let mut c0 = self.c0.to_bits_strict(cs.ns(|| "c0"))?;
let mut c1 = self.c1.to_bits_strict(cs.ns(|| "c1"))?;
let mut c2 = self.c2.to_bits_strict(cs.ns(|| "c2"))?;
let mut c0 = self.c0.to_non_unique_bits(cs.ns(|| "c0"))?;
let mut c1 = self.c1.to_non_unique_bits(cs.ns(|| "c1"))?;
let mut c2 = self.c2.to_non_unique_bits(cs.ns(|| "c2"))?;
c0.append(&mut c1);
c0.append(&mut c2);
@ -834,11 +834,18 @@ where
Ok(c0)
}
fn to_bytes_strict<CS: ConstraintSystem<ConstraintF>>(
fn to_non_unique_bytes<CS: ConstraintSystem<ConstraintF>>(
&self,
cs: CS,
mut cs: CS,
) -> Result<Vec<UInt8>, SynthesisError> {
self.to_bytes(cs)
let mut c0 = self.c0.to_non_unique_bytes(cs.ns(|| "c0"))?;
let mut c1 = self.c1.to_non_unique_bytes(cs.ns(|| "c1"))?;
let mut c2 = self.c2.to_non_unique_bytes(cs.ns(|| "c2"))?;
c0.append(&mut c1);
c0.append(&mut c2);
Ok(c0)
}
}

+ 3
- 1
r1cs-std/src/fields/mod.rs

@ -452,7 +452,9 @@ pub(crate) mod tests {
let n = F::alloc(&mut cs.ns(|| "alloc new var"), || Ok(negone)).unwrap();
let _ = n.to_bytes(&mut cs.ns(|| "ToBytes")).unwrap();
let _ = n.to_bytes_strict(&mut cs.ns(|| "ToBytes Strict")).unwrap();
let _ = n
.to_non_unique_bytes(&mut cs.ns(|| "ToBytes Strict"))
.unwrap();
let ab_false = a
.conditionally_add_constant(

+ 13
- 6
r1cs-std/src/groups/curves/short_weierstrass/bls12/mod.rs

@ -52,11 +52,12 @@ impl ToBytesGadget for G1PreparedGadget

{

self.0.to_bytes(&mut cs.ns(|| "g_alpha to bytes"))
}
fn to_bytes_strict<CS: ConstraintSystem<P::Fp>>(
fn to_non_unique_bytes<CS: ConstraintSystem<P::Fp>>(
&self,
cs: CS,
mut cs: CS,
) -> Result<Vec<UInt8>, SynthesisError> {
self.to_bytes(cs)
self.0
.to_non_unique_bytes(&mut cs.ns(|| "g_alpha to bytes"))
}
}
@ -86,11 +87,17 @@ impl ToBytesGadget for G2PreparedGadget

{

Ok(bytes)
}
fn to_bytes_strict<CS: ConstraintSystem<P::Fp>>(
fn to_non_unique_bytes<CS: ConstraintSystem<P::Fp>>(
&self,
cs: CS,
mut cs: CS,
) -> Result<Vec<UInt8>, SynthesisError> {
self.to_bytes(cs)
let mut bytes = Vec::new();
for (i, coeffs) in self.ell_coeffs.iter().enumerate() {
let mut cs = cs.ns(|| format!("Iteration {}", i));
bytes.extend_from_slice(&coeffs.0.to_non_unique_bytes(&mut cs.ns(|| "c0"))?);
bytes.extend_from_slice(&coeffs.1.to_non_unique_bytes(&mut cs.ns(|| "c1"))?);
}
Ok(bytes)
}
}

+ 9
- 7
r1cs-std/src/groups/curves/short_weierstrass/mod.rs

@ -605,16 +605,16 @@ where
Ok(x_bits)
}
fn to_bits_strict<CS: ConstraintSystem<ConstraintF>>(
fn to_non_unique_bits<CS: ConstraintSystem<ConstraintF>>(
&self,
mut cs: CS,
) -> Result<Vec<Boolean>, SynthesisError> {
let mut x_bits = self
.x
.to_bits_strict(&mut cs.ns(|| "X Coordinate To Bits"))?;
.to_non_unique_bits(&mut cs.ns(|| "X Coordinate To Bits"))?;
let y_bits = self
.y
.to_bits_strict(&mut cs.ns(|| "Y Coordinate To Bits"))?;
.to_non_unique_bits(&mut cs.ns(|| "Y Coordinate To Bits"))?;
x_bits.extend_from_slice(&y_bits);
x_bits.push(self.infinity);
@ -640,17 +640,19 @@ where
Ok(x_bytes)
}
fn to_bytes_strict<CS: ConstraintSystem<ConstraintF>>(
fn to_non_unique_bytes<CS: ConstraintSystem<ConstraintF>>(
&self,
mut cs: CS,
) -> Result<Vec<UInt8>, SynthesisError> {
let mut x_bytes = self
.x
.to_bytes_strict(&mut cs.ns(|| "X Coordinate To Bytes"))?;
.to_non_unique_bytes(&mut cs.ns(|| "X Coordinate To Bytes"))?;
let y_bytes = self
.y
.to_bytes_strict(&mut cs.ns(|| "Y Coordinate To Bytes"))?;
let inf_bytes = self.infinity.to_bytes(&mut cs.ns(|| "Infinity to Bytes"))?;
.to_non_unique_bytes(&mut cs.ns(|| "Y Coordinate To Bytes"))?;
let inf_bytes = self
.infinity
.to_non_unique_bytes(&mut cs.ns(|| "Infinity to Bytes"))?;
x_bytes.extend_from_slice(&y_bytes);
x_bytes.extend_from_slice(&inf_bytes);

+ 10
- 6
r1cs-std/src/groups/curves/twisted_edwards/mod.rs

@ -1359,12 +1359,16 @@ where
Ok(x_bits)
}
fn to_bits_strict<CS: ConstraintSystem<ConstraintF>>(
fn to_non_unique_bits<CS: ConstraintSystem<ConstraintF>>(
&self,
mut cs: CS,
) -> Result<Vec<Boolean>, SynthesisError> {
let mut x_bits = self.x.to_bits_strict(cs.ns(|| "X Coordinate To Bits"))?;
let y_bits = self.y.to_bits_strict(cs.ns(|| "Y Coordinate To Bits"))?;
let mut x_bits = self
.x
.to_non_unique_bits(cs.ns(|| "X Coordinate To Bits"))?;
let y_bits = self
.y
.to_non_unique_bits(cs.ns(|| "Y Coordinate To Bits"))?;
x_bits.extend_from_slice(&y_bits);
Ok(x_bits)
@ -1387,12 +1391,12 @@ where
Ok(x_bytes)
}
fn to_bytes_strict<CS: ConstraintSystem<ConstraintF>>(
fn to_non_unique_bytes<CS: ConstraintSystem<ConstraintF>>(
&self,
mut cs: CS,
) -> Result<Vec<UInt8>, SynthesisError> {
let mut x_bytes = self.x.to_bytes_strict(cs.ns(|| "x"))?;
let y_bytes = self.y.to_bytes_strict(cs.ns(|| "y"))?;
let mut x_bytes = self.x.to_non_unique_bytes(cs.ns(|| "x"))?;
let y_bytes = self.y.to_non_unique_bytes(cs.ns(|| "y"))?;
x_bytes.extend_from_slice(&y_bytes);
Ok(x_bytes)

+ 4
- 2
r1cs-std/src/groups/mod.rs

@ -206,11 +206,13 @@ mod test {
assert_eq!(b2, b_b);
let _ = a.to_bytes(&mut cs.ns(|| "ToBytes")).unwrap();
let _ = a.to_bytes_strict(&mut cs.ns(|| "ToBytes Strict")).unwrap();
let _ = a
.to_non_unique_bytes(&mut cs.ns(|| "ToBytes Strict"))
.unwrap();
let _ = b.to_bytes(&mut cs.ns(|| "b ToBytes")).unwrap();
let _ = b
.to_bytes_strict(&mut cs.ns(|| "b ToBytes Strict"))
.to_non_unique_bytes(&mut cs.ns(|| "b ToBytes Strict"))
.unwrap();
if !cs.is_satisfied() {
println!("{:?}", cs.which_is_unsatisfied().unwrap());

Loading…
Cancel
Save