@aztec-foundation/protocol-contracts-artifacts 6.0.0-rc.6 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1306,31 +1306,31 @@
1306
1306
  },
1307
1307
  {
1308
1308
  "name": "Poseidon2::absorb",
1309
- "start": 923
1309
+ "start": 1028
1310
1310
  },
1311
1311
  {
1312
1312
  "name": "Poseidon2::squeeze",
1313
- "start": 1453
1313
+ "start": 1558
1314
1314
  },
1315
1315
  {
1316
1316
  "name": "Poseidon2::hash_internal",
1317
- "start": 1814
1317
+ "start": 1919
1318
1318
  },
1319
1319
  {
1320
1320
  "name": "<impl Hasher for Poseidon2Hasher>::finish",
1321
- "start": 4105
1321
+ "start": 4210
1322
1322
  },
1323
1323
  {
1324
1324
  "name": "<impl Hasher for Poseidon2Hasher>::write",
1325
- "start": 4426
1325
+ "start": 4531
1326
1326
  },
1327
1327
  {
1328
1328
  "name": "<impl Default for Poseidon2Hasher>::default",
1329
- "start": 4549
1329
+ "start": 4654
1330
1330
  }
1331
1331
  ],
1332
- "path": "/home/aztec-dev/nargo/github.com/noir-lang/poseidon/v0.3.0/src/poseidon2.nr",
1333
- "source": "use std::default::Default;\nuse std::hash::Hasher;\n\nglobal RATE: u32 = 3;\n\npub struct Poseidon2 {\n cache: [Field; 3],\n state: [Field; 4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n #[no_predicates]\n pub fn hash<let N: u32>(input: [Field; N], message_size: u32) -> Field {\n Poseidon2::hash_internal(input, message_size)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2 {\n let mut result =\n Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) {\n // add the cache into sponge state\n self.state[0] += self.cache[0];\n self.state[1] += self.cache[1];\n self.state[2] += self.cache[2];\n self.state = crate::poseidon2_permutation(self.state);\n }\n\n fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal<let N: u32>(input: [Field; N], in_len: u32) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv: Field = (in_len as Field) * two_pow_64;\n let mut state = [0; 4];\n state[RATE] = iv;\n\n if std::runtime::is_unconstrained() {\n for i in 0..(in_len / RATE) {\n state[0] += input[i * RATE];\n state[1] += input[i * RATE + 1];\n state[2] += input[i * RATE + 2];\n state = crate::poseidon2_permutation(state);\n }\n\n // handle remaining elements after last full RATE-sized chunk\n let num_extra_fields = in_len % RATE;\n if num_extra_fields != 0 {\n let remainder_start = in_len - num_extra_fields;\n state[0] += input[remainder_start];\n if num_extra_fields > 1 {\n state[1] += input[remainder_start + 1];\n }\n }\n } else {\n let mut states: [[Field; 4]; N / RATE + 1] = [[0; 4]; N / RATE + 1];\n states[0] = state;\n\n // process all full RATE-sized chunks, storing state after each permutation\n for chunk_idx in 0..(N / RATE) {\n for i in 0..RATE {\n state[i] += input[chunk_idx * RATE + i];\n }\n state = crate::poseidon2_permutation(state);\n states[chunk_idx + 1] = state;\n }\n\n // get state at the last full block before in_len\n let first_partially_filled_chunk = in_len / RATE;\n state = states[first_partially_filled_chunk];\n\n // handle remaining elements after last full RATE-sized chunk\n let remainder_start = (in_len / RATE) * RATE;\n for j in 0..RATE {\n let idx = remainder_start + j;\n if idx < in_len {\n state[j] += input[idx];\n }\n }\n }\n\n // always run final permutation unless we just completed a full chunk\n // still need to permute once if in_len is 0\n if (in_len == 0) | (in_len % RATE != 0) {\n state = crate::poseidon2_permutation(state);\n };\n\n state[0]\n }\n}\n\npub struct Poseidon2Hasher {\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv: Field = (self._state.len() as Field) * 18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field) {\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher { _state: @[] }\n }\n}\n"
1332
+ "path": "/home/aztec-dev/nargo/github.com/noir-lang/poseidon/v0.4.0/src/poseidon2.nr",
1333
+ "source": "use std::default::Default;\nuse std::hash::Hasher;\n\nglobal RATE: u32 = 3;\n\npub struct Poseidon2 {\n cache: [Field; 3],\n state: [Field; 4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n #[no_predicates]\n pub fn hash<let N: u32>(input: [Field; N], message_size: u32) -> Field {\n Poseidon2::hash_internal(input, message_size)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2 {\n let mut result =\n Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) {\n // add the cache into sponge state\n self.state[0] += self.cache[0] * ((0 < self.cache_size) as Field);\n self.state[1] += self.cache[1] * ((1 < self.cache_size) as Field);\n self.state[2] += self.cache[2] * ((2 < self.cache_size) as Field);\n self.state = crate::poseidon2_permutation(self.state);\n }\n\n fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal<let N: u32>(input: [Field; N], in_len: u32) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv: Field = (in_len as Field) * two_pow_64;\n let mut state = [0; 4];\n state[RATE] = iv;\n\n if std::runtime::is_unconstrained() {\n for i in 0..(in_len / RATE) {\n state[0] += input[i * RATE];\n state[1] += input[i * RATE + 1];\n state[2] += input[i * RATE + 2];\n state = crate::poseidon2_permutation(state);\n }\n\n // handle remaining elements after last full RATE-sized chunk\n let num_extra_fields = in_len % RATE;\n if num_extra_fields != 0 {\n let remainder_start = in_len - num_extra_fields;\n state[0] += input[remainder_start];\n if num_extra_fields > 1 {\n state[1] += input[remainder_start + 1];\n }\n }\n } else {\n let mut states: [[Field; 4]; N / RATE + 1] = [[0; 4]; N / RATE + 1];\n states[0] = state;\n\n // process all full RATE-sized chunks, storing state after each permutation\n for chunk_idx in 0..(N / RATE) {\n for i in 0..RATE {\n state[i] += input[chunk_idx * RATE + i];\n }\n state = crate::poseidon2_permutation(state);\n states[chunk_idx + 1] = state;\n }\n\n // get state at the last full block before in_len\n let first_partially_filled_chunk = in_len / RATE;\n state = states[first_partially_filled_chunk];\n\n // handle remaining elements after last full RATE-sized chunk\n let remainder_start = (in_len / RATE) * RATE;\n for j in 0..RATE {\n let idx = remainder_start + j;\n if idx < in_len {\n state[j] += input[idx];\n }\n }\n }\n\n // always run final permutation unless we just completed a full chunk\n // still need to permute once if in_len is 0\n if (in_len == 0) | (in_len % RATE != 0) {\n state = crate::poseidon2_permutation(state);\n };\n\n state[0]\n }\n}\n\npub struct Poseidon2Hasher {\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv: Field = (self._state.len() as Field) * 18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field) {\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher { _state: @[] }\n }\n}\n"
1334
1334
  },
1335
1335
  "233": {
1336
1336
  "function_locations": [
@@ -1390,23 +1390,23 @@
1390
1390
  },
1391
1391
  {
1392
1392
  "name": "derive_deserialize",
1393
- "start": 7176
1393
+ "start": 7397
1394
1394
  },
1395
1395
  {
1396
1396
  "name": "get_params_len_quote",
1397
- "start": 11002
1397
+ "start": 11362
1398
1398
  },
1399
1399
  {
1400
1400
  "name": "get_generics_declarations",
1401
- "start": 11494
1401
+ "start": 11854
1402
1402
  },
1403
1403
  {
1404
1404
  "name": "get_where_trait_clause",
1405
- "start": 12587
1405
+ "start": 12947
1406
1406
  }
1407
1407
  ],
1408
1408
  "path": "/home/aztec-dev/aztec-packages/noir-projects/fnd/noir-protocol-circuits/crates/serde/src/serialization.nr",
