Skip to content

Commit b4a0b44

Browse files
authored
refactor: cleaning up CallInterface related utils (#17854)
When I was looking at how to implement `self` approach in contracts I was investigating current implementation of how `ContractInterface` stubs are generated. This made me realize that a lot of utils there can be removed and it can all be made much cleaner by using new Noir features like `<type as Serialize>::N`. When looking at the `create_stub_base` I figured that we can reuse the serialization functionality of `derive_serialize` so I refactored the relevant code out of `derive_serialize` into a separate function that can be reused between the 1 functions. I removed a lot of code so overall I think the outcome is nice.
2 parents 510c394 + a5e09fd commit b4a0b44

File tree

5 files changed

+130
-235
lines changed

5 files changed

+130
-235
lines changed

noir-projects/aztec-nr/aztec/src/macros/dispatch.nr

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
use super::utils::{compute_fn_selector, size_in_fields};
1+
use super::utils::compute_fn_selector;
22
use poseidon::poseidon2::Poseidon2Hasher;
3+
use protocol_types::meta::utils::get_params_len_quote;
34
use std::{collections::umap::UHashMap, hash::BuildHasherDefault, panic};
45

56
/// Returns an `fn public_dispatch(...)` function for the given module that's assumed to be an Aztec contract.
@@ -31,10 +32,7 @@ pub comptime fn generate_public_dispatch(m: Module) -> Quoted {
3132
}
3233
seen_selectors.insert(selector, fn_name);
3334

34-
let mut parameters_size = 0;
35-
for param in parameters {
36-
parameters_size += size_in_fields(param.1);
37-
}
35+
let params_len_quote = get_params_len_quote(parameters);
3836

3937
let initial_read = if parameters.len() == 0 {
4038
quote {}
@@ -46,7 +44,7 @@ pub comptime fn generate_public_dispatch(m: Module) -> Quoted {
4644
// That is, exactly what is expected for a call to the target function,
4745
// but with a selector added at the beginning.
4846
quote {
49-
let input_calldata: [Field; $parameters_size] = dep::aztec::context::public_context::calldata_copy(1, $parameters_size);
47+
let input_calldata: [Field; $params_len_quote] = dep::aztec::context::public_context::calldata_copy(1, $params_len_quote);
5048
let mut reader = dep::aztec::protocol_types::utils::reader::Reader::new(input_calldata);
5149
}
5250
};

noir-projects/aztec-nr/aztec/src/macros/functions/call_interface_stubs.nr

Lines changed: 18 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
// for invoking contract functions across different contexts (private, public, static, utility).
44

55
use crate::macros::utils::{
6-
add_to_field_array, AsStrQuote, compute_fn_selector, is_fn_private, is_fn_public, is_fn_view,
6+
AsStrQuote, compute_fn_selector, is_fn_private, is_fn_public, is_fn_view,
77
};
8+
use protocol_types::meta::utils::derive_serialization_quotes;
89
use std::meta::unquote;
910

1011
comptime global FROM_FIELD: TypedExpr = {
@@ -17,8 +18,6 @@ comptime global FROM_FIELD: TypedExpr = {
1718
.as_typed_expr()
1819
};
1920

20-
comptime global SERIALIZED_ARGS_NAME: Quoted = quote { serialized_args };
21-
2221
pub comptime fn stub_fn(f: FunctionDefinition) -> Quoted {
2322
let is_static_call = is_fn_view(f);
2423

@@ -42,7 +41,7 @@ pub comptime fn stub_fn(f: FunctionDefinition) -> Quoted {
4241
/// Utility function creating stubs used by all the stub functions in this file.
4342
comptime fn create_stub_base(
4443
f: FunctionDefinition,
45-
) -> (Quoted, Quoted, Quoted, Quoted, u32, Field) {
44+
) -> (Quoted, Quoted, Quoted, Quoted, Quoted, u32, Field) {
4645
// Dear privacy adventurer,
4746
// Chances are, you've command+clicked on the name of an external function
4847
// call -- seeking to view that function -- only to end up here.
@@ -63,51 +62,22 @@ comptime fn create_stub_base(
6362
let fn_parameters = f.parameters();
6463
let fn_parameters_list =
6564
fn_parameters.map(|(name, typ): (Quoted, Type)| quote { $name: $typ }).join(quote {,});
66-
let params_num_fields =
67-
fn_parameters.fold(0, |acc, (_, typ)| acc + crate::macros::utils::size_in_fields(typ));
68-
69-
let serialized_args_index_name = quote { serialized_args_index };
70-
// Example of what the fold(...) below will generate for `target_address` and `fee_juice_limit_per_tx` function
71-
// parameters:
72-
// ```
73-
// let mut serialized_args = [0;2];
74-
// let mut serialized_args_index = 0;
75-
// let target_address_serialized = aztec::protocol_types::traits::Serialize::serialize(target_address)
76-
// for i in 0..target_address_serialized.len() {
77-
// serialized_args[serialized_args_index] = target_address_serialized[i];
78-
// serialized_args_index += 1;
79-
// }
80-
// serialized_args[serialized_args_index] = fee_juice_limit_per_tx as Field
81-
// serialized_args_index += 1;
82-
// ```
83-
let serialized_args_array_construction = fn_parameters.fold(
84-
quote {
85-
let mut $SERIALIZED_ARGS_NAME = [0; $params_num_fields];
86-
let mut $serialized_args_index_name: u32 = 0;
87-
},
88-
|args, param: (Quoted, Type)| {
89-
let (name, typ) = param;
90-
let arg_to_append =
91-
add_to_field_array(SERIALIZED_ARGS_NAME, serialized_args_index_name, name, typ);
92-
quote {
93-
$args
94-
$arg_to_append
95-
}
96-
},
97-
);
65+
66+
let (serialized_args_array_construction, _, serialized_args_array_name) =
67+
derive_serialization_quotes(fn_parameters, false);
9868

9969
let (fn_name_str, _) = fn_name.as_str_quote();
10070
let fn_name_len: u32 = unquote!(quote { $fn_name_str.as_bytes().len()});
10171
let fn_selector: Field = compute_fn_selector(f);
10272

10373
(
104-
fn_name, fn_parameters_list, serialized_args_array_construction, fn_name_str, fn_name_len,
105-
fn_selector,
74+
fn_name, fn_parameters_list, serialized_args_array_construction, serialized_args_array_name,
75+
fn_name_str, fn_name_len, fn_selector,
10676
)
10777
}
10878

10979
comptime fn create_private_stub(f: FunctionDefinition) -> Quoted {
110-
let (fn_name, fn_parameters_list, serialized_args_array_construction, fn_name_str, fn_name_len, fn_selector) =
80+
let (fn_name, fn_parameters_list, serialized_args_array_construction, serialized_args_array_name, fn_name_str, fn_name_len, fn_selector) =
11181
create_stub_base(f);
11282
let fn_return_type = f.return_type();
11383

@@ -119,15 +89,15 @@ comptime fn create_private_stub(f: FunctionDefinition) -> Quoted {
11989
self.target_contract,
12090
selector,
12191
$fn_name_str,
122-
$SERIALIZED_ARGS_NAME,
92+
$serialized_args_array_name,
12393
false
12494
)
12595
}
12696
}
12797
}
12898

12999
comptime fn create_private_static_stub(f: FunctionDefinition) -> Quoted {
130-
let (fn_name, fn_parameters_list, serialized_args_slice_construction, fn_name_str, fn_name_len, fn_selector) =
100+
let (fn_name, fn_parameters_list, serialized_args_slice_construction, serialized_args_array_name, fn_name_str, fn_name_len, fn_selector) =
131101
create_stub_base(f);
132102
let fn_return_type = f.return_type();
133103

@@ -139,14 +109,14 @@ comptime fn create_private_static_stub(f: FunctionDefinition) -> Quoted {
139109
self.target_contract,
140110
selector,
141111
$fn_name_str,
142-
$SERIALIZED_ARGS_NAME,
112+
$serialized_args_array_name,
143113
)
144114
}
145115
}
146116
}
147117

148118
comptime fn create_public_stub(f: FunctionDefinition) -> Quoted {
149-
let (fn_name, fn_parameters_list, serialized_args_slice_construction, fn_name_str, fn_name_len, fn_selector) =
119+
let (fn_name, fn_parameters_list, serialized_args_slice_construction, serialized_args_array_name, fn_name_str, fn_name_len, fn_selector) =
150120
create_stub_base(f);
151121
let fn_return_type = f.return_type();
152122

@@ -158,15 +128,15 @@ comptime fn create_public_stub(f: FunctionDefinition) -> Quoted {
158128
self.target_contract,
159129
selector,
160130
$fn_name_str,
161-
$SERIALIZED_ARGS_NAME,
131+
$serialized_args_array_name,
162132
false
163133
)
164134
}
165135
}
166136
}
167137

