diff --git a/Cargo.lock b/Cargo.lock index 15fa04711e..4f6573fa56 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -580,6 +580,7 @@ dependencies = [ "bincode", "hex", "leo-ast", + "leo-gadgets", "leo-inputs", "leo-types", "log", diff --git a/compiler/Cargo.toml b/compiler/Cargo.toml index dbcdf01c2e..8b437a297b 100644 --- a/compiler/Cargo.toml +++ b/compiler/Cargo.toml @@ -6,8 +6,9 @@ edition = "2018" [dependencies] leo-ast = { path = "../ast", version = "0.1.0" } -leo-types = { path = "../types", version = "0.1.0" } +leo-gadgets = { path = "../gadgets", version = "0.1.0" } leo-inputs = { path = "../leo-inputs", version = "0.1.0" } +leo-types = { path = "../types", version = "0.1.0" } snarkos-curves = { git = "ssh://git@github.com/AleoHQ/snarkOS.git", rev = "c7a56d9", default-features = false } snarkos-dpc = { git = "ssh://git@github.com/AleoHQ/snarkOS.git", rev = "c7a56d9", default-features = false } diff --git a/compiler/src/expression/relational/ge.rs b/compiler/src/expression/relational/ge.rs index f2628a932b..97fd6dbc1c 100644 --- a/compiler/src/expression/relational/ge.rs +++ b/compiler/src/expression/relational/ge.rs @@ -1,6 +1,7 @@ //! Enforces a relational `>=` operator in a resolved Leo program. -use crate::{comparator::ComparatorGadget, errors::ExpressionError, value::ConstrainedValue, GroupType}; +use crate::{errors::ExpressionError, value::ConstrainedValue, GroupType}; +use leo_gadgets::binary::ComparatorGadget; use leo_types::Span; use snarkos_models::{ diff --git a/compiler/src/expression/relational/gt.rs b/compiler/src/expression/relational/gt.rs index 283005f1cf..198b04716a 100644 --- a/compiler/src/expression/relational/gt.rs +++ b/compiler/src/expression/relational/gt.rs @@ -1,6 +1,7 @@ //! Enforces a relational `>` operator in a resolved Leo program. -use crate::{comparator::ComparatorGadget, errors::ExpressionError, value::ConstrainedValue, GroupType}; +use crate::{errors::ExpressionError, value::ConstrainedValue, GroupType}; +use leo_gadgets::binary::ComparatorGadget; use leo_types::Span; use snarkos_models::{ diff --git a/compiler/src/expression/relational/le.rs b/compiler/src/expression/relational/le.rs index 945dae2794..63a98ceba2 100644 --- a/compiler/src/expression/relational/le.rs +++ b/compiler/src/expression/relational/le.rs @@ -1,6 +1,7 @@ //! Enforces a relational `<=` operator in a resolved Leo program. -use crate::{comparator::ComparatorGadget, errors::ExpressionError, value::ConstrainedValue, GroupType}; +use crate::{errors::ExpressionError, value::ConstrainedValue, GroupType}; +use leo_gadgets::binary::ComparatorGadget; use leo_types::Span; use snarkos_models::{ diff --git a/compiler/src/expression/relational/lt.rs b/compiler/src/expression/relational/lt.rs index 1b8f94a2c0..0f7f15bdce 100644 --- a/compiler/src/expression/relational/lt.rs +++ b/compiler/src/expression/relational/lt.rs @@ -1,6 +1,7 @@ //! Enforces a relational `<` operator in a resolved Leo program. -use crate::{comparator::EvaluateLtGadget, errors::ExpressionError, value::ConstrainedValue, GroupType}; +use crate::{errors::ExpressionError, value::ConstrainedValue, GroupType}; +use leo_gadgets::binary::comparator::EvaluateLtGadget; use leo_types::Span; use snarkos_models::{ diff --git a/compiler/src/value/field/field_type.rs b/compiler/src/value/field/field_type.rs index 864c414729..057e50fce4 100644 --- a/compiler/src/value/field/field_type.rs +++ b/compiler/src/value/field/field_type.rs @@ -1,9 +1,7 @@ //! A data type that represents a field value -use crate::{ - comparator::{ComparatorGadget, EvaluateLtGadget}, - errors::FieldError, -}; +use crate::errors::FieldError; +use leo_gadgets::binary::{ComparatorGadget, EvaluateLtGadget}; use leo_types::Span; use snarkos_errors::gadgets::SynthesisError; diff --git a/compiler/src/value/integer.rs b/compiler/src/value/integer.rs index c16d1991a0..306dd98113 100644 --- a/compiler/src/value/integer.rs +++ b/compiler/src/value/integer.rs @@ -1,8 +1,6 @@ //! Conversion of integer declarations to constraints in Leo. -use crate::{ - comparator::{ComparatorGadget, EvaluateLtGadget}, - errors::IntegerError, -}; +use crate::errors::IntegerError; +use leo_gadgets::binary::comparator::{ComparatorGadget, EvaluateLtGadget}; use leo_types::{InputValue, IntegerType, Span}; use snarkos_errors::gadgets::SynthesisError; diff --git a/compiler/src/value/mod.rs b/compiler/src/value/mod.rs index 095f164bff..654fa0211d 100644 --- a/compiler/src/value/mod.rs +++ b/compiler/src/value/mod.rs @@ -5,8 +5,6 @@ pub use self::address::*; pub mod boolean; -pub(crate) mod comparator; - pub mod field; pub use self::field::*; diff --git a/compiler/src/value/comparator.rs b/gadgets/src/binary/comparator.rs similarity index 100% rename from compiler/src/value/comparator.rs rename to gadgets/src/binary/comparator.rs diff --git a/gadgets/src/binary/mod.rs b/gadgets/src/binary/mod.rs index f7bb9d9086..f91c69ece9 100644 --- a/gadgets/src/binary/mod.rs +++ b/gadgets/src/binary/mod.rs @@ -2,5 +2,8 @@ pub mod adder; pub use self::adder::*; +pub mod comparator; +pub use self::comparator::*; + pub mod rca; pub use self::rca::*; diff --git a/gadgets/src/signed_integer/relational/lt.rs b/gadgets/src/signed_integer/relational/lt.rs new file mode 100644 index 0000000000..0509097c29 --- /dev/null +++ b/gadgets/src/signed_integer/relational/lt.rs @@ -0,0 +1,70 @@ +use crate::{ + binary::{ComparatorGadget, EvaluateLtGadget}, + Int128, + Int16, + Int32, + Int64, + Int8, +}; + +use snarkos_errors::gadgets::SynthesisError; +use snarkos_models::{ + curves::PrimeField, + gadgets::{r1cs::ConstraintSystem, utilities::boolean::Boolean}, +}; + +macro_rules! cmp_gadget_impl { + ($($gadget: ident)*) => ($( + impl EvaluateLtGadget for $gadget { + fn less_than>( + &self, + mut cs: CS, + other: &Self + ) -> Result { + + for (i, (a, b)) in self.bits + .iter() + .rev() + .zip(other.bits.iter().rev()) + .enumerate() + { + let is_greater = if i == 0 { + // Check sign bit + // is_greater = !a_msb & b_msb + // only true when a > b + Boolean::and(cs.ns(|| format!("not a and b [{}]", i)), &a.not(), b)? + } else { + // is_greater = a & !b + // only true when a > b + Boolean::and(cs.ns(|| format!("a and not b [{}]", i)), a, &b.not())? + }; + + let is_less = if i == 0 { + // Check sign bit + // is_less = a_msb & ! b_msb + // only true when a < b + Boolean::and(cs.ns(|| format!("a and not b [{}]", i)), a, &b.not())? + } else { + // is_less = !a & b + // only true when a < b + Boolean::and(cs.ns(|| format!("not a and b [{}]", i)), &a.not(), b)? + }; + + if is_greater.get_value().unwrap() { + return Ok(is_greater.not()); + } else if is_less.get_value().unwrap() { + return Ok(is_less); + } else if i == self.bits.len() - 1 { + return Ok(is_less); + } + } + + Err(SynthesisError::Unsatisfiable) + } + } + + impl ComparatorGadget for $gadget {} + )*) +} + +cmp_gadget_impl!(Int8 Int16 Int32 Int64 Int128); diff --git a/gadgets/src/signed_integer/relational/mod.rs b/gadgets/src/signed_integer/relational/mod.rs index 9d43347649..fab3ee2dfd 100644 --- a/gadgets/src/signed_integer/relational/mod.rs +++ b/gadgets/src/signed_integer/relational/mod.rs @@ -1,2 +1,6 @@ +#[macro_use] pub mod eq; pub use self::eq::*; + +pub mod lt; +pub use self::lt::*;