1409
- "source": "use crate::{reader::Reader, writer::Writer};\nuse std::meta::type_def::StructField;\n\n/// Trait for serializing Noir types into arrays of Fields.\n///\n/// An implementation of the Serialize trait has to follow Noir's intrinsic serialization (each member of a struct\n/// converted directly into one or more Fields without any packing or compression). This trait (and Deserialize) are\n/// typically used to communicate between Noir and TypeScript (via oracles and function arguments).\n///\n/// # On Following Noir's Intrinsic Serialization\n/// When calling a Noir function from TypeScript (TS), first the function arguments are serialized into an array\n/// of fields. This array is then included in the initial witness. Noir's intrinsic serialization is then used\n/// to deserialize the arguments from the witness. When the same Noir function is called from Noir this Serialize trait\n/// is used instead of the serialization in TS. For this reason we need to have a match between TS serialization,\n/// Noir's intrinsic serialization and the implementation of this trait. If there is a mismatch, the function calls\n/// fail with an arguments hash mismatch error message.\n///\n/// # Associated Constants\n/// * `N` - The length of the output Field array, known at compile time\n///\n/// # Example\n/// ```\n/// impl<let N: u32> Serialize for str<N> {\n/// let N: u32 = N;\n///\n/// fn serialize(self) -> [Field; Self::N] {\n/// let mut writer: Writer<Self::N> = Writer::new();\n/// self.stream_serialize(&mut writer);\n/// writer.finish()\n/// }\n///\n/// fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n/// let bytes = self.as_bytes();\n/// for i in 0..bytes.len() {\n/// writer.write(bytes[i] as Field);\n/// }\n/// }\n/// }\n/// ```\n#[derive_via(derive_serialize)]\npub trait Serialize {\n let N: u32;\n\n fn serialize(self) -> [Field; Self::N];\n\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>);\n}\n\n/// Generates a `Serialize` trait implementation for a struct type.\n///\n/// # Parameters\n/// - `s`: The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A quoted code block containing the trait implementation\n///\n/// # Example\n/// For a struct defined as:\n/// ```\n/// struct Log<N> {\n/// fields: [Field; N],\n/// length: u32\n/// }\n/// ```\n///\n/// This function generates code equivalent to:\n/// ```\n/// impl<let N: u32> Serialize for Log<N> {\n/// let N: u32 = <[Field; N] as Serialize>::N + <u32 as Serialize>::N;\n///\n/// fn serialize(self) -> [Field; Self::N] {\n/// let mut writer: Writer<Self::N> = Writer::new();\n/// self.stream_serialize(&mut writer);\n/// writer.finish()\n/// }\n///\n/// #[inline_always]\n/// fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n/// Serialize::stream_serialize(self.fields, writer);\n/// Serialize::stream_serialize(self.length, writer);\n/// }\n/// }\n/// ```\npub comptime fn derive_serialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n let params = nested_struct.definition().fields(nested_struct.generics());\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Serialize` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_serialize_clause = get_where_trait_clause(s, quote { Serialize });\n\n let params_len_quote = get_params_len_quote(params);\n\n let function_body = params\n .map(|field: StructField| {\n let name = field.name();\n quote {\n $crate::serialization::Serialize::stream_serialize(self.$name, writer);\n }\n })\n .join(quote {});\n\n quote {\n impl$generics_declarations $crate::serialization::Serialize for $typ\n $where_serialize_clause\n {\n let N: u32 = $params_len_quote;\n\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: $crate::writer::Writer<Self::N> = $crate::writer::Writer::new();\n $crate::serialization::Serialize::stream_serialize(self, &mut writer);\n writer.finish()\n }\n\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut $crate::writer::Writer<K>) {\n $function_body\n }\n }\n }\n}\n\n/// Trait for deserializing Noir types from arrays of Fields.\n///\n/// An implementation of the Deserialize trait has to follow Noir's intrinsic serialization (each member of a struct\n/// converted directly into one or more Fields without any packing or compression). This trait is typically used when\n/// deserializing return values from function calls in Noir. Since the same function could be called from TypeScript\n/// (TS), in which case the TS deserialization would get used, we need to have a match between the 2.\n///\n/// # Associated Constants\n/// * `N` - The length of the input Field array, known at compile time\n///\n/// # Example\n/// ```\n/// impl<let M: u32> Deserialize for str<M> {\n/// let N: u32 = M;\n///\n/// fn deserialize(fields: [Field; Self::N]) -> Self {\n/// let mut reader = Reader::new(fields);\n/// let result = Self::stream_deserialize(&mut reader);\n/// reader.finish();\n/// result\n/// }\n///\n/// fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n/// let mut bytes = [0 as u8; M];\n/// for i in 0..M {\n/// bytes[i] = reader.read() as u8;\n/// }\n/// str::<M>::from(bytes)\n/// }\n/// }\n/// ```\n#[derive_via(derive_deserialize)]\npub trait Deserialize {\n let N: u32;\n\n fn deserialize(fields: [Field; Self::N]) -> Self;\n\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self;\n}\n\n/// Generates a `Deserialize` trait implementation for a given struct `s`.\n///\n/// # Arguments\n/// * `s` - The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A `Quoted` block containing the generated trait implementation\n///\n/// # Requirements\n/// Each struct member type must implement the `Deserialize` trait (it gets used in the generated code).\n///\n/// # Example\n/// For a struct like:\n/// ```\n/// struct MyStruct {\n/// x: AztecAddress,\n/// y: Field,\n/// }\n/// ```\n///\n/// This generates:\n/// ```\n/// impl Deserialize for MyStruct {\n/// let N: u32 = <AztecAddress as Deserialize>::N + <Field as Deserialize>::N;\n///\n/// fn deserialize(fields: [Field; Self::N]) -> Self {\n/// let mut reader = Reader::new(fields);\n/// let result = Self::stream_deserialize(&mut reader);\n/// reader.finish();\n/// result\n/// }\n///\n/// #[inline_always]\n/// fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n/// let x = <AztecAddress as Deserialize>::stream_deserialize(reader);\n/// let y = <Field as Deserialize>::stream_deserialize(reader);\n/// Self { x, y }\n/// }\n/// }\n/// ```\npub comptime fn derive_deserialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n let params = nested_struct.definition().fields(nested_struct.generics());\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Deserialize` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_deserialize_clause = get_where_trait_clause(s, quote { Deserialize });\n\n // The following will give us:\n // <type_of_struct_member_1 as Deserialize>::N + <type_of_struct_member_2 as Deserialize>::N + ...\n // (or 0 if the struct has no members)\n let right_hand_side_of_definition_of_n = if params.len() > 0 {\n params\n .map(|field: StructField| {\n let param_type = field.typ();\n quote {\n <$param_type as $crate::serialization::Deserialize>::N\n }\n })\n .join(quote {+})\n } else {\n quote { 0 }\n };\n\n // For structs containing a single member, we can enhance performance by directly deserializing the input array,\n // bypassing the need for loop-based array construction. While this optimization yields significant benefits in\n // Brillig where the loops are expected to not be optimized, it is not relevant in ACIR where the loops are\n // expected to be optimized away.\n let function_body = if params.len() > 1 {\n // This generates deserialization code for each struct member and concatenates them together.\n let deserialization_of_struct_members = params\n .map(|field: StructField| {\n let param_name = field.name();\n let param_type = field.typ();\n quote {\n let $param_name = <$param_type as Deserialize>::stream_deserialize(reader);\n }\n })\n .join(quote {});\n\n // We join the struct member names with a comma to be used in the `Self { ... }` syntax\n // This will give us e.g. `a, b, c` for a struct with three fields named `a`, `b`, and `c`.\n let struct_members = params\n .map(|field: StructField| {\n let param_name = field.name();\n quote { $param_name }\n })\n .join(quote {,});\n\n quote {\n $deserialization_of_struct_members\n\n Self { $struct_members }\n }\n } else if params.len() == 1 {\n let param_name = params[0].name();\n quote {\n Self { $param_name: $crate::serialization::Deserialize::stream_deserialize(reader) }\n }\n } else {\n quote {\n Self {}\n }\n };\n\n quote {\n impl$generics_declarations $crate::serialization::Deserialize for $typ\n $where_deserialize_clause\n {\n let N: u32 = $right_hand_side_of_definition_of_n;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = $crate::reader::Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut $crate::reader::Reader<K>) -> Self {\n $function_body\n }\n }\n }\n}\n\n/// Generates a quoted expression that computes the total serialized length of function parameters.\n///\n/// # Parameters\n/// * `params` - The struct fields to serialize. Each field's type needs to implement the Serialize trait.\n///\n/// # Returns\n/// A quoted expression that evaluates to:\n/// * `0` if there are no parameters\n/// * `(<type1 as Serialize>::N + <type2 as Serialize>::N + ...)` for one or more parameters\ncomptime fn get_params_len_quote(params: [StructField]) -> Quoted {\n if params.len() == 0 {\n quote { 0 }\n } else {\n let params_quote_without_parentheses = params\n .map(|field: StructField| {\n let param_type = field.typ();\n quote {\n <$param_type as $crate::serialization::Serialize>::N\n }\n })\n .join(quote {+});\n quote { ($params_quote_without_parentheses) }\n }\n}\n\ncomptime fn get_generics_declarations(s: TypeDefinition) -> Quoted {\n let generics = s.generics();\n\n if generics.len() > 0 {\n let generics_declarations_items = generics\n .map(|generic| {\n let name = generic.typ();\n let maybe_integer_typ = generic.numeric_type();\n // numeric_type is Some only when the generic is numeric.\n if maybe_integer_typ.is_some() {\n // The generic is numeric, so we return a quote defined as e.g. \"let N: u32\"\n let integer_type = maybe_integer_typ.unwrap();\n quote {let $name: $integer_type}\n } else {\n // The generic is not numeric, so we return a quote containing the name of the generic (e.g. \"T\")\n quote { $name }\n }\n })\n .join(quote {,});\n quote {<$generics_declarations_items>}\n } else {\n // The struct doesn't have any generics defined, so we just return an empty quote.\n quote {}\n }\n}\n\ncomptime fn get_where_trait_clause(s: TypeDefinition, trait_name: Quoted) -> Quoted {\n let generics = s.generics();\n\n // numeric_type is Some only when the generic is numeric.\n let non_numeric_generics = generics.filter(|generic| generic.numeric_type().is_none());\n\n if non_numeric_generics.len() > 0 {\n let non_numeric_generics_declarations = non_numeric_generics\n .map(|generic| {\n let name = generic.typ();\n quote {$name: $trait_name}\n })\n .join(quote {,});\n quote {where $non_numeric_generics_declarations}\n } else {\n // There are no non-numeric generics, so we return an empty quote.\n quote {}\n }\n}\n"
1409
+ "source": "use crate::{reader::Reader, writer::Writer};\nuse std::meta::type_def::StructField;\n\n/// Trait for serializing Noir types into arrays of Fields.\n///\n/// An implementation of the Serialize trait has to follow Noir's intrinsic serialization (each member of a struct\n/// converted directly into one or more Fields without any packing or compression). This trait (and Deserialize) are\n/// typically used to communicate between Noir and TypeScript (via oracles and function arguments).\n///\n/// # On Following Noir's Intrinsic Serialization\n/// When calling a Noir function from TypeScript (TS), first the function arguments are serialized into an array\n/// of fields. This array is then included in the initial witness. Noir's intrinsic serialization is then used\n/// to deserialize the arguments from the witness. When the same Noir function is called from Noir this Serialize trait\n/// is used instead of the serialization in TS. For this reason we need to have a match between TS serialization,\n/// Noir's intrinsic serialization and the implementation of this trait. If there is a mismatch, the function calls\n/// fail with an arguments hash mismatch error message.\n///\n/// # Associated Constants\n/// * `N` - The length of the output Field array, known at compile time\n///\n/// # Example\n/// ```\n/// impl<let N: u32> Serialize for str<N> {\n/// let N: u32 = N;\n///\n/// fn serialize(self) -> [Field; Self::N] {\n/// let mut writer: Writer<Self::N> = Writer::new();\n/// self.stream_serialize(&mut writer);\n/// writer.finish()\n/// }\n///\n/// fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n/// let bytes = self.as_bytes();\n/// for i in 0..bytes.len() {\n/// writer.write(bytes[i] as Field);\n/// }\n/// }\n/// }\n/// ```\n#[derive_via(derive_serialize)]\npub trait Serialize {\n let N: u32;\n\n fn serialize(self) -> [Field; Self::N];\n\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>);\n}\n\n/// Generates a `Serialize` trait implementation for a struct type.\n///\n/// # Parameters\n/// - `s`: The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A quoted code block containing the trait implementation\n///\n/// # Example\n/// For a struct defined as:\n/// ```\n/// struct Log<N> {\n/// fields: [Field; N],\n/// length: u32\n/// }\n/// ```\n///\n/// This function generates code equivalent to:\n/// ```\n/// impl<let N: u32> Serialize for Log<N> {\n/// let N: u32 = <[Field; N] as Serialize>::N + <u32 as Serialize>::N;\n///\n/// fn serialize(self) -> [Field; Self::N] {\n/// let mut writer: Writer<Self::N> = Writer::new();\n/// self.stream_serialize(&mut writer);\n/// writer.finish()\n/// }\n///\n/// #[inline_always]\n/// fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n/// Serialize::stream_serialize(self.fields, writer);\n/// Serialize::stream_serialize(self.length, writer);\n/// }\n/// }\n/// ```\npub comptime fn derive_serialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n let params = nested_struct.definition().fields(nested_struct.generics());\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Serialize` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_serialize_clause = get_where_trait_clause(s, quote { Serialize });\n\n let params_len_quote = get_params_len_quote(params);\n\n let function_body = if params.len() == 0 {\n // Nothing to serialize, so the parameter is referenced to keep the generated function warning-free.\n quote { let _ = writer; }\n } else {\n params\n .map(|field: StructField| {\n let name = field.name();\n quote {\n $crate::serialization::Serialize::stream_serialize(self.$name, writer);\n }\n })\n .join(quote {})\n };\n\n quote {\n impl$generics_declarations $crate::serialization::Serialize for $typ\n $where_serialize_clause\n {\n let N: u32 = $params_len_quote;\n\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: $crate::writer::Writer<Self::N> = $crate::writer::Writer::new();\n $crate::serialization::Serialize::stream_serialize(self, &mut writer);\n writer.finish()\n }\n\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut $crate::writer::Writer<K>) {\n $function_body\n }\n }\n }\n}\n\n/// Trait for deserializing Noir types from arrays of Fields.\n///\n/// An implementation of the Deserialize trait has to follow Noir's intrinsic serialization (each member of a struct\n/// converted directly into one or more Fields without any packing or compression). This trait is typically used when\n/// deserializing return values from function calls in Noir. Since the same function could be called from TypeScript\n/// (TS), in which case the TS deserialization would get used, we need to have a match between the 2.\n///\n/// # Associated Constants\n/// * `N` - The length of the input Field array, known at compile time\n///\n/// # Example\n/// ```\n/// impl<let M: u32> Deserialize for str<M> {\n/// let N: u32 = M;\n///\n/// fn deserialize(fields: [Field; Self::N]) -> Self {\n/// let mut reader = Reader::new(fields);\n/// let result = Self::stream_deserialize(&mut reader);\n/// reader.finish();\n/// result\n/// }\n///\n/// fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n/// let mut bytes = [0 as u8; M];\n/// for i in 0..M {\n/// bytes[i] = reader.read() as u8;\n/// }\n/// str::<M>::from(bytes)\n/// }\n/// }\n/// ```\n#[derive_via(derive_deserialize)]\npub trait Deserialize {\n let N: u32;\n\n fn deserialize(fields: [Field; Self::N]) -> Self;\n\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self;\n}\n\n/// Generates a `Deserialize` trait implementation for a given struct `s`.\n///\n/// # Arguments\n/// * `s` - The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A `Quoted` block containing the generated trait implementation\n///\n/// # Requirements\n/// Each struct member type must implement the `Deserialize` trait (it gets used in the generated code).\n///\n/// # Example\n/// For a struct like:\n/// ```\n/// struct MyStruct {\n/// x: AztecAddress,\n/// y: Field,\n/// }\n/// ```\n///\n/// This generates:\n/// ```\n/// impl Deserialize for MyStruct {\n/// let N: u32 = <AztecAddress as Deserialize>::N + <Field as Deserialize>::N;\n///\n/// fn deserialize(fields: [Field; Self::N]) -> Self {\n/// let mut reader = Reader::new(fields);\n/// let result = Self::stream_deserialize(&mut reader);\n/// reader.finish();\n/// result\n/// }\n///\n/// #[inline_always]\n/// fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n/// let x = <AztecAddress as Deserialize>::stream_deserialize(reader);\n/// let y = <Field as Deserialize>::stream_deserialize(reader);\n/// Self { x, y }\n/// }\n/// }\n/// ```\npub comptime fn derive_deserialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n let params = nested_struct.definition().fields(nested_struct.generics());\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Deserialize` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_deserialize_clause = get_where_trait_clause(s, quote { Deserialize });\n\n // The following will give us:\n // <type_of_struct_member_1 as Deserialize>::N + <type_of_struct_member_2 as Deserialize>::N + ...\n // (or 0 if the struct has no members)\n let right_hand_side_of_definition_of_n = if params.len() > 0 {\n params\n .map(|field: StructField| {\n let param_type = field.typ();\n quote {\n <$param_type as $crate::serialization::Deserialize>::N\n }\n })\n .join(quote {+})\n } else {\n quote { 0 }\n };\n\n // For structs containing a single member, we can enhance performance by directly deserializing the input array,\n // bypassing the need for loop-based array construction. While this optimization yields significant benefits in\n // Brillig where the loops are expected to not be optimized, it is not relevant in ACIR where the loops are\n // expected to be optimized away.\n let function_body = if params.len() > 1 {\n // This generates deserialization code for each struct member and concatenates them together.\n let deserialization_of_struct_members = params\n .map(|field: StructField| {\n let param_name = field.name();\n let param_type = field.typ();\n quote {\n let $param_name = <$param_type as Deserialize>::stream_deserialize(reader);\n }\n })\n .join(quote {});\n\n // We join the struct member names with a comma to be used in the `Self { ... }` syntax\n // This will give us e.g. `a, b, c` for a struct with three fields named `a`, `b`, and `c`.\n let struct_members = params\n .map(|field: StructField| {\n let param_name = field.name();\n quote { $param_name }\n })\n .join(quote {,});\n\n quote {\n $deserialization_of_struct_members\n\n Self { $struct_members }\n }\n } else if params.len() == 1 {\n let param_name = params[0].name();\n quote {\n Self { $param_name: $crate::serialization::Deserialize::stream_deserialize(reader) }\n }\n } else {\n // Nothing to deserialize, so the parameter is referenced to keep the generated function warning-free.\n quote {\n let _ = reader;\n Self {}\n }\n };\n\n quote {\n impl$generics_declarations $crate::serialization::Deserialize for $typ\n $where_deserialize_clause\n {\n let N: u32 = $right_hand_side_of_definition_of_n;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = $crate::reader::Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut $crate::reader::Reader<K>) -> Self {\n $function_body\n }\n }\n }\n}\n\n/// Generates a quoted expression that computes the total serialized length of function parameters.\n///\n/// # Parameters\n/// * `params` - The struct fields to serialize. Each field's type needs to implement the Serialize trait.\n///\n/// # Returns\n/// A quoted expression that evaluates to:\n/// * `0` if there are no parameters\n/// * `(<type1 as Serialize>::N + <type2 as Serialize>::N + ...)` for one or more parameters\ncomptime fn get_params_len_quote(params: [StructField]) -> Quoted {\n if params.len() == 0 {\n quote { 0 }\n } else {\n let params_quote_without_parentheses = params\n .map(|field: StructField| {\n let param_type = field.typ();\n quote {\n <$param_type as $crate::serialization::Serialize>::N\n }\n })\n .join(quote {+});\n quote { ($params_quote_without_parentheses) }\n }\n}\n\ncomptime fn get_generics_declarations(s: TypeDefinition) -> Quoted {\n let generics = s.generics();\n\n if generics.len() > 0 {\n let generics_declarations_items = generics\n .map(|generic| {\n let name = generic.typ();\n let maybe_integer_typ = generic.numeric_type();\n // numeric_type is Some only when the generic is numeric.\n if maybe_integer_typ.is_some() {\n // The generic is numeric, so we return a quote defined as e.g. \"let N: u32\"\n let integer_type = maybe_integer_typ.unwrap();\n quote {let $name: $integer_type}\n } else {\n // The generic is not numeric, so we return a quote containing the name of the generic (e.g. \"T\")\n quote { $name }\n }\n })\n .join(quote {,});\n quote {<$generics_declarations_items>}\n } else {\n // The struct doesn't have any generics defined, so we just return an empty quote.\n quote {}\n }\n}\n\ncomptime fn get_where_trait_clause(s: TypeDefinition, trait_name: Quoted) -> Quoted {\n let generics = s.generics();\n\n // numeric_type is Some only when the generic is numeric.\n let non_numeric_generics = generics.filter(|generic| generic.numeric_type().is_none());\n\n if non_numeric_generics.len() > 0 {\n let non_numeric_generics_declarations = non_numeric_generics\n .map(|generic| {\n let name = generic.typ();\n quote {$name: $trait_name}\n })\n .join(quote {,});\n quote {where $non_numeric_generics_declarations}\n } else {\n // There are no non-numeric generics, so we return an empty quote.\n quote {}\n }\n}\n"
1410
1410
  },
