From 3c8264e9ccddb1ec780738a8648dd477f985f988 Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Tue, 13 Jun 2023 08:33:35 +0000 Subject: [PATCH 1/9] chore: refactor `InputValue` to accept arrays of `InputValues` --- crates/noirc_abi/src/input_parser/json.rs | 23 ++++++++++++++----- crates/noirc_abi/src/input_parser/mod.rs | 18 +++++++++------ crates/noirc_abi/src/input_parser/toml.rs | 23 ++++++++++++++----- crates/noirc_abi/src/lib.rs | 28 ++++++++++++++++++----- 4 files changed, 67 insertions(+), 25 deletions(-) diff --git a/crates/noirc_abi/src/input_parser/json.rs b/crates/noirc_abi/src/input_parser/json.rs index d0d53ce38b2..bf8762b6c8d 100644 --- a/crates/noirc_abi/src/input_parser/json.rs +++ b/crates/noirc_abi/src/input_parser/json.rs @@ -79,7 +79,15 @@ impl From for JsonTypes { JsonTypes::String(f_str) } InputValue::Vec(v) => { - let array = v.iter().map(|i| format!("0x{}", i.to_hex())).collect(); + let array = v + .iter() + .map(|i| match i { + InputValue::Field(field) => format!("0x{}", field.to_hex()), + _ => unreachable!( + "Only arrays of simple field elements are allowable currently" + ), + }) + .collect(); JsonTypes::ArrayString(array) } InputValue::String(s) => JsonTypes::String(s), @@ -116,22 +124,25 @@ impl InputValue { } JsonTypes::Bool(boolean) => InputValue::Field(boolean.into()), JsonTypes::ArrayNum(arr_num) => { - let array_elements = - vecmap(arr_num, |elem_num| FieldElement::from(i128::from(elem_num))); + let array_elements = vecmap(arr_num, |elem_num| { + InputValue::Field(FieldElement::from(i128::from(elem_num))) + }); InputValue::Vec(array_elements) } JsonTypes::ArrayString(arr_str) => { - let array_elements = try_vecmap(arr_str, |elem_str| parse_str_to_field(&elem_str))?; + let array_elements = try_vecmap(arr_str, |elem_str| { + parse_str_to_field(&elem_str).map(InputValue::Field) + })?; InputValue::Vec(array_elements) } JsonTypes::ArrayBool(arr_bool) => { - let array_elements = vecmap(arr_bool, FieldElement::from); + let array_elements = + vecmap(arr_bool, |boolean| InputValue::Field(FieldElement::from(boolean))); InputValue::Vec(array_elements) } - JsonTypes::Table(table) => match param_type { AbiType::Struct { fields } => { let native_table = try_btree_map(fields, |(field_name, abi_type)| { diff --git a/crates/noirc_abi/src/input_parser/mod.rs b/crates/noirc_abi/src/input_parser/mod.rs index 7eaa5c6322c..39d2bf2883d 100644 --- a/crates/noirc_abi/src/input_parser/mod.rs +++ b/crates/noirc_abi/src/input_parser/mod.rs @@ -14,8 +14,8 @@ use crate::{Abi, AbiType}; #[derive(Debug, Clone, Serialize, PartialEq)] pub enum InputValue { Field(FieldElement), - Vec(Vec), String(String), + Vec(Vec), Struct(BTreeMap), } @@ -32,14 +32,12 @@ impl InputValue { field_element.is_one() || field_element.is_zero() } - (InputValue::Vec(field_elements), AbiType::Array { length, typ, .. }) => { - if field_elements.len() != *length as usize { + (InputValue::Vec(array_elements), AbiType::Array { length, typ, .. }) => { + if array_elements.len() != *length as usize { return false; } // Check that all of the array's elements' values match the ABI as well. - field_elements - .iter() - .all(|field_element| Self::Field(*field_element).matches_abi(typ)) + array_elements.iter().all(|input_value| input_value.matches_abi(typ)) } (InputValue::String(string), AbiType::String { length }) => { @@ -163,7 +161,13 @@ mod serialization_tests { "bar".into(), InputValue::Struct(BTreeMap::from([ ("field1".into(), InputValue::Field(255u128.into())), - ("field2".into(), InputValue::Vec(vec![true.into(), false.into()])), + ( + "field2".into(), + InputValue::Vec(vec![ + InputValue::Field(true.into()), + InputValue::Field(false.into()), + ]), + ), ])), ), (MAIN_RETURN_NAME.into(), InputValue::String("hello".to_owned())), diff --git a/crates/noirc_abi/src/input_parser/toml.rs b/crates/noirc_abi/src/input_parser/toml.rs index a5a50456e23..1c624abd265 100644 --- a/crates/noirc_abi/src/input_parser/toml.rs +++ b/crates/noirc_abi/src/input_parser/toml.rs @@ -76,7 +76,15 @@ impl From for TomlTypes { TomlTypes::String(f_str) } InputValue::Vec(v) => { - let array = v.iter().map(|i| format!("0x{}", i.to_hex())).collect(); + let array = v + .iter() + .map(|i| match i { + InputValue::Field(field) => format!("0x{}", field.to_hex()), + _ => unreachable!( + "Only arrays of simple field elements are allowable currently" + ), + }) + .collect(); TomlTypes::ArrayString(array) } InputValue::String(s) => TomlTypes::String(s), @@ -113,22 +121,25 @@ impl InputValue { } TomlTypes::Bool(boolean) => InputValue::Field(boolean.into()), TomlTypes::ArrayNum(arr_num) => { - let array_elements = - vecmap(arr_num, |elem_num| FieldElement::from(i128::from(elem_num))); + let array_elements = vecmap(arr_num, |elem_num| { + InputValue::Field(FieldElement::from(i128::from(elem_num))) + }); InputValue::Vec(array_elements) } TomlTypes::ArrayString(arr_str) => { - let array_elements = try_vecmap(arr_str, |elem_str| parse_str_to_field(&elem_str))?; + let array_elements = try_vecmap(arr_str, |elem_str| { + parse_str_to_field(&elem_str).map(InputValue::Field) + })?; InputValue::Vec(array_elements) } TomlTypes::ArrayBool(arr_bool) => { - let array_elements = vecmap(arr_bool, FieldElement::from); + let array_elements = + vecmap(arr_bool, |boolean| InputValue::Field(FieldElement::from(boolean))); InputValue::Vec(array_elements) } - TomlTypes::Table(table) => match param_type { AbiType::Struct { fields } => { let native_table = try_btree_map(fields, |(field_name, abi_type)| { diff --git a/crates/noirc_abi/src/lib.rs b/crates/noirc_abi/src/lib.rs index 1f0cc0ff616..0cdd0ef2562 100644 --- a/crates/noirc_abi/src/lib.rs +++ b/crates/noirc_abi/src/lib.rs @@ -304,7 +304,14 @@ impl Abi { let mut encoded_value = Vec::new(); match value { InputValue::Field(elem) => encoded_value.push(elem), - InputValue::Vec(vec_elem) => encoded_value.extend(vec_elem), + InputValue::Vec(vec_elements) => match abi_type { + AbiType::Array { typ, .. } => { + for elem in vec_elements { + encoded_value.extend(Self::encode_value(elem, typ)?); + } + } + _ => unreachable!("value should have already been checked to match abi type"), + }, InputValue::String(string) => { let str_as_fields = string.bytes().map(|byte| FieldElement::from_be_bytes_reduce(&[byte])); @@ -383,11 +390,14 @@ impl Abi { InputValue::Field(field_element) } - AbiType::Array { length, .. } => { - let field_elements: Vec = - field_iterator.take(*length as usize).collect(); + AbiType::Array { length, typ } => { + let length = *length as usize; + let mut array_elements = Vec::with_capacity(length); + for _ in 0..length { + array_elements.push(Self::decode_value(field_iterator, typ)?); + } - InputValue::Vec(field_elements) + InputValue::Vec(array_elements) } AbiType::String { length } => { let field_elements: Vec = @@ -458,7 +468,13 @@ mod test { // Note we omit return value from inputs let inputs: InputMap = BTreeMap::from([ - ("thing1".to_string(), InputValue::Vec(vec![FieldElement::one(), FieldElement::one()])), + ( + "thing1".to_string(), + InputValue::Vec(vec![ + InputValue::Field(FieldElement::one()), + InputValue::Field(FieldElement::one()), + ]), + ), ("thing2".to_string(), InputValue::Field(FieldElement::zero())), ]); From b866133b8f4b506b1f0d00bd7443db55eaf692ae Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Tue, 13 Jun 2023 10:25:41 +0000 Subject: [PATCH 2/9] chore: generalize `TomlTypes` and `JsonTypes` to have a single array type --- crates/noirc_abi/src/input_parser/json.rs | 49 +++++++++-------------- crates/noirc_abi/src/input_parser/toml.rs | 49 +++++++++-------------- 2 files changed, 40 insertions(+), 58 deletions(-) diff --git a/crates/noirc_abi/src/input_parser/json.rs b/crates/noirc_abi/src/input_parser/json.rs index bf8762b6c8d..77218e1d866 100644 --- a/crates/noirc_abi/src/input_parser/json.rs +++ b/crates/noirc_abi/src/input_parser/json.rs @@ -1,7 +1,7 @@ use super::{parse_str_to_field, InputValue}; use crate::{errors::InputParserError, Abi, AbiType, MAIN_RETURN_NAME}; use acvm::FieldElement; -use iter_extended::{btree_map, try_btree_map, try_vecmap, vecmap}; +use iter_extended::{btree_map, try_btree_map, try_vecmap}; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; @@ -61,12 +61,8 @@ enum JsonTypes { Integer(u64), // Simple boolean flag Bool(bool), - // Array of regular integers - ArrayNum(Vec), - // Array of hexadecimal integers - ArrayString(Vec), - // Array of booleans - ArrayBool(Vec), + // Array of JsonTypes + Array(Vec), // Struct of JsonTypes Table(BTreeMap), } @@ -82,13 +78,15 @@ impl From for JsonTypes { let array = v .iter() .map(|i| match i { - InputValue::Field(field) => format!("0x{}", field.to_hex()), + InputValue::Field(field) => { + JsonTypes::String(format!("0x{}", field.to_hex())) + } _ => unreachable!( "Only arrays of simple field elements are allowable currently" ), }) .collect(); - JsonTypes::ArrayString(array) + JsonTypes::Array(array) } InputValue::String(s) => JsonTypes::String(s), InputValue::Struct(map) => { @@ -123,26 +121,19 @@ impl InputValue { InputValue::Field(new_value) } JsonTypes::Bool(boolean) => InputValue::Field(boolean.into()), - JsonTypes::ArrayNum(arr_num) => { - let array_elements = vecmap(arr_num, |elem_num| { - InputValue::Field(FieldElement::from(i128::from(elem_num))) - }); - - InputValue::Vec(array_elements) - } - JsonTypes::ArrayString(arr_str) => { - let array_elements = try_vecmap(arr_str, |elem_str| { - parse_str_to_field(&elem_str).map(InputValue::Field) - })?; - - InputValue::Vec(array_elements) - } - JsonTypes::ArrayBool(arr_bool) => { - let array_elements = - vecmap(arr_bool, |boolean| InputValue::Field(FieldElement::from(boolean))); - - InputValue::Vec(array_elements) - } + JsonTypes::Array(array) => match param_type { + AbiType::Array { typ, .. } + if matches!( + typ.as_ref(), + AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean + ) => + { + let array_elements = + try_vecmap(array, |value| InputValue::try_from_json(value, typ, arg_name))?; + InputValue::Vec(array_elements) + } + _ => return Err(InputParserError::AbiTypeMismatch(param_type.clone())), + }, JsonTypes::Table(table) => match param_type { AbiType::Struct { fields } => { let native_table = try_btree_map(fields, |(field_name, abi_type)| { diff --git a/crates/noirc_abi/src/input_parser/toml.rs b/crates/noirc_abi/src/input_parser/toml.rs index 1c624abd265..0981c8b14f7 100644 --- a/crates/noirc_abi/src/input_parser/toml.rs +++ b/crates/noirc_abi/src/input_parser/toml.rs @@ -1,7 +1,7 @@ use super::{parse_str_to_field, InputValue}; use crate::{errors::InputParserError, Abi, AbiType, MAIN_RETURN_NAME}; use acvm::FieldElement; -use iter_extended::{btree_map, try_btree_map, try_vecmap, vecmap}; +use iter_extended::{btree_map, try_btree_map, try_vecmap}; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; @@ -58,12 +58,8 @@ enum TomlTypes { Integer(u64), // Simple boolean flag Bool(bool), - // Array of regular integers - ArrayNum(Vec), - // Array of hexadecimal integers - ArrayString(Vec), - // Array of booleans - ArrayBool(Vec), + // Array of TomlTypes + Array(Vec), // Struct of TomlTypes Table(BTreeMap), } @@ -79,13 +75,15 @@ impl From for TomlTypes { let array = v .iter() .map(|i| match i { - InputValue::Field(field) => format!("0x{}", field.to_hex()), + InputValue::Field(field) => { + TomlTypes::String(format!("0x{}", field.to_hex())) + } _ => unreachable!( "Only arrays of simple field elements are allowable currently" ), }) .collect(); - TomlTypes::ArrayString(array) + TomlTypes::Array(array) } InputValue::String(s) => TomlTypes::String(s), InputValue::Struct(map) => { @@ -120,26 +118,19 @@ impl InputValue { InputValue::Field(new_value) } TomlTypes::Bool(boolean) => InputValue::Field(boolean.into()), - TomlTypes::ArrayNum(arr_num) => { - let array_elements = vecmap(arr_num, |elem_num| { - InputValue::Field(FieldElement::from(i128::from(elem_num))) - }); - - InputValue::Vec(array_elements) - } - TomlTypes::ArrayString(arr_str) => { - let array_elements = try_vecmap(arr_str, |elem_str| { - parse_str_to_field(&elem_str).map(InputValue::Field) - })?; - - InputValue::Vec(array_elements) - } - TomlTypes::ArrayBool(arr_bool) => { - let array_elements = - vecmap(arr_bool, |boolean| InputValue::Field(FieldElement::from(boolean))); - - InputValue::Vec(array_elements) - } + TomlTypes::Array(array) => match param_type { + AbiType::Array { typ, .. } + if matches!( + typ.as_ref(), + AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean + ) => + { + let array_elements = + try_vecmap(array, |value| InputValue::try_from_toml(value, typ, arg_name))?; + InputValue::Vec(array_elements) + } + _ => return Err(InputParserError::AbiTypeMismatch(param_type.clone())), + }, TomlTypes::Table(table) => match param_type { AbiType::Struct { fields } => { let native_table = try_btree_map(fields, |(field_name, abi_type)| { From 8062ab51e184e78c04b19dec1d9204c1245db415 Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Tue, 13 Jun 2023 10:47:03 +0000 Subject: [PATCH 3/9] chore: add test for arrays of structs in program ABI --- .../tests/test_data/struct_array_inputs/Nargo.toml | 5 +++++ .../tests/test_data/struct_array_inputs/Prover.toml | 11 +++++++++++ .../tests/test_data/struct_array_inputs/src/main.nr | 8 ++++++++ 3 files changed, 24 insertions(+) create mode 100644 crates/nargo_cli/tests/test_data/struct_array_inputs/Nargo.toml create mode 100644 crates/nargo_cli/tests/test_data/struct_array_inputs/Prover.toml create mode 100644 crates/nargo_cli/tests/test_data/struct_array_inputs/src/main.nr diff --git a/crates/nargo_cli/tests/test_data/struct_array_inputs/Nargo.toml b/crates/nargo_cli/tests/test_data/struct_array_inputs/Nargo.toml new file mode 100644 index 00000000000..670888e37cd --- /dev/null +++ b/crates/nargo_cli/tests/test_data/struct_array_inputs/Nargo.toml @@ -0,0 +1,5 @@ +[package] +authors = [""] +compiler_version = "0.6.0" + +[dependencies] \ No newline at end of file diff --git a/crates/nargo_cli/tests/test_data/struct_array_inputs/Prover.toml b/crates/nargo_cli/tests/test_data/struct_array_inputs/Prover.toml new file mode 100644 index 00000000000..c2212c1a9c9 --- /dev/null +++ b/crates/nargo_cli/tests/test_data/struct_array_inputs/Prover.toml @@ -0,0 +1,11 @@ +[[foos]] +bar = 0 +baz = 0 + +[[foos]] +bar = 0 +baz = 0 + +[[foos]] +bar = 1 +baz = 2 diff --git a/crates/nargo_cli/tests/test_data/struct_array_inputs/src/main.nr b/crates/nargo_cli/tests/test_data/struct_array_inputs/src/main.nr new file mode 100644 index 00000000000..de317fe35e7 --- /dev/null +++ b/crates/nargo_cli/tests/test_data/struct_array_inputs/src/main.nr @@ -0,0 +1,8 @@ +struct Foo { + bar: Field, + baz: Field, +} + +fn main(foos: [Foo; 3]) -> pub Field { + foos[2].bar + foos[2].baz +} \ No newline at end of file From fd7c2417f303771ec281540a8f079240a9ca0880 Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Tue, 13 Jun 2023 16:12:03 +0000 Subject: [PATCH 4/9] chore: use `vecmap` over plain iterators --- crates/noirc_abi/src/input_parser/json.rs | 21 ++++++++------------- crates/noirc_abi/src/input_parser/toml.rs | 21 ++++++++------------- 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/crates/noirc_abi/src/input_parser/json.rs b/crates/noirc_abi/src/input_parser/json.rs index 77218e1d866..eb561cbfba9 100644 --- a/crates/noirc_abi/src/input_parser/json.rs +++ b/crates/noirc_abi/src/input_parser/json.rs @@ -1,7 +1,7 @@ use super::{parse_str_to_field, InputValue}; use crate::{errors::InputParserError, Abi, AbiType, MAIN_RETURN_NAME}; use acvm::FieldElement; -use iter_extended::{btree_map, try_btree_map, try_vecmap}; +use iter_extended::{btree_map, try_btree_map, try_vecmap, vecmap}; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; @@ -74,18 +74,13 @@ impl From for JsonTypes { let f_str = format!("0x{}", f.to_hex()); JsonTypes::String(f_str) } - InputValue::Vec(v) => { - let array = v - .iter() - .map(|i| match i { - InputValue::Field(field) => { - JsonTypes::String(format!("0x{}", field.to_hex())) - } - _ => unreachable!( - "Only arrays of simple field elements are allowable currently" - ), - }) - .collect(); + InputValue::Vec(vector) => { + let array = vecmap(vector, |i| match i { + InputValue::Field(field) => JsonTypes::String(format!("0x{}", field.to_hex())), + _ => { + unreachable!("Only arrays of simple field elements are allowable currently") + } + }); JsonTypes::Array(array) } InputValue::String(s) => JsonTypes::String(s), diff --git a/crates/noirc_abi/src/input_parser/toml.rs b/crates/noirc_abi/src/input_parser/toml.rs index 0981c8b14f7..b54ef30855f 100644 --- a/crates/noirc_abi/src/input_parser/toml.rs +++ b/crates/noirc_abi/src/input_parser/toml.rs @@ -1,7 +1,7 @@ use super::{parse_str_to_field, InputValue}; use crate::{errors::InputParserError, Abi, AbiType, MAIN_RETURN_NAME}; use acvm::FieldElement; -use iter_extended::{btree_map, try_btree_map, try_vecmap}; +use iter_extended::{btree_map, try_btree_map, try_vecmap, vecmap}; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; @@ -71,18 +71,13 @@ impl From for TomlTypes { let f_str = format!("0x{}", f.to_hex()); TomlTypes::String(f_str) } - InputValue::Vec(v) => { - let array = v - .iter() - .map(|i| match i { - InputValue::Field(field) => { - TomlTypes::String(format!("0x{}", field.to_hex())) - } - _ => unreachable!( - "Only arrays of simple field elements are allowable currently" - ), - }) - .collect(); + InputValue::Vec(vector) => { + let array = vecmap(vector, |i| match i { + InputValue::Field(field) => TomlTypes::String(format!("0x{}", field.to_hex())), + _ => { + unreachable!("Only arrays of simple field elements are allowable currently") + } + }); TomlTypes::Array(array) } InputValue::String(s) => TomlTypes::String(s), From 68207a4953b0a275557545ca8770eddd4669c712 Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Tue, 13 Jun 2023 16:20:25 +0000 Subject: [PATCH 5/9] chore: improve functions to convert to `InputValue` --- crates/noirc_abi/src/input_parser/json.rs | 79 +++++++++++------------ crates/noirc_abi/src/input_parser/toml.rs | 79 +++++++++++------------ 2 files changed, 74 insertions(+), 84 deletions(-) diff --git a/crates/noirc_abi/src/input_parser/json.rs b/crates/noirc_abi/src/input_parser/json.rs index eb561cbfba9..55168e3796c 100644 --- a/crates/noirc_abi/src/input_parser/json.rs +++ b/crates/noirc_abi/src/input_parser/json.rs @@ -99,52 +99,47 @@ impl InputValue { param_type: &AbiType, arg_name: &str, ) -> Result { - let input_value = match value { - JsonTypes::String(string) => match param_type { - AbiType::String { .. } => InputValue::String(string), - AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean => { - InputValue::Field(parse_str_to_field(&string)?) - } - - AbiType::Array { .. } | AbiType::Struct { .. } => { - return Err(InputParserError::AbiTypeMismatch(param_type.clone())) - } - }, - JsonTypes::Integer(integer) => { + let input_value = match (value, param_type) { + (JsonTypes::String(string), AbiType::String { .. }) => InputValue::String(string), + ( + JsonTypes::String(string), + AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean, + ) => InputValue::Field(parse_str_to_field(&string)?), + + (JsonTypes::Integer(integer), AbiType::Field | AbiType::Integer { .. }) => { let new_value = FieldElement::from(i128::from(integer)); InputValue::Field(new_value) } - JsonTypes::Bool(boolean) => InputValue::Field(boolean.into()), - JsonTypes::Array(array) => match param_type { - AbiType::Array { typ, .. } - if matches!( - typ.as_ref(), - AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean - ) => - { - let array_elements = - try_vecmap(array, |value| InputValue::try_from_json(value, typ, arg_name))?; - InputValue::Vec(array_elements) - } - _ => return Err(InputParserError::AbiTypeMismatch(param_type.clone())), - }, - JsonTypes::Table(table) => match param_type { - AbiType::Struct { fields } => { - let native_table = try_btree_map(fields, |(field_name, abi_type)| { - // Check that json contains a value for each field of the struct. - let field_id = format!("{arg_name}.{field_name}"); - let value = table - .get(field_name) - .ok_or_else(|| InputParserError::MissingArgument(field_id.clone()))?; - InputValue::try_from_json(value.clone(), abi_type, &field_id) - .map(|input_value| (field_name.to_string(), input_value)) - })?; - - InputValue::Struct(native_table) - } - _ => return Err(InputParserError::AbiTypeMismatch(param_type.clone())), - }, + + (JsonTypes::Bool(boolean), AbiType::Boolean) => InputValue::Field(boolean.into()), + + (JsonTypes::Array(array), AbiType::Array { typ, .. }) + if matches!( + typ.as_ref(), + AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean + ) => + { + let array_elements = + try_vecmap(array, |value| InputValue::try_from_json(value, typ, arg_name))?; + InputValue::Vec(array_elements) + } + + (JsonTypes::Table(table), AbiType::Struct { fields }) => { + let native_table = try_btree_map(fields, |(field_name, abi_type)| { + // Check that json contains a value for each field of the struct. + let field_id = format!("{arg_name}.{field_name}"); + let value = table + .get(field_name) + .ok_or_else(|| InputParserError::MissingArgument(field_id.clone()))?; + InputValue::try_from_json(value.clone(), abi_type, &field_id) + .map(|input_value| (field_name.to_string(), input_value)) + })?; + + InputValue::Struct(native_table) + } + + (_, _) => return Err(InputParserError::AbiTypeMismatch(param_type.clone())), }; Ok(input_value) diff --git a/crates/noirc_abi/src/input_parser/toml.rs b/crates/noirc_abi/src/input_parser/toml.rs index b54ef30855f..9357065cbf2 100644 --- a/crates/noirc_abi/src/input_parser/toml.rs +++ b/crates/noirc_abi/src/input_parser/toml.rs @@ -96,52 +96,47 @@ impl InputValue { param_type: &AbiType, arg_name: &str, ) -> Result { - let input_value = match value { - TomlTypes::String(string) => match param_type { - AbiType::String { .. } => InputValue::String(string), - AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean => { - InputValue::Field(parse_str_to_field(&string)?) - } - - AbiType::Array { .. } | AbiType::Struct { .. } => { - return Err(InputParserError::AbiTypeMismatch(param_type.clone())) - } - }, - TomlTypes::Integer(integer) => { + let input_value = match (value, param_type) { + (TomlTypes::String(string), AbiType::String { .. }) => InputValue::String(string), + ( + TomlTypes::String(string), + AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean, + ) => InputValue::Field(parse_str_to_field(&string)?), + + (TomlTypes::Integer(integer), AbiType::Field | AbiType::Integer { .. }) => { let new_value = FieldElement::from(i128::from(integer)); InputValue::Field(new_value) } - TomlTypes::Bool(boolean) => InputValue::Field(boolean.into()), - TomlTypes::Array(array) => match param_type { - AbiType::Array { typ, .. } - if matches!( - typ.as_ref(), - AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean - ) => - { - let array_elements = - try_vecmap(array, |value| InputValue::try_from_toml(value, typ, arg_name))?; - InputValue::Vec(array_elements) - } - _ => return Err(InputParserError::AbiTypeMismatch(param_type.clone())), - }, - TomlTypes::Table(table) => match param_type { - AbiType::Struct { fields } => { - let native_table = try_btree_map(fields, |(field_name, abi_type)| { - // Check that toml contains a value for each field of the struct. - let field_id = format!("{arg_name}.{field_name}"); - let value = table - .get(field_name) - .ok_or_else(|| InputParserError::MissingArgument(field_id.clone()))?; - InputValue::try_from_toml(value.clone(), abi_type, &field_id) - .map(|input_value| (field_name.to_string(), input_value)) - })?; - - InputValue::Struct(native_table) - } - _ => return Err(InputParserError::AbiTypeMismatch(param_type.clone())), - }, + + (TomlTypes::Bool(boolean), AbiType::Boolean) => InputValue::Field(boolean.into()), + + (TomlTypes::Array(array), AbiType::Array { typ, .. }) + if matches!( + typ.as_ref(), + AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean + ) => + { + let array_elements = + try_vecmap(array, |value| InputValue::try_from_toml(value, typ, arg_name))?; + InputValue::Vec(array_elements) + } + + (TomlTypes::Table(table), AbiType::Struct { fields }) => { + let native_table = try_btree_map(fields, |(field_name, abi_type)| { + // Check that json contains a value for each field of the struct. + let field_id = format!("{arg_name}.{field_name}"); + let value = table + .get(field_name) + .ok_or_else(|| InputParserError::MissingArgument(field_id.clone()))?; + InputValue::try_from_toml(value.clone(), abi_type, &field_id) + .map(|input_value| (field_name.to_string(), input_value)) + })?; + + InputValue::Struct(native_table) + } + + (_, _) => return Err(InputParserError::AbiTypeMismatch(param_type.clone())), }; Ok(input_value) From ce5992b76afe0900d271dfd4986e5d4bf9f7199a Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Tue, 13 Jun 2023 16:28:00 +0000 Subject: [PATCH 6/9] chore: remove restrictions on array element types --- crates/noirc_abi/src/input_parser/json.rs | 17 +++++------------ crates/noirc_abi/src/input_parser/toml.rs | 17 +++++------------ 2 files changed, 10 insertions(+), 24 deletions(-) diff --git a/crates/noirc_abi/src/input_parser/json.rs b/crates/noirc_abi/src/input_parser/json.rs index 55168e3796c..8f8e5e37ef6 100644 --- a/crates/noirc_abi/src/input_parser/json.rs +++ b/crates/noirc_abi/src/input_parser/json.rs @@ -75,12 +75,10 @@ impl From for JsonTypes { JsonTypes::String(f_str) } InputValue::Vec(vector) => { - let array = vecmap(vector, |i| match i { - InputValue::Field(field) => JsonTypes::String(format!("0x{}", field.to_hex())), - _ => { - unreachable!("Only arrays of simple field elements are allowable currently") - } - }); + // TODO: enforce that all `JsonTypes` in the vector are the same variant. + // This is technically valid in rust but doesn't correspond to a valid Noir ABI. + // Requires knowledge of the ABI (see #1655) + let array = vecmap(vector, |element| JsonTypes::from(element)); JsonTypes::Array(array) } InputValue::String(s) => JsonTypes::String(s), @@ -114,12 +112,7 @@ impl InputValue { (JsonTypes::Bool(boolean), AbiType::Boolean) => InputValue::Field(boolean.into()), - (JsonTypes::Array(array), AbiType::Array { typ, .. }) - if matches!( - typ.as_ref(), - AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean - ) => - { + (JsonTypes::Array(array), AbiType::Array { typ, .. }) => { let array_elements = try_vecmap(array, |value| InputValue::try_from_json(value, typ, arg_name))?; InputValue::Vec(array_elements) diff --git a/crates/noirc_abi/src/input_parser/toml.rs b/crates/noirc_abi/src/input_parser/toml.rs index 9357065cbf2..034d0c4e799 100644 --- a/crates/noirc_abi/src/input_parser/toml.rs +++ b/crates/noirc_abi/src/input_parser/toml.rs @@ -72,12 +72,10 @@ impl From for TomlTypes { TomlTypes::String(f_str) } InputValue::Vec(vector) => { - let array = vecmap(vector, |i| match i { - InputValue::Field(field) => TomlTypes::String(format!("0x{}", field.to_hex())), - _ => { - unreachable!("Only arrays of simple field elements are allowable currently") - } - }); + // TODO: enforce that all `TomlTypes` in the vector are the same variant. + // This is technically valid in rust but doesn't correspond to a valid Noir ABI. + // Requires knowledge of the ABI (see #1655) + let array = vecmap(vector, |element| TomlTypes::from(element)); TomlTypes::Array(array) } InputValue::String(s) => TomlTypes::String(s), @@ -111,12 +109,7 @@ impl InputValue { (TomlTypes::Bool(boolean), AbiType::Boolean) => InputValue::Field(boolean.into()), - (TomlTypes::Array(array), AbiType::Array { typ, .. }) - if matches!( - typ.as_ref(), - AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean - ) => - { + (TomlTypes::Array(array), AbiType::Array { typ, .. }) => { let array_elements = try_vecmap(array, |value| InputValue::try_from_toml(value, typ, arg_name))?; InputValue::Vec(array_elements) From 9ccfc5e076f71252e210f36df062f6c7eb85f7ba Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Wed, 14 Jun 2023 05:43:23 +0000 Subject: [PATCH 7/9] chore: clippy --- crates/noirc_abi/src/input_parser/json.rs | 2 +- crates/noirc_abi/src/input_parser/toml.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/noirc_abi/src/input_parser/json.rs b/crates/noirc_abi/src/input_parser/json.rs index 443a5179f62..a4cd3013374 100644 --- a/crates/noirc_abi/src/input_parser/json.rs +++ b/crates/noirc_abi/src/input_parser/json.rs @@ -78,7 +78,7 @@ impl From for JsonTypes { // TODO: enforce that all `JsonTypes` in the vector are the same variant. // This is technically valid in rust but doesn't correspond to a valid Noir ABI. // Requires knowledge of the ABI (see #1655) - let array = vecmap(vector, |element| JsonTypes::from(element)); + let array = vecmap(vector, JsonTypes::from); JsonTypes::Array(array) } InputValue::String(s) => JsonTypes::String(s), diff --git a/crates/noirc_abi/src/input_parser/toml.rs b/crates/noirc_abi/src/input_parser/toml.rs index cae5fa3d0c0..b0ba56e373a 100644 --- a/crates/noirc_abi/src/input_parser/toml.rs +++ b/crates/noirc_abi/src/input_parser/toml.rs @@ -75,7 +75,7 @@ impl From for TomlTypes { // TODO: enforce that all `TomlTypes` in the vector are the same variant. // This is technically valid in rust but doesn't correspond to a valid Noir ABI. // Requires knowledge of the ABI (see #1655) - let array = vecmap(vector, |element| TomlTypes::from(element)); + let array = vecmap(vector, TomlTypes::from); TomlTypes::Array(array) } InputValue::String(s) => TomlTypes::String(s), From 06fdce13a9476dd0ab00e6defd681906b40ed665 Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Wed, 5 Jul 2023 14:25:04 +0000 Subject: [PATCH 8/9] chore: remove stale comment --- crates/noirc_abi/src/input_parser/toml.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/crates/noirc_abi/src/input_parser/toml.rs b/crates/noirc_abi/src/input_parser/toml.rs index 0a85c622692..d96496410d9 100644 --- a/crates/noirc_abi/src/input_parser/toml.rs +++ b/crates/noirc_abi/src/input_parser/toml.rs @@ -87,9 +87,6 @@ impl TomlTypes { (InputValue::Field(f), AbiType::Boolean) => TomlTypes::Bool(f.is_one()), (InputValue::Vec(vector), AbiType::Array { typ, .. }) => { - // TODO: enforce that all `TomlTypes` in the vector are the same variant. - // This is technically valid in rust but doesn't correspond to a valid Noir ABI. - // Requires knowledge of the ABI (see #1655) let array = try_vecmap(vector, |value| TomlTypes::try_from_input_value(value, typ))?; TomlTypes::Array(array) From 5dde2f5bfd7028220c7271e26ff1c1171c59adaa Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Tue, 11 Jul 2023 02:45:09 +0000 Subject: [PATCH 9/9] chore: move new test case to be run on experimental ssa --- .../struct_array_inputs/Nargo.toml | 0 .../struct_array_inputs/Prover.toml | 0 .../struct_array_inputs/src/main.nr | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename crates/nargo_cli/tests/{test_data => test_data_ssa_refactor}/struct_array_inputs/Nargo.toml (100%) rename crates/nargo_cli/tests/{test_data => test_data_ssa_refactor}/struct_array_inputs/Prover.toml (100%) rename crates/nargo_cli/tests/{test_data => test_data_ssa_refactor}/struct_array_inputs/src/main.nr (100%) diff --git a/crates/nargo_cli/tests/test_data/struct_array_inputs/Nargo.toml b/crates/nargo_cli/tests/test_data_ssa_refactor/struct_array_inputs/Nargo.toml similarity index 100% rename from crates/nargo_cli/tests/test_data/struct_array_inputs/Nargo.toml rename to crates/nargo_cli/tests/test_data_ssa_refactor/struct_array_inputs/Nargo.toml diff --git a/crates/nargo_cli/tests/test_data/struct_array_inputs/Prover.toml b/crates/nargo_cli/tests/test_data_ssa_refactor/struct_array_inputs/Prover.toml similarity index 100% rename from crates/nargo_cli/tests/test_data/struct_array_inputs/Prover.toml rename to crates/nargo_cli/tests/test_data_ssa_refactor/struct_array_inputs/Prover.toml diff --git a/crates/nargo_cli/tests/test_data/struct_array_inputs/src/main.nr b/crates/nargo_cli/tests/test_data_ssa_refactor/struct_array_inputs/src/main.nr similarity index 100% rename from crates/nargo_cli/tests/test_data/struct_array_inputs/src/main.nr rename to crates/nargo_cli/tests/test_data_ssa_refactor/struct_array_inputs/src/main.nr