merge dev, fix conflicts
This commit is contained in:
commit
c3978c3d49
31 changed files with 896 additions and 530 deletions
13
Cargo.lock
generated
13
Cargo.lock
generated
|
@ -76,6 +76,17 @@ dependencies = [
|
|||
"ark-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ark-bls12-381"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70e1c2ad76c4f725520440b981df3ce2d635f2baa1122750c757c0cf0f3d4b74"
|
||||
dependencies = [
|
||||
"ark-ec",
|
||||
"ark-ff",
|
||||
"ark-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ark-bn254"
|
||||
version = "0.2.0"
|
||||
|
@ -2516,10 +2527,12 @@ name = "zokrates_field"
|
|||
version = "0.4.0"
|
||||
dependencies = [
|
||||
"ark-bls12-377",
|
||||
"ark-bls12-381",
|
||||
"ark-bn254",
|
||||
"ark-bw6-761",
|
||||
"ark-ec",
|
||||
"ark-ff",
|
||||
"ark-serialize",
|
||||
"bellman_ce",
|
||||
"bincode",
|
||||
"lazy_static",
|
||||
|
|
1
changelogs/unreleased/1061-schaeff
Normal file
1
changelogs/unreleased/1061-schaeff
Normal file
|
@ -0,0 +1 @@
|
|||
Use ark-ff under the hood for optimized field operations
|
|
@ -1,2 +1,2 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2021-08-01"
|
||||
channel = "nightly-2021-12-10"
|
||||
|
|
|
@ -74,7 +74,7 @@ fn cli_check<T: Field>(sub_matches: &ArgMatches) -> Result<(), String> {
|
|||
format!(
|
||||
"{}:{}",
|
||||
file.strip_prefix(std::env::current_dir().unwrap())
|
||||
.unwrap_or_else(|_| file.as_path())
|
||||
.unwrap_or(file.as_path())
|
||||
.display(),
|
||||
e.value()
|
||||
)
|
||||
|
|
|
@ -90,7 +90,7 @@ fn cli_compile<T: Field>(sub_matches: &ArgMatches) -> Result<(), String> {
|
|||
format!(
|
||||
"{}:{}",
|
||||
file.strip_prefix(std::env::current_dir().unwrap())
|
||||
.unwrap_or_else(|_| file.as_path())
|
||||
.unwrap_or(file.as_path())
|
||||
.display(),
|
||||
e.value()
|
||||
)
|
||||
|
|
|
@ -261,7 +261,7 @@
|
|||
(declare-const |_254| Int)
|
||||
(declare-const |_257| Int)
|
||||
(declare-const |_258| Int)
|
||||
(declare-const |_263| Int)
|
||||
(declare-const |_264| Int)
|
||||
(assert (and
|
||||
(= |~prime| 21888242871839275222246405745257275088548364400416034343698204186575808495617)
|
||||
(= |~one| 1)
|
||||
|
@ -524,6 +524,6 @@
|
|||
(= (mod (* (+ (* |~one| 14651237294507013008273219182214280847718990358813499091232105186081237893121) (* |_0| 1) (* |_1| 21888242871839275222246405745257275088548364400416034343698204186575808495616)) (* |_258| 1)) |~prime|) (mod (* |_257| 1) |~prime|))
|
||||
(= (mod (* (+ (* |~one| 1) (* |_257| 21888242871839275222246405745257275088548364400416034343698204186575808495616)) (+ (* |~one| 14651237294507013008273219182214280847718990358813499091232105186081237893121) (* |_0| 1) (* |_1| 21888242871839275222246405745257275088548364400416034343698204186575808495616))) |~prime|) (mod 0 |~prime|))
|
||||
(= (mod (* (* |~one| 1) 0) |~prime|) (mod (+ (* |~one| 1) (* |_257| 21888242871839275222246405745257275088548364400416034343698204186575808495616)) |~prime|))
|
||||
(= (mod (* (* |_2| 1) (+ (* |_0| 21888242871839275222246405745257275088548364400416034343698204186575808495616) (* |_1| 1))) |~prime|) (mod (* |_263| 1) |~prime|))
|
||||
(= (mod (* (* |~one| 1) (* |_263| 1)) |~prime|) (mod (* |~out_0| 1) |~prime|))
|
||||
(= (mod (* (* |_2| 1) (+ (* |_0| 21888242871839275222246405745257275088548364400416034343698204186575808495616) (* |_1| 1))) |~prime|) (mod (* |_264| 1) |~prime|))
|
||||
(= (mod (* (* |~one| 1) (* |_264| 1)) |~prime|) (mod (* |~out_0| 1) |~prime|))
|
||||
))
|
|
@ -13,7 +13,7 @@ libsnark = ["cc", "cmake", "git2"]
|
|||
bellman = ["bellman_ce", "pairing_ce", "ff_ce", "zokrates_field/bellman"]
|
||||
wasm = ["bellman_ce/nolog", "bellman_ce/wasm"]
|
||||
multicore = ["bellman_ce/multicore"]
|
||||
ark = ["ark-ff", "ark-ec", "ark-bn254", "ark-bls12-377", "ark-bw6-761", "ark-gm17", "ark-serialize", "ark-relations", "ark-marlin", "ark-poly", "ark-poly-commit", "zokrates_field/ark", "sha2"]
|
||||
ark = ["ark-ff", "ark-ec", "ark-bn254", "ark-bls12-377", "ark-bw6-761", "ark-gm17", "ark-serialize", "ark-relations", "ark-marlin", "ark-poly", "ark-poly-commit", "sha2"]
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
|
|
|
@ -137,6 +137,7 @@ pub enum SymbolDefinition<'ast> {
|
|||
Function(FunctionNode<'ast>),
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum Symbol<'ast> {
|
||||
Here(SymbolDefinition<'ast>),
|
||||
|
|
84
zokrates_core/src/ast/memory.rs
Normal file
84
zokrates_core/src/ast/memory.rs
Normal file
|
@ -0,0 +1,84 @@
|
|||
use super::{DynamicError, StatementTrait};
|
||||
use fallible_iterator::{FallibleIterator, FromFallibleIterator, IntoFallibleIterator};
|
||||
use std::iter::FromIterator;
|
||||
|
||||
/// A newtype around Vec because we need `FromFallibleIterator` and `IntoFallibleIterator` to
|
||||
/// be implemented, and they are not on `Vec`
|
||||
#[derive(Clone, PartialEq, Debug, Hash)]
|
||||
pub struct MemoryStatements<S>(pub Vec<S>);
|
||||
|
||||
impl<S> Default for MemoryStatements<S> {
|
||||
fn default() -> Self {
|
||||
MemoryStatements(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> From<Vec<S>> for MemoryStatements<S> {
|
||||
fn from(v: Vec<S>) -> Self {
|
||||
MemoryStatements(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> MemoryStatements<S> {
|
||||
pub fn iter(&self) -> std::slice::Iter<S> {
|
||||
self.0.iter()
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.0.is_empty()
|
||||
}
|
||||
|
||||
pub fn into_inner(self) -> Vec<S> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> IntoIterator for MemoryStatements<S> {
|
||||
type Item = S;
|
||||
type IntoIter = std::vec::IntoIter<S>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.0.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> FromIterator<S> for MemoryStatements<S> {
|
||||
fn from_iter<I: IntoIterator<Item = S>>(i: I) -> Self {
|
||||
MemoryStatements(i.into_iter().collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: StatementTrait> FromFallibleIterator<S> for MemoryStatements<S> {
|
||||
fn from_fallible_iter<I: IntoFallibleIterator<Item = S>>(i: I) -> Result<Self, I::Error> {
|
||||
Ok(MemoryStatements(i.into_fallible_iter().collect()?))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MemoryStatementsIterator<S, I: Iterator<Item = S>> {
|
||||
statements: I,
|
||||
}
|
||||
|
||||
impl<S, I: Iterator<Item = S>> FallibleIterator for MemoryStatementsIterator<S, I> {
|
||||
type Item = S;
|
||||
type Error = DynamicError;
|
||||
|
||||
fn next(&mut self) -> Result<Option<Self::Item>, Self::Error> {
|
||||
Ok(self.statements.next())
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> IntoFallibleIterator for MemoryStatements<S> {
|
||||
type Item = S;
|
||||
type Error = DynamicError;
|
||||
type IntoFallibleIter = MemoryStatementsIterator<S, std::vec::IntoIter<S>>;
|
||||
|
||||
fn into_fallible_iter(self) -> Self::IntoFallibleIter {
|
||||
MemoryStatementsIterator {
|
||||
statements: self.into_iter(),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,41 +1,11 @@
|
|||
use fallible_iterator::{FallibleIterator, FromFallibleIterator, IntoFallibleIterator};
|
||||
use std::iter::FromIterator;
|
||||
mod memory;
|
||||
|
||||
#[derive(Clone, PartialEq, Debug, Hash)]
|
||||
pub struct MemoryStatements<S>(pub Vec<S>);
|
||||
|
||||
impl<S> Default for MemoryStatements<S> {
|
||||
fn default() -> Self {
|
||||
MemoryStatements(vec![])
|
||||
}
|
||||
}
|
||||
use fallible_iterator::{FallibleIterator, IntoFallibleIterator};
|
||||
pub use memory::MemoryStatements;
|
||||
|
||||
pub type DynamicError = Box<dyn std::error::Error>;
|
||||
|
||||
impl<S> From<Vec<S>> for MemoryStatements<S> {
|
||||
fn from(v: Vec<S>) -> Self {
|
||||
MemoryStatements(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> MemoryStatements<S> {
|
||||
pub fn iter(&self) -> std::slice::Iter<S> {
|
||||
self.0.iter()
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.0.is_empty()
|
||||
}
|
||||
|
||||
pub fn into_inner(self) -> Vec<S> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// A marker trait for statements, so that we can recover the underlying `Field`
|
||||
pub trait StatementTrait {
|
||||
type Field;
|
||||
}
|
||||
|
@ -47,6 +17,11 @@ pub trait IntoStatements:
|
|||
type Field;
|
||||
}
|
||||
|
||||
pub trait Statements: FallibleIterator<Item = Self::Statement, Error = DynamicError> {
|
||||
type Statement: StatementTrait;
|
||||
type Field;
|
||||
}
|
||||
|
||||
impl<S: StatementTrait, U: IntoFallibleIterator<Item = S, Error = DynamicError>> IntoStatements
|
||||
for U
|
||||
{
|
||||
|
@ -54,58 +29,7 @@ impl<S: StatementTrait, U: IntoFallibleIterator<Item = S, Error = DynamicError>>
|
|||
type Field = S::Field;
|
||||
}
|
||||
|
||||
pub trait Statements: FallibleIterator<Item = Self::Statement, Error = DynamicError> {
|
||||
type Statement: StatementTrait;
|
||||
type Field;
|
||||
}
|
||||
|
||||
impl<S: StatementTrait, U: FallibleIterator<Item = S, Error = DynamicError>> Statements for U {
|
||||
type Statement = S;
|
||||
type Field = S::Field;
|
||||
}
|
||||
|
||||
impl<S> IntoIterator for MemoryStatements<S> {
|
||||
type Item = S;
|
||||
type IntoIter = std::vec::IntoIter<S>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.0.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> FromIterator<S> for MemoryStatements<S> {
|
||||
fn from_iter<I: IntoIterator<Item = S>>(i: I) -> Self {
|
||||
MemoryStatements(i.into_iter().collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: StatementTrait> FromFallibleIterator<S> for MemoryStatements<S> {
|
||||
fn from_fallible_iter<I: IntoFallibleIterator<Item = S>>(i: I) -> Result<Self, I::Error> {
|
||||
Ok(MemoryStatements(i.into_fallible_iter().collect()?))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MemoryStatementsIterator<S, I: Iterator<Item = S>> {
|
||||
statements: I,
|
||||
}
|
||||
|
||||
impl<S, I: Iterator<Item = S>> FallibleIterator for MemoryStatementsIterator<S, I> {
|
||||
type Item = S;
|
||||
type Error = DynamicError;
|
||||
|
||||
fn next(&mut self) -> Result<Option<Self::Item>, Self::Error> {
|
||||
Ok(self.statements.next())
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> IntoFallibleIterator for MemoryStatements<S> {
|
||||
type Item = S;
|
||||
type Error = DynamicError;
|
||||
type IntoFallibleIter = MemoryStatementsIterator<S, std::vec::IntoIter<S>>;
|
||||
|
||||
fn into_fallible_iter(self) -> Self::IntoFallibleIter {
|
||||
MemoryStatementsIterator {
|
||||
statements: self.into_iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,8 +98,6 @@ pub struct Flattener<'ast, T> {
|
|||
layout: HashMap<Identifier<'ast>, FlatVariable>,
|
||||
/// Cached bit decompositions to avoid re-generating them
|
||||
bits_cache: HashMap<FlatExpression<T>, Vec<FlatExpression<T>>>,
|
||||
/// Cached flattened conditions for branches
|
||||
condition_cache: HashMap<BooleanExpression<'ast, T>, FlatVariable>,
|
||||
}
|
||||
|
||||
trait FlattenOutput<T: Field>: Sized {
|
||||
|
@ -228,7 +226,6 @@ impl<'ast, T: Field> Flattener<'ast, T> {
|
|||
next_var_idx: 0,
|
||||
layout: HashMap::new(),
|
||||
bits_cache: HashMap::new(),
|
||||
condition_cache: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -519,8 +516,6 @@ impl<'ast, T: Field> Flattener<'ast, T> {
|
|||
let condition_id = self.use_sym();
|
||||
statements_flattened.push_back(FlatStatement::Definition(condition_id, condition_flat));
|
||||
|
||||
self.condition_cache.insert(condition, condition_id);
|
||||
|
||||
let (consequence, alternative) = if self.config.isolate_branches {
|
||||
let mut consequence_statements = VecDeque::new();
|
||||
|
||||
|
@ -683,11 +678,10 @@ impl<'ast, T: Field> Flattener<'ast, T> {
|
|||
self.enforce_constant_le_check(
|
||||
statements_flattened,
|
||||
&e_bits_be,
|
||||
&T::max_value().bit_vector_be(),
|
||||
&T::max_value().to_bits_be(),
|
||||
);
|
||||
|
||||
let conditions =
|
||||
self.constant_le_check(statements_flattened, &e_bits_be, &c.bit_vector_be());
|
||||
let conditions = self.constant_le_check(statements_flattened, &e_bits_be, &c.to_bits_be());
|
||||
|
||||
// return `len(conditions) == sum(conditions)`
|
||||
self.eq_check(
|
||||
|
@ -814,11 +808,6 @@ impl<'ast, T: Field> Flattener<'ast, T> {
|
|||
statements_flattened: &mut FlatStatements<T>,
|
||||
expression: BooleanExpression<'ast, T>,
|
||||
) -> FlatExpression<T> {
|
||||
// check the cache
|
||||
if let Some(c) = self.condition_cache.get(&expression) {
|
||||
return (*c).into();
|
||||
}
|
||||
|
||||
match expression {
|
||||
BooleanExpression::Identifier(x) => {
|
||||
FlatExpression::Identifier(*self.layout.get(&x).unwrap())
|
||||
|
@ -2260,8 +2249,6 @@ impl<'ast, T: Field> Flattener<'ast, T> {
|
|||
statements_flattened
|
||||
.push_back(FlatStatement::Definition(condition_id, condition_flat));
|
||||
|
||||
self.condition_cache.insert(condition, condition_id);
|
||||
|
||||
if self.config.isolate_branches {
|
||||
let mut consequence_statements = VecDeque::new();
|
||||
let mut alternative_statements = VecDeque::new();
|
||||
|
|
|
@ -148,7 +148,7 @@ impl Interpreter {
|
|||
|
||||
// pad with zeroes so that the result is exactly `bit_width` long
|
||||
(0..bit_width - bits.len())
|
||||
.map(|_| 0)
|
||||
.map(|_| false)
|
||||
.chain(bits)
|
||||
.map(T::from)
|
||||
.collect()
|
||||
|
|
388
zokrates_core/src/static_analysis/condition_redefiner.rs
Normal file
388
zokrates_core/src/static_analysis/condition_redefiner.rs
Normal file
|
@ -0,0 +1,388 @@
|
|||
use crate::typed_absy::{
|
||||
folder::*, BlockExpression, BooleanExpression, Conditional, ConditionalExpression,
|
||||
ConditionalOrExpression, CoreIdentifier, Expr, Identifier, TypedStatement, Variable,
|
||||
};
|
||||
use zokrates_field::Field;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ConditionRedefiner<'ast, T> {
|
||||
index: usize,
|
||||
buffer: Vec<TypedStatement<'ast, T>>,
|
||||
}
|
||||
|
||||
impl<'ast, T: Field> Folder<'ast, T> for ConditionRedefiner<'ast, T> {
|
||||
fn fold_statement(&mut self, s: TypedStatement<'ast, T>) -> Vec<TypedStatement<'ast, T>> {
|
||||
assert!(self.buffer.is_empty());
|
||||
let s = fold_statement(self, s);
|
||||
let buffer = std::mem::take(&mut self.buffer);
|
||||
buffer.into_iter().chain(s).collect()
|
||||
}
|
||||
|
||||
fn fold_block_expression<E: Fold<'ast, T>>(
|
||||
&mut self,
|
||||
b: BlockExpression<'ast, T, E>,
|
||||
) -> BlockExpression<'ast, T, E> {
|
||||
// start with a fresh state, but keep the global counter
|
||||
let mut redefiner = ConditionRedefiner {
|
||||
index: self.index,
|
||||
buffer: vec![],
|
||||
};
|
||||
|
||||
let b = fold_block_expression(&mut redefiner, b);
|
||||
|
||||
// we add the buffer statements *after* the block statements because they refer to the return value,
|
||||
// the buffered statements for the block statements are already included in the result
|
||||
let b = BlockExpression {
|
||||
statements: b
|
||||
.statements
|
||||
.into_iter()
|
||||
.chain(std::mem::take(&mut redefiner.buffer))
|
||||
.collect(),
|
||||
..b
|
||||
};
|
||||
|
||||
// continue from the latest index
|
||||
self.index = redefiner.index;
|
||||
|
||||
b
|
||||
}
|
||||
|
||||
fn fold_conditional_expression<E: Expr<'ast, T> + Conditional<'ast, T> + Fold<'ast, T>>(
|
||||
&mut self,
|
||||
_: &E::Ty,
|
||||
e: ConditionalExpression<'ast, T, E>,
|
||||
) -> ConditionalOrExpression<'ast, T, E> {
|
||||
let condition = self.fold_boolean_expression(*e.condition);
|
||||
let condition = match condition {
|
||||
condition @ BooleanExpression::Value(_)
|
||||
| condition @ BooleanExpression::Identifier(_) => condition,
|
||||
condition => {
|
||||
let condition_id = Identifier::from(CoreIdentifier::Condition(self.index));
|
||||
self.buffer.push(TypedStatement::Definition(
|
||||
Variable::boolean(condition_id.clone()).into(),
|
||||
condition.into(),
|
||||
));
|
||||
self.index += 1;
|
||||
BooleanExpression::Identifier(condition_id)
|
||||
}
|
||||
};
|
||||
|
||||
let consequence = e.consequence.fold(self);
|
||||
let alternative = e.alternative.fold(self);
|
||||
|
||||
ConditionalOrExpression::Conditional(ConditionalExpression::new(
|
||||
condition,
|
||||
consequence,
|
||||
alternative,
|
||||
e.kind,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::typed_absy::{
|
||||
Block, BooleanExpression, Conditional, ConditionalKind, FieldElementExpression, Type,
|
||||
};
|
||||
use zokrates_field::Bn128Field;
|
||||
|
||||
#[test]
|
||||
fn no_redefine_if_constant() {
|
||||
// field foo = if true then 1 else 2
|
||||
// should be left unchanged
|
||||
|
||||
let s = TypedStatement::Definition(
|
||||
Variable::field_element("foo").into(),
|
||||
FieldElementExpression::conditional(
|
||||
BooleanExpression::Value(true),
|
||||
FieldElementExpression::Number(Bn128Field::from(1)),
|
||||
FieldElementExpression::Number(Bn128Field::from(2)),
|
||||
ConditionalKind::IfElse,
|
||||
)
|
||||
.into(),
|
||||
);
|
||||
|
||||
let mut r = ConditionRedefiner::default();
|
||||
|
||||
assert_eq!(r.fold_statement(s.clone()), vec![s]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_redefine_if_identifier() {
|
||||
// field foo = if c then 1 else 2
|
||||
// should be left unchanged
|
||||
|
||||
let s = TypedStatement::Definition(
|
||||
Variable::field_element("foo").into(),
|
||||
FieldElementExpression::conditional(
|
||||
BooleanExpression::Identifier("c".into()),
|
||||
FieldElementExpression::Number(Bn128Field::from(1)),
|
||||
FieldElementExpression::Number(Bn128Field::from(2)),
|
||||
ConditionalKind::IfElse,
|
||||
)
|
||||
.into(),
|
||||
);
|
||||
|
||||
let mut r = ConditionRedefiner::default();
|
||||
|
||||
assert_eq!(r.fold_statement(s.clone()), vec![s]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn redefine_if_expression() {
|
||||
// field foo = if c && d then 1 else 2 fi
|
||||
// should become
|
||||
// bool #CONDITION_0 = c && d
|
||||
// field foo = if #CONDITION_0 then 1 else 2
|
||||
|
||||
let condition = BooleanExpression::And(
|
||||
box BooleanExpression::Identifier("c".into()),
|
||||
box BooleanExpression::Identifier("d".into()),
|
||||
);
|
||||
|
||||
let s = TypedStatement::Definition(
|
||||
Variable::field_element("foo").into(),
|
||||
FieldElementExpression::conditional(
|
||||
condition.clone(),
|
||||
FieldElementExpression::Number(Bn128Field::from(1)),
|
||||
FieldElementExpression::Number(Bn128Field::from(2)),
|
||||
ConditionalKind::IfElse,
|
||||
)
|
||||
.into(),
|
||||
);
|
||||
|
||||
let mut r = ConditionRedefiner::default();
|
||||
|
||||
let expected = vec![
|
||||
// define condition
|
||||
TypedStatement::Definition(
|
||||
Variable::with_id_and_type(CoreIdentifier::Condition(0), Type::Boolean).into(),
|
||||
condition.into(),
|
||||
),
|
||||
// rewrite statement
|
||||
TypedStatement::Definition(
|
||||
Variable::field_element("foo").into(),
|
||||
FieldElementExpression::conditional(
|
||||
BooleanExpression::Identifier(CoreIdentifier::Condition(0).into()),
|
||||
FieldElementExpression::Number(Bn128Field::from(1)),
|
||||
FieldElementExpression::Number(Bn128Field::from(2)),
|
||||
ConditionalKind::IfElse,
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
];
|
||||
|
||||
assert_eq!(r.fold_statement(s), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn redefine_rec() {
|
||||
// field foo = if c && d then (if e && f then 1 else 2 fi) else 3 fi
|
||||
//
|
||||
// should become
|
||||
//
|
||||
// bool #CONDITION_0 = c && d
|
||||
// bool #CONDITION_1 = e && f
|
||||
// field foo = if #CONDITION_0 then (if #CONDITION_1 then 1 else 2 fi) else 3 fi
|
||||
|
||||
let condition_0 = BooleanExpression::And(
|
||||
box BooleanExpression::Identifier("c".into()),
|
||||
box BooleanExpression::Identifier("d".into()),
|
||||
);
|
||||
|
||||
let condition_1 = BooleanExpression::And(
|
||||
box BooleanExpression::Identifier("e".into()),
|
||||
box BooleanExpression::Identifier("f".into()),
|
||||
);
|
||||
|
||||
let s = TypedStatement::Definition(
|
||||
Variable::field_element("foo").into(),
|
||||
FieldElementExpression::conditional(
|
||||
condition_0.clone(),
|
||||
FieldElementExpression::conditional(
|
||||
condition_1.clone(),
|
||||
FieldElementExpression::Number(Bn128Field::from(1)),
|
||||
FieldElementExpression::Number(Bn128Field::from(2)),
|
||||
ConditionalKind::IfElse,
|
||||
),
|
||||
FieldElementExpression::Number(Bn128Field::from(3)),
|
||||
ConditionalKind::IfElse,
|
||||
)
|
||||
.into(),
|
||||
);
|
||||
|
||||
let mut r = ConditionRedefiner::default();
|
||||
|
||||
let expected = vec![
|
||||
// define conditions
|
||||
TypedStatement::Definition(
|
||||
Variable::with_id_and_type(CoreIdentifier::Condition(0), Type::Boolean).into(),
|
||||
condition_0.into(),
|
||||
),
|
||||
TypedStatement::Definition(
|
||||
Variable::with_id_and_type(CoreIdentifier::Condition(1), Type::Boolean).into(),
|
||||
condition_1.into(),
|
||||
),
|
||||
// rewrite statement
|
||||
TypedStatement::Definition(
|
||||
Variable::field_element("foo").into(),
|
||||
FieldElementExpression::conditional(
|
||||
BooleanExpression::Identifier(CoreIdentifier::Condition(0).into()),
|
||||
FieldElementExpression::conditional(
|
||||
BooleanExpression::Identifier(CoreIdentifier::Condition(1).into()),
|
||||
FieldElementExpression::Number(Bn128Field::from(1)),
|
||||
FieldElementExpression::Number(Bn128Field::from(2)),
|
||||
ConditionalKind::IfElse,
|
||||
),
|
||||
FieldElementExpression::Number(Bn128Field::from(3)),
|
||||
ConditionalKind::IfElse,
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
];
|
||||
|
||||
assert_eq!(r.fold_statement(s), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn redefine_block() {
|
||||
// field foo = if c && d then {
|
||||
// field a = 1
|
||||
// if e && f then 2 else 3
|
||||
// } else {
|
||||
// field b = 2
|
||||
// if e && f then 2 else 3
|
||||
// }
|
||||
//
|
||||
// should become
|
||||
//
|
||||
// bool #CONDITION_0 = c && d
|
||||
// field foo = if #CONDITION_0 then {
|
||||
// field a = 1
|
||||
// bool #CONDITION_1 = e && f
|
||||
// if #CONDITION_1 then 2 else 3
|
||||
// } else {
|
||||
// field b = 2
|
||||
// bool #CONDITION_2 = e && f
|
||||
// if #CONDITION_2 then 2 else 3
|
||||
// }
|
||||
|
||||
let condition_0 = BooleanExpression::And(
|
||||
box BooleanExpression::Identifier("c".into()),
|
||||
box BooleanExpression::Identifier("d".into()),
|
||||
);
|
||||
|
||||
let condition_1 = BooleanExpression::And(
|
||||
box BooleanExpression::Identifier("e".into()),
|
||||
box BooleanExpression::Identifier("f".into()),
|
||||
);
|
||||
|
||||
let condition_2 = BooleanExpression::And(
|
||||
box BooleanExpression::Identifier("e".into()),
|
||||
box BooleanExpression::Identifier("f".into()),
|
||||
);
|
||||
|
||||
let condition_id_0 = BooleanExpression::Identifier(CoreIdentifier::Condition(0).into());
|
||||
let condition_id_1 = BooleanExpression::Identifier(CoreIdentifier::Condition(1).into());
|
||||
let condition_id_2 = BooleanExpression::Identifier(CoreIdentifier::Condition(2).into());
|
||||
|
||||
let s = TypedStatement::Definition(
|
||||
Variable::field_element("foo").into(),
|
||||
FieldElementExpression::conditional(
|
||||
condition_0.clone(),
|
||||
FieldElementExpression::block(
|
||||
vec![TypedStatement::Definition(
|
||||
Variable::field_element("a").into(),
|
||||
FieldElementExpression::Number(Bn128Field::from(1)).into(),
|
||||
)],
|
||||
FieldElementExpression::conditional(
|
||||
condition_1.clone(),
|
||||
FieldElementExpression::Number(Bn128Field::from(2)),
|
||||
FieldElementExpression::Number(Bn128Field::from(3)),
|
||||
ConditionalKind::IfElse,
|
||||
),
|
||||
),
|
||||
FieldElementExpression::block(
|
||||
vec![TypedStatement::Definition(
|
||||
Variable::field_element("b").into(),
|
||||
FieldElementExpression::Number(Bn128Field::from(2)).into(),
|
||||
)],
|
||||
FieldElementExpression::conditional(
|
||||
condition_2.clone(),
|
||||
FieldElementExpression::Number(Bn128Field::from(2)),
|
||||
FieldElementExpression::Number(Bn128Field::from(3)),
|
||||
ConditionalKind::IfElse,
|
||||
),
|
||||
),
|
||||
ConditionalKind::IfElse,
|
||||
)
|
||||
.into(),
|
||||
);
|
||||
|
||||
let mut r = ConditionRedefiner::default();
|
||||
|
||||
let expected = vec![
|
||||
// define conditions
|
||||
TypedStatement::Definition(
|
||||
Variable::with_id_and_type(CoreIdentifier::Condition(0), Type::Boolean).into(),
|
||||
condition_0.into(),
|
||||
),
|
||||
// rewrite statement
|
||||
TypedStatement::Definition(
|
||||
Variable::field_element("foo").into(),
|
||||
FieldElementExpression::conditional(
|
||||
condition_id_0.clone(),
|
||||
FieldElementExpression::block(
|
||||
vec![
|
||||
TypedStatement::Definition(
|
||||
Variable::field_element("a").into(),
|
||||
FieldElementExpression::Number(Bn128Field::from(1)).into(),
|
||||
),
|
||||
TypedStatement::Definition(
|
||||
Variable::with_id_and_type(
|
||||
CoreIdentifier::Condition(1),
|
||||
Type::Boolean,
|
||||
)
|
||||
.into(),
|
||||
condition_1.into(),
|
||||
),
|
||||
],
|
||||
FieldElementExpression::conditional(
|
||||
condition_id_1,
|
||||
FieldElementExpression::Number(Bn128Field::from(2)),
|
||||
FieldElementExpression::Number(Bn128Field::from(3)),
|
||||
ConditionalKind::IfElse,
|
||||
),
|
||||
),
|
||||
FieldElementExpression::block(
|
||||
vec![
|
||||
TypedStatement::Definition(
|
||||
Variable::field_element("b").into(),
|
||||
FieldElementExpression::Number(Bn128Field::from(2)).into(),
|
||||
),
|
||||
TypedStatement::Definition(
|
||||
Variable::with_id_and_type(
|
||||
CoreIdentifier::Condition(2),
|
||||
Type::Boolean,
|
||||
)
|
||||
.into(),
|
||||
condition_2.into(),
|
||||
),
|
||||
],
|
||||
FieldElementExpression::conditional(
|
||||
condition_id_2,
|
||||
FieldElementExpression::Number(Bn128Field::from(2)),
|
||||
FieldElementExpression::Number(Bn128Field::from(3)),
|
||||
ConditionalKind::IfElse,
|
||||
),
|
||||
),
|
||||
ConditionalKind::IfElse,
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
];
|
||||
|
||||
assert_eq!(r.fold_statement(s), expected);
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
//! @date 2018
|
||||
|
||||
mod branch_isolator;
|
||||
mod condition_redefiner;
|
||||
mod constant_argument_checker;
|
||||
mod constant_resolver;
|
||||
mod flat_propagation;
|
||||
|
@ -18,6 +19,7 @@ mod variable_write_remover;
|
|||
mod zir_propagation;
|
||||
|
||||
use self::branch_isolator::Isolator;
|
||||
use self::condition_redefiner::ConditionRedefiner;
|
||||
use self::constant_argument_checker::ConstantArgumentChecker;
|
||||
use self::flatten_complex_types::{Flattener, FlattenerInner};
|
||||
use self::out_of_bounds::OutOfBoundsChecker;
|
||||
|
@ -135,6 +137,7 @@ impl<'ast, T: Field> TypedProgram<'ast, T> {
|
|||
let mut type_flattener_inner = FlattenerInner::default();
|
||||
let mut zir_propagator = ZirPropagator::default();
|
||||
let mut uint_optimizer = UintOptimizer::default();
|
||||
let condition_redefiner = ConditionRedefiner::default();
|
||||
|
||||
let arguments = r.arguments;
|
||||
let statements = r.statements.into_fallible_iter();
|
||||
|
@ -175,6 +178,7 @@ impl<'ast, T: Field> TypedProgram<'ast, T> {
|
|||
typed_absy::result_folder::fold_statements(constant_argument_checker, statements);
|
||||
let statements =
|
||||
typed_absy::result_folder::fold_statements(out_of_bounds_checker, statements);
|
||||
let statements = typed_absy::folder::fold_statements(condition_redefiner, statements);
|
||||
|
||||
let type_flattener = Flattener {
|
||||
input: statements.into_fallible_iter(),
|
||||
|
|
|
@ -261,8 +261,7 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Reducer<'ast, 'a, T> {
|
|||
}
|
||||
Err(InlineError::Generic(decl, conc)) => Err(Error::Incompatible(format!(
|
||||
"Call site `{}` incompatible with declaration `{}`",
|
||||
conc.to_string(),
|
||||
decl.to_string()
|
||||
conc, decl
|
||||
))),
|
||||
Err(InlineError::NonConstant(key, generics, arguments, _)) => Ok(
|
||||
FunctionCallOrExpression::Expression(E::function_call(key, generics, arguments)),
|
||||
|
@ -397,8 +396,7 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Reducer<'ast, 'a, T> {
|
|||
}
|
||||
Err(InlineError::Generic(decl, conc)) => Err(Error::Incompatible(format!(
|
||||
"Call site `{}` incompatible with declaration `{}`",
|
||||
conc.to_string(),
|
||||
decl.to_string()
|
||||
conc, decl
|
||||
))),
|
||||
Err(InlineError::NonConstant(key, generics, arguments, output_types)) => {
|
||||
self.send_to_complete_buffer = false;
|
||||
|
|
|
@ -72,6 +72,41 @@ impl<'ast, T: Field> ResultFolder<'ast, T> for ZirPropagator<'ast, T> {
|
|||
}
|
||||
}
|
||||
}
|
||||
ZirStatement::IfElse(e, consequence, alternative) => {
|
||||
match self.fold_boolean_expression(e)? {
|
||||
BooleanExpression::Value(true) => Ok(consequence
|
||||
.into_iter()
|
||||
.map(|s| self.fold_statement(s))
|
||||
.collect::<Result<Vec<_>, _>>()?
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect()),
|
||||
BooleanExpression::Value(false) => Ok(alternative
|
||||
.into_iter()
|
||||
.map(|s| self.fold_statement(s))
|
||||
.collect::<Result<Vec<_>, _>>()?
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect()),
|
||||
e => Ok(vec![ZirStatement::IfElse(
|
||||
e,
|
||||
consequence
|
||||
.into_iter()
|
||||
.map(|s| self.fold_statement(s))
|
||||
.collect::<Result<Vec<_>, _>>()?
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect(),
|
||||
alternative
|
||||
.into_iter()
|
||||
.map(|s| self.fold_statement(s))
|
||||
.collect::<Result<Vec<_>, _>>()?
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect(),
|
||||
)]),
|
||||
}
|
||||
}
|
||||
ZirStatement::MultipleDefinition(assignees, list) => {
|
||||
for a in &assignees {
|
||||
self.constants.remove(&a.id);
|
||||
|
@ -108,7 +143,7 @@ impl<'ast, T: Field> ResultFolder<'ast, T> for ZirPropagator<'ast, T> {
|
|||
UExpressionInner::Value(v) => e
|
||||
.get(v as usize)
|
||||
.cloned()
|
||||
.ok_or_else(|| Error::OutOfBounds(v, e.len() as u128)),
|
||||
.ok_or(Error::OutOfBounds(v, e.len() as u128)),
|
||||
i => Ok(FieldElementExpression::Select(
|
||||
e,
|
||||
box i.annotate(UBitwidth::B32),
|
||||
|
@ -240,7 +275,7 @@ impl<'ast, T: Field> ResultFolder<'ast, T> for ZirPropagator<'ast, T> {
|
|||
UExpressionInner::Value(v) => e
|
||||
.get(*v as usize)
|
||||
.cloned()
|
||||
.ok_or_else(|| Error::OutOfBounds(*v, e.len() as u128)),
|
||||
.ok_or(Error::OutOfBounds(*v, e.len() as u128)),
|
||||
_ => Ok(BooleanExpression::Select(e, box index)),
|
||||
}
|
||||
}
|
||||
|
@ -459,7 +494,7 @@ impl<'ast, T: Field> ResultFolder<'ast, T> for ZirPropagator<'ast, T> {
|
|||
UExpressionInner::Value(v) => e
|
||||
.get(v as usize)
|
||||
.cloned()
|
||||
.ok_or_else(|| Error::OutOfBounds(v, e.len() as u128))
|
||||
.ok_or(Error::OutOfBounds(v, e.len() as u128))
|
||||
.map(|e| e.into_inner()),
|
||||
i => Ok(UExpressionInner::Select(e, box i.annotate(UBitwidth::B32))),
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ pub enum CoreIdentifier<'ast> {
|
|||
Source(&'ast str),
|
||||
Call(usize),
|
||||
Constant(CanonicalConstantIdentifier<'ast>),
|
||||
Condition(usize),
|
||||
}
|
||||
|
||||
impl<'ast> fmt::Display for CoreIdentifier<'ast> {
|
||||
|
@ -15,6 +16,7 @@ impl<'ast> fmt::Display for CoreIdentifier<'ast> {
|
|||
CoreIdentifier::Source(s) => write!(f, "{}", s),
|
||||
CoreIdentifier::Call(i) => write!(f, "#CALL_RETURN_AT_INDEX_{}", i),
|
||||
CoreIdentifier::Constant(c) => write!(f, "{}/{}", c.module.display(), c.id),
|
||||
CoreIdentifier::Condition(i) => write!(f, "#CONDITION_{}", i),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,6 +183,7 @@ impl<'ast, T> TypedConstantSymbolDeclaration<'ast, T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub enum TypedSymbolDeclaration<'ast, T> {
|
||||
Function(TypedFunctionSymbolDeclaration<'ast, T>),
|
||||
|
@ -433,6 +434,7 @@ impl<'ast, T: Field> Typed<'ast, T> for TypedConstant<'ast, T> {
|
|||
}
|
||||
|
||||
/// Something we can assign to.
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Clone, PartialEq, Debug, Hash, Eq, PartialOrd, Ord)]
|
||||
pub enum TypedAssignee<'ast, T> {
|
||||
Identifier(Variable<'ast, T>),
|
||||
|
@ -1252,8 +1254,7 @@ impl<'ast, T: Clone> ArrayValue<'ast, T> {
|
|||
) -> Option<U> {
|
||||
self.0
|
||||
.iter()
|
||||
.map(|v| Self::expression_at_aux(v.clone()))
|
||||
.flatten()
|
||||
.flat_map(|v| Self::expression_at_aux(v.clone()))
|
||||
.take_while(|e| e.is_some())
|
||||
.map(|e| e.unwrap())
|
||||
.nth(index)
|
||||
|
|
|
@ -343,17 +343,14 @@ impl<'ast, T> Iterator for ConjunctionIterator<BooleanExpression<'ast, T>> {
|
|||
type Item = BooleanExpression<'ast, T>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.current
|
||||
.pop()
|
||||
.map(|n| match n {
|
||||
BooleanExpression::And(box left, box right) => {
|
||||
self.current.push(left);
|
||||
self.current.push(right);
|
||||
self.next()
|
||||
}
|
||||
n => Some(n),
|
||||
})
|
||||
.flatten()
|
||||
self.current.pop().and_then(|n| match n {
|
||||
BooleanExpression::And(box left, box right) => {
|
||||
self.current.push(left);
|
||||
self.current.push(right);
|
||||
self.next()
|
||||
}
|
||||
n => Some(n),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -144,17 +144,12 @@ pub fn generate_verify_constraints(
|
|||
var_to_index(&vk.h_gamma_g2.y.c1, num_instance_variables),
|
||||
];
|
||||
|
||||
vk_indices.extend(
|
||||
vk.query
|
||||
.iter()
|
||||
.map(|q| {
|
||||
vec![
|
||||
var_to_index(&q.x, num_instance_variables),
|
||||
var_to_index(&q.y, num_instance_variables),
|
||||
]
|
||||
})
|
||||
.flatten(),
|
||||
);
|
||||
vk_indices.extend(vk.query.iter().flat_map(|q| {
|
||||
vec![
|
||||
var_to_index(&q.x, num_instance_variables),
|
||||
var_to_index(&q.y, num_instance_variables),
|
||||
]
|
||||
}));
|
||||
|
||||
let out_index = match &res {
|
||||
Boolean::Is(x) => x
|
||||
|
|
|
@ -5,8 +5,7 @@ authors = ["Thibaut Schaeffer <thibaut@schaeff.fr>", "Guillaume Ballet <gballet@
|
|||
edition = "2018"
|
||||
|
||||
[features]
|
||||
default = ["ark", "bellman"]
|
||||
ark = ["ark-ff", "ark-ec", "ark-bn254", "ark-bls12-377", "ark-bw6-761"]
|
||||
default = ["bellman"]
|
||||
bellman = ["bellman_ce"]
|
||||
|
||||
[dependencies]
|
||||
|
@ -23,11 +22,13 @@ num-integer = { version = "0.1", default-features = false }
|
|||
bellman_ce = { version = "^0.3", default-features = false, optional = true }
|
||||
|
||||
# ark
|
||||
ark-ff = { version = "^0.2.0", default-features = false, optional = true }
|
||||
ark-ec = { version = "^0.2.0", default-features = false, optional = true }
|
||||
ark-bn254 = { version = "^0.2.0", features = ["curve"], default-features = false, optional = true }
|
||||
ark-bls12-377 = { version = "^0.2.0", features = ["curve"], default-features = false, optional = true }
|
||||
ark-bw6-761 = { version = "^0.2.0", default-features = false, optional = true }
|
||||
ark-ec = { version = "^0.2.0", default-features = false }
|
||||
ark-ff = { version = "^0.2.0", default-features = false }
|
||||
ark-bn254 = { version = "^0.2.0", features = ["curve"], default-features = false }
|
||||
ark-bls12-377 = { version = "^0.2.0", features = ["curve"], default-features = false }
|
||||
ark-bls12-381 = { version = "^0.2.0", features = ["curve"], default-features = false }
|
||||
ark-bw6-761 = { version = "^0.2.0", default-features = false }
|
||||
ark-serialize = { version = "^0.2.0", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
rand = "0.4"
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
prime_field!(
|
||||
b"8444461749428370424248824938781546531375899335154063827935233455917409239041",
|
||||
"bls12_377"
|
||||
);
|
||||
use ark_bls12_377::Bls12_377;
|
||||
|
||||
#[cfg(feature = "ark")]
|
||||
ark_extensions!(ark_bls12_377::Bls12_377);
|
||||
prime_field!("bls12_377", Bls12_377);
|
||||
|
||||
ark_extensions!(Bls12_377);
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
prime_field!(
|
||||
b"52435875175126190479447740508185965837690552500527637822603658699938581184513",
|
||||
"bls12_381"
|
||||
);
|
||||
use ark_bls12_381::Bls12_381;
|
||||
|
||||
prime_field!("bls12_381", Bls12_381);
|
||||
|
||||
ark_extensions!(Bls12_381);
|
||||
|
||||
#[cfg(feature = "bellman")]
|
||||
use bellman_ce::pairing::bls12_381::{Bls12, Fq2};
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
prime_field!(
|
||||
b"21888242871839275222246405745257275088548364400416034343698204186575808495617",
|
||||
"bn128"
|
||||
);
|
||||
use ark_bn254::Bn254;
|
||||
|
||||
prime_field!("bn128", Bn254);
|
||||
|
||||
ark_extensions!(Bn254);
|
||||
|
||||
#[cfg(feature = "bellman")]
|
||||
use bellman_ce::pairing::bn256::{Bn256, Fq2};
|
||||
#[cfg(feature = "bellman")]
|
||||
bellman_extensions!(Bn256, Fq2);
|
||||
|
||||
#[cfg(feature = "ark")]
|
||||
use ark_bn254::Bn254;
|
||||
#[cfg(feature = "ark")]
|
||||
ark_extensions!(Bn254);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -29,165 +25,152 @@ mod tests {
|
|||
use bincode::{deserialize, serialize, Infinite};
|
||||
|
||||
#[test]
|
||||
fn max_value_bits() {
|
||||
let bits = FieldPrime::max_value().bit_vector_be();
|
||||
fn to_bits_be() {
|
||||
let bits = FieldPrime::max_value().to_bits_be();
|
||||
assert_eq!(bits.len(), 254);
|
||||
assert_eq!(
|
||||
bits[0..10].to_vec(),
|
||||
vec![true, true, false, false, false, false, false, true, true, false]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn positive_number() {
|
||||
assert_eq!(
|
||||
"1234245612".parse::<BigInt>().unwrap(),
|
||||
FieldPrime::from("1234245612").value
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn negative_number() {
|
||||
assert_eq!(
|
||||
P.checked_sub(&"12".parse::<BigInt>().unwrap()).unwrap(),
|
||||
FieldPrime::from("-12").value
|
||||
);
|
||||
let bits = FieldPrime::one().to_bits_be();
|
||||
assert_eq!(bits.len(), 254);
|
||||
assert_eq!(bits[253], true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn addition() {
|
||||
assert_eq!(
|
||||
"65484493".parse::<BigInt>().unwrap(),
|
||||
(FieldPrime::from("65416358") + FieldPrime::from("68135")).value
|
||||
FieldPrime::from("65484493"),
|
||||
FieldPrime::from("65416358") + FieldPrime::from("68135")
|
||||
);
|
||||
assert_eq!(
|
||||
"65484493".parse::<BigInt>().unwrap(),
|
||||
(FieldPrime::from("65416358") + &FieldPrime::from("68135")).value
|
||||
FieldPrime::from("65484493"),
|
||||
FieldPrime::from("65416358") + &FieldPrime::from("68135")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn addition_negative_small() {
|
||||
assert_eq!(
|
||||
"3".parse::<BigInt>().unwrap(),
|
||||
(FieldPrime::from("5") + FieldPrime::from("-2")).value
|
||||
FieldPrime::from("3"),
|
||||
FieldPrime::from("5") + FieldPrime::from(-2)
|
||||
);
|
||||
assert_eq!(
|
||||
"3".parse::<BigInt>().unwrap(),
|
||||
(FieldPrime::from("5") + &FieldPrime::from("-2")).value
|
||||
FieldPrime::from("3"),
|
||||
FieldPrime::from("5") + &FieldPrime::from(-2)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn addition_negative() {
|
||||
assert_eq!(
|
||||
"65348223".parse::<BigInt>().unwrap(),
|
||||
(FieldPrime::from("65416358") + FieldPrime::from("-68135")).value
|
||||
FieldPrime::from("65348223"),
|
||||
FieldPrime::from("65416358") + FieldPrime::from(-68135)
|
||||
);
|
||||
assert_eq!(
|
||||
"65348223".parse::<BigInt>().unwrap(),
|
||||
(FieldPrime::from("65416358") + &FieldPrime::from("-68135")).value
|
||||
FieldPrime::from("65348223"),
|
||||
FieldPrime::from("65416358") + &FieldPrime::from(-68135)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn subtraction() {
|
||||
assert_eq!(
|
||||
"65348223".parse::<BigInt>().unwrap(),
|
||||
(FieldPrime::from("65416358") - FieldPrime::from("68135")).value
|
||||
FieldPrime::from("65348223"),
|
||||
FieldPrime::from("65416358") - FieldPrime::from("68135")
|
||||
);
|
||||
assert_eq!(
|
||||
"65348223".parse::<BigInt>().unwrap(),
|
||||
(FieldPrime::from("65416358") - &FieldPrime::from("68135")).value
|
||||
FieldPrime::from("65348223"),
|
||||
FieldPrime::from("65416358") - &FieldPrime::from("68135")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn subtraction_negative() {
|
||||
assert_eq!(
|
||||
"65484493".parse::<BigInt>().unwrap(),
|
||||
(FieldPrime::from("65416358") - FieldPrime::from("-68135")).value
|
||||
FieldPrime::from("65484493"),
|
||||
FieldPrime::from("65416358") - FieldPrime::from(-68135)
|
||||
);
|
||||
assert_eq!(
|
||||
"65484493".parse::<BigInt>().unwrap(),
|
||||
(FieldPrime::from("65416358") - &FieldPrime::from("-68135")).value
|
||||
FieldPrime::from("65484493"),
|
||||
FieldPrime::from("65416358") - &FieldPrime::from(-68135)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn subtraction_overflow() {
|
||||
assert_eq!(
|
||||
"21888242871839275222246405745257275088548364400416034343698204186575743147394"
|
||||
.parse::<BigInt>()
|
||||
.unwrap(),
|
||||
(FieldPrime::from("68135") - FieldPrime::from("65416358")).value
|
||||
FieldPrime::from(
|
||||
"21888242871839275222246405745257275088548364400416034343698204186575743147394"
|
||||
),
|
||||
FieldPrime::from("68135") - FieldPrime::from("65416358")
|
||||
);
|
||||
assert_eq!(
|
||||
"21888242871839275222246405745257275088548364400416034343698204186575743147394"
|
||||
.parse::<BigInt>()
|
||||
.unwrap(),
|
||||
(FieldPrime::from("68135") - &FieldPrime::from("65416358")).value
|
||||
FieldPrime::from(
|
||||
"21888242871839275222246405745257275088548364400416034343698204186575743147394"
|
||||
),
|
||||
FieldPrime::from("68135") - &FieldPrime::from("65416358")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiplication() {
|
||||
assert_eq!(
|
||||
"13472".parse::<BigInt>().unwrap(),
|
||||
(FieldPrime::from("32") * FieldPrime::from("421")).value
|
||||
FieldPrime::from("13472"),
|
||||
FieldPrime::from("32") * FieldPrime::from("421")
|
||||
);
|
||||
assert_eq!(
|
||||
"13472".parse::<BigInt>().unwrap(),
|
||||
(FieldPrime::from("32") * &FieldPrime::from("421")).value
|
||||
FieldPrime::from("13472"),
|
||||
FieldPrime::from("32") * &FieldPrime::from("421")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiplication_negative() {
|
||||
assert_eq!(
|
||||
"21888242871839275222246405745257275088548364400416034343698204186575808014369"
|
||||
.parse::<BigInt>()
|
||||
.unwrap(),
|
||||
(FieldPrime::from("54") * FieldPrime::from("-8912")).value
|
||||
FieldPrime::from(
|
||||
"21888242871839275222246405745257275088548364400416034343698204186575808014369"
|
||||
),
|
||||
FieldPrime::from("54") * FieldPrime::from(-8912)
|
||||
);
|
||||
assert_eq!(
|
||||
"21888242871839275222246405745257275088548364400416034343698204186575808014369"
|
||||
.parse::<BigInt>()
|
||||
.unwrap(),
|
||||
(FieldPrime::from("54") * &FieldPrime::from("-8912")).value
|
||||
FieldPrime::from(
|
||||
"21888242871839275222246405745257275088548364400416034343698204186575808014369"
|
||||
),
|
||||
FieldPrime::from("54") * &FieldPrime::from(-8912)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiplication_two_negative() {
|
||||
assert_eq!(
|
||||
"648".parse::<BigInt>().unwrap(),
|
||||
(FieldPrime::from("-54") * FieldPrime::from("-12")).value
|
||||
FieldPrime::from("648"),
|
||||
FieldPrime::from(-54) * FieldPrime::from(-12)
|
||||
);
|
||||
assert_eq!(
|
||||
"648".parse::<BigInt>().unwrap(),
|
||||
(FieldPrime::from("-54") * &FieldPrime::from("-12")).value
|
||||
FieldPrime::from("648"),
|
||||
FieldPrime::from(-54) * &FieldPrime::from(-12)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiplication_overflow() {
|
||||
assert_eq!(
|
||||
"6042471409729479866150380306128222617399890671095126975526159292198160466142"
|
||||
.parse::<BigInt>()
|
||||
.unwrap(),
|
||||
(FieldPrime::from(
|
||||
FieldPrime::from(
|
||||
"6042471409729479866150380306128222617399890671095126975526159292198160466142"
|
||||
),
|
||||
FieldPrime::from(
|
||||
"21888242871839225222246405785257275088694311157297823662689037894645225727"
|
||||
) * FieldPrime::from("218882428715392752222464057432572755886923"))
|
||||
.value
|
||||
) * FieldPrime::from("218882428715392752222464057432572755886923")
|
||||
);
|
||||
assert_eq!(
|
||||
"6042471409729479866150380306128222617399890671095126975526159292198160466142"
|
||||
.parse::<BigInt>()
|
||||
.unwrap(),
|
||||
(FieldPrime::from(
|
||||
FieldPrime::from(
|
||||
"6042471409729479866150380306128222617399890671095126975526159292198160466142"
|
||||
),
|
||||
FieldPrime::from(
|
||||
"21888242871839225222246405785257275088694311157297823662689037894645225727"
|
||||
) * &FieldPrime::from("218882428715392752222464057432572755886923"))
|
||||
.value
|
||||
) * &FieldPrime::from("218882428715392752222464057432572755886923")
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -203,6 +186,36 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn required_bits() {
|
||||
assert_eq!(FieldPrime::get_required_bits(), 254);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bits() {
|
||||
assert_eq!(FieldPrime::from(0).bits(), 1);
|
||||
assert_eq!(FieldPrime::from(1).bits(), 1);
|
||||
assert_eq!(FieldPrime::from(2).bits(), 2);
|
||||
assert_eq!(FieldPrime::from(3).bits(), 2);
|
||||
assert_eq!(FieldPrime::from(4).bits(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_biguint() {
|
||||
assert_eq!(
|
||||
FieldPrime::try_from(FieldPrime::from(2).to_biguint()),
|
||||
Ok(FieldPrime::from(2))
|
||||
);
|
||||
assert_eq!(
|
||||
FieldPrime::try_from(FieldPrime::from(0).to_biguint()),
|
||||
Ok(FieldPrime::from(0))
|
||||
);
|
||||
assert_eq!(
|
||||
FieldPrime::try_from(FieldPrime::max_value().to_biguint()),
|
||||
Ok(FieldPrime::max_value())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn division_negative() {
|
||||
let res = FieldPrime::from(-54) / FieldPrime::from(12);
|
||||
|
@ -218,8 +231,8 @@ mod tests {
|
|||
#[test]
|
||||
fn pow_usize() {
|
||||
assert_eq!(
|
||||
"614787626176508399616".parse::<BigInt>().unwrap(),
|
||||
(FieldPrime::from("54").pow(12)).value
|
||||
FieldPrime::from("614787626176508399616"),
|
||||
FieldPrime::from("54").pow(12)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -275,72 +288,6 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bigint_assertions() {
|
||||
let x = BigInt::parse_bytes(b"65", 10).unwrap();
|
||||
assert_eq!(&x + &x, BigInt::parse_bytes(b"130", 10).unwrap());
|
||||
assert_eq!(
|
||||
"1".parse::<BigInt>().unwrap(),
|
||||
"3".parse::<BigInt>()
|
||||
.unwrap()
|
||||
.div_floor(&"2".parse::<BigInt>().unwrap())
|
||||
);
|
||||
assert_eq!(
|
||||
"-2".parse::<BigInt>().unwrap(),
|
||||
"-3".parse::<BigInt>()
|
||||
.unwrap()
|
||||
.div_floor(&"2".parse::<BigInt>().unwrap())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extended_euclid() {
|
||||
assert_eq!(
|
||||
(
|
||||
ToBigInt::to_bigint(&1).unwrap(),
|
||||
ToBigInt::to_bigint(&-9).unwrap(),
|
||||
ToBigInt::to_bigint(&47).unwrap()
|
||||
),
|
||||
extended_euclid(
|
||||
&ToBigInt::to_bigint(&120).unwrap(),
|
||||
&ToBigInt::to_bigint(&23).unwrap()
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
(
|
||||
ToBigInt::to_bigint(&2).unwrap(),
|
||||
ToBigInt::to_bigint(&2).unwrap(),
|
||||
ToBigInt::to_bigint(&-11).unwrap()
|
||||
),
|
||||
extended_euclid(
|
||||
&ToBigInt::to_bigint(&122).unwrap(),
|
||||
&ToBigInt::to_bigint(&22).unwrap()
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
(
|
||||
ToBigInt::to_bigint(&2).unwrap(),
|
||||
ToBigInt::to_bigint(&-9).unwrap(),
|
||||
ToBigInt::to_bigint(&47).unwrap()
|
||||
),
|
||||
extended_euclid(
|
||||
&ToBigInt::to_bigint(&240).unwrap(),
|
||||
&ToBigInt::to_bigint(&46).unwrap()
|
||||
)
|
||||
);
|
||||
let (b, s, _) = extended_euclid(&ToBigInt::to_bigint(&253).unwrap(), &*P);
|
||||
assert_eq!(b, BigInt::one());
|
||||
let s_field = FieldPrime {
|
||||
value: &s - s.div_floor(&*P) * &*P,
|
||||
};
|
||||
assert_eq!(
|
||||
FieldPrime::from(
|
||||
"12717674712096337777352654721552646000065650461901806515903699665717959876900"
|
||||
),
|
||||
s_field
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "bellman")]
|
||||
mod bellman {
|
||||
use super::*;
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
prime_field!(
|
||||
b"258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177",
|
||||
"bw6_761"
|
||||
);
|
||||
|
||||
#[cfg(feature = "ark")]
|
||||
use ark_bw6_761::BW6_761;
|
||||
#[cfg(feature = "ark")]
|
||||
|
||||
prime_field!("bw6_761", BW6_761);
|
||||
|
||||
ark_extensions!(BW6_761);
|
||||
|
|
|
@ -6,9 +6,6 @@
|
|||
|
||||
extern crate num_bigint;
|
||||
|
||||
#[cfg(feature = "ark")]
|
||||
use ark_ec::PairingEngine;
|
||||
|
||||
#[cfg(feature = "bellman")]
|
||||
use bellman_ce::pairing::{ff::ScalarEngine, Engine};
|
||||
|
||||
|
@ -36,10 +33,9 @@ pub trait BellmanFieldExtensions {
|
|||
fn new_fq2(c0: &str, c1: &str) -> <Self::BellmanEngine as Engine>::Fqe;
|
||||
}
|
||||
|
||||
#[cfg(feature = "ark")]
|
||||
pub trait ArkFieldExtensions {
|
||||
/// An associated type to be able to operate with ark ff traits
|
||||
type ArkEngine: PairingEngine;
|
||||
type ArkEngine: ark_ec::PairingEngine;
|
||||
|
||||
fn from_ark(e: <Self::ArkEngine as ark_ec::PairingEngine>::Fr) -> Self;
|
||||
fn into_ark(self) -> <Self::ArkEngine as ark_ec::PairingEngine>::Fr;
|
||||
|
@ -55,8 +51,8 @@ impl fmt::Debug for FieldParseError {
|
|||
|
||||
pub trait Field:
|
||||
'static
|
||||
+ From<bool>
|
||||
+ From<i32>
|
||||
+ From<u8>
|
||||
+ From<u32>
|
||||
+ From<usize>
|
||||
+ From<u128>
|
||||
|
@ -104,7 +100,7 @@ pub trait Field:
|
|||
/// m` has a single `n`-bit decomposition
|
||||
fn max_unique_value() -> Self;
|
||||
/// Return the number of bits required to represent this element
|
||||
fn to_bits_be(&self) -> Vec<u8>;
|
||||
fn to_bits_be(&self) -> Vec<bool>;
|
||||
/// Returns the number of bits required to represent any element of this field type.
|
||||
fn get_required_bits() -> usize;
|
||||
/// Tries to parse a string into this representation
|
||||
|
@ -119,37 +115,6 @@ pub trait Field:
|
|||
fn name() -> &'static str;
|
||||
/// Gets the number of bits
|
||||
fn bits(&self) -> u32;
|
||||
/// Returns this `Field`'s largest value as a big-endian bit vector
|
||||
/// Always returns `Self::get_required_bits()` elements
|
||||
fn bit_vector_be(&self) -> Vec<bool> {
|
||||
fn bytes_to_bits(bytes: &[u8]) -> Vec<bool> {
|
||||
bytes
|
||||
.iter()
|
||||
.flat_map(|&v| (0..8).rev().map(move |i| (v >> i) & 1 == 1))
|
||||
.collect()
|
||||
}
|
||||
|
||||
let field_bytes_le = self.to_byte_vector();
|
||||
|
||||
// reverse for big-endianess
|
||||
let field_bytes_be = field_bytes_le.into_iter().rev().collect::<Vec<u8>>();
|
||||
let field_bits_be = bytes_to_bits(&field_bytes_be);
|
||||
|
||||
let field_bits_be: Vec<_> = (0..Self::get_required_bits()
|
||||
.saturating_sub(field_bits_be.len()))
|
||||
.map(|_| &false)
|
||||
.chain(
|
||||
&field_bits_be[field_bits_be
|
||||
.len()
|
||||
.saturating_sub(Self::get_required_bits())..],
|
||||
)
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
assert_eq!(field_bits_be.len(), Self::get_required_bits());
|
||||
|
||||
field_bits_be
|
||||
}
|
||||
/// Returns the value as a BigUint
|
||||
fn to_biguint(&self) -> BigUint;
|
||||
}
|
||||
|
@ -157,114 +122,119 @@ pub trait Field:
|
|||
#[macro_use]
|
||||
mod prime_field {
|
||||
macro_rules! prime_field {
|
||||
($modulus:expr, $name:expr) => {
|
||||
($name:expr, $v:ty) => {
|
||||
use crate::{Field, FieldParseError, Pow};
|
||||
use lazy_static::lazy_static;
|
||||
use num_bigint::{BigInt, BigUint, Sign, ToBigInt};
|
||||
use num_integer::Integer;
|
||||
use ark_ff::{Field as ArkField, PrimeField};
|
||||
use num_bigint::BigUint;
|
||||
use num_traits::{CheckedDiv, One, Zero};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use serde::de::{self, Visitor};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::convert::From;
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt;
|
||||
use std::fmt::{Debug, Display};
|
||||
use std::ops::{Add, Div, Mul, Sub};
|
||||
|
||||
lazy_static! {
|
||||
static ref P: BigInt = BigInt::parse_bytes($modulus, 10).unwrap();
|
||||
}
|
||||
type Fr = <$v as ark_ec::PairingEngine>::Fr;
|
||||
|
||||
#[derive(PartialEq, PartialOrd, Clone, Eq, Ord, Hash, Serialize, Deserialize)]
|
||||
#[derive(PartialEq, PartialOrd, Clone, Eq, Ord, Hash)]
|
||||
pub struct FieldPrime {
|
||||
value: BigInt,
|
||||
v: Fr,
|
||||
}
|
||||
|
||||
impl Field for FieldPrime {
|
||||
fn bits(&self) -> u32 {
|
||||
self.value.bits() as u32
|
||||
use ark_ff::BigInteger;
|
||||
let bits = self.v.into_repr().to_bits_be();
|
||||
let mut size = bits.len();
|
||||
for bit in bits {
|
||||
if !bit {
|
||||
size -= 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::cmp::max(size as u32, 1)
|
||||
}
|
||||
|
||||
fn to_biguint(&self) -> BigUint {
|
||||
self.value.to_biguint().unwrap()
|
||||
use ark_ff::BigInteger;
|
||||
BigUint::from_bytes_le(&self.v.into_repr().to_bytes_le())
|
||||
}
|
||||
|
||||
fn to_bits_be(&self) -> Vec<u8> {
|
||||
self.value.to_radix_be(2).1
|
||||
fn to_bits_be(&self) -> Vec<bool> {
|
||||
use ark_ff::BigInteger;
|
||||
let res = self.v.into_repr().to_bits_be();
|
||||
res[res.len() - Self::get_required_bits()..].to_vec()
|
||||
}
|
||||
|
||||
fn to_byte_vector(&self) -> Vec<u8> {
|
||||
match self.value.to_biguint() {
|
||||
Option::Some(val) => val.to_bytes_le(),
|
||||
Option::None => panic!("Should never happen."),
|
||||
}
|
||||
use ark_ff::BigInteger;
|
||||
self.v.into_repr().to_bytes_le()
|
||||
}
|
||||
|
||||
fn from_byte_vector(bytes: Vec<u8>) -> Self {
|
||||
let uval = BigUint::from_bytes_le(bytes.as_slice());
|
||||
use ark_ff::FromBytes;
|
||||
|
||||
FieldPrime {
|
||||
value: BigInt::from_biguint(Sign::Plus, uval),
|
||||
v: Fr::from(<Fr as PrimeField>::BigInt::read(&bytes[..]).unwrap()),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_dec_string(&self) -> String {
|
||||
self.value.to_str_radix(10)
|
||||
self.to_string()
|
||||
}
|
||||
|
||||
fn inverse_mul(&self) -> Option<FieldPrime> {
|
||||
let (b, s, _) = extended_euclid(&self.value, &*P);
|
||||
if b == BigInt::one() {
|
||||
Some(FieldPrime {
|
||||
value: &s - s.div_floor(&*P) * &*P,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
fn inverse_mul(&self) -> Option<Self> {
|
||||
use ark_ff::Field;
|
||||
Some(FieldPrime {
|
||||
v: self.v.inverse()?,
|
||||
})
|
||||
}
|
||||
|
||||
fn min_value() -> FieldPrime {
|
||||
FieldPrime {
|
||||
value: ToBigInt::to_bigint(&0).unwrap(),
|
||||
}
|
||||
FieldPrime { v: Fr::zero() }
|
||||
}
|
||||
fn max_value() -> FieldPrime {
|
||||
FieldPrime {
|
||||
value: &*P - ToBigInt::to_bigint(&1).unwrap(),
|
||||
}
|
||||
FieldPrime { v: -Fr::one() }
|
||||
}
|
||||
fn max_unique_value() -> FieldPrime {
|
||||
use num_traits::Pow;
|
||||
|
||||
FieldPrime {
|
||||
value: BigInt::from(2u32).pow(Self::get_required_bits() - 1) - 1,
|
||||
v: Fr::from(2u32).pow([Self::get_required_bits() as u64 - 1]) - Fr::one(),
|
||||
}
|
||||
}
|
||||
fn get_required_bits() -> usize {
|
||||
(*P).bits()
|
||||
use ark_ff::FpParameters;
|
||||
<Fr as PrimeField>::Params::MODULUS_BITS as usize
|
||||
}
|
||||
fn try_from_dec_str(s: &str) -> Result<Self, FieldParseError> {
|
||||
Self::try_from_str(s, 10)
|
||||
}
|
||||
fn try_from_str(s: &str, radix: u32) -> Result<Self, FieldParseError> {
|
||||
let x = BigInt::parse_bytes(s.as_bytes(), radix).ok_or(FieldParseError)?;
|
||||
use std::str::FromStr;
|
||||
|
||||
Ok(FieldPrime {
|
||||
value: &x - x.div_floor(&*P) * &*P,
|
||||
v: Fr::from_str(s).map_err(|_| FieldParseError)?,
|
||||
})
|
||||
}
|
||||
fn try_from_str(s: &str, radix: u32) -> Result<Self, FieldParseError> {
|
||||
let x = BigUint::parse_bytes(s.as_bytes(), radix).ok_or(FieldParseError)?;
|
||||
FieldPrime::try_from(x).map_err(|_| FieldParseError)
|
||||
}
|
||||
fn to_compact_dec_string(&self) -> String {
|
||||
// values up to (p-1)/2 included are represented as positive, values between (p+1)/2 and p-1 as represented as negative by subtracting p
|
||||
if self.value <= FieldPrime::max_value().value / 2 {
|
||||
format!("{}", self.value.to_str_radix(10))
|
||||
//values up to (p-1)/2 included are represented as positive, values between (p+1)/2 and p-1 as represented as negative by subtracting p
|
||||
if self.v.into_repr() <= Fr::modulus_minus_one_div_two() {
|
||||
format!("{}", self.to_string())
|
||||
} else {
|
||||
format!(
|
||||
"({})",
|
||||
(&self.value - (FieldPrime::max_value().value + BigInt::one()))
|
||||
.to_str_radix(10)
|
||||
"(-{})",
|
||||
(FieldPrime::max_value() - self + FieldPrime::one()).to_string()
|
||||
)
|
||||
}
|
||||
}
|
||||
fn id() -> [u8; 4] {
|
||||
let mut res = [0u8; 4];
|
||||
use ark_ff::BigInteger;
|
||||
use ark_ff::FpParameters;
|
||||
use sha2::{Digest, Sha256};
|
||||
let hash = Sha256::digest(&P.to_bytes_le().1);
|
||||
let hash = Sha256::digest(&<Fr as PrimeField>::Params::MODULUS.to_bytes_le());
|
||||
for i in 0..4 {
|
||||
res[i] = hash[i];
|
||||
}
|
||||
|
@ -278,66 +248,61 @@ mod prime_field {
|
|||
|
||||
impl Default for FieldPrime {
|
||||
fn default() -> Self {
|
||||
FieldPrime {
|
||||
value: BigInt::default(),
|
||||
}
|
||||
FieldPrime { v: Fr::zero() }
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for FieldPrime {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.value.to_str_radix(10))
|
||||
write!(f, "{}", self.to_biguint())
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for FieldPrime {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.value.to_str_radix(10))
|
||||
write!(f, "{}", self.to_biguint())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i32> for FieldPrime {
|
||||
fn from(num: i32) -> Self {
|
||||
let x = ToBigInt::to_bigint(&num).unwrap();
|
||||
FieldPrime {
|
||||
value: &x - x.div_floor(&*P) * &*P,
|
||||
if num < 0 {
|
||||
FieldPrime {
|
||||
v: -Fr::from((-num) as u32),
|
||||
}
|
||||
} else {
|
||||
FieldPrime {
|
||||
v: Fr::from(num as u32),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u8> for FieldPrime {
|
||||
fn from(num: u8) -> Self {
|
||||
let x = ToBigInt::to_bigint(&num).unwrap();
|
||||
impl From<bool> for FieldPrime {
|
||||
fn from(num: bool) -> Self {
|
||||
FieldPrime {
|
||||
value: &x - x.div_floor(&*P) * &*P,
|
||||
v: Fr::from(num as u32),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for FieldPrime {
|
||||
fn from(num: u32) -> Self {
|
||||
let x = ToBigInt::to_bigint(&num).unwrap();
|
||||
FieldPrime {
|
||||
value: &x - x.div_floor(&*P) * &*P,
|
||||
}
|
||||
FieldPrime { v: Fr::from(num) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for FieldPrime {
|
||||
fn from(num: usize) -> Self {
|
||||
let x = ToBigInt::to_bigint(&num).unwrap();
|
||||
FieldPrime {
|
||||
value: &x - x.div_floor(&*P) * &*P,
|
||||
v: Fr::from(num as u128),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u128> for FieldPrime {
|
||||
fn from(num: u128) -> Self {
|
||||
let x = ToBigInt::to_bigint(&num).unwrap();
|
||||
FieldPrime {
|
||||
value: &x - x.div_floor(&*P) * &*P,
|
||||
}
|
||||
FieldPrime { v: Fr::from(num) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -347,8 +312,10 @@ mod prime_field {
|
|||
fn try_from(value: BigUint) -> Result<Self, ()> {
|
||||
match value <= Self::max_value().to_biguint() {
|
||||
true => {
|
||||
let x = ToBigInt::to_bigint(&value).unwrap();
|
||||
Ok(FieldPrime { value: x })
|
||||
use std::str::FromStr;
|
||||
Ok(FieldPrime {
|
||||
v: Fr::from_str(&value.to_string()).unwrap(),
|
||||
})
|
||||
}
|
||||
false => Err(()),
|
||||
}
|
||||
|
@ -357,20 +324,16 @@ mod prime_field {
|
|||
|
||||
impl Zero for FieldPrime {
|
||||
fn zero() -> FieldPrime {
|
||||
FieldPrime {
|
||||
value: ToBigInt::to_bigint(&0).unwrap(),
|
||||
}
|
||||
FieldPrime { v: Fr::zero() }
|
||||
}
|
||||
fn is_zero(&self) -> bool {
|
||||
self.value == ToBigInt::to_bigint(&0).unwrap()
|
||||
self.v.is_zero()
|
||||
}
|
||||
}
|
||||
|
||||
impl One for FieldPrime {
|
||||
fn one() -> FieldPrime {
|
||||
FieldPrime {
|
||||
value: ToBigInt::to_bigint(&1).unwrap(),
|
||||
}
|
||||
FieldPrime { v: Fr::one() }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -378,16 +341,8 @@ mod prime_field {
|
|||
type Output = FieldPrime;
|
||||
|
||||
fn add(self, other: FieldPrime) -> FieldPrime {
|
||||
if self.value == BigInt::zero() {
|
||||
return other;
|
||||
}
|
||||
|
||||
if other.value == BigInt::zero() {
|
||||
return self;
|
||||
}
|
||||
|
||||
FieldPrime {
|
||||
value: (self.value + other.value) % &*P,
|
||||
v: self.v + other.v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -396,16 +351,8 @@ mod prime_field {
|
|||
type Output = FieldPrime;
|
||||
|
||||
fn add(self, other: &FieldPrime) -> FieldPrime {
|
||||
if self.value == BigInt::zero() {
|
||||
return other.clone();
|
||||
}
|
||||
|
||||
if other.value == BigInt::zero() {
|
||||
return self;
|
||||
}
|
||||
|
||||
FieldPrime {
|
||||
value: (self.value + &other.value) % &*P,
|
||||
v: self.v + other.v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -414,9 +361,8 @@ mod prime_field {
|
|||
type Output = FieldPrime;
|
||||
|
||||
fn sub(self, other: FieldPrime) -> FieldPrime {
|
||||
let x = self.value - other.value;
|
||||
FieldPrime {
|
||||
value: &x - x.div_floor(&*P) * &*P,
|
||||
v: self.v - other.v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -425,9 +371,8 @@ mod prime_field {
|
|||
type Output = FieldPrime;
|
||||
|
||||
fn sub(self, other: &FieldPrime) -> FieldPrime {
|
||||
let x = self.value - &other.value;
|
||||
FieldPrime {
|
||||
value: &x - x.div_floor(&*P) * &*P,
|
||||
v: self.v - other.v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -436,16 +381,8 @@ mod prime_field {
|
|||
type Output = FieldPrime;
|
||||
|
||||
fn mul(self, other: FieldPrime) -> FieldPrime {
|
||||
if self.value == BigInt::one() {
|
||||
return other;
|
||||
}
|
||||
|
||||
if other.value == BigInt::one() {
|
||||
return self;
|
||||
}
|
||||
|
||||
FieldPrime {
|
||||
value: (self.value * other.value) % &*P,
|
||||
v: self.v * other.v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -454,23 +391,21 @@ mod prime_field {
|
|||
type Output = FieldPrime;
|
||||
|
||||
fn mul(self, other: &FieldPrime) -> FieldPrime {
|
||||
if self.value == BigInt::one() {
|
||||
return other.clone();
|
||||
}
|
||||
|
||||
if other.value == BigInt::one() {
|
||||
return self;
|
||||
}
|
||||
|
||||
FieldPrime {
|
||||
value: (self.value * &other.value) % &*P,
|
||||
v: self.v * other.v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckedDiv for FieldPrime {
|
||||
fn checked_div(&self, other: &FieldPrime) -> Option<FieldPrime> {
|
||||
other.inverse_mul().map(|inv| inv * self)
|
||||
if other.v == Fr::zero() {
|
||||
None
|
||||
} else {
|
||||
Some(FieldPrime {
|
||||
v: self.v / other.v,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -494,11 +429,9 @@ mod prime_field {
|
|||
type Output = FieldPrime;
|
||||
|
||||
fn pow(self, exp: usize) -> FieldPrime {
|
||||
let mut res = FieldPrime::from(1);
|
||||
for _ in 0..exp {
|
||||
res = res * &self;
|
||||
FieldPrime {
|
||||
v: self.v.pow(&[exp as u64]),
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -509,12 +442,16 @@ mod prime_field {
|
|||
assert!(self <= &bound);
|
||||
assert!(other <= &bound);
|
||||
|
||||
let big_res = &self.value + &other.value;
|
||||
let left = self.to_biguint();
|
||||
let right = other.to_biguint();
|
||||
|
||||
if big_res > bound.value {
|
||||
let big_res = left + right;
|
||||
|
||||
// we only go up to 2**(bitwidth - 1) because after that we lose uniqueness of bit decomposition
|
||||
if big_res > bound.to_biguint() {
|
||||
None
|
||||
} else {
|
||||
Some(FieldPrime { value: big_res })
|
||||
Some(self.clone() + other)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -526,40 +463,84 @@ mod prime_field {
|
|||
assert!(self <= &bound);
|
||||
assert!(other <= &bound);
|
||||
|
||||
let big_res = &self.value * &other.value;
|
||||
let left = self.to_biguint();
|
||||
let right = other.to_biguint();
|
||||
|
||||
let big_res = left * right;
|
||||
|
||||
// we only go up to 2**(bitwidth - 1) because after that we lose uniqueness of bit decomposition
|
||||
if big_res > bound.value {
|
||||
if big_res > bound.to_biguint() {
|
||||
None
|
||||
} else {
|
||||
Some(FieldPrime { value: big_res })
|
||||
Some(self.clone() * other)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculates the gcd using an iterative implementation of the extended euclidian algorithm.
|
||||
/// Returning `(d, s, t)` so that `d = s * a + t * b`
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `a` - First number as `BigInt`
|
||||
/// * `b` - Second number as `BigInt`
|
||||
fn extended_euclid(a: &BigInt, b: &BigInt) -> (BigInt, BigInt, BigInt) {
|
||||
let (mut s, mut old_s) = (BigInt::zero(), BigInt::one());
|
||||
let (mut t, mut old_t) = (BigInt::one(), BigInt::zero());
|
||||
let (mut r, mut old_r) = (b.clone(), a.clone());
|
||||
while !&r.is_zero() {
|
||||
let quotient = &old_r / &r;
|
||||
let tmp_r = old_r.clone();
|
||||
old_r = r.clone();
|
||||
r = &tmp_r - "ient * &r;
|
||||
let tmp_s = old_s.clone();
|
||||
old_s = s.clone();
|
||||
s = &tmp_s - "ient * &s;
|
||||
let tmp_t = old_t.clone();
|
||||
old_t = t.clone();
|
||||
t = &tmp_t - "ient * &t;
|
||||
impl Serialize for FieldPrime {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
use ark_serialize::CanonicalSerialize;
|
||||
use serde::ser::Error;
|
||||
let mut data: Vec<u8> = vec![];
|
||||
self.v
|
||||
.serialize(&mut data)
|
||||
.map_err(|e| S::Error::custom(e.to_string()))?;
|
||||
serializer.serialize_bytes(&data)
|
||||
}
|
||||
}
|
||||
|
||||
struct FieldVisitor;
|
||||
|
||||
use serde::de::SeqAccess;
|
||||
|
||||
impl<'de> Visitor<'de> for FieldVisitor {
|
||||
type Value = FieldPrime;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("an ark field element")
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
use ark_serialize::CanonicalDeserialize;
|
||||
let value: Fr = Fr::deserialize(value).map_err(|e| E::custom(e.to_string()))?;
|
||||
|
||||
Ok(FieldPrime { v: value })
|
||||
}
|
||||
|
||||
fn visit_byte_buf<E>(self, value: Vec<u8>) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
self.visit_bytes(&value[..])
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, value: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
let mut value = value;
|
||||
let mut elements = vec![];
|
||||
while let Some(v) = value.next_element()? {
|
||||
elements.push(v);
|
||||
}
|
||||
|
||||
self.visit_bytes(&elements[..])
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for FieldPrime {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_bytes(FieldVisitor)
|
||||
}
|
||||
return (old_r, old_s, old_t);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -599,7 +580,6 @@ mod prime_field {
|
|||
};
|
||||
}
|
||||
|
||||
#[cfg(feature = "ark")]
|
||||
macro_rules! ark_extensions {
|
||||
($ark_type:ty) => {
|
||||
use crate::ArkFieldExtensions;
|
||||
|
@ -608,16 +588,11 @@ mod prime_field {
|
|||
type ArkEngine = $ark_type;
|
||||
|
||||
fn from_ark(e: <Self::ArkEngine as ark_ec::PairingEngine>::Fr) -> Self {
|
||||
use ark_ff::{BigInteger, PrimeField};
|
||||
let mut res: Vec<u8> = vec![];
|
||||
e.into_repr().write_le(&mut res).unwrap();
|
||||
Self::from_byte_vector(res)
|
||||
Self { v: e }
|
||||
}
|
||||
|
||||
fn into_ark(self) -> <Self::ArkEngine as ark_ec::PairingEngine>::Fr {
|
||||
use core::str::FromStr;
|
||||
let s = self.to_dec_string();
|
||||
<Self::ArkEngine as ark_ec::PairingEngine>::Fr::from_str(&s).unwrap()
|
||||
self.v
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
29
zokrates_js/Cargo.lock
generated
29
zokrates_js/Cargo.lock
generated
|
@ -49,6 +49,28 @@ dependencies = [
|
|||
"ark-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ark-bls12-381"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70e1c2ad76c4f725520440b981df3ce2d635f2baa1122750c757c0cf0f3d4b74"
|
||||
dependencies = [
|
||||
"ark-ec",
|
||||
"ark-ff",
|
||||
"ark-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ark-bn254"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ead066869de5e8cb2938123204d1572f09496b629e146a6f80fa8ec508446ba"
|
||||
dependencies = [
|
||||
"ark-ec",
|
||||
"ark-ff",
|
||||
"ark-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ark-bw6-761"
|
||||
version = "0.2.0"
|
||||
|
@ -1627,6 +1649,13 @@ dependencies = [
|
|||
name = "zokrates_field"
|
||||
version = "0.4.0"
|
||||
dependencies = [
|
||||
"ark-bls12-377",
|
||||
"ark-bls12-381",
|
||||
"ark-bn254",
|
||||
"ark-bw6-761",
|
||||
"ark-ec",
|
||||
"ark-ff",
|
||||
"ark-serialize",
|
||||
"bellman_ce",
|
||||
"bincode",
|
||||
"lazy_static",
|
||||
|
|
|
@ -15,6 +15,6 @@ wasm-bindgen = { version = "0.2.46", features = ["serde-serialize"] }
|
|||
typed-arena = "1.4.1"
|
||||
zokrates_core = { path = "../zokrates_core", features = ["wasm", "bellman"], default-features = false }
|
||||
zokrates_common = { path = "../zokrates_common" }
|
||||
zokrates_field = { path = "../zokrates_field", default-features = false, features = ["bellman"] }
|
||||
zokrates_field = { path = "../zokrates_field", features = ["bellman"] }
|
||||
zokrates_abi = { path = "../zokrates_abi" }
|
||||
console_error_panic_hook = "0.1.6"
|
|
@ -702,6 +702,7 @@ mod ast {
|
|||
Member(MemberAccess<'ast>),
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Debug, FromPest, PartialEq, Clone)]
|
||||
#[pest_ast(rule(Rule::assignee_access))]
|
||||
pub enum AssigneeAccess<'ast> {
|
||||
|
|
|
@ -24,18 +24,6 @@
|
|||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["21888242871839275222246405745257275088548364400416034343698204186575808495617", "0", "0"]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": [
|
||||
"14543742788565021628577424853847564376151732847602780516906950225481254681152", "21165881269406212375659499083070944693027168220143204011932538650149052385959"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -28,9 +28,9 @@ fn write_test<W: Write>(test_file: &mut W, test_path: &Path, base_path: &Path) {
|
|||
.unwrap()
|
||||
.display()
|
||||
.to_string()
|
||||
.replace("/", "_")
|
||||
.replace('/', "_")
|
||||
.replace(".json", "")
|
||||
.replace(".", "")
|
||||
.replace('.', "")
|
||||
);
|
||||
|
||||
write!(
|
||||
|
|
Loading…
Reference in a new issue