mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-23 23:23:50 +03:00
Merge #678
678: Bug 662 Fix r=collinc97 a=gluax Allows -field values in input values, resolves #662. Also add tests for that and group - input values. Cleans up the re-written code used in a few places by adding a pub crate function. Depends on #626. Co-authored-by: gluax <jonathan.t.pavlik@gmail.com> Co-authored-by: gluax <16431709+gluax@users.noreply.github.com>
This commit is contained in:
commit
211fcb0195
@ -16,7 +16,7 @@
|
||||
|
||||
//! A data type that represents a field value
|
||||
|
||||
use crate::errors::FieldError;
|
||||
use crate::{errors::FieldError, number_string_typing};
|
||||
use leo_ast::Span;
|
||||
|
||||
use snarkvm_errors::gadgets::SynthesisError;
|
||||
@ -54,22 +54,14 @@ impl<F: PrimeField> FieldType<F> {
|
||||
}
|
||||
|
||||
pub fn constant(string: String, span: &Span) -> Result<Self, FieldError> {
|
||||
let first_char = string.chars().next().unwrap();
|
||||
let new_string: &str;
|
||||
let value;
|
||||
let number_info = number_string_typing(&string);
|
||||
|
||||
// Check if first symbol is a negative.
|
||||
// If so strip it, parse rest of string and then negate it.
|
||||
if first_char == '-' {
|
||||
new_string = string
|
||||
.chars()
|
||||
.next()
|
||||
.map(|c| &string[c.len_utf8()..])
|
||||
.ok_or_else(|| FieldError::invalid_field(string.clone(), span.to_owned()))?;
|
||||
value = -F::from_str(&new_string).map_err(|_| FieldError::invalid_field(string, span.to_owned()))?;
|
||||
} else {
|
||||
value = F::from_str(&string).map_err(|_| FieldError::invalid_field(string, span.to_owned()))?;
|
||||
}
|
||||
let value = match number_info {
|
||||
(number, neg) if neg => {
|
||||
-F::from_str(&number).map_err(|_| FieldError::invalid_field(string, span.to_owned()))?
|
||||
}
|
||||
(number, _) => F::from_str(&number).map_err(|_| FieldError::invalid_field(string, span.to_owned()))?,
|
||||
};
|
||||
|
||||
Ok(FieldType::Constant(value))
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
//! Methods to enforce constraints on input field values in a compiled Leo program.
|
||||
|
||||
use crate::{errors::FieldError, value::ConstrainedValue, FieldType, GroupType};
|
||||
use crate::{errors::FieldError, number_string_typing, value::ConstrainedValue, FieldType, GroupType};
|
||||
use leo_ast::{InputValue, Span};
|
||||
|
||||
use snarkvm_errors::gadgets::SynthesisError;
|
||||
@ -31,11 +31,26 @@ pub(crate) fn allocate_field<F: PrimeField, CS: ConstraintSystem<F>>(
|
||||
option: Option<String>,
|
||||
span: &Span,
|
||||
) -> Result<FieldType<F>, FieldError> {
|
||||
FieldType::alloc(
|
||||
cs.ns(|| format!("`{}: field` {}:{}", name, span.line, span.start)),
|
||||
|| option.ok_or(SynthesisError::AssignmentMissing),
|
||||
)
|
||||
.map_err(|_| FieldError::missing_field(format!("{}: field", name), span.to_owned()))
|
||||
match option {
|
||||
Some(string) => {
|
||||
let number_info = number_string_typing(&string);
|
||||
|
||||
match number_info {
|
||||
(number, neg) if neg => FieldType::alloc(
|
||||
cs.ns(|| format!("`{}: field` {}:{}", name, span.line, span.start)),
|
||||
|| Some(number).ok_or(SynthesisError::AssignmentMissing),
|
||||
)
|
||||
.map(|value| value.negate(cs, span))
|
||||
.map_err(|_| FieldError::missing_field(format!("{}: field", name), span.to_owned()))?,
|
||||
(number, _) => FieldType::alloc(
|
||||
cs.ns(|| format!("`{}: field` {}:{}", name, span.line, span.start)),
|
||||
|| Some(number).ok_or(SynthesisError::AssignmentMissing),
|
||||
)
|
||||
.map_err(|_| FieldError::missing_field(format!("{}: field", name), span.to_owned())),
|
||||
}
|
||||
}
|
||||
None => Err(FieldError::missing_field(format!("{}: field", name), span.to_owned())),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn field_from_input<'a, F: PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{errors::GroupError, GroupType};
|
||||
use crate::{errors::GroupError, number_string_typing, GroupType};
|
||||
use leo_asg::{GroupCoordinate, GroupValue, Span};
|
||||
|
||||
use snarkvm_curves::{
|
||||
@ -133,23 +133,6 @@ impl GroupType<Fq> for EdwardsGroupType {
|
||||
}
|
||||
}
|
||||
|
||||
fn number_string_typing(number: &str, span: &Span) -> Result<(String, bool), GroupError> {
|
||||
let first_char = number.chars().next().unwrap();
|
||||
|
||||
// Check if first symbol is a negative.
|
||||
// If so strip it, parse rest of string and then negate it.
|
||||
if first_char == '-' {
|
||||
let uint = number
|
||||
.chars()
|
||||
.next()
|
||||
.map(|c| &number[c.len_utf8()..])
|
||||
.ok_or_else(|| GroupError::invalid_group(number.to_string(), span.to_owned()))?;
|
||||
Ok((uint.to_string(), true))
|
||||
} else {
|
||||
Ok((number.to_string(), false))
|
||||
}
|
||||
}
|
||||
|
||||
impl EdwardsGroupType {
|
||||
pub fn edwards_affine_from_value(value: &GroupValue, span: &Span) -> Result<EdwardsAffine, GroupError> {
|
||||
match value {
|
||||
@ -159,7 +142,7 @@ impl EdwardsGroupType {
|
||||
}
|
||||
|
||||
pub fn edwards_affine_from_single(number: &str, span: &Span) -> Result<EdwardsAffine, GroupError> {
|
||||
let number_info = number_string_typing(number, &span.clone())?;
|
||||
let number_info = number_string_typing(number);
|
||||
|
||||
if number_info.0.eq("0") {
|
||||
Ok(EdwardsAffine::zero())
|
||||
@ -189,41 +172,35 @@ impl EdwardsGroupType {
|
||||
match (x, y) {
|
||||
// (x, y)
|
||||
(GroupCoordinate::Number(x_string), GroupCoordinate::Number(y_string)) => Self::edwards_affine_from_pair(
|
||||
number_string_typing(&x_string, &span.clone())?,
|
||||
number_string_typing(&y_string, &span.clone())?,
|
||||
number_string_typing(&x_string),
|
||||
number_string_typing(&y_string),
|
||||
span,
|
||||
span,
|
||||
span,
|
||||
),
|
||||
// (x, +)
|
||||
(GroupCoordinate::Number(x_string), GroupCoordinate::SignHigh) => {
|
||||
Self::edwards_affine_from_x_str(number_string_typing(&x_string, &span.clone())?, span, Some(true), span)
|
||||
Self::edwards_affine_from_x_str(number_string_typing(&x_string), span, Some(true), span)
|
||||
}
|
||||
// (x, -)
|
||||
(GroupCoordinate::Number(x_string), GroupCoordinate::SignLow) => Self::edwards_affine_from_x_str(
|
||||
number_string_typing(&x_string, &span.clone())?,
|
||||
span,
|
||||
Some(false),
|
||||
span,
|
||||
),
|
||||
(GroupCoordinate::Number(x_string), GroupCoordinate::SignLow) => {
|
||||
Self::edwards_affine_from_x_str(number_string_typing(&x_string), span, Some(false), span)
|
||||
}
|
||||
// (x, _)
|
||||
(GroupCoordinate::Number(x_string), GroupCoordinate::Inferred) => {
|
||||
Self::edwards_affine_from_x_str(number_string_typing(&x_string, &span.clone())?, span, None, span)
|
||||
Self::edwards_affine_from_x_str(number_string_typing(&x_string), span, None, span)
|
||||
}
|
||||
// (+, y)
|
||||
(GroupCoordinate::SignHigh, GroupCoordinate::Number(y_string)) => {
|
||||
Self::edwards_affine_from_y_str(number_string_typing(&y_string, &span.clone())?, span, Some(true), span)
|
||||
Self::edwards_affine_from_y_str(number_string_typing(&y_string), span, Some(true), span)
|
||||
}
|
||||
// (-, y)
|
||||
(GroupCoordinate::SignLow, GroupCoordinate::Number(y_string)) => Self::edwards_affine_from_y_str(
|
||||
number_string_typing(&y_string, &span.clone())?,
|
||||
span,
|
||||
Some(false),
|
||||
span,
|
||||
),
|
||||
(GroupCoordinate::SignLow, GroupCoordinate::Number(y_string)) => {
|
||||
Self::edwards_affine_from_y_str(number_string_typing(&y_string), span, Some(false), span)
|
||||
}
|
||||
// (_, y)
|
||||
(GroupCoordinate::Inferred, GroupCoordinate::Number(y_string)) => {
|
||||
Self::edwards_affine_from_y_str(number_string_typing(&y_string, &span.clone())?, span, None, span)
|
||||
Self::edwards_affine_from_y_str(number_string_typing(&y_string), span, None, span)
|
||||
}
|
||||
// Invalid
|
||||
(x, y) => Err(GroupError::invalid_group(format!("({}, {})", x, y), span.clone())),
|
||||
|
@ -32,3 +32,16 @@ pub use self::integer::*;
|
||||
|
||||
pub mod value;
|
||||
pub use self::value::*;
|
||||
|
||||
pub(crate) fn number_string_typing(number: &str) -> (String, bool) {
|
||||
let first_char = number.chars().next().unwrap();
|
||||
|
||||
// Check if first symbol is a negative.
|
||||
// If so strip it, parse rest of string and then negate it.
|
||||
if first_char == '-' {
|
||||
let uint = number.chars().next().map(|c| &number[c.len_utf8()..]).unwrap_or("");
|
||||
(uint.to_string(), true)
|
||||
} else {
|
||||
(number.to_string(), false)
|
||||
}
|
||||
}
|
||||
|
@ -1,2 +1,3 @@
|
||||
[main]
|
||||
a: field = 1;
|
||||
a: field = 1;
|
||||
b: field = -1;
|
@ -0,0 +1,4 @@
|
||||
[main]
|
||||
a: group = 1group;
|
||||
b: group = -1group;
|
||||
c: group = (0, -1)group;
|
@ -1,4 +1,5 @@
|
||||
function main(a: field) {
|
||||
function main(a: field, b: field) {
|
||||
// Change to assert when == is implemented for field.
|
||||
console.log("a: {}", a);
|
||||
console.log("b: {}", b);
|
||||
}
|
6
compiler/tests/input_files/program_input/main_group.leo
Normal file
6
compiler/tests/input_files/program_input/main_group.leo
Normal file
@ -0,0 +1,6 @@
|
||||
function main(a: group, b: group, c: group) {
|
||||
// Change to assert when == is implemented for group.
|
||||
console.log("a: {}", a);
|
||||
console.log("b: {}", b);
|
||||
console.log("c: {}", c);
|
||||
}
|
@ -103,3 +103,13 @@ fn test_field_input() {
|
||||
|
||||
assert_satisfied(program);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_group_input() {
|
||||
let program_string = include_str!("main_group.leo");
|
||||
let input_string = include_str!("input/main_group.in");
|
||||
|
||||
let program = parse_program_with_input(program_string, input_string).unwrap();
|
||||
|
||||
assert_satisfied(program);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user