Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move Fp and R1CS to manta-crypto #248

Closed
wants to merge 12 commits into from
Closed
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]
### Added
- [\#248](https://github.com/Manta-Network/manta-rs/pull/248) Move Fp and R1CS to manta-crypto
- [\#237](https://github.com/Manta-Network/manta-rs/pull/237) Public input fuzzing tests for transfer protocol
- [\#215](https://github.com/Manta-Network/manta-rs/pull/215) Add windowed multiplication algorithm for groups
- [\#213](https://github.com/Manta-Network/manta-rs/pull/197) Add Ceremony Utilities
Expand Down
2 changes: 2 additions & 0 deletions manta-crypto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ arkworks = [
"ark-r1cs-std",
"ark-relations",
"ark-serialize",
"ark-std",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in this case, cause we need it, lets re-export it too

]

# Dalek Cryptography Backend
Expand Down Expand Up @@ -75,6 +76,7 @@ ark-ff = { version = "0.3.0", optional = true, default-features = false }
ark-r1cs-std = { version = "0.3.1", optional = true, default-features = false }
ark-relations = { version = "0.3.0", optional = true, default-features = false }
ark-serialize = { version = "0.3.0", optional = true, default-features = false, features = ["derive"] }
ark-std = { version = "0.3.0", optional = true, default-features = false }
derivative = { version = "2.2.0", default-features = false, features = ["use_core"] }
ed25519-dalek = { version = "1.0.1", optional = true, default-features = false, features = ["u64_backend"] }
manta-util = { path = "../manta-util", default-features = false, features = ["alloc"] }
Expand Down
171 changes: 171 additions & 0 deletions manta-crypto/src/arkworks/codec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
// Copyright 2019-2022 Manta Network.
// This file is part of manta-rs.
//
// manta-rs is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// manta-rs is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with manta-rs. If not, see <http://www.gnu.org/licenses/>.

//! Codec Utilities
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The stuff in this file can go in arkworks::serialize instead, we don't need to split this out.


use ark_std::io::{self, Error, ErrorKind};
use manta_util::codec::{Read, ReadExactError, Write};

pub use crate::arkworks::serialize::{
CanonicalDeserialize, CanonicalSerialize, SerializationError,
};

/// Serialization Hook
pub trait HasSerialization<'s>: 's {
/// Serialize Type
type Serialize: CanonicalSerialize + From<&'s Self>;
}

/// Deserialization Hook
pub trait HasDeserialization: Sized {
/// Deserialize Type
type Deserialize: CanonicalDeserialize + Into<Self>;
}

/// Arkworks Reader
pub struct ArkReader<R>
where
R: Read,
{
/// Reader State
state: Result<R, R::Error>,
}

impl<R> ArkReader<R>
where
R: Read,
{
/// Builds a new [`ArkReader`] from `reader`.
#[inline]
pub fn new(reader: R) -> Self {
Self { state: Ok(reader) }
}

/// Updates the internal reader state by performing the `f` computation.
#[inline]
fn update<T, F>(&mut self, f: F) -> Option<T>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we want this fn to be private?

where
F: FnOnce(&mut R) -> Result<T, R::Error>,
{
if let Ok(reader) = self.state.as_mut() {
match f(reader) {
Ok(value) => return Some(value),
Err(err) => self.state = Err(err),
}
}
None
}

/// Returns the reader state back or an error if it occured during any [`Read`](io::Read)
/// methods.
#[inline]
pub fn finish(self) -> Result<R, R::Error> {
self.state
}
}

impl<R> io::Read for ArkReader<R>
where
R: Read,
{
#[inline]
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
self.update(|reader| reader.read(buf))
.ok_or_else(|| Error::new(ErrorKind::Other, "Reading Error"))
}

#[inline]
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Error> {
match self.update(|reader| match reader.read_exact(buf) {
Ok(value) => Ok(Ok(value)),
Err(ReadExactError::Read(err)) => Err(err),
Err(ReadExactError::UnexpectedEnd(err)) => Ok(Err(err)),
}) {
Some(Ok(_)) => Ok(()),
Some(Err(_)) => Err(Error::new(
ErrorKind::UnexpectedEof,
"Unexpected end of buffer.",
)),
_ => Err(Error::new(ErrorKind::Other, "Reading Error")),
}
}
}

/// Arkworks Writer
pub struct ArkWriter<W>
where
W: Write,
{
/// Writer State
state: Result<W, W::Error>,
}

impl<W> ArkWriter<W>
where
W: Write,
{
/// Builds a new [`ArkWriter`] from `writer`.
#[inline]
pub fn new(writer: W) -> Self {
Self { state: Ok(writer) }
}

/// Updates the internal writer state by performing the `f` computation.
#[inline]
fn update<T, F>(&mut self, f: F) -> Option<T>
where
F: FnOnce(&mut W) -> Result<T, W::Error>,
{
if let Ok(writer) = self.state.as_mut() {
match f(writer) {
Ok(value) => return Some(value),
Err(err) => self.state = Err(err),
}
}
None
}

/// Returns the writer state back or an error if it occured during any [`Write`](io::Write)
/// methods.
#[inline]
pub fn finish(self) -> Result<W, W::Error> {
self.state
}
}

impl<W> io::Write for ArkWriter<W>
where
W: Write,
{
#[inline]
fn write(&mut self, mut buf: &[u8]) -> Result<usize, Error> {
self.update(|writer| writer.write(&mut buf))
.ok_or_else(|| Error::new(ErrorKind::Other, "Writing Error"))
}

#[inline]
fn flush(&mut self) -> Result<(), Error> {
// NOTE: We can't necessarily do better than this for now, unfortunately.
Ok(())
}

#[inline]
fn write_all(&mut self, mut buf: &[u8]) -> Result<(), Error> {
self.update(|writer| writer.write(&mut buf))
.map(|_| ())
.ok_or_else(|| Error::new(ErrorKind::Other, "Writing Error"))
}
}
123 changes: 118 additions & 5 deletions manta-crypto/src/arkworks/constraint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@

use crate::{
arkworks::{
ff::{FpParameters, PrimeField},
r1cs_std::{alloc::AllocVar, eq::EqGadget, select::CondSelectGadget, ToBitsGadget},
ff::{Fp, FpParameters, PrimeField},
r1cs_std::{
alloc::AllocVar, eq::EqGadget, fields::FieldVar, select::CondSelectGadget, ToBitsGadget,
},
relations::{
ns,
r1cs::{
Expand All @@ -36,9 +38,9 @@ use crate::{
Constant, Variable,
},
bool::{Assert, ConditionalSwap},
num::AssertWithinBitRange,
ops::Add,
Has,
num::{AssertWithinBitRange, Zero},
ops::{Add, BitAnd, BitOr},
Has, NonNative,
},
};

Expand Down Expand Up @@ -114,6 +116,8 @@ where
}
}

impl<F> NonNative for R1CS<F> where F: PrimeField {}

impl<F> Has<bool> for R1CS<F>
where
F: PrimeField,
Expand Down Expand Up @@ -267,6 +271,96 @@ where
}
}

impl<F> BitAnd<Self, R1CS<F>> for Boolean<F>
where
F: PrimeField,
{
type Output = Self;

#[inline]
fn bitand(self, rhs: Self, compiler: &mut R1CS<F>) -> Self::Output {
let _ = compiler;
self.and(&rhs).expect("Bitwise AND is not allowed to fail.")
}
}

impl<F> BitOr<Self, R1CS<F>> for Boolean<F>
where
F: PrimeField,
{
type Output = Self;

#[inline]
fn bitor(self, rhs: Self, compiler: &mut R1CS<F>) -> Self::Output {
let _ = compiler;
self.or(&rhs).expect("Bitwise OR is not allowed to fail.")
}
}

impl<F> Constant<R1CS<F>> for FpVar<F>
where
F: PrimeField,
{
type Type = Fp<F>;

#[inline]
fn new_constant(this: &Self::Type, compiler: &mut R1CS<F>) -> Self {
AllocVar::new_constant(ns!(compiler.0, "field constant"), this.0)
.expect("Variable allocation is not allowed to fail.")
}
}

impl<F> Constant<R1CS<F>> for Fp<F>
where
F: PrimeField,
{
type Type = Self;

#[inline]
fn new_constant(this: &Self::Type, compiler: &mut R1CS<F>) -> Self {
let _ = compiler;
*this
}
}

impl<F> Variable<Public, R1CS<F>> for FpVar<F>
where
F: PrimeField,
{
type Type = Fp<F>;

#[inline]
fn new_known(this: &Self::Type, compiler: &mut R1CS<F>) -> Self {
Self::new_input(ns!(compiler.0, "field public input"), full(this.0))
.expect("Variable allocation is not allowed to fail.")
}

#[inline]
fn new_unknown(compiler: &mut R1CS<F>) -> Self {
Self::new_input(ns!(compiler.0, "field public input"), empty::<F>)
.expect("Variable allocation is not allowed to fail.")
}
}

impl<F> Variable<Secret, R1CS<F>> for FpVar<F>
where
F: PrimeField,
{
type Type = Fp<F>;

#[inline]
fn new_known(this: &Self::Type, compiler: &mut R1CS<F>) -> Self {
Self::new_witness(ns!(compiler.0, "field secret witness"), full(this.0))
.expect("Variable allocation is not allowed to fail.")
}

#[inline]
fn new_unknown(compiler: &mut R1CS<F>) -> Self {
Self::new_witness(ns!(compiler.0, "field secret witness"), empty::<F>)
.expect("Variable allocation is not allowed to fail.")
}
}

impl<F> eclair::cmp::PartialEq<Self, R1CS<F>> for FpVar<F>
where
F: PrimeField,
Expand Down Expand Up @@ -315,3 +409,22 @@ where
self + rhs
}
}

impl<F> Zero<R1CS<F>> for FpVar<F>
where
F: PrimeField,
{
type Verification = Boolean<F>;

#[inline]
fn zero(compiler: &mut R1CS<F>) -> Self {
let _ = compiler;
FieldVar::zero()
}

#[inline]
fn is_zero(&self, compiler: &mut R1CS<F>) -> Self::Verification {
let _ = compiler;
FieldVar::is_zero(self).expect("Comparison with zero is not allowed to fail.")
}
}
Loading