Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(abi): Tuples as inputs/outputs to main #2899

Merged
merged 14 commits into from
Sep 29, 2023
Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "tuple_inputs"
type = "bin"
authors = [""]
compiler_version = "0.14.1"

[dependencies]
12 changes: 12 additions & 0 deletions tooling/nargo_cli/tests/execution_success/tuple_inputs/Prover.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
pair = [1, 0]
x = [[0, 1, 2], [3, 4, 5]]

[[struct_pair]]
a = "1"
b = ["2", "3", "20"]

[struct_pair.bar]
inner = ["100", "101", "102"]

[[struct_pair]]
inner = ["103", "104", "105"]
37 changes: 37 additions & 0 deletions tooling/nargo_cli/tests/execution_success/tuple_inputs/src/main.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
struct Bar {
inner: [Field; 3],
}

struct Foo {
a: Field,
b: [Field; 3],
bar: Bar,
}

fn main(pair : (Field, Field), x: [(u8, u8, u8); 2], struct_pair: (Foo, Bar)) -> pub (Field, u8) {
assert(pair.0 == 1);
assert(pair.1 == 0);

let mut start_val = 0;
for i in 0..2 {
assert(x[i].0 == start_val);
assert(x[i].1 == start_val + 1);
assert(x[i].2 == start_val + 2);
start_val += 3;
}

assert(struct_pair.0.a == 1);
assert(struct_pair.0.b == [2, 3, 20]);
assert(struct_pair.0.bar.inner == [100, 101, 102]);
assert(struct_pair.1.inner == [103, 104, 105]);

let (u, v) = if pair.0 as u32 < 1 {
(pair.0, pair.0 + 1)
} else {
(pair.0 + 1, pair.0)
};
assert(u == pair.0 + 1);
assert(v == pair.0);

(u, v as u8)
}
14 changes: 14 additions & 0 deletions tooling/noirc_abi/src/input_parser/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,13 @@ impl JsonTypes {
JsonTypes::Table(map_with_json_types)
}

(InputValue::Vec(vector), AbiType::Tuple { fields }) => {
let fields = try_vecmap(vector.iter().zip(fields), |(value, typ)| {
JsonTypes::try_from_input_value(value, typ)
})?;
JsonTypes::Array(fields)
}

_ => return Err(InputParserError::AbiTypeMismatch(abi_type.clone())),
};
Ok(json_value)
Expand Down Expand Up @@ -169,6 +176,13 @@ impl InputValue {
InputValue::Struct(native_table)
}

(JsonTypes::Array(array), AbiType::Tuple { fields }) => {
let tuple_fields = try_vecmap(array.into_iter().zip(fields), |(value, typ)| {
InputValue::try_from_json(value, typ, arg_name)
})?;
InputValue::Vec(tuple_fields)
}

(_, _) => return Err(InputParserError::AbiTypeMismatch(param_type.clone())),
};

Expand Down
11 changes: 11 additions & 0 deletions tooling/noirc_abi/src/input_parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,17 @@ impl InputValue {
})
}

(InputValue::Vec(vec_elements), AbiType::Tuple { fields }) => {
if vec_elements.len() != fields.len() {
return false;
}

vec_elements
.iter()
.zip(fields)
.all(|(input_value, abi_param)| input_value.matches_abi(abi_param))
}

// All other InputValue-AbiType combinations are fundamentally incompatible.
_ => false,
}
Expand Down
14 changes: 14 additions & 0 deletions tooling/noirc_abi/src/input_parser/toml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,13 @@ impl TomlTypes {
TomlTypes::Table(map_with_toml_types)
}

(InputValue::Vec(vector), AbiType::Tuple { fields }) => {
let fields = try_vecmap(vector.iter().zip(fields), |(value, typ)| {
TomlTypes::try_from_input_value(value, typ)
})?;
TomlTypes::Array(fields)
}

_ => return Err(InputParserError::AbiTypeMismatch(abi_type.clone())),
};
Ok(toml_value)
Expand Down Expand Up @@ -156,6 +163,13 @@ impl InputValue {
InputValue::Struct(native_table)
}

(TomlTypes::Array(array), AbiType::Tuple { fields }) => {
let tuple_fields = try_vecmap(array.into_iter().zip(fields), |(value, typ)| {
InputValue::try_from_toml(value, typ, arg_name)
})?;
InputValue::Vec(tuple_fields)
}

(_, _) => return Err(InputParserError::AbiTypeMismatch(param_type.clone())),
};

Expand Down
24 changes: 23 additions & 1 deletion tooling/noirc_abi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ pub enum AbiType {
)]
fields: Vec<(String, AbiType)>,
},
Tuple {
fields: Vec<AbiType>,
},
String {
length: u64,
},
Expand Down Expand Up @@ -164,7 +167,10 @@ impl AbiType {
context.fully_qualified_struct_path(context.root_crate_id(), struct_type.id);
Self::Struct { fields, path }
}
Type::Tuple(_) => todo!("AbiType::from_type not yet implemented for tuple types"),
Type::Tuple(fields) => {
let fields = vecmap(fields, |typ| Self::from_type(context, typ));
Self::Tuple { fields }
}
Type::TypeVariable(_, _) => unreachable!(),
Type::NamedGeneric(..) => unreachable!(),
Type::Forall(..) => unreachable!(),
Expand All @@ -182,6 +188,9 @@ impl AbiType {
AbiType::Struct { fields, .. } => {
fields.iter().fold(0, |acc, (_, field_type)| acc + field_type.field_count())
}
AbiType::Tuple { fields } => {
fields.iter().fold(0, |acc, field_typ| acc + field_typ.field_count())
}
AbiType::String { length } => *length as u32,
}
}
Expand Down Expand Up @@ -370,6 +379,11 @@ impl Abi {
encoded_value.extend(Self::encode_value(object[field].clone(), typ)?);
}
}
(InputValue::Vec(vec_elements), AbiType::Tuple { fields }) => {
for (value, typ) in vec_elements.into_iter().zip(fields) {
encoded_value.extend(Self::encode_value(value, typ)?);
}
}
_ => unreachable!("value should have already been checked to match abi type"),
}
Ok(encoded_value)
Expand Down Expand Up @@ -462,6 +476,14 @@ fn decode_value(

InputValue::Struct(struct_map)
}
AbiType::Tuple { fields } => {
let mut tuple_elements = Vec::with_capacity(fields.len());
for field_typ in fields {
tuple_elements.push(decode_value(field_iterator, field_typ)?);
}

InputValue::Vec(tuple_elements)
}
};

Ok(value)
Expand Down
14 changes: 14 additions & 0 deletions tooling/noirc_abi_wasm/src/temp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ impl JsonTypes {
JsonTypes::Table(map_with_json_types)
}

(InputValue::Vec(vector), AbiType::Tuple { fields }) => {
let fields = try_vecmap(vector.iter().zip(fields), |(value, typ)| {
JsonTypes::try_from_input_value(value, typ)
})?;
JsonTypes::Array(fields)
}

_ => return Err(InputParserError::AbiTypeMismatch(abi_type.clone())),
};
Ok(json_value)
Expand Down Expand Up @@ -104,6 +111,13 @@ pub(super) fn input_value_from_json_type(
InputValue::Struct(native_table)
}

(JsonTypes::Array(array), AbiType::Tuple { fields }) => {
let tuple_fields = try_vecmap(array.into_iter().zip(fields), |(value, typ)| {
input_value_from_json_type(value, typ, arg_name)
})?;
InputValue::Vec(tuple_fields)
}

(_, _) => return Err(InputParserError::AbiTypeMismatch(param_type.clone())),
};

Expand Down
Loading