1411
1411
  "236": {
1412
1412
  "function_locations": [
@@ -1612,115 +1612,111 @@
1612
1612
  },
1613
1613
  {
1614
1614
  "name": "<impl Deserialize for Option<T>>::deserialize",
1615
- "start": 10997
1615
+ "start": 11278
1616
1616
  },
1617
1617
  {
1618
1618
  "name": "<impl Deserialize for Option<T>>::stream_deserialize",
1619
- "start": 11243
1619
+ "start": 11524
1620
1620
  },
1621
1621
  {
1622
1622
  "name": "<impl Serialize for EmbeddedCurveScalar>::serialize",
1623
- "start": 11621
1623
+ "start": 11902
1624
1624
  },
1625
1625
  {
1626
1626
  "name": "<impl Serialize for EmbeddedCurveScalar>::stream_serialize",
1627
- "start": 11744
1627
+ "start": 12025
1628
1628
  },
1629
1629
  {
1630
1630
  "name": "<impl Deserialize for EmbeddedCurveScalar>::deserialize",
1631
- "start": 11944
1631
+ "start": 12225
1632
1632
  },
1633
1633
  {
1634
1634
  "name": "<impl Deserialize for EmbeddedCurveScalar>::stream_deserialize",
1635
- "start": 12090
1635
+ "start": 12371
1636
1636
  },
1637
1637
  {
1638
1638
  "name": "<impl Serialize for EmbeddedCurvePoint>::serialize",
1639
- "start": 12297
1639
+ "start": 12578
1640
1640
  },
1641
1641
  {
1642
1642
  "name": "<impl Serialize for EmbeddedCurvePoint>::stream_serialize",
1643
- "start": 12397
1643
+ "start": 12678
1644
1644
  },
1645
1645
  {
1646
1646
  "name": "<impl Deserialize for EmbeddedCurvePoint>::deserialize",
1647
- "start": 12593
1647
+ "start": 12874
1648
1648
  },
1649
1649
  {
1650
1650
  "name": "<impl Deserialize for EmbeddedCurvePoint>::stream_deserialize",
1651
- "start": 12737
1651
+ "start": 13018
1652
1652
  },
1653
1653
  {
1654
1654
  "name": "<impl Deserialize for str<M>>::deserialize",
1655
- "start": 12916
1655
+ "start": 13197
1656
1656
  },
1657
1657
  {
1658
1658
  "name": "<impl Deserialize for str<M>>::stream_deserialize",
1659
- "start": 13162
1659
+ "start": 13443
1660
1660
  },
1661
1661
  {
1662
1662
  "name": "<impl Serialize for str<M>>::serialize",
1663
- "start": 13395
1663
+ "start": 13676
1664
1664
  },
1665
1665
  {
1666
1666
  "name": "<impl Serialize for str<M>>::stream_serialize",
1667
- "start": 13616
1667
+ "start": 13897
1668
1668
  },
1669
1669
  {
1670
1670
  "name": "<impl Deserialize for BoundedVec<T, M>>::deserialize",
1671
- "start": 13997
1671
+ "start": 14278
1672
1672
  },
1673
1673
  {
1674
1674
  "name": "<impl Deserialize for BoundedVec<T, M>>::stream_deserialize",
1675
- "start": 14243
1675
+ "start": 14524
1676
1676
  },
1677
1677
  {
1678
1678
  "name": "<impl Deserialize for ()>::deserialize",
1679
- "start": 15299
1679
+ "start": 15744
1680
1680
  },
1681
1681
  {
1682
1682
  "name": "<impl Deserialize for ()>::stream_deserialize",
1683
- "start": 15546
1683
+ "start": 15991
1684
1684
  },
1685
1685
  {
1686
1686
  "name": "<impl Serialize for BoundedVec<T, M>>::serialize",
1687
- "start": 15911
1687
+ "start": 16356
1688
1688
  },
1689
1689
  {
1690
1690
  "name": "<impl Serialize for BoundedVec<T, M>>::stream_serialize",
1691
- "start": 16132
1691
+ "start": 16577
1692
1692
  },
1693
1693
  {
1694
1694
  "name": "make_slice",
1695
- "start": 16617
1695
+ "start": 17137
1696
1696
  },
1697
1697
  {
1698
1698
  "name": "impl_serialize_for_tuple",
1699
- "start": 16867
1699
+ "start": 17387
1700
1700
  },
1701
1701
  {
1702
1702
  "name": "<impl Serialize for (T1,)>::serialize",
1703
- "start": 20178
1703
+ "start": 20698
1704
1704
  },
1705
1705
  {
1706
1706
  "name": "<impl Serialize for (T1,)>::stream_serialize",
1707
- "start": 20429
1707
+ "start": 20949
1708
1708
  },
1709
1709
  {
1710
1710
  "name": "<impl Deserialize for (T1,)>::deserialize",
1711
- "start": 20636
1711
+ "start": 21156
1712
1712
  },
1713
1713
  {
1714
1714
  "name": "<impl Deserialize for (T1,)>::stream_deserialize",
1715
- "start": 20897
1716
- },
1717
- {
1718
- "name": "bounded_vec_serialization",
1719
- "start": 21246
1715
+ "start": 21417
1720
1716
  }
1721
1717
  ],
1722
1718
  "path": "/home/aztec-dev/aztec-packages/noir-projects/fnd/noir-protocol-circuits/crates/serde/src/type_impls.nr",
