mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-24 07:48:04 +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
|
//! A data type that represents a field value
|
||||||
|
|
||||||
use crate::errors::FieldError;
|
use crate::{errors::FieldError, number_string_typing};
|
||||||
use leo_ast::Span;
|
use leo_ast::Span;
|
||||||
|
|
||||||
use snarkvm_errors::gadgets::SynthesisError;
|
use snarkvm_errors::gadgets::SynthesisError;
|
||||||
@ -54,22 +54,14 @@ impl<F: PrimeField> FieldType<F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn constant(string: String, span: &Span) -> Result<Self, FieldError> {
|
pub fn constant(string: String, span: &Span) -> Result<Self, FieldError> {
|
||||||
let first_char = string.chars().next().unwrap();
|
let number_info = number_string_typing(&string);
|
||||||
let new_string: &str;
|
|
||||||
let value;
|
|
||||||
|
|
||||||
// Check if first symbol is a negative.
|
let value = match number_info {
|
||||||
// If so strip it, parse rest of string and then negate it.
|
(number, neg) if neg => {
|
||||||
if first_char == '-' {
|
-F::from_str(&number).map_err(|_| FieldError::invalid_field(string, span.to_owned()))?
|
||||||
new_string = string
|
}
|
||||||
.chars()
|
(number, _) => F::from_str(&number).map_err(|_| FieldError::invalid_field(string, span.to_owned()))?,
|
||||||
.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()))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(FieldType::Constant(value))
|
Ok(FieldType::Constant(value))
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
//! Methods to enforce constraints on input field values in a compiled Leo program.
|
//! 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 leo_ast::{InputValue, Span};
|
||||||
|
|
||||||
use snarkvm_errors::gadgets::SynthesisError;
|
use snarkvm_errors::gadgets::SynthesisError;
|
||||||
@ -31,11 +31,26 @@ pub(crate) fn allocate_field<F: PrimeField, CS: ConstraintSystem<F>>(
|
|||||||
option: Option<String>,
|
option: Option<String>,
|
||||||
span: &Span,
|
span: &Span,
|
||||||
) -> Result<FieldType<F>, FieldError> {
|
) -> Result<FieldType<F>, FieldError> {
|
||||||
FieldType::alloc(
|
match option {
|
||||||
cs.ns(|| format!("`{}: field` {}:{}", name, span.line, span.start)),
|
Some(string) => {
|
||||||
|| option.ok_or(SynthesisError::AssignmentMissing),
|
let number_info = number_string_typing(&string);
|
||||||
)
|
|
||||||
.map_err(|_| FieldError::missing_field(format!("{}: field", name), span.to_owned()))
|
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>>(
|
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
|
// 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/>.
|
// 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 leo_asg::{GroupCoordinate, GroupValue, Span};
|
||||||
|
|
||||||
use snarkvm_curves::{
|
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 {
|
impl EdwardsGroupType {
|
||||||
pub fn edwards_affine_from_value(value: &GroupValue, span: &Span) -> Result<EdwardsAffine, GroupError> {
|
pub fn edwards_affine_from_value(value: &GroupValue, span: &Span) -> Result<EdwardsAffine, GroupError> {
|
||||||
match value {
|
match value {
|
||||||
@ -159,7 +142,7 @@ impl EdwardsGroupType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn edwards_affine_from_single(number: &str, span: &Span) -> Result<EdwardsAffine, GroupError> {
|
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") {
|
if number_info.0.eq("0") {
|
||||||
Ok(EdwardsAffine::zero())
|
Ok(EdwardsAffine::zero())
|
||||||
@ -189,41 +172,35 @@ impl EdwardsGroupType {
|
|||||||
match (x, y) {
|
match (x, y) {
|
||||||
// (x, y)
|
// (x, y)
|
||||||
(GroupCoordinate::Number(x_string), GroupCoordinate::Number(y_string)) => Self::edwards_affine_from_pair(
|
(GroupCoordinate::Number(x_string), GroupCoordinate::Number(y_string)) => Self::edwards_affine_from_pair(
|
||||||
number_string_typing(&x_string, &span.clone())?,
|
number_string_typing(&x_string),
|
||||||
number_string_typing(&y_string, &span.clone())?,
|
number_string_typing(&y_string),
|
||||||
span,
|
span,
|
||||||
span,
|
span,
|
||||||
span,
|
span,
|
||||||
),
|
),
|
||||||
// (x, +)
|
// (x, +)
|
||||||
(GroupCoordinate::Number(x_string), GroupCoordinate::SignHigh) => {
|
(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, -)
|
// (x, -)
|
||||||
(GroupCoordinate::Number(x_string), GroupCoordinate::SignLow) => Self::edwards_affine_from_x_str(
|
(GroupCoordinate::Number(x_string), GroupCoordinate::SignLow) => {
|
||||||
number_string_typing(&x_string, &span.clone())?,
|
Self::edwards_affine_from_x_str(number_string_typing(&x_string), span, Some(false), span)
|
||||||
span,
|
}
|
||||||
Some(false),
|
|
||||||
span,
|
|
||||||
),
|
|
||||||
// (x, _)
|
// (x, _)
|
||||||
(GroupCoordinate::Number(x_string), GroupCoordinate::Inferred) => {
|
(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)
|
// (+, y)
|
||||||
(GroupCoordinate::SignHigh, GroupCoordinate::Number(y_string)) => {
|
(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)
|
// (-, y)
|
||||||
(GroupCoordinate::SignLow, GroupCoordinate::Number(y_string)) => Self::edwards_affine_from_y_str(
|
(GroupCoordinate::SignLow, GroupCoordinate::Number(y_string)) => {
|
||||||
number_string_typing(&y_string, &span.clone())?,
|
Self::edwards_affine_from_y_str(number_string_typing(&y_string), span, Some(false), span)
|
||||||
span,
|
}
|
||||||
Some(false),
|
|
||||||
span,
|
|
||||||
),
|
|
||||||
// (_, y)
|
// (_, y)
|
||||||
(GroupCoordinate::Inferred, GroupCoordinate::Number(y_string)) => {
|
(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
|
// Invalid
|
||||||
(x, y) => Err(GroupError::invalid_group(format!("({}, {})", x, y), span.clone())),
|
(x, y) => Err(GroupError::invalid_group(format!("({}, {})", x, y), span.clone())),
|
||||||
|
@ -32,3 +32,16 @@ pub use self::integer::*;
|
|||||||
|
|
||||||
pub mod value;
|
pub mod value;
|
||||||
pub use self::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]
|
[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.
|
// Change to assert when == is implemented for field.
|
||||||
console.log("a: {}", a);
|
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);
|
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