mirror of
https://github.com/AleoHQ/leo.git
synced 2024-11-11 16:10:09 +03:00
add initial address type to constraints
This commit is contained in:
parent
f1030117ee
commit
d5bdda89e7
32
compiler/src/address/address.rs
Normal file
32
compiler/src/address/address.rs
Normal file
@ -0,0 +1,32 @@
|
||||
use crate::errors::AddressError;
|
||||
use leo_types::Span;
|
||||
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
gadgets::r1cs::ConstraintSystem,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Address(pub String);
|
||||
|
||||
impl Address {
|
||||
pub(crate) fn constant(address: String, span: Span) -> Result<Self, AddressError> {
|
||||
Ok(Self(address))
|
||||
}
|
||||
|
||||
// pub(crate) fn allocate<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||
// cs: &mut CS,
|
||||
// name: String,
|
||||
// option: Option<bool>,
|
||||
// span: Span,
|
||||
// ) -> Result<Self, AddressError> {
|
||||
// let boolean_name = format!("{}: bool", name);
|
||||
// let boolean_name_unique = format!("`{}` {}:{}", boolean_name, span.line, span.start);
|
||||
//
|
||||
// Self::alloc(cs.ns(|| boolean_name_unique), || {
|
||||
// option.ok_or(SynthesisError::AssignmentMissing)
|
||||
// })
|
||||
// .map_err(|_| AddressError::missing_boolean(boolean_name, span))
|
||||
// }
|
||||
}
|
2
compiler/src/address/mod.rs
Normal file
2
compiler/src/address/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod address;
|
||||
pub use self::address::*;
|
@ -10,6 +10,7 @@ use crate::{
|
||||
ConstrainedValue,
|
||||
},
|
||||
errors::ExpressionError,
|
||||
Address,
|
||||
FieldType,
|
||||
GroupType,
|
||||
Integer,
|
||||
@ -933,13 +934,14 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
}
|
||||
|
||||
// Values
|
||||
Expression::Address(address, span) => Ok(ConstrainedValue::Address(Address::constant(address, span)?)),
|
||||
Expression::Boolean(boolean, span) => Ok(ConstrainedValue::Boolean(new_bool_constant(boolean, span)?)),
|
||||
Expression::Field(field, span) => Ok(ConstrainedValue::Field(FieldType::constant(field, span)?)),
|
||||
Expression::Group(group_affine, span) => Ok(ConstrainedValue::Group(G::constant(group_affine, span)?)),
|
||||
Expression::Implicit(value, span) => Self::enforce_number_implicit(expected_types, value, span),
|
||||
Expression::Integer(type_, integer, span) => {
|
||||
Ok(ConstrainedValue::Integer(Integer::new_constant(&type_, integer, span)?))
|
||||
}
|
||||
Expression::Field(field, span) => Ok(ConstrainedValue::Field(FieldType::constant(field, span)?)),
|
||||
Expression::Group(group_affine, span) => Ok(ConstrainedValue::Group(G::constant(group_affine, span)?)),
|
||||
Expression::Boolean(boolean, span) => Ok(ConstrainedValue::Boolean(new_bool_constant(boolean, span)?)),
|
||||
Expression::Implicit(value, span) => Self::enforce_number_implicit(expected_types, value, span),
|
||||
|
||||
// Binary operations
|
||||
Expression::Add(left, right, span) => {
|
||||
|
@ -5,6 +5,7 @@ use crate::{
|
||||
errors::{ExpressionError, FieldError, ValueError},
|
||||
is_in_scope,
|
||||
new_scope,
|
||||
Address,
|
||||
FieldType,
|
||||
GroupType,
|
||||
Integer,
|
||||
@ -26,25 +27,31 @@ pub struct ConstrainedCircuitMember<F: Field + PrimeField, G: GroupType<F>>(pub
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub enum ConstrainedValue<F: Field + PrimeField, G: GroupType<F>> {
|
||||
Integer(Integer),
|
||||
// Data types
|
||||
Address(Address),
|
||||
Boolean(Boolean),
|
||||
Field(FieldType<F>),
|
||||
Group(G),
|
||||
Boolean(Boolean),
|
||||
Integer(Integer),
|
||||
|
||||
// Arrays
|
||||
Array(Vec<ConstrainedValue<F, G>>),
|
||||
|
||||
// Circuits
|
||||
CircuitDefinition(Circuit),
|
||||
CircuitExpression(Identifier, Vec<ConstrainedCircuitMember<F, G>>),
|
||||
|
||||
// Functions
|
||||
Function(Option<Identifier>, Function), // (optional circuit identifier, function definition)
|
||||
Return(Vec<ConstrainedValue<F, G>>),
|
||||
|
||||
// Modifiers
|
||||
Mutable(Box<ConstrainedValue<F, G>>),
|
||||
Static(Box<ConstrainedValue<F, G>>),
|
||||
|
||||
Import(String, Box<ConstrainedValue<F, G>>),
|
||||
|
||||
Unresolved(String),
|
||||
|
||||
// Imports
|
||||
Import(String, Box<ConstrainedValue<F, G>>),
|
||||
}
|
||||
|
||||
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
||||
@ -56,14 +63,18 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
||||
|
||||
pub(crate) fn from_type(value: String, _type: &Type, span: Span) -> Result<Self, ValueError> {
|
||||
match _type {
|
||||
// Data types
|
||||
Type::Address => Ok(ConstrainedValue::Address(Address::constant(value, span)?)),
|
||||
Type::Boolean => Ok(ConstrainedValue::Boolean(new_bool_constant(value, span)?)),
|
||||
Type::Field => Ok(ConstrainedValue::Field(FieldType::constant(value, span)?)),
|
||||
Type::Group => Ok(ConstrainedValue::Group(G::constant(value, span)?)),
|
||||
Type::IntegerType(integer_type) => Ok(ConstrainedValue::Integer(Integer::new_constant(
|
||||
integer_type,
|
||||
value,
|
||||
span,
|
||||
)?)),
|
||||
Type::Field => Ok(ConstrainedValue::Field(FieldType::constant(value, span)?)),
|
||||
Type::Group => Ok(ConstrainedValue::Group(G::constant(value, span)?)),
|
||||
Type::Boolean => Ok(ConstrainedValue::Boolean(new_bool_constant(value, span)?)),
|
||||
|
||||
// Data type wrappers
|
||||
Type::Array(ref _type, _dimensions) => ConstrainedValue::from_type(value, _type, span),
|
||||
_ => Ok(ConstrainedValue::Unresolved(value)),
|
||||
}
|
||||
@ -71,10 +82,14 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
||||
|
||||
pub(crate) fn to_type(&self, span: Span) -> Result<Type, ValueError> {
|
||||
Ok(match self {
|
||||
ConstrainedValue::Integer(integer) => Type::IntegerType(integer.get_type()),
|
||||
// Data types
|
||||
ConstrainedValue::Address(_address) => Type::Address,
|
||||
ConstrainedValue::Boolean(_bool) => Type::Boolean,
|
||||
ConstrainedValue::Field(_field) => Type::Field,
|
||||
ConstrainedValue::Group(_group) => Type::Group,
|
||||
ConstrainedValue::Boolean(_bool) => Type::Boolean,
|
||||
ConstrainedValue::Integer(integer) => Type::IntegerType(integer.get_type()),
|
||||
|
||||
// Data type wrappers
|
||||
ConstrainedValue::Array(types) => {
|
||||
let array_type = types[0].to_type(span.clone())?;
|
||||
let count = types.len();
|
||||
@ -153,20 +168,14 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
||||
|
||||
pub(crate) fn allocate_value<CS: ConstraintSystem<F>>(&mut self, mut cs: CS, span: Span) -> Result<(), ValueError> {
|
||||
match self {
|
||||
// allocated values
|
||||
// Data types
|
||||
ConstrainedValue::Address(address) => unimplemented!("allocating addresses not impl"),
|
||||
ConstrainedValue::Boolean(boolean) => {
|
||||
let option = boolean.get_value();
|
||||
let name = option.map(|b| b.to_string()).unwrap_or(format!("[allocated]"));
|
||||
|
||||
*boolean = allocate_bool(&mut cs, name, option, span)?;
|
||||
}
|
||||
ConstrainedValue::Integer(integer) => {
|
||||
let integer_type = integer.get_type();
|
||||
let option = integer.get_value();
|
||||
let name = option.map(|n| n.to_string()).unwrap_or(format!("[allocated]"));
|
||||
|
||||
*integer = Integer::allocate_type(&mut cs, integer_type, name, option, span)?;
|
||||
}
|
||||
ConstrainedValue::Field(field) => {
|
||||
let gadget = field
|
||||
.allocated(cs.ns(|| format!("allocate field {}:{}", span.line, span.start)))
|
||||
@ -177,7 +186,15 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
||||
ConstrainedValue::Group(group) => {
|
||||
*group = group.to_allocated(cs, span)?;
|
||||
}
|
||||
// value wrappers
|
||||
ConstrainedValue::Integer(integer) => {
|
||||
let integer_type = integer.get_type();
|
||||
let option = integer.get_value();
|
||||
let name = option.map(|n| n.to_string()).unwrap_or(format!("[allocated]"));
|
||||
|
||||
*integer = Integer::allocate_type(&mut cs, integer_type, name, option, span)?;
|
||||
}
|
||||
|
||||
// Data type wrappers
|
||||
ConstrainedValue::Array(array) => {
|
||||
array
|
||||
.iter_mut()
|
||||
@ -217,11 +234,13 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
||||
ConstrainedValue::Static(value) => {
|
||||
value.allocate_value(cs, span)?;
|
||||
}
|
||||
// empty wrappers
|
||||
|
||||
// Empty wrappers that are unreachable
|
||||
ConstrainedValue::CircuitDefinition(_) => {}
|
||||
ConstrainedValue::Function(_, _) => {}
|
||||
ConstrainedValue::Import(_, _) => {}
|
||||
|
||||
// Cannot allocate an unresolved value
|
||||
ConstrainedValue::Unresolved(value) => {
|
||||
return Err(ValueError::implicit(value.to_string(), span));
|
||||
}
|
||||
@ -234,9 +253,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
||||
impl<F: Field + PrimeField, G: GroupType<F>> fmt::Display for ConstrainedValue<F, G> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
ConstrainedValue::Integer(ref value) => write!(f, "{}", value),
|
||||
ConstrainedValue::Field(ref value) => write!(f, "{:?}", value),
|
||||
ConstrainedValue::Group(ref value) => write!(f, "{:?}", value),
|
||||
// Data types
|
||||
ConstrainedValue::Address(ref value) => write!(f, "{}", value),
|
||||
ConstrainedValue::Boolean(ref value) => write!(
|
||||
f,
|
||||
"{}",
|
||||
@ -245,6 +263,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> fmt::Display for ConstrainedValue<F
|
||||
.map(|v| v.to_string())
|
||||
.unwrap_or(format!("[allocated]"))
|
||||
),
|
||||
ConstrainedValue::Field(ref value) => write!(f, "{:?}", value),
|
||||
ConstrainedValue::Group(ref value) => write!(f, "{:?}", value),
|
||||
ConstrainedValue::Integer(ref value) => write!(f, "{}", value),
|
||||
|
||||
// Data type wrappers
|
||||
ConstrainedValue::Array(ref array) => {
|
||||
write!(f, "[")?;
|
||||
for (i, e) in array.iter().enumerate() {
|
||||
@ -301,18 +324,19 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConditionalEqGadget<F> for Constrai
|
||||
condition: &Boolean,
|
||||
) -> Result<(), SynthesisError> {
|
||||
match (self, other) {
|
||||
(ConstrainedValue::Address(address_1), ConstrainedValue::Address(address_2)) => unimplemented!(),
|
||||
(ConstrainedValue::Boolean(bool_1), ConstrainedValue::Boolean(bool_2)) => {
|
||||
bool_1.conditional_enforce_equal(cs, bool_2, &condition)
|
||||
}
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
num_1.conditional_enforce_equal(cs, num_2, &condition)
|
||||
}
|
||||
(ConstrainedValue::Field(field_1), ConstrainedValue::Field(field_2)) => {
|
||||
field_1.conditional_enforce_equal(cs, field_2, &condition)
|
||||
}
|
||||
(ConstrainedValue::Group(group_1), ConstrainedValue::Group(group_2)) => {
|
||||
group_1.conditional_enforce_equal(cs, group_2, &condition)
|
||||
}
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
num_1.conditional_enforce_equal(cs, num_2, &condition)
|
||||
}
|
||||
(ConstrainedValue::Array(arr_1), ConstrainedValue::Array(arr_2)) => {
|
||||
for (i, (left, right)) in arr_1.into_iter().zip(arr_2.into_iter()).enumerate() {
|
||||
left.conditional_enforce_equal(cs.ns(|| format!("array[{}]", i)), right, &condition)?;
|
||||
@ -336,18 +360,19 @@ impl<F: Field + PrimeField, G: GroupType<F>> CondSelectGadget<F> for Constrained
|
||||
second: &Self,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
Ok(match (first, second) {
|
||||
(ConstrainedValue::Address(address_1), ConstrainedValue::Address(address_2)) => unimplemented!(),
|
||||
(ConstrainedValue::Boolean(bool_1), ConstrainedValue::Boolean(bool_2)) => {
|
||||
ConstrainedValue::Boolean(Boolean::conditionally_select(cs, cond, bool_1, bool_2)?)
|
||||
}
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
ConstrainedValue::Integer(Integer::conditionally_select(cs, cond, num_1, num_2)?)
|
||||
}
|
||||
(ConstrainedValue::Field(field_1), ConstrainedValue::Field(field_2)) => {
|
||||
ConstrainedValue::Field(FieldType::conditionally_select(cs, cond, field_1, field_2)?)
|
||||
}
|
||||
(ConstrainedValue::Group(group_1), ConstrainedValue::Group(group_2)) => {
|
||||
ConstrainedValue::Group(G::conditionally_select(cs, cond, group_1, group_2)?)
|
||||
}
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
ConstrainedValue::Integer(Integer::conditionally_select(cs, cond, num_1, num_2)?)
|
||||
}
|
||||
(ConstrainedValue::Array(arr_1), ConstrainedValue::Array(arr_2)) => {
|
||||
let mut array = vec![];
|
||||
|
||||
|
49
compiler/src/errors/constraints/address.rs
Normal file
49
compiler/src/errors/constraints/address.rs
Normal file
@ -0,0 +1,49 @@
|
||||
use leo_types::{Error as FormattedError, Span};
|
||||
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum AddressError {
|
||||
#[error("{}", _0)]
|
||||
Error(#[from] FormattedError),
|
||||
}
|
||||
|
||||
impl AddressError {
|
||||
pub fn set_path(&mut self, path: PathBuf) {
|
||||
match self {
|
||||
AddressError::Error(error) => error.set_path(path),
|
||||
}
|
||||
}
|
||||
|
||||
fn new_from_span(message: String, span: Span) -> Self {
|
||||
AddressError::Error(FormattedError::new_from_span(message, span))
|
||||
}
|
||||
|
||||
pub fn cannot_enforce(operation: String, error: SynthesisError, span: Span) -> Self {
|
||||
let message = format!(
|
||||
"the address operation `{}` failed due to the synthesis error `{}`",
|
||||
operation, error,
|
||||
);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn cannot_evaluate(operation: String, span: Span) -> Self {
|
||||
let message = format!("no implementation found for `{}`", operation);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn invalid_address(actual: String, span: Span) -> Self {
|
||||
let message = format!("expected address input type, found `{}`", actual);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn missing_address(expected: String, span: Span) -> Self {
|
||||
let message = format!("expected address input `{}` not found", expected);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
use crate::errors::{BooleanError, FieldError, FunctionError, GroupError, IntegerError, ValueError};
|
||||
use crate::errors::{AddressError, BooleanError, FieldError, FunctionError, GroupError, IntegerError, ValueError};
|
||||
use leo_types::{Error as FormattedError, Identifier, Span};
|
||||
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
@ -6,6 +6,9 @@ use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ExpressionError {
|
||||
#[error("{}", _0)]
|
||||
AddressError(#[from] AddressError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
BooleanError(#[from] BooleanError),
|
||||
|
||||
@ -31,6 +34,7 @@ pub enum ExpressionError {
|
||||
impl ExpressionError {
|
||||
pub fn set_path(&mut self, path: PathBuf) {
|
||||
match self {
|
||||
ExpressionError::AddressError(error) => error.set_path(path),
|
||||
ExpressionError::BooleanError(error) => error.set_path(path),
|
||||
ExpressionError::Error(error) => error.set_path(path),
|
||||
ExpressionError::FieldError(error) => error.set_path(path),
|
||||
|
@ -1,9 +1,22 @@
|
||||
use crate::errors::{BooleanError, ExpressionError, FieldError, GroupError, IntegerError, StatementError, ValueError};
|
||||
use crate::errors::{
|
||||
AddressError,
|
||||
BooleanError,
|
||||
ExpressionError,
|
||||
FieldError,
|
||||
GroupError,
|
||||
IntegerError,
|
||||
StatementError,
|
||||
ValueError,
|
||||
};
|
||||
use leo_types::{Error as FormattedError, Span};
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum FunctionError {
|
||||
#[error("{}", _0)]
|
||||
AddressError(#[from] AddressError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
BooleanError(#[from] BooleanError),
|
||||
|
||||
@ -32,6 +45,7 @@ pub enum FunctionError {
|
||||
impl FunctionError {
|
||||
pub fn set_path(&mut self, path: PathBuf) {
|
||||
match self {
|
||||
FunctionError::AddressError(error) => error.set_path(path),
|
||||
FunctionError::BooleanError(error) => error.set_path(path),
|
||||
FunctionError::ExpressionError(error) => error.set_path(path),
|
||||
FunctionError::Error(error) => error.set_path(path),
|
||||
|
@ -1,4 +1,6 @@
|
||||
//! Module containing errors returned when enforcing constraints in an Leo program
|
||||
pub mod address;
|
||||
pub use self::address::*;
|
||||
|
||||
pub mod boolean;
|
||||
pub use self::boolean::*;
|
||||
|
@ -1,9 +1,13 @@
|
||||
use crate::errors::{BooleanError, ExpressionError, IntegerError, ValueError};
|
||||
use crate::errors::{AddressError, BooleanError, ExpressionError, IntegerError, ValueError};
|
||||
use leo_types::{Error as FormattedError, Span, Type};
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum StatementError {
|
||||
#[error("{}", _0)]
|
||||
AddressError(#[from] AddressError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
BooleanError(#[from] BooleanError),
|
||||
|
||||
@ -23,6 +27,7 @@ pub enum StatementError {
|
||||
impl StatementError {
|
||||
pub fn set_path(&mut self, path: PathBuf) {
|
||||
match self {
|
||||
StatementError::AddressError(error) => error.set_path(path),
|
||||
StatementError::BooleanError(error) => error.set_path(path),
|
||||
StatementError::Error(error) => error.set_path(path),
|
||||
StatementError::ExpressionError(error) => error.set_path(path),
|
||||
|
@ -1,9 +1,13 @@
|
||||
use crate::errors::{BooleanError, FieldError, GroupError, IntegerError};
|
||||
use crate::errors::{AddressError, BooleanError, FieldError, GroupError, IntegerError};
|
||||
use leo_types::{Error as FormattedError, Span};
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ValueError {
|
||||
#[error("{}", _0)]
|
||||
AddressError(#[from] AddressError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
BooleanError(#[from] BooleanError),
|
||||
|
||||
@ -23,6 +27,7 @@ pub enum ValueError {
|
||||
impl ValueError {
|
||||
pub fn set_path(&mut self, path: PathBuf) {
|
||||
match self {
|
||||
ValueError::AddressError(error) => error.set_path(path),
|
||||
ValueError::BooleanError(error) => error.set_path(path),
|
||||
ValueError::Error(error) => error.set_path(path),
|
||||
ValueError::FieldError(error) => error.set_path(path),
|
||||
|
@ -1,9 +1,8 @@
|
||||
//! A data type that represents a field value
|
||||
|
||||
use crate::errors::FieldError;
|
||||
use crate::{errors::FieldError, ComparatorGadget, EvaluateLtGadget};
|
||||
use leo_types::Span;
|
||||
|
||||
use crate::{ComparatorGadget, EvaluateLtGadget};
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
|
@ -3,6 +3,9 @@
|
||||
#[macro_use]
|
||||
extern crate thiserror;
|
||||
|
||||
pub mod address;
|
||||
pub use self::address::*;
|
||||
|
||||
pub mod compiler;
|
||||
|
||||
pub mod constraints;
|
||||
|
Loading…
Reference in New Issue
Block a user