1723
- "source": "use crate::{reader::Reader, serialization::{Deserialize, Serialize}, writer::Writer};\nuse std::embedded_curve_ops::EmbeddedCurvePoint;\nuse std::embedded_curve_ops::EmbeddedCurveScalar;\n\nglobal BOOL_SERIALIZED_LEN: u32 = 1;\nglobal U8_SERIALIZED_LEN: u32 = 1;\nglobal U16_SERIALIZED_LEN: u32 = 1;\nglobal U32_SERIALIZED_LEN: u32 = 1;\nglobal U64_SERIALIZED_LEN: u32 = 1;\nglobal U128_SERIALIZED_LEN: u32 = 1;\nglobal FIELD_SERIALIZED_LEN: u32 = 1;\nglobal I8_SERIALIZED_LEN: u32 = 1;\nglobal I16_SERIALIZED_LEN: u32 = 1;\nglobal I32_SERIALIZED_LEN: u32 = 1;\nglobal I64_SERIALIZED_LEN: u32 = 1;\n\nimpl Serialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> bool {\n reader.read() != 0\n }\n}\n\nimpl Serialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u8\n }\n}\n\nimpl Serialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u16\n }\n}\n\nimpl Serialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u32\n }\n}\n\nimpl Serialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u64\n }\n}\n\nimpl Serialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u128\n }\n}\n\nimpl Serialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self);\n }\n}\n\nimpl Deserialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read()\n }\n}\n\nimpl Serialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u8 as Field);\n }\n}\n\nimpl Deserialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u8 as i8\n }\n}\n\nimpl Serialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u16 as Field);\n }\n}\n\nimpl Deserialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u16 as i16\n }\n}\n\nimpl Serialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u32 as Field);\n }\n}\n\nimpl Deserialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u32 as i32\n }\n}\n\nimpl Serialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u64 as Field);\n }\n}\n\nimpl Deserialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u64 as i64\n }\n}\n\nimpl<T, let M: u32> Serialize for [T; M]\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N * M;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n for i in 0..M {\n self[i].stream_serialize(writer);\n }\n }\n}\n\nimpl<T, let M: u32> Deserialize for [T; M]\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N * M;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let mut result: [T; M] = std::mem::zeroed();\n for i in 0..M {\n result[i] = T::stream_deserialize(reader);\n }\n result\n }\n}\n\nimpl<T> Serialize for Option<T>\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N + 1;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write_bool(self.is_some());\n if self.is_some() {\n self.unwrap_unchecked().stream_serialize(writer);\n } else {\n writer.advance_offset(<T as Serialize>::N);\n }\n }\n}\n\nimpl<T> Deserialize for Option<T>\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N + 1;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n if reader.read_bool() {\n Option::some(<T as Deserialize>::stream_deserialize(reader))\n } else {\n reader.advance_offset(<T as Deserialize>::N);\n Option::none()\n }\n }\n}\n\nglobal SCALAR_SIZE: u32 = 2;\n\nimpl Serialize for EmbeddedCurveScalar {\n\n let N: u32 = SCALAR_SIZE;\n\n fn serialize(self) -> [Field; SCALAR_SIZE] {\n [self.lo, self.hi]\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self.lo);\n writer.write(self.hi);\n }\n}\n\nimpl Deserialize for EmbeddedCurveScalar {\n let N: u32 = SCALAR_SIZE;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n Self { lo: fields[0], hi: fields[1] }\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n Self { lo: reader.read(), hi: reader.read() }\n }\n}\n\nglobal POINT_SIZE: u32 = 2;\n\nimpl Serialize for EmbeddedCurvePoint {\n let N: u32 = POINT_SIZE;\n\n fn serialize(self) -> [Field; Self::N] {\n [self.x, self.y]\n }\n\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self.x);\n writer.write(self.y);\n }\n}\n\nimpl Deserialize for EmbeddedCurvePoint {\n let N: u32 = POINT_SIZE;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n Self { x: fields[0], y: fields[1] }\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n Self { x: reader.read(), y: reader.read() }\n }\n}\n\nimpl<let M: u32> Deserialize for str<M> {\n let N: u32 = M;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let u8_arr = <[u8; Self::N] as Deserialize>::stream_deserialize(reader);\n str::<Self::N>::from(u8_arr)\n }\n}\n\nimpl<let M: u32> Serialize for str<M> {\n let N: u32 = M;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n self.as_bytes().stream_serialize(writer);\n }\n}\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl<T, let M: u32> Deserialize for BoundedVec<T, M>\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N * M + 1;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let mut new_bounded_vec: BoundedVec<T, M> = BoundedVec::new();\n let payload_len = Self::N - 1;\n\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n let len = reader.peek_offset(payload_len) as u32;\n\n for i in 0..M {\n if i < len {\n new_bounded_vec.push(<T as Deserialize>::stream_deserialize(reader));\n }\n }\n\n // +1 for the length of the BoundedVec\n reader.advance_offset((M - len) * <T as Deserialize>::N + 1);\n\n new_bounded_vec\n }\n}\n\n// This may cause issues if used as program input, because noir disallows empty arrays for program input.\n// I think this is okay because I don't foresee a unit type being used as input. But leaving this comment as a hint\n// if someone does run into this in the future.\nimpl Deserialize for () {\n let N: u32 = 0;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(_reader: &mut Reader<K>) -> Self {\n ()\n }\n}\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl<T, let M: u32> Serialize for BoundedVec<T, M>\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N * M + 1; // +1 for the length of the BoundedVec\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n self.storage().stream_serialize(writer);\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n writer.write_u32(self.len() as u32);\n }\n}\n\n// Create a slice of the given length with each element made from `f(i)` where `i` is the current index\ncomptime fn make_slice<Env, T>(length: u32, f: fn[Env](u32) -> T) -> [T] {\n let mut slice = @[];\n for i in 0..length {\n slice = slice.push_back(f(i));\n }\n slice\n}\n\n// Implements Serialize and Deserialize for an arbitrary tuple type\ncomptime fn impl_serialize_for_tuple(_m: Module, length: u32) -> Quoted {\n // `T0`, `T1`, `T2`\n let type_names = make_slice(length, |i| f\"T{i}\".quoted_contents());\n\n // `result0`, `result1`, `result2`\n let result_names = make_slice(length, |i| f\"result{i}\".quoted_contents());\n\n // `T0, T1, T2`\n let field_generics = type_names.join(quote [,]);\n\n // `<T0 as Serialize>::N + <T1 as Serialize>::N + <T2 as Serialize>::N`\n let full_size_serialize = type_names\n .map(|type_name| quote {\n <$type_name as Serialize>::N\n })\n .join(quote [+]);\n\n // `<T0 as Deserialize>::N + <T1 as Deserialize>::N + <T2 as Deserialize>::N`\n let full_size_deserialize = type_names\n .map(|type_name| quote {\n <$type_name as Deserialize>::N\n })\n .join(quote [+]);\n\n // `T0: Serialize, T1: Serialize, T2: Serialize,`\n let serialize_constraints = type_names\n .map(|field_name| quote {\n $field_name: Serialize,\n })\n .join(quote []);\n\n // `T0: Deserialize, T1: Deserialize, T2: Deserialize,`\n let deserialize_constraints = type_names\n .map(|field_name| quote {\n $field_name: Deserialize,\n })\n .join(quote []);\n\n // Statements to serialize each field\n let serialized_fields = type_names\n .mapi(|i, _type_name| quote {\n $crate::serialization::Serialize::stream_serialize(self.$i, writer);\n })\n .join(quote []);\n\n // Statements to deserialize each field\n let deserialized_fields = type_names\n .mapi(|i, type_name| {\n let result_name = result_names[i];\n quote {\n let $result_name = <$type_name as $crate::serialization::Deserialize>::stream_deserialize(reader);\n }\n })\n .join(quote []);\n let deserialize_results = result_names.join(quote [,]);\n\n quote {\n impl<$field_generics> Serialize for ($field_generics) where $serialize_constraints {\n let N: u32 = $full_size_serialize;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: $crate::writer::Writer<Self::N> = $crate::writer::Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut $crate::writer::Writer<K>) {\n\n $serialized_fields\n }\n }\n\n impl<$field_generics> Deserialize for ($field_generics) where $deserialize_constraints {\n let N: u32 = $full_size_deserialize;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = $crate::reader::Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n \n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut $crate::reader::Reader<K>) -> Self {\n $deserialized_fields\n ($deserialize_results)\n }\n }\n }\n}\n\n// Keeping these manual impls. They are more efficient since they do not\n// require copying sub-arrays from any serialized arrays.\nimpl<T1> Serialize for (T1,)\nwhere\n T1: Serialize,\n{\n let N: u32 = <T1 as Serialize>::N;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: crate::writer::Writer<Self::N> = crate::writer::Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n self.0.stream_serialize(writer);\n }\n}\n\nimpl<T1> Deserialize for (T1,)\nwhere\n T1: Deserialize,\n{\n let N: u32 = <T1 as Deserialize>::N;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = crate::reader::Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n (<T1 as Deserialize>::stream_deserialize(reader),)\n }\n}\n\n#[impl_serialize_for_tuple(2)]\n#[impl_serialize_for_tuple(3)]\n#[impl_serialize_for_tuple(4)]\n#[impl_serialize_for_tuple(5)]\n#[impl_serialize_for_tuple(6)]\nmod impls {\n use crate::serialization::{Deserialize, Serialize};\n}\n\n#[test]\nunconstrained fn bounded_vec_serialization() {\n // Test empty BoundedVec\n let empty_vec: BoundedVec<Field, 3> = BoundedVec::from_array([]);\n let serialized = empty_vec.serialize();\n let deserialized = BoundedVec::<Field, 3>::deserialize(serialized);\n assert_eq(empty_vec, deserialized);\n assert_eq(deserialized.len(), 0);\n\n // Test partially filled BoundedVec\n let partial_vec: BoundedVec<[u32; 2], 3> = BoundedVec::from_array([[1, 2]]);\n let serialized = partial_vec.serialize();\n let deserialized = BoundedVec::<[u32; 2], 3>::deserialize(serialized);\n assert_eq(partial_vec, deserialized);\n assert_eq(deserialized.len(), 1);\n assert_eq(deserialized.get(0), [1, 2]);\n\n // Test full BoundedVec\n let full_vec: BoundedVec<[u32; 2], 3> = BoundedVec::from_array([[1, 2], [3, 4], [5, 6]]);\n let serialized = full_vec.serialize();\n let deserialized = BoundedVec::<[u32; 2], 3>::deserialize(serialized);\n assert_eq(full_vec, deserialized);\n assert_eq(deserialized.len(), 3);\n assert_eq(deserialized.get(0), [1, 2]);\n assert_eq(deserialized.get(1), [3, 4]);\n assert_eq(deserialized.get(2), [5, 6]);\n}\n"
1719
+ "source": "use crate::{reader::Reader, serialization::{Deserialize, Serialize}, writer::Writer};\nuse std::embedded_curve_ops::EmbeddedCurvePoint;\nuse std::embedded_curve_ops::EmbeddedCurveScalar;\n\nglobal BOOL_SERIALIZED_LEN: u32 = 1;\nglobal U8_SERIALIZED_LEN: u32 = 1;\nglobal U16_SERIALIZED_LEN: u32 = 1;\nglobal U32_SERIALIZED_LEN: u32 = 1;\nglobal U64_SERIALIZED_LEN: u32 = 1;\nglobal U128_SERIALIZED_LEN: u32 = 1;\nglobal FIELD_SERIALIZED_LEN: u32 = 1;\nglobal I8_SERIALIZED_LEN: u32 = 1;\nglobal I16_SERIALIZED_LEN: u32 = 1;\nglobal I32_SERIALIZED_LEN: u32 = 1;\nglobal I64_SERIALIZED_LEN: u32 = 1;\n\nimpl Serialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> bool {\n reader.read() != 0\n }\n}\n\nimpl Serialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u8\n }\n}\n\nimpl Serialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u16\n }\n}\n\nimpl Serialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u32\n }\n}\n\nimpl Serialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u64\n }\n}\n\nimpl Serialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u128\n }\n}\n\nimpl Serialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self);\n }\n}\n\nimpl Deserialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read()\n }\n}\n\nimpl Serialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u8 as Field);\n }\n}\n\nimpl Deserialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u8 as i8\n }\n}\n\nimpl Serialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u16 as Field);\n }\n}\n\nimpl Deserialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u16 as i16\n }\n}\n\nimpl Serialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u32 as Field);\n }\n}\n\nimpl Deserialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u32 as i32\n }\n}\n\nimpl Serialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u64 as Field);\n }\n}\n\nimpl Deserialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u64 as i64\n }\n}\n\nimpl<T, let M: u32> Serialize for [T; M]\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N * M;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n for i in 0..M {\n self[i].stream_serialize(writer);\n }\n }\n}\n\nimpl<T, let M: u32> Deserialize for [T; M]\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N * M;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let mut result: [T; M] = std::mem::zeroed();\n for i in 0..M {\n result[i] = T::stream_deserialize(reader);\n }\n result\n }\n}\n\nimpl<T> Serialize for Option<T>\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N + 1;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n let is_some = self.is_some();\n writer.write_bool(is_some);\n // A `None` must have an all-zero payload, so every `Option` value has exactly one encoding. Private function\n // arguments are bound to the caller only through a hash of this encoding.\n let payload = self.unwrap_unchecked().serialize();\n if !is_some {\n assert_eq(payload, [0; <T as Serialize>::N], \"Option None payload must be zero\");\n }\n writer.write_array(payload);\n }\n}\n\nimpl<T> Deserialize for Option<T>\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N + 1;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n if reader.read_bool() {\n Option::some(<T as Deserialize>::stream_deserialize(reader))\n } else {\n reader.advance_offset(<T as Deserialize>::N);\n Option::none()\n }\n }\n}\n\nglobal SCALAR_SIZE: u32 = 2;\n\nimpl Serialize for EmbeddedCurveScalar {\n\n let N: u32 = SCALAR_SIZE;\n\n fn serialize(self) -> [Field; SCALAR_SIZE] {\n [self.lo, self.hi]\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self.lo);\n writer.write(self.hi);\n }\n}\n\nimpl Deserialize for EmbeddedCurveScalar {\n let N: u32 = SCALAR_SIZE;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n Self { lo: fields[0], hi: fields[1] }\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n Self { lo: reader.read(), hi: reader.read() }\n }\n}\n\nglobal POINT_SIZE: u32 = 2;\n\nimpl Serialize for EmbeddedCurvePoint {\n let N: u32 = POINT_SIZE;\n\n fn serialize(self) -> [Field; Self::N] {\n [self.x, self.y]\n }\n\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self.x);\n writer.write(self.y);\n }\n}\n\nimpl Deserialize for EmbeddedCurvePoint {\n let N: u32 = POINT_SIZE;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n Self { x: fields[0], y: fields[1] }\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n Self { x: reader.read(), y: reader.read() }\n }\n}\n\nimpl<let M: u32> Deserialize for str<M> {\n let N: u32 = M;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let u8_arr = <[u8; Self::N] as Deserialize>::stream_deserialize(reader);\n str::<Self::N>::from(u8_arr)\n }\n}\n\nimpl<let M: u32> Serialize for str<M> {\n let N: u32 = M;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n self.as_bytes().stream_serialize(writer);\n }\n}\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl<T, let M: u32> Deserialize for BoundedVec<T, M>\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N * M + 1;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let mut new_bounded_vec: BoundedVec<T, M> = BoundedVec::new();\n let payload_len = Self::N - 1;\n\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n let raw_len = reader.peek_offset(payload_len);\n let len = raw_len as u32;\n assert_eq(raw_len, len as Field, \"BoundedVec length is not u32\");\n assert(len <= M, \"BoundedVec length exceeds max\");\n\n for i in 0..M {\n if i < len {\n new_bounded_vec.push(<T as Deserialize>::stream_deserialize(reader));\n }\n }\n\n // +1 for the length of the BoundedVec\n reader.advance_offset((M - len) * <T as Deserialize>::N + 1);\n\n new_bounded_vec\n }\n}\n\n// This may cause issues if used as program input, because noir disallows empty arrays for program input.\n// I think this is okay because I don't foresee a unit type being used as input. But leaving this comment as a hint\n// if someone does run into this in the future.\nimpl Deserialize for () {\n let N: u32 = 0;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(_reader: &mut Reader<K>) -> Self {\n ()\n }\n}\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl<T, let M: u32> Serialize for BoundedVec<T, M>\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N * M + 1; // +1 for the length of the BoundedVec\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n let len = self.len();\n assert(len <= M, \"BoundedVec length exceeds max\");\n self.storage().stream_serialize(writer);\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n writer.write_u32(len);\n }\n}\n\n// Create a slice of the given length with each element made from `f(i)` where `i` is the current index\ncomptime fn make_slice<Env, T>(length: u32, f: fn[Env](u32) -> T) -> [T] {\n let mut slice = @[];\n for i in 0..length {\n slice = slice.push_back(f(i));\n }\n slice\n}\n\n// Implements Serialize and Deserialize for an arbitrary tuple type\ncomptime fn impl_serialize_for_tuple(_m: Module, length: u32) -> Quoted {\n // `T0`, `T1`, `T2`\n let type_names = make_slice(length, |i| f\"T{i}\".quoted_contents());\n\n // `result0`, `result1`, `result2`\n let result_names = make_slice(length, |i| f\"result{i}\".quoted_contents());\n\n // `T0, T1, T2`\n let field_generics = type_names.join(quote [,]);\n\n // `<T0 as Serialize>::N + <T1 as Serialize>::N + <T2 as Serialize>::N`\n let full_size_serialize = type_names\n .map(|type_name| quote {\n <$type_name as Serialize>::N\n })\n .join(quote [+]);\n\n // `<T0 as Deserialize>::N + <T1 as Deserialize>::N + <T2 as Deserialize>::N`\n let full_size_deserialize = type_names\n .map(|type_name| quote {\n <$type_name as Deserialize>::N\n })\n .join(quote [+]);\n\n // `T0: Serialize, T1: Serialize, T2: Serialize,`\n let serialize_constraints = type_names\n .map(|field_name| quote {\n $field_name: Serialize,\n })\n .join(quote []);\n\n // `T0: Deserialize, T1: Deserialize, T2: Deserialize,`\n let deserialize_constraints = type_names\n .map(|field_name| quote {\n $field_name: Deserialize,\n })\n .join(quote []);\n\n // Statements to serialize each field\n let serialized_fields = type_names\n .mapi(|i, _type_name| quote {\n $crate::serialization::Serialize::stream_serialize(self.$i, writer);\n })\n .join(quote []);\n\n // Statements to deserialize each field\n let deserialized_fields = type_names\n .mapi(|i, type_name| {\n let result_name = result_names[i];\n quote {\n let $result_name = <$type_name as $crate::serialization::Deserialize>::stream_deserialize(reader);\n }\n })\n .join(quote []);\n let deserialize_results = result_names.join(quote [,]);\n\n quote {\n impl<$field_generics> Serialize for ($field_generics) where $serialize_constraints {\n let N: u32 = $full_size_serialize;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: $crate::writer::Writer<Self::N> = $crate::writer::Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut $crate::writer::Writer<K>) {\n\n $serialized_fields\n }\n }\n\n impl<$field_generics> Deserialize for ($field_generics) where $deserialize_constraints {\n let N: u32 = $full_size_deserialize;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = $crate::reader::Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n \n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut $crate::reader::Reader<K>) -> Self {\n $deserialized_fields\n ($deserialize_results)\n }\n }\n }\n}\n\n// Keeping these manual impls. They are more efficient since they do not\n// require copying sub-arrays from any serialized arrays.\nimpl<T1> Serialize for (T1,)\nwhere\n T1: Serialize,\n{\n let N: u32 = <T1 as Serialize>::N;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: crate::writer::Writer<Self::N> = crate::writer::Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n self.0.stream_serialize(writer);\n }\n}\n\nimpl<T1> Deserialize for (T1,)\nwhere\n T1: Deserialize,\n{\n let N: u32 = <T1 as Deserialize>::N;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = crate::reader::Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n (<T1 as Deserialize>::stream_deserialize(reader),)\n }\n}\n\n#[impl_serialize_for_tuple(2)]\n#[impl_serialize_for_tuple(3)]\n#[impl_serialize_for_tuple(4)]\n#[impl_serialize_for_tuple(5)]\n#[impl_serialize_for_tuple(6)]\nmod impls {\n use crate::serialization::{Deserialize, Serialize};\n}\n"
1724
1720
  },