168138
comptime fn create_public_static_stub(f: FunctionDefinition) -> Quoted {
169-
let (fn_name, fn_parameters_list, serialized_args_slice_construction, fn_name_str, fn_name_len, fn_selector) =
139+
let (fn_name, fn_parameters_list, serialized_args_slice_construction, serialized_args_array_name, fn_name_str, fn_name_len, fn_selector) =
170140
create_stub_base(f);
171141
let fn_return_type = f.return_type();
172142

@@ -178,14 +148,14 @@ comptime fn create_public_static_stub(f: FunctionDefinition) -> Quoted {
178148
self.target_contract,
179149
selector,
180150
$fn_name_str,
181-
$SERIALIZED_ARGS_NAME,
151+
$serialized_args_array_name,
182152
)
183153
}
184154
}
185155
}
186156

187157
comptime fn create_utility_stub(f: FunctionDefinition) -> Quoted {
188-
let (fn_name, fn_parameters_list, serialized_args_slice_construction, fn_name_str, fn_name_len, fn_selector) =
158+
let (fn_name, fn_parameters_list, serialized_args_slice_construction, serialized_args_array_name, fn_name_str, fn_name_len, fn_selector) =
189159
create_stub_base(f);
190160
let fn_return_type = f.return_type();
191161

@@ -197,7 +167,7 @@ comptime fn create_utility_stub(f: FunctionDefinition) -> Quoted {
197167
self.target_contract,
198168
selector,
199169
$fn_name_str,
200-
$SERIALIZED_ARGS_NAME,
170+
$serialized_args_array_name,
201171
)
202172
}
203173
}