1725
1721
  "44": {
1726
1722
  "function_locations": [
@@ -2310,15 +2306,15 @@
2310
2306
  },
2311
2307
  {
2312
2308
  "name": "PrivateContext::call_public_function_with_calldata_hash",
2313
- "start": 10558
2309
+ "start": 10500
2314
2310
  },
2315
2311
  {
2316
2312
  "name": "PrivateContext::next_counter",
2317
- "start": 11127
2313
+ "start": 11069
2318
2314
  }
2319
2315
  ],
2320
2316
  "path": "/home/aztec-dev/aztec-packages/noir-projects/fnd/noir-contracts/contracts/protocol/aztec_sublib/src/context/private_context.nr",
2321
- "source": "use crate::{\n context::{inputs::PrivateContextInputs, NullifierExistenceRequest},\n messaging::process_l1_to_l2_message,\n oracle::{\n logs::notify_created_contract_class_log, nullifiers::notify_created_nullifier,\n public_call::validate_public_calldata, tx_phase::notify_revertible_phase_start,\n },\n};\nuse crate::protocol::{\n abis::{\n block_header::BlockHeader,\n log_hash::LogHash,\n nullifier::Nullifier,\n private_call_request::PrivateCallRequest,\n private_circuit_public_inputs::PrivateCircuitPublicInputs,\n private_log::{PrivateLog, PrivateLogData},\n public_call_request::PublicCallRequest,\n },\n address::{AztecAddress, EthAddress},\n constants::{\n CONTRACT_CLASS_LOG_SIZE_IN_FIELDS, MAX_CONTRACT_CLASS_LOGS_PER_CALL, MAX_ENQUEUED_CALLS_PER_CALL,\n MAX_L2_TO_L1_MSGS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PRIVATE_LOGS_PER_CALL, MAX_TX_LIFETIME,\n NULL_MSG_SENDER_CONTRACT_ADDRESS, PRIVATE_LOG_SIZE_IN_FIELDS,\n },\n hash::poseidon2_hash,\n messaging::l2_to_l1_message::L2ToL1Message,\n side_effect::{Counted, scoped::Scoped},\n traits::Empty,\n utils::arrays::{ClaimedLengthArray, trimmed_array_length_hint},\n};\n\n/// Minimal PrivateContext for protocol contracts going to audit.\n/// Contains only the methods actually used by: fee_juice, auth_registry, contract_class_registry,\n/// contract_instance_registry\npub struct PrivateContext {\n pub inputs: PrivateContextInputs,\n pub side_effect_counter: u32,\n\n pub min_revertible_side_effect_counter: u32,\n pub is_fee_payer: bool,\n\n pub args_hash: Field,\n pub return_hash: Field,\n\n pub expiration_timestamp: u64,\n\n pub nullifier_read_requests: BoundedVec<Scoped<Counted<Field>>, MAX_NULLIFIER_READ_REQUESTS_PER_CALL>,\n\n pub nullifiers: BoundedVec<Counted<Nullifier>, MAX_NULLIFIERS_PER_CALL>,\n\n pub private_call_requests: BoundedVec<PrivateCallRequest, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL>,\n pub public_call_requests: BoundedVec<Counted<PublicCallRequest>, MAX_ENQUEUED_CALLS_PER_CALL>,\n pub public_teardown_call_request: PublicCallRequest,\n pub l2_to_l1_msgs: BoundedVec<Counted<L2ToL1Message>, MAX_L2_TO_L1_MSGS_PER_CALL>,\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n pub anchor_block_header: BlockHeader,\n\n pub private_logs: BoundedVec<Counted<PrivateLogData>, MAX_PRIVATE_LOGS_PER_CALL>,\n pub contract_class_logs_hashes: BoundedVec<Counted<LogHash>, MAX_CONTRACT_CLASS_LOGS_PER_CALL>,\n\n pub expected_non_revertible_side_effect_counter: u32,\n pub expected_revertible_side_effect_counter: u32,\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs,\n side_effect_counter: inputs.start_side_effect_counter + 1,\n min_revertible_side_effect_counter: 0,\n is_fee_payer: false,\n args_hash,\n return_hash: 0,\n expiration_timestamp: inputs.anchor_block_header.global_variables.timestamp + MAX_TX_LIFETIME,\n nullifier_read_requests: BoundedVec::new(),\n nullifiers: BoundedVec::new(),\n anchor_block_header: inputs.anchor_block_header,\n private_call_requests: BoundedVec::new(),\n public_call_requests: BoundedVec::new(),\n public_teardown_call_request: PublicCallRequest::empty(),\n l2_to_l1_msgs: BoundedVec::new(),\n private_logs: BoundedVec::new(),\n contract_class_logs_hashes: BoundedVec::new(),\n expected_non_revertible_side_effect_counter: 0,\n expected_revertible_side_effect_counter: 0,\n }\n }\n\n /// Returns the contract address that initiated this function call (similar to msg.sender in Solidity).\n pub fn maybe_msg_sender(self) -> Option<AztecAddress> {\n let maybe_msg_sender = self.inputs.call_context.msg_sender;\n if maybe_msg_sender == NULL_MSG_SENDER_CONTRACT_ADDRESS {\n Option::none()\n } else {\n Option::some(maybe_msg_sender)\n }\n }\n\n /// Returns the contract address of the current function being executed.\n pub fn this_address(self) -> AztecAddress {\n self.inputs.call_context.contract_address\n }\n\n /// Returns the chain ID of the current network.\n pub fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n /// Returns the protocol version.\n pub fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n /// Builds the PrivateCircuitPublicInputs for this private function.\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n returns_hash: self.return_hash,\n min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,\n is_fee_payer: self.is_fee_payer,\n expiration_timestamp: self.expiration_timestamp,\n note_hash_read_requests: ClaimedLengthArray::empty(), // Not used by protocol contracts\n nullifier_read_requests: ClaimedLengthArray::from_bounded_vec(self.nullifier_read_requests),\n key_validation_requests_and_separators: ClaimedLengthArray::empty(), // Not used by protocol contracts\n note_hashes: ClaimedLengthArray::empty(), // Not used by protocol contracts\n nullifiers: ClaimedLengthArray::from_bounded_vec(self.nullifiers),\n private_call_requests: ClaimedLengthArray::from_bounded_vec(self.private_call_requests),\n public_call_requests: ClaimedLengthArray::from_bounded_vec(self.public_call_requests),\n public_teardown_call_request: self.public_teardown_call_request,\n l2_to_l1_msgs: ClaimedLengthArray::from_bounded_vec(self.l2_to_l1_msgs),\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n private_logs: ClaimedLengthArray::from_bounded_vec(self.private_logs),\n contract_class_logs_hashes: ClaimedLengthArray::from_bounded_vec(self.contract_class_logs_hashes),\n anchor_block_header: self.anchor_block_header,\n tx_context: self.inputs.tx_context,\n expected_non_revertible_side_effect_counter: self.expected_non_revertible_side_effect_counter,\n expected_revertible_side_effect_counter: self.expected_revertible_side_effect_counter,\n protocol_nullifier: self.inputs.protocol_nullifier,\n }\n }\n\n /// Declares the end of the \"setup phase\" of this tx. Used by fee_juice.\n pub fn end_setup(&mut self) {\n self.side_effect_counter += 1;\n self.min_revertible_side_effect_counter = self.next_counter();\n notify_revertible_phase_start(self.min_revertible_side_effect_counter);\n }\n\n /// Pushes a new nullifier. Used by class_registry and instance_registry.\n pub fn push_nullifier(&mut self, nullifier: Field) {\n notify_created_nullifier(nullifier);\n self.nullifiers.push(Nullifier { value: nullifier, note_hash: 0 }.count(self.next_counter()));\n }\n\n /// Asserts that a nullifier has been emitted. Used by instance_registry.\n pub fn assert_nullifier_exists(&mut self, nullifier_existence_request: NullifierExistenceRequest) {\n let nullifier = nullifier_existence_request.nullifier();\n let contract_address = nullifier_existence_request.maybe_contract_address().unwrap_or(AztecAddress::zero());\n\n let request = Scoped::new(\n Counted::new(nullifier, self.next_counter()),\n contract_address,\n );\n\n self.nullifier_read_requests.push(request);\n }\n\n /// Consumes a message sent from Ethereum (L1) to Aztec (L2). Used by fee_juice.\n pub fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress, leaf_index: Field) {\n let nullifier = process_l1_to_l2_message(\n self.anchor_block_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n sender,\n self.chain_id(),\n self.version(),\n content,\n secret,\n leaf_index,\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_nullifier(nullifier)\n }\n\n /// Emits a private log. Used by instance_registry.\n pub fn emit_private_log(&mut self, log: [Field; PRIVATE_LOG_SIZE_IN_FIELDS], length: u32) {\n let counter = self.next_counter();\n let private_log = PrivateLogData { log: PrivateLog::new(log, length), note_hash_counter: 0 }.count(counter);\n self.private_logs.push(private_log);\n }\n\n /// Emits a contract class log. Used by class_registry.\n pub fn emit_contract_class_log<let N: u32>(&mut self, log: [Field; N]) {\n let contract_address = self.this_address();\n let counter = self.next_counter();\n\n let log_to_emit: [Field; CONTRACT_CLASS_LOG_SIZE_IN_FIELDS] =\n log.concat([0; CONTRACT_CLASS_LOG_SIZE_IN_FIELDS - N]);\n // Safety: The below length is constrained in the base rollup, which will make sure that all the fields beyond\n // length are zero. However, it won't be able to check that we didn't add extra padding (trailing zeroes) or\n // that we cut trailing zeroes from the end.\n let length = unsafe { trimmed_array_length_hint(log_to_emit) };\n // We hash the entire padded log to ensure a user cannot pass a shorter length and so emit incorrect shorter\n // bytecode.\n let log_hash = poseidon2_hash(log_to_emit);\n // Safety: the below only exists to broadcast the raw log, so we can provide it to the base rollup later to be\n // constrained.\n unsafe {\n notify_created_contract_class_log(contract_address, log_to_emit, length, counter);\n }\n\n self.contract_class_logs_hashes.push(LogHash { value: log_hash, length: length }.count(counter));\n }\n\n /// Enqueues a call to a public function with a calldata hash. Used by fee_juice and auth_registry.\n pub fn call_public_function_with_calldata_hash(\n &mut self,\n contract_address: AztecAddress,\n calldata_hash: Field,\n is_static_call: bool,\n hide_msg_sender: bool,\n ) {\n let counter = self.next_counter();\n\n let is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n\n validate_public_calldata(calldata_hash);\n\n let msg_sender = if hide_msg_sender {\n NULL_MSG_SENDER_CONTRACT_ADDRESS\n } else {\n self.this_address()\n };\n\n let call_request = PublicCallRequest { msg_sender, contract_address, is_static_call, calldata_hash };\n\n self.public_call_requests.push(Counted::new(call_request, counter));\n }\n\n fn next_counter(&mut self) -> u32 {\n let counter = self.side_effect_counter;\n self.side_effect_counter += 1;\n counter\n }\n}\n"
2317
+ "source": "use crate::{\n context::{inputs::PrivateContextInputs, NullifierExistenceRequest},\n messaging::process_l1_to_l2_message,\n oracle::{\n logs::notify_created_contract_class_log, nullifiers::notify_created_nullifier,\n public_call::validate_public_calldata, tx_phase::notify_revertible_phase_start,\n },\n};\nuse crate::protocol::{\n abis::{\n block_header::BlockHeader,\n log_hash::LogHash,\n nullifier::Nullifier,\n private_call_request::PrivateCallRequest,\n private_circuit_public_inputs::PrivateCircuitPublicInputs,\n private_log::{PrivateLog, PrivateLogData},\n public_call_request::PublicCallRequest,\n },\n address::{AztecAddress, EthAddress},\n constants::{\n CONTRACT_CLASS_LOG_SIZE_IN_FIELDS, MAX_CONTRACT_CLASS_LOGS_PER_CALL, MAX_ENQUEUED_CALLS_PER_CALL,\n MAX_L2_TO_L1_MSGS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PRIVATE_LOGS_PER_CALL, MAX_TX_LIFETIME,\n NULL_MSG_SENDER_CONTRACT_ADDRESS, PRIVATE_LOG_SIZE_IN_FIELDS,\n },\n hash::poseidon2_hash,\n messaging::l2_to_l1_message::L2ToL1Message,\n side_effect::{Counted, scoped::Scoped},\n traits::Empty,\n utils::arrays::{ClaimedLengthArray, trimmed_array_length_hint},\n};\n\n/// Minimal PrivateContext for protocol contracts going to audit.\n/// Contains only the methods actually used by: fee_juice, auth_registry, contract_class_registry,\n/// contract_instance_registry\npub struct PrivateContext {\n pub inputs: PrivateContextInputs,\n pub side_effect_counter: u32,\n\n pub min_revertible_side_effect_counter: u32,\n pub is_fee_payer: bool,\n\n pub args_hash: Field,\n pub return_hash: Field,\n\n pub expiration_timestamp: u64,\n\n pub nullifier_read_requests: BoundedVec<Scoped<Counted<Field>>, MAX_NULLIFIER_READ_REQUESTS_PER_CALL>,\n\n pub nullifiers: BoundedVec<Counted<Nullifier>, MAX_NULLIFIERS_PER_CALL>,\n\n pub private_call_requests: BoundedVec<PrivateCallRequest, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL>,\n pub public_call_requests: BoundedVec<Counted<PublicCallRequest>, MAX_ENQUEUED_CALLS_PER_CALL>,\n pub public_teardown_call_request: PublicCallRequest,\n pub l2_to_l1_msgs: BoundedVec<Counted<L2ToL1Message>, MAX_L2_TO_L1_MSGS_PER_CALL>,\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n pub anchor_block_header: BlockHeader,\n\n pub private_logs: BoundedVec<Counted<PrivateLogData>, MAX_PRIVATE_LOGS_PER_CALL>,\n pub contract_class_logs_hashes: BoundedVec<Counted<LogHash>, MAX_CONTRACT_CLASS_LOGS_PER_CALL>,\n\n pub expected_non_revertible_side_effect_counter: u32,\n pub expected_revertible_side_effect_counter: u32,\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs,\n side_effect_counter: inputs.start_side_effect_counter + 1,\n min_revertible_side_effect_counter: 0,\n is_fee_payer: false,\n args_hash,\n return_hash: 0,\n expiration_timestamp: inputs.anchor_block_header.global_variables.timestamp + MAX_TX_LIFETIME,\n nullifier_read_requests: BoundedVec::new(),\n nullifiers: BoundedVec::new(),\n anchor_block_header: inputs.anchor_block_header,\n private_call_requests: BoundedVec::new(),\n public_call_requests: BoundedVec::new(),\n public_teardown_call_request: PublicCallRequest::empty(),\n l2_to_l1_msgs: BoundedVec::new(),\n private_logs: BoundedVec::new(),\n contract_class_logs_hashes: BoundedVec::new(),\n expected_non_revertible_side_effect_counter: 0,\n expected_revertible_side_effect_counter: 0,\n }\n }\n\n /// Returns the contract address that initiated this function call (similar to msg.sender in Solidity).\n pub fn maybe_msg_sender(self) -> Option<AztecAddress> {\n let maybe_msg_sender = self.inputs.call_context.msg_sender;\n if maybe_msg_sender == NULL_MSG_SENDER_CONTRACT_ADDRESS {\n Option::none()\n } else {\n Option::some(maybe_msg_sender)\n }\n }\n\n /// Returns the contract address of the current function being executed.\n pub fn this_address(self) -> AztecAddress {\n self.inputs.call_context.contract_address\n }\n\n /// Returns the chain ID of the current network.\n pub fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n /// Returns the protocol version.\n pub fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n /// Builds the PrivateCircuitPublicInputs for this private function.\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n returns_hash: self.return_hash,\n min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,\n is_fee_payer: self.is_fee_payer,\n expiration_timestamp: self.expiration_timestamp,\n note_hash_read_requests: ClaimedLengthArray::empty(), // Not used by protocol contracts\n nullifier_read_requests: ClaimedLengthArray::from_bounded_vec(self.nullifier_read_requests),\n key_validation_requests_and_separators: ClaimedLengthArray::empty(), // Not used by protocol contracts\n note_hashes: ClaimedLengthArray::empty(), // Not used by protocol contracts\n nullifiers: ClaimedLengthArray::from_bounded_vec(self.nullifiers),\n private_call_requests: ClaimedLengthArray::from_bounded_vec(self.private_call_requests),\n public_call_requests: ClaimedLengthArray::from_bounded_vec(self.public_call_requests),\n public_teardown_call_request: self.public_teardown_call_request,\n l2_to_l1_msgs: ClaimedLengthArray::from_bounded_vec(self.l2_to_l1_msgs),\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n private_logs: ClaimedLengthArray::from_bounded_vec(self.private_logs),\n contract_class_logs_hashes: ClaimedLengthArray::from_bounded_vec(self.contract_class_logs_hashes),\n anchor_block_header: self.anchor_block_header,\n tx_context: self.inputs.tx_context,\n expected_non_revertible_side_effect_counter: self.expected_non_revertible_side_effect_counter,\n expected_revertible_side_effect_counter: self.expected_revertible_side_effect_counter,\n protocol_nullifier: self.inputs.protocol_nullifier,\n }\n }\n\n /// Declares the end of the \"setup phase\" of this tx. Used by fee_juice.\n pub fn end_setup(&mut self) {\n self.side_effect_counter += 1;\n self.min_revertible_side_effect_counter = self.next_counter();\n notify_revertible_phase_start(self.min_revertible_side_effect_counter);\n }\n\n /// Pushes a new nullifier. Used by class_registry and instance_registry.\n pub fn push_nullifier(&mut self, nullifier: Field) {\n notify_created_nullifier(nullifier);\n self.nullifiers.push(Nullifier { value: nullifier, note_hash: 0 }.count(self.next_counter()));\n }\n\n /// Asserts that a nullifier has been emitted. Used by instance_registry.\n pub fn assert_nullifier_exists(&mut self, nullifier_existence_request: NullifierExistenceRequest) {\n let nullifier = nullifier_existence_request.nullifier();\n let contract_address = nullifier_existence_request.maybe_contract_address().unwrap_or(AztecAddress::zero());\n\n let request = Scoped::new(\n Counted::new(nullifier, self.next_counter()),\n contract_address,\n );\n\n self.nullifier_read_requests.push(request);\n }\n\n /// Consumes a message sent from Ethereum (L1) to Aztec (L2). Used by fee_juice.\n pub fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress, leaf_index: Field) {\n let nullifier = process_l1_to_l2_message(\n self.anchor_block_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n sender,\n self.chain_id(),\n self.version(),\n content,\n secret,\n leaf_index,\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_nullifier(nullifier)\n }\n\n /// Emits a private log. Used by instance_registry.\n pub fn emit_private_log(&mut self, log: [Field; PRIVATE_LOG_SIZE_IN_FIELDS], length: u32) {\n let counter = self.next_counter();\n let private_log = PrivateLogData { log: PrivateLog::new(log, length), note_hash_counter: 0 }.count(counter);\n self.private_logs.push(private_log);\n }\n\n /// Emits a contract class log. Used by class_registry.\n pub fn emit_contract_class_log<let N: u32>(&mut self, log: [Field; N]) {\n let contract_address = self.this_address();\n let counter = self.next_counter();\n\n let log_to_emit: [Field; CONTRACT_CLASS_LOG_SIZE_IN_FIELDS] =\n log.concat([0; CONTRACT_CLASS_LOG_SIZE_IN_FIELDS - N]);\n // Safety: The below length is constrained in the base rollup, which checks that all the fields beyond length\n // are zero and that the field at length - 1 is not, i.e. that the length is exactly the trimmed length.\n let length = unsafe { trimmed_array_length_hint(log_to_emit) };\n // We hash the entire padded log to ensure a user cannot pass a shorter length and so emit incorrect shorter\n // bytecode.\n let log_hash = poseidon2_hash(log_to_emit);\n // Safety: the below only exists to broadcast the raw log, so we can provide it to the base rollup later to be\n // constrained.\n unsafe {\n notify_created_contract_class_log(contract_address, log_to_emit, length, counter);\n }\n\n self.contract_class_logs_hashes.push(LogHash { value: log_hash, length: length }.count(counter));\n }\n\n /// Enqueues a call to a public function with a calldata hash. Used by fee_juice and auth_registry.\n pub fn call_public_function_with_calldata_hash(\n &mut self,\n contract_address: AztecAddress,\n calldata_hash: Field,\n is_static_call: bool,\n hide_msg_sender: bool,\n ) {\n let counter = self.next_counter();\n\n let is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n\n validate_public_calldata(calldata_hash);\n\n let msg_sender = if hide_msg_sender {\n NULL_MSG_SENDER_CONTRACT_ADDRESS\n } else {\n self.this_address()\n };\n\n let call_request = PublicCallRequest { msg_sender, contract_address, is_static_call, calldata_hash };\n\n self.public_call_requests.push(Counted::new(call_request, counter));\n }\n\n fn next_counter(&mut self) -> u32 {\n let counter = self.side_effect_counter;\n self.side_effect_counter += 1;\n counter\n }\n}\n"
2322
2318
  },
2323
2319
  "58": {
2324
2320
  "function_locations": [
@@ -2626,19 +2622,19 @@
2626
2622
  "function_locations": [
2627
2623
  {
2628
2624
  "name": "WithHash<T, M>::new",
2629
- "start": 768
2625
+ "start": 763
2630
2626
  },
2631
2627
  {
2632
2628
  "name": "<impl Packable for WithHash<T, M>>::pack",
2633
- "start": 1018
2629
+ "start": 1013
2634
2630
  },
2635
2631
  {
2636
2632
  "name": "<impl Packable for WithHash<T, M>>::unpack",
2637
- "start": 1259
2633
+ "start": 1254
2638
2634
  }
2639
2635
  ],
2640
2636
  "path": "/home/aztec-dev/aztec-packages/noir-projects/fnd/noir-contracts/contracts/protocol/aztec_sublib/src/utils/with_hash.nr",
2641
- "source": "use crate::protocol::{hash::poseidon2_hash, traits::Packable};\n\n/// A struct that allows for efficient reading of value `T` from public storage in private.\n///\n/// The efficient reads are achieved by verifying large values through a single hash check and then proving inclusion\n/// only of the hash in public storage. This reduces the number of required tree inclusion proofs from `M` to 1.\n///\n/// # Type Parameters\n/// - `T`: The underlying type being wrapped, must implement `Packable<N>`\n/// - `M`: The number of field elements required to pack values of type `T`\npub struct WithHash<T, let M: u32> {\n value: T,\n packed: [Field; M],\n hash: Field,\n}\n\nimpl<T, let M: u32> WithHash<T, M>\nwhere\n T: Packable<N = M> + Eq,\n{\n pub fn new(value: T) -> Self {\n let packed = value.pack();\n Self { value, packed, hash: poseidon2_hash(packed) }\n }\n}\n\nimpl<T, let M: u32> Packable for WithHash<T, M>\nwhere\n T: Packable<N = M>,\n{\n let N: u32 = M + 1;\n\n fn pack(self) -> [Field; Self::N] {\n let mut result: [Field; Self::N] = std::mem::zeroed();\n for i in 0..M {\n result[i] = self.packed[i];\n }\n result[M] = self.hash;\n\n result\n }\n\n fn unpack(packed: [Field; Self::N]) -> Self {\n let mut value_packed = [0; M];\n for i in 0..M {\n value_packed[i] = packed[i];\n }\n let hash = packed[M];\n\n Self { value: T::unpack(value_packed), packed: value_packed, hash }\n }\n}\n"
2637
+ "source": "use crate::protocol::{hash::poseidon2_hash, traits::Packable};\n\n/// A struct that allows for efficient reading of value `T` from public storage in private.\n///\n/// The efficient reads are achieved by verifying large values through a single hash check and then proving inclusion\n/// only of the hash in public storage. This reduces the number of required tree inclusion proofs from `M` to 1.\n///\n/// # Type Parameters\n/// - `T`: The underlying type being wrapped, must implement `Packable<N>`\n/// - `M`: The number of field elements required to pack values of type `T`\npub struct WithHash<T, let M: u32> {\n value: T,\n packed: [Field; M],\n hash: Field,\n}\n\nimpl<T, let M: u32> WithHash<T, M>\nwhere\n T: Packable<N = M>,\n{\n pub fn new(value: T) -> Self {\n let packed = value.pack();\n Self { value, packed, hash: poseidon2_hash(packed) }\n }\n}\n\nimpl<T, let M: u32> Packable for WithHash<T, M>\nwhere\n T: Packable<N = M>,\n{\n let N: u32 = M + 1;\n\n fn pack(self) -> [Field; Self::N] {\n let mut result: [Field; Self::N] = std::mem::zeroed();\n for i in 0..M {\n result[i] = self.packed[i];\n }\n result[M] = self.hash;\n\n result\n }\n\n fn unpack(packed: [Field; Self::N]) -> Self {\n let mut value_packed = [0; M];\n for i in 0..M {\n value_packed[i] = packed[i];\n }\n let hash = packed[M];\n\n Self { value: T::unpack(value_packed), packed: value_packed, hash }\n }\n}\n"
2642
2638
  }
2643
2639
  },