noir-projects/aztec-nr/aztec/src/macros/utils.nr

Lines changed: 0 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -72,63 +72,6 @@ pub(crate) comptime fn modify_fn_body(body: [Expr], prepend: Quoted, append: Quo
7272
body_expr.expect(f"Body is not an expression: {body_quote}")
7373
}
7474

75-
/// Adds a value to a field array. Structs and values inside arrays are required to implement the Serialize trait.
76-
///
77-
/// The function takes the name of the array, the index in the array where the value should be added, the name of the
78-
/// variable to be added, and the type of the variable. It returns a quoted expression that can be used in a function body.
79-
///
80-
/// The returned quoted expression will increment the `index_name` variable by the number of fields added to the array,
81-
/// which is typically 1 for simple types, but can be more for complex types like structs or arrays.
82-
pub(crate) comptime fn add_to_field_array(
83-
array_name: Quoted,
84-
index_name: Quoted,
85-
name: Quoted,
86-
typ: Type,
87-
) -> Quoted {
88-
let serialized_name = f"{name}_serialized".quoted_contents();
89-
90-
if typ.is_field() | typ.as_integer().is_some() | typ.is_bool() {
91-
quote {
92-
$array_name[$index_name] = $name as Field;
93-
$index_name += 1;
94-
}
95-
} else if typ.as_data_type().is_some() {
96-
// We invoke serialize as a static trait function rather than calling $name.serialize() directly in the quote
97-
// to avoid "trait not in scope" compiler warnings.
98-
quote {
99-
let $serialized_name = aztec::protocol_types::traits::Serialize::serialize($name);
100-
for i in 0..$serialized_name.len() {
101-
$array_name[$index_name] = $serialized_name[i];
102-
$index_name += 1;
103-
}
104-
}
105-
} else if typ.as_array().is_some() {
106-
// We invoke serialize as a static trait function rather than calling x.serialize() directly in the quote
107-
// to avoid "trait not in scope" compiler warnings.
108-
quote {
109-
for i in 0..$name.len() {
110-
let $serialized_name = aztec::protocol_types::traits::Serialize::serialize($name[i]);
111-
for i in 0..$serialized_name.len() {
112-
$array_name[$index_name] = $serialized_name[i];
113-
$index_name += 1;
114-
}
115-
}
116-
}
117-
} else if typ.as_str().is_some() {
118-
quote {
119-
let $serialized_name = $name.as_bytes();
120-
for i in 0..$serialized_name.len() {
121-
$array_name[$index_name] = $serialized_name[i] as Field;
122-
$index_name += 1;
123-
}
124-
}
125-
} else {
126-
panic(
127-
f"Cannot add to slice: unsupported type {typ} variable {name}",
128-
)
129-
}
130-
}
131-
13275
/// Adds a value to a hash::ArgsHasher. Structs and values inside arrays are required to implement the Serialize trait.
13376
pub(crate) comptime fn add_to_hasher(hasher_name: Quoted, name: Quoted, typ: Type) -> Quoted {
13477
if typ.is_field() | typ.as_integer().is_some() | typ.is_bool() {
@@ -336,79 +279,6 @@ pub(crate) comptime fn get_trait_impl_method(
336279
.as_typed_expr()
337280
}
338281

339-
pub comptime fn size_in_fields(typ: Type) -> u32 {
340-
array_size_in_fields(typ)
341-
.or_else(|| bool_size_in_fields(typ))
342-
.or_else(|| constant_size_in_fields(typ))
343-
.or_else(|| field_size_in_fields(typ))
344-
.or_else(|| int_size_in_fields(typ))
345-
.or_else(|| str_size_in_fields(typ))
346-
.or_else(|| struct_size_in_fields(typ))
347-
.or_else(|| tuple_size_in_fields(typ))
348-
.expect(f"Can't determine size in fields of {typ}")
349-
}
350-
351-
comptime fn array_size_in_fields(typ: Type) -> Option<u32> {
352-
typ.as_array().and_then(|typ: (Type, Type)| {
353-
let (typ, element_size) = typ;
354-
element_size.as_constant().map(|x: u32| x * size_in_fields(typ))
355-
})
356-
}
357-
358-
comptime fn bool_size_in_fields(typ: Type) -> Option<u32> {
359-
if typ.is_bool() {
360-
Option::some(1)
361-
} else {
362-
Option::none()
363-
}
364-
}
365-
366-
comptime fn field_size_in_fields(typ: Type) -> Option<u32> {
367-
if typ.is_field() {
368-
Option::some(1)
369-
} else {
370-
Option::none()
371-
}
372-
}
373-
374-
comptime fn int_size_in_fields(typ: Type) -> Option<u32> {
375-
if typ.as_integer().is_some() {
376-
Option::some(1)
377-
} else {
378-
Option::none()
379-
}
380-
}
381-
382-
comptime fn constant_size_in_fields(typ: Type) -> Option<u32> {
383-
typ.as_constant()
384-
}
385-
386-
comptime fn str_size_in_fields(typ: Type) -> Option<u32> {
387-
typ.as_str().map(|typ| size_in_fields(typ))
388-
}
389-
390-
comptime fn struct_size_in_fields(typ: Type) -> Option<u32> {
391-
typ.as_data_type().map(|typ: (TypeDefinition, [Type])| {
392-
let struct_type = typ.0;
393-
let generics = typ.1;
394-
let mut size = 0;
395-
for field in struct_type.fields(generics) {
396-
size += size_in_fields(field.1);
397-
}
398-
size
399-
})
400-
}
401-
402-
comptime fn tuple_size_in_fields(typ: Type) -> Option<u32> {
403-
typ.as_tuple().map(|types: [Type]| {
404-
let mut size = 0;
405-
for typ in types {
406-
size += size_in_fields(typ);
407-
}
408-
size
409-
})
410-
}
411-
412282
/// Generates a quote that implements `Serialize` for a given struct `s`.
413283
/// If the struct already implements `Serialize`, we return an empty quote.
414284
pub comptime fn derive_serialize_if_not_implemented(s: TypeDefinition) -> Quoted {

0 commit comments

Comments
 (0)