2644
2640
  "functions": [
@@ -2670,7 +2666,7 @@
2670
2666
  "abi_public",
2671
2667
  "abi_view"
2672
2668
  ],
2673
- "debug_symbols": "rVjbbiI7EPyXeebBffMlv7JaRSQhKyREIhaOdBTx76cbpj0QyT6Jd1+YooapKbfLPWY+ppfN0+nX43b/+vZ7evjxMT0dtrvd9tfj7u15fdy+7ZX9mIJ9RP2k1RRleuDVlML1kC+HTNND1IN+A/1NSdcjBJwBkgM/RX6KnGFn2BkBBzIDM3EF7KDMIPkt0uwCsgmKgTiDAg5mBgM4cAacAbOho0JEB86Q/SYbiDNgY4qBOANxRsoMzDOSAWXQmKQMgQKzSnYqpxkUY9iAMeqHiB3o5aQ2iNmBMUmBGJMNGKO3ILvpFThjN+VgoMwgGwMGygyKM8UmGFcTBy0vkwFj1BizzEAsC2JAZmDTxNGAMWqML3nJBmQG2ZlsjBrjEhwoI2pMQnCgfgQMqENRPwLGkAFj1IYgOzBGbYhV7AqcYWesYqIOxSp2Bc5EZ6xioubFKiblfF5Nviwej4fNxlbFzTrR1fO+Pmz2x+lhf9rtVtM/693p8qPf7+v95XhcH/SsDmizf9GjCr5udxtD59VydWhfChgtm5fLFVOqEkJ3GtDW0GTyLIFCsijkOwVsK4gV/iIgKdbrY/rGKEJeRlFKaxRdjRSXSqSUWxrS1iByBZIwNI5ky889RG55SD0NXoZRltlI5U4hd+Yze6B0tdbrMfCdQOlYCJDQPQQMy3Qof5+qTjFKAfdRiqS2RieaxB4syjdDofv1AZ1oatf2GUHIPKaB5DYQY8cHd0ZSkiecA8hNNb5sQyWgTmwqTRu9cEEpPrEUYitc0JFIUDyfCQEXifwNiZyrREotia8vtNJse9gTocB4Uw1uGcFe88TadRAzNJtnZ165rle+Wa+fus7/DKSGXPGNyOeBdAIKTMXjBcwQmyK9Bgrg+SLg0KxG7HWv4pOC5ab1fJbopZxiHQml9gOt10NjfSTm5pOgPwzb5szDQGp5oG7IQx0GCjZddCeVl6cJc24mg3rtr2CNeKFFQvfc39CI9aEUAgxqSA3XXQv9hgYFqT00RBjUSHWbAECjGlw1MI1pgKSqEeOoRqwaCf6CxqiPUjUQR32U8OcauWYMicc0sLYfwtGaYq4Z0046qlEzpnhMg5aM0WjGaMkHjdbjTmPUx5IxxjCqEf5cY8kY02D/4KUXcixjGqluf7SkOKaRb/5sDPZ1/ZeSlq1xuxd+fQsE7X2p9B76IdR9fuBbI/rE/alf18/bw92bsLOJHbbrp91m/vp62j/fnD3+++5n/E3a++HtefNyOmxMaXmdZq+ZfoD+GdJHys+z3e8/",
2669
+ "debug_symbols": "rVjbbiI7EPyXeebBffMlv7JaRSQhKyREIhaOdBTx76cbpj0QyT6Jd1+YooapKbfL7Rk+ppfN0+nX43b/+vZ7evjxMT0dtrvd9tfj7u15fdy+7ZX9mIJ9RP2k1RRleuDVlML1kC+HTNND1IN+A/1NSdcjBJwBkgM/RX6KnGFn2BkBBzIDM3EF7KDMIPkt0uwCsgmKgTiDAg5mBgM4cAacAbOho0JEB86Q/SYbiDNgY4qBOANxRsoMzDOSAWXQmKQMgQKzSnYqpxkUY9iAMeqHiB3o5aQ2iNmBMUmBGJMNGKO3ILvpFThjN+VgoMwgGwMGygyKM8UmGFcTBy0vkwFj1BizzEAsC2JAZmDTxNGAMWqML3nJBmQG2ZlsjBrjEhwoI2pMQnCgfgQMqENRPwLGkAFj1IYgOzBGbYhV7AqcYWesYqIOxSp2Bc5EZ6xioubFKiblfF5Nviwej4fNxlbFzTrR1fO+Pmz2x+lhf9rtVtM/693p8qPf7+v95XhcH/SsDmizf9GjCr5udxtD59VydWhfChgtm5fLFVOqEkJ3GtDW0GTyLIFCsijkOwVsK4gV/iIgKdbrY/rGKEJeRlFKaxRdjRSXSqSUWxrS1iByBZIwNI5ky889RG55SD0NXoZRltlI5U4hd+Yze6B0tdbrMfCdQOlYCJDQPQQMy3Qof5+qTjFKAfdRiqS2RieaxB4syjdDofv1AZ1oImbwcGMuYxpEnk6kRG0N7oykJNfgAHJTjS/b4JBilcjctNELF5TiE0shtsIFHYkExfOZEHCRyN+QyLlKpNSS+PpCK822hz0RCow31eCWEew1T6xdx6LWbJ69ea3rlW/W66eu8z8DqclQfCPyeSCdgAJT8ZUCzBCbIr0GCuD5IuDQrEbsda/ik4LlpvV8luilnGIdCaX2htbrobFuibm5E/SHYY858zCQWh6oG/JQh4GCTRfdSeVlN2HOzWRQr/0VrBEvtEjoM/c3NGLdlEKAQQ2p4bprod/QoCBQNSIMaqT6mABAoxpcNTCNaYCkqhHjqEasGgn+gsaoj1I1EEd9lPDnGrlmDInHNLC2H8LRmmKuGdNOOqpRM6Z4TIOWjNFoxmjJB43W405j1MeSMcYwqhH+XGPJGNNg/+ClF3IsYxqpPv5oSXFMI9+8bAz2dX1LScujcbsXfv0RCNrPpdLb9EPw1w19W7o1ojvuT/26ft4e7v4JO5vYYbt+2m3mr6+n/fPN2eO/737G/0l7P7w9b15Oh40pLX+n2d9MP0BfhnRL+Xm2+/0H",
2674
2670
  "is_unconstrained": true,
2675
2671
  "name": "get_update_delay"
2676
2672
  },
@@ -2739,7 +2735,7 @@
2739
2735
  "custom_attributes": [
2740
2736
  "abi_public"
2741
2737
  ],
2742
- "debug_symbols": "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",
2738
+ "debug_symbols": "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",
2743
2739
  "is_unconstrained": true,
2744
2740
  "name": "public_dispatch"
2745
2741
  },
@@ -4649,7 +4645,7 @@
4649
4645
  "custom_attributes": [
4650
4646
  "abi_private"
4651
4647
  ],
4652
- "debug_symbols": "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",
4648
+ "debug_symbols": "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",
4653
4649
  "is_unconstrained": false,
4654
4650
  "name": "publish_for_public_execution",
4655
4651
  "verification_key": "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"
@@ -4704,7 +4700,7 @@
4704
4700
  "custom_attributes": [
4705
4701
  "abi_public"
4706
4702
  ],
4707
- "debug_symbols": "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",
4703
+ "debug_symbols": "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",
4708
4704
  "is_unconstrained": true,
4709
4705
  "name": "set_update_delay"
4710
4706
  },
@@ -4765,7 +4761,7 @@
4765
4761
  "custom_attributes": [
4766
4762
  "abi_public"
4767
4763
  ],
4768
- "debug_symbols": "tZvbbhs5D8ffxde50IkU2VdZLIq0TRcBgrTIth/woei7L6kDNQ4g1dWkN/HP9Pg/pETqNM6Py6eHD9//ef/4/PnLv5d3f/24fHh5fHp6/Of905eP998evzyL9cfF6R8PcHkX7y4e5S3oK7RXrvac2qu8z/JKqb2295zLa3ChveLlnXcC3guoJbgGqVsSNID+EXQLdguahRvk2IEaUOiQG3C/BWOF6FSQFVIHbuC7xXdL6JbQLVHcCBJOTK6DXBOCgDofogI1QPEw6jWYG+TQoVuoW6hb1OcKUCGpzxVSB27gYwdqEFQwKGCD6Dt0S+qW1C3QLaBuiPMJQwe9RlIgFedRgFwH8TDpNZw6UAVwsUO3+G7x3aKuVsAG6mqFpgzazhVSB24AKggKuYH6XKFbcrfkbqFuIXVDogCOHfQaurugJm8FtUi/ow8NNHsraGHItzBqpejFUQRBP0qxfZSofQTYPkLfAds12bdrtKLQC2hJVVCLdApq86Jew1pl0stZHcvyUVbHKqhFmiVrq+YkANwAtUZBgRtoFWdUUIvURS51TArcgLul3FR8Jk2/CmIhcYO0ZCp0S5DYyStI7CSOUVSLOEbZdZCmI3GMNJEqqEUcI1YLKqhFHGNN/grd4tVCCtBAO4VYATqIPyz+cBQP2SuoRfxhTSSOCtwA1JIUuAF2C3aLthiDAjegbqFu0RZjVFCLuOFdGWWcV9Su9y4URMM8rKrckMrXoCAbaqJqqgi1xPLeRSOzebNpqcnVitoxYihIhjEbpmBYxuGGOu56HfHLlNCRDbVhGpbxt2HRTYpcrFgwd6zzQsUyMzRkwzL26pAtWKwaRYjJMMWBZAhoWBpcx2hBNMzDqnnYkQ0pDiRDHtYSRcHoipgvWG6hvRdLQDoDCKJhGNYAA9kwxoFkmIY1ZUMoYqlguYUmSKwRY0E0zMNaI67IhjXiimTIw1ojVkw14lyw3ELzLNWIuSAahmGtEVdkwxpxRTJMw1ojLlgi1hlOUG8RtdVTiVgnLl/mqYZ5WEvEDdmwRNyQDHlYS8QFoUSsM6FguYW2OpSIIxUEw7K2aTiscVjjwcqGJeKGZAhhYDbEceMacUEdW6VHCqaBbEjDSsPKw8pmRR1ppSMVvRtYri1rwRJmQzSM6q9OpILZsAwr9YISm86rsqqMA4cVhxWzYQ4Dh5WGldCwLPgaQsdcFn0ND1Y29HGguVNm0o524xz9QLtxTuMWadxCpxhJG0WdZDoOa4m4IRlms5ZJU5KpIBjSsJaObciGPKxsVnZp4LCWMBuiYbRbcOkh0ArgXC7QCmDSdgAoiIY8rPXGoJuAemMsyIa6ZGlYfag4rHFYS1ND2VGUfYPOb4LFyoplfEBXUK26ggp10tU1VKiTLoafP+8ufd/z/tvLw4Nuew4bIdkefb1/eXj+dnn3/P3p6e7yv/un7+Wif7/eP5fXb/cv8qnc6uH5k7yK4OfHpweln3fj227+VQYdr8u3ZfHBJgDxSsHPFbTEmoJU0HAB6EohzBVi7C7Ew/cx3+4BdgEpmjzzIM0VUuhNmFI4CGy1otx20oq4UHDUBcLohZRu9oB06V0FiMPMA1q0YtQ8ra0os/OsFXmuEDA1gUDTflzGYN3ABH6ai4tUYJ2hqwL7WQh+kYvArvek7L3QJGTcvdaIi5aU4aR3hqyiHc9VFjkpAVhrMOS5BiwqS3entbJoZGWI18ODX+Rl8Lo5q50qJyx7GiF2N0LAhR+L7JSFXy8QWfjBoTVudkMkeoIL8tyN1VDjyAY7f0iP14PdQgKhNyhy3qoSN/IiTccatwoiRDfyE6eVFtLJSgtwvtICvkWl6T7hbKUFOltpgc9X2lLjxkqL/nSlrdy4tdJW+XVjpcX05ypNMsqPOpGzz61aSzAyNNFUIy4SVLbXtsAJPLpEmvZKYpGfgZz1yCEv3PUCI/Jb1Fpy52st+bO1lsL5Wltq3FhrKZ2utZUbt9baMr88sy39HM7yKy0ksueeojn4sf7M9BsSRCaR80zi5mIDP93OwEJEtry9MXI+zI2v3IDVKiEmtoFDDshgKrLq2HJ2WDtWTkNmAyDEVdFzb47Ah4J9LZFO7woATm4L1mGkbGGEOPVhOYI6CyNA2PPCdpnSrvP+WOYFpDTygnGWF+hWY1ew9jzmhRxq/Y5GHBo01VjXiSVXlqcv01BWG6UU2bpFHgXO2yOdrhOE03WCeLpOMJ+sk3UYN9UJ8uk6WXdqGquVlA4z9KtOzYtKEf+t2DjOE3Stgbbmcc5vaoAl19UE/Rsa0YHN0A79pka2MzJ5rrWrkUzjcMr1Wxrl4LNpIO5qoGlk/wYau36waYSw64dN9Cc0yHJMniruaQQbfmLYbdNAlmPR7/pBlmPCexpx5FjczbE48iPutseVxq4fI8fkkHlXw53XGDkmzzr3NNIYCxPynkZOfaaVJg17GnTYy26O67IJzmPjlfcWQGTjeqYcZ9Mcr6b8MNaUgabHaLzY2CdrjHTY2L9e167CGOdw+fjs4VUY3q3Wk87ZetKlY3Pe7gc5G37I++mqYSlRfgPQJADnocTVg5hgD1Lk+d4hFH4lsto1ke3rPV8NpXx7MON8gUKK82BWq1KItqjUZ/s0V1ltzG2RTodyI3ilsEhSCLEPgxDyfPj5lQiYCM/nJ+8XrQq5Nyr641D6G25E3xMEVlOLXz5megM3bFaQjvWbTTqmBUgQFrHAH40l2RkWgN+NJWVrEIirWOiPxoLQSx9wsXr5hYi3esHsNkUA4xDZbdVspw3SNmE3HJttRQTPh5Nj3g3HTjqB3LYImCe0na6HcMjvNizZ8A6Ut0Vs1hSR/AbhZNoUYTt6BU67nhBbmzCE8+EwrCasxbxJyeZNjNN5M8Ib/AYg4ukfAaweENz8K4ClyK0/A4h8/ncAK0du/iHAemmVEo+lVZ6e8fvl0xscZ1RIYbYB8Cmu+tfOymKabyJ8Wh7zxzCOL+NsH/ELP+xw+2p/CL/x/IZsD+Adu+mPG/zqORLaFhNznrfGSiH0/EByc4VFmmY7jskcNh495/Lj9Srgr6bdax+WTxtCsk1IuFqJ3O6FncQI8pZCtodpntyOwjiRFsxbPticLwp0VsFv+RBsV5l1mNnyYTwdvVrv3+5DHI9oYS+KmEwBw9koXin8Le/uPz6+XP0v4E/Venm8//D00N5+/v788fDpt/9/7Z/0/yX8+vLl48On7y8PqnT4h8LLu78ixbvI8PfdxZe3Ae/kmPLvn3r3/wA=",
4764
+ "debug_symbols": "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",
4769
4765
  "is_unconstrained": true,
4770
4766
  "name": "update"
4771
4767
  }
@@ -5197,5 +5193,5 @@
5197
5193
  }
5198
5194
  },
5199
5195
  "transpiled": true,
5200
- "aztec_version": "6.0.0-rc.6"
5196
+ "aztec_version": "6.0.0"
5201
5197
  }