@aztec/accounts 0.0.1-commit.0dc957cde → 0.0.1-commit.0ec55a70b
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.
- package/artifacts/EcdsaKAccount.json +234 -234
- package/artifacts/EcdsaRAccount.json +226 -226
- package/artifacts/SchnorrAccount.json +188 -188
- package/artifacts/SimulatedEcdsaAccount.json +126 -188
- package/artifacts/SimulatedSchnorrAccount.json +126 -188
- package/package.json +6 -6
|
@@ -18,35 +18,35 @@
|
|
|
18
18
|
"function_locations": [
|
|
19
19
|
{
|
|
20
20
|
"name": "AztecConfig::new",
|
|
21
|
-
"start":
|
|
21
|
+
"start": 1825
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
"name": "AztecConfig::custom_message_handler",
|
|
25
|
-
"start":
|
|
25
|
+
"start": 2333
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
28
|
"name": "aztec",
|
|
29
|
-
"start":
|
|
29
|
+
"start": 3227
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
32
|
"name": "generate_contract_interface",
|
|
33
|
-
"start":
|
|
33
|
+
"start": 6704
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
36
|
"name": "generate_sync_state",
|
|
37
|
-
"start":
|
|
37
|
+
"start": 8566
|
|
38
38
|
},
|
|
39
39
|
{
|
|
40
40
|
"name": "generate_offchain_receive",
|
|
41
|
-
"start":
|
|
41
|
+
"start": 9620
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
44
|
"name": "check_each_fn_macroified",
|
|
45
|
-
"start":
|
|
45
|
+
"start": 11209
|
|
46
46
|
}
|
|
47
47
|
],
|
|
48
48
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/aztec-nr/aztec/src/macros/aztec.nr",
|
|
49
|
-
"source": "mod compute_note_hash_and_nullifier;\n\nuse crate::{\n macros::{\n calls_generation::{\n external_functions::{generate_external_function_calls, generate_external_function_self_calls_structs},\n internal_functions::generate_call_internal_struct,\n },\n dispatch::generate_public_dispatch,\n emit_public_init_nullifier::generate_emit_public_init_nullifier,\n internals_functions_generation::{create_fn_abi_exports, process_functions},\n storage::STORAGE_LAYOUT_NAME,\n utils::{is_fn_contract_library_method, is_fn_external, is_fn_internal, is_fn_test, module_has_storage},\n },\n messages::discovery::CustomMessageHandler,\n};\n\nuse compute_note_hash_and_nullifier::generate_contract_library_methods_compute_note_hash_and_nullifier;\n\n/// Configuration for the [`aztec`] macro.\n///\n/// This type lets users override different parts of the default aztec-nr contract behavior, such\n/// as message handling. These are advanced features that require careful understanding of\n/// the behavior of these systems.\n///\n/// ## Examples\n///\n/// ```noir\n/// #[aztec(aztec::macros::AztecConfig::new().custom_message_handler(my_handler))]\n/// contract MyContract { ... }\n/// ```\npub struct AztecConfig {\n custom_message_handler: Option<CustomMessageHandler<()>>,\n}\n\nimpl AztecConfig {\n /// Creates a new `AztecConfig` with default values.\n ///\n /// Calling `new` is equivalent to invoking the [`aztec`] macro with no parameters. The different methods\n /// (e.g. [`AztecConfig::custom_message_handler`]) can then be used to change the default behavior.\n pub comptime fn new() -> Self {\n Self { custom_message_handler: Option::none() }\n }\n\n /// Sets a handler for custom messages.\n ///\n /// This enables contracts to process non-standard messages (i.e. any with a message type that is not in\n /// [`crate::messages::msg_type`]).\n ///\n /// `handler` must be a function that conforms to the\n /// [`crate::messages::discovery::CustomMessageHandler`] type signature.\n pub comptime fn custom_message_handler(_self: Self, handler: CustomMessageHandler<()>) -> Self {\n Self { custom_message_handler: Option::some(handler) }\n }\n}\n\n/// Enables aztec-nr features on a `contract`.\n///\n/// All aztec-nr contracts should have this macro invoked on them, as it is the one that processes all contract\n/// functions, notes, storage, generates interfaces for external calls, and creates the message processing\n/// boilerplate.\n///\n/// ## Examples\n///\n/// Most contracts can simply invoke the macro with no parameters, resulting in default aztec-nr behavior:\n/// ```noir\n/// #[aztec]\n/// contract MyContract { ... }\n/// ```\n///\n/// Advanced contracts can use [`AztecConfig`] to customize parts of its behavior, such as message\n/// processing.\n/// ```noir\n/// #[aztec(aztec::macros::AztecConfig::new().custom_message_handler(my_handler))]\n/// contract MyAdvancedContract { ... }\n/// ```\n#[varargs]\npub comptime fn aztec(m: Module, args: [AztecConfig]) -> Quoted {\n let num_args = args.len();\n let config = if num_args == 0 {\n AztecConfig::new()\n } else if num_args == 1 {\n args[0]\n } else {\n panic(f\"#[aztec] expects 0 or 1 arguments, got {num_args}\")\n };\n\n // Functions that don't have #[external(...)], #[contract_library_method], or #[test] are not allowed in contracts.\n check_each_fn_macroified(m);\n\n // We generate new functions prefixed with `__aztec_nr_internals__` and we replace the original functions' bodies\n // with `static_assert(false, ...)` to prevent them from being called directly from within the contract.\n let functions = process_functions(m);\n\n // We generate structs and their implementations necessary for convenient functions calls.\n let interface = generate_contract_interface(m);\n let self_call_structs = generate_external_function_self_calls_structs(m);\n let call_internal_struct = generate_call_internal_struct(m);\n\n // We generate ABI exports for all the external functions in the contract.\n let fn_abi_exports = create_fn_abi_exports(m);\n\n // We generate `_compute_note_hash`, `_compute_note_nullifier` (and the deprecated\n // `_compute_note_hash_and_nullifier` wrapper) and `sync_state` functions only if they are not already implemented.\n // If they are implemented we just insert empty quotes.\n let contract_library_method_compute_note_hash_and_nullifier = if !m.functions().any(|f| {\n // Note that we don't test for `_compute_note_hash` or `_compute_note_nullifier` in order to make this simpler\n // - users must either implement all three or none.\n // Down the line we'll remove this check and use `AztecConfig`.\n f.name() == quote { _compute_note_hash_and_nullifier }\n }) {\n generate_contract_library_methods_compute_note_hash_and_nullifier()\n } else {\n quote {}\n };\n let process_custom_message_option = if config.custom_message_handler.is_some() {\n let handler = config.custom_message_handler.unwrap();\n quote { Option::some($handler) }\n } else {\n quote { Option::<aztec::messages::discovery::CustomMessageHandler<()>>::none() }\n };\n\n let offchain_inbox_sync_option = quote {\n Option::some(aztec::messages::processing::offchain::sync_inbox)\n };\n\n let sync_state_fn_and_abi_export = if !m.functions().any(|f| f.name() == quote { sync_state }) {\n generate_sync_state(process_custom_message_option, offchain_inbox_sync_option)\n } else {\n quote {}\n };\n\n if m.functions().any(|f| f.name() == quote { offchain_receive }) {\n panic(\n \"User-defined 'offchain_receive' is not allowed. The function is auto-injected by the #[aztec] macro. See https://docs.aztec.network/errors/7\",\n );\n }\n let offchain_receive_fn_and_abi_export = generate_offchain_receive();\n\n let (has_public_init_nullifier_fn, emit_public_init_nullifier_fn_body) = generate_emit_public_init_nullifier(m);\n let public_dispatch = generate_public_dispatch(m, has_public_init_nullifier_fn);\n\n quote {\n $interface\n $self_call_structs\n $call_internal_struct\n $functions\n $fn_abi_exports\n $contract_library_method_compute_note_hash_and_nullifier\n $public_dispatch\n $sync_state_fn_and_abi_export\n $emit_public_init_nullifier_fn_body\n $offchain_receive_fn_and_abi_export\n }\n}\n\ncomptime fn generate_contract_interface(m: Module) -> Quoted {\n let calls = generate_external_function_calls(m);\n\n let module_name = m.name();\n\n let has_storage_layout = module_has_storage(m) & STORAGE_LAYOUT_NAME.get(m).is_some();\n let storage_layout_getter = if has_storage_layout {\n let storage_layout_name = STORAGE_LAYOUT_NAME.get(m).unwrap();\n quote {\n pub fn storage_layout() -> StorageLayoutFields {\n $storage_layout_name.fields\n }\n }\n } else {\n quote {}\n };\n\n let library_storage_layout_getter = if has_storage_layout {\n quote {\n #[contract_library_method]\n $storage_layout_getter\n }\n } else {\n quote {}\n };\n\n quote {\n pub struct $module_name {\n pub target_contract: aztec::protocol::address::AztecAddress\n }\n\n impl $module_name {\n $calls\n\n pub fn at(\n addr: aztec::protocol::address::AztecAddress\n ) -> Self {\n Self { target_contract: addr }\n }\n\n pub fn interface() -> Self {\n Self { target_contract: aztec::protocol::address::AztecAddress::zero() }\n }\n\n $storage_layout_getter\n }\n\n #[contract_library_method]\n pub fn at(\n addr: aztec::protocol::address::AztecAddress\n ) -> $module_name {\n $module_name { target_contract: addr }\n }\n\n #[contract_library_method]\n pub fn interface() -> $module_name {\n $module_name { target_contract: aztec::protocol::address::AztecAddress::zero() }\n }\n\n $library_storage_layout_getter\n\n }\n}\n\n/// Generates the `sync_state` utility function that performs message discovery.\ncomptime fn generate_sync_state(process_custom_message_option: Quoted, offchain_inbox_sync_option: Quoted) -> Quoted {\n quote {\n pub struct sync_state_parameters {\n pub scope: aztec::protocol::address::AztecAddress,\n }\n\n #[abi(functions)]\n pub struct sync_state_abi {\n parameters: sync_state_parameters,\n }\n\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_utility]\n unconstrained fn sync_state(scope: aztec::protocol::address::AztecAddress) {\n let address = aztec::context::UtilityContext::new().this_address();\n aztec::messages::discovery::do_sync_state(\n address,\n _compute_note_hash,\n _compute_note_nullifier,\n $process_custom_message_option,\n $offchain_inbox_sync_option,\n scope,\n );\n }\n }\n}\n\n/// Generates an `offchain_receive` utility function that lets callers add messages to the offchain message inbox.\n///\n/// For more details, see `aztec::messages::processing::offchain::receive`.\ncomptime fn generate_offchain_receive() -> Quoted {\n quote {\n pub struct offchain_receive_parameters {\n pub messages: BoundedVec<\n aztec::messages::processing::offchain::OffchainMessage,\n aztec::messages::processing::offchain::MAX_OFFCHAIN_MESSAGES_PER_RECEIVE_CALL,\n >,\n }\n\n #[abi(functions)]\n pub struct offchain_receive_abi {\n parameters: offchain_receive_parameters,\n }\n\n /// Receives offchain messages into this contract's offchain inbox for subsequent processing.\n ///\n /// Each message is routed to the inbox scoped to its `recipient` field.\n ///\n /// For more details, see `aztec::messages::processing::offchain::receive`.\n ///\n /// This function is automatically injected by the `#[aztec]` macro.\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_utility]\n unconstrained fn offchain_receive(\n messages: BoundedVec<\n aztec::messages::processing::offchain::OffchainMessage,\n aztec::messages::processing::offchain::MAX_OFFCHAIN_MESSAGES_PER_RECEIVE_CALL,\n >,\n ) {\n let address = aztec::context::UtilityContext::new().this_address();\n aztec::messages::processing::offchain::receive(address, messages);\n }\n }\n}\n\n/// Checks that all functions in the module have a context macro applied.\n///\n/// Non-macroified functions are not allowed in contracts. They must all be one of\n/// [`crate::macros::functions::external`], [`crate::macros::functions::internal`] or `test`.\ncomptime fn check_each_fn_macroified(m: Module) {\n for f in m.functions() {\n let name = f.name();\n if !is_fn_external(f) & !is_fn_contract_library_method(f) & !is_fn_internal(f) & !is_fn_test(f) {\n // We don't suggest that #[contract_library_method] is allowed because we don't want to introduce another\n // concept\n panic(\n f\"Function {name} must be marked as either #[external(...)], #[internal(...)], or #[test]\",\n );\n }\n }\n}\n"
|
|
49
|
+
"source": "mod compute_note_hash_and_nullifier;\n\nuse crate::{\n macros::{\n calls_generation::{\n external_functions::{generate_external_function_calls, generate_external_function_self_calls_structs},\n internal_functions::generate_call_internal_struct,\n },\n dispatch::generate_public_dispatch,\n emit_public_init_nullifier::generate_emit_public_init_nullifier,\n internals_functions_generation::{create_fn_abi_exports, process_functions},\n offchain_receive::{\n OFFCHAIN_RECEIVE_FN_NAME, OFFCHAIN_RECEIVE_PARAM_NAME, offchain_receive_param_type,\n OFFCHAIN_RECEIVE_RETURN_TYPE,\n },\n storage::STORAGE_LAYOUT_NAME,\n utils::{is_fn_contract_library_method, is_fn_external, is_fn_internal, is_fn_test, module_has_storage},\n },\n messages::discovery::CustomMessageHandler,\n};\n\nuse compute_note_hash_and_nullifier::generate_contract_library_methods_compute_note_hash_and_nullifier;\n\n/// Configuration for the [`aztec`] macro.\n///\n/// This type lets users override different parts of the default aztec-nr contract behavior, such\n/// as message handling. These are advanced features that require careful understanding of\n/// the behavior of these systems.\n///\n/// ## Examples\n///\n/// ```noir\n/// #[aztec(aztec::macros::AztecConfig::new().custom_message_handler(my_handler))]\n/// contract MyContract { ... }\n/// ```\npub struct AztecConfig {\n custom_message_handler: Option<CustomMessageHandler<()>>,\n}\n\nimpl AztecConfig {\n /// Creates a new `AztecConfig` with default values.\n ///\n /// Calling `new` is equivalent to invoking the [`aztec`] macro with no parameters. The different methods\n /// (e.g. [`AztecConfig::custom_message_handler`]) can then be used to change the default behavior.\n pub comptime fn new() -> Self {\n Self { custom_message_handler: Option::none() }\n }\n\n /// Sets a handler for custom messages.\n ///\n /// This enables contracts to process non-standard messages (i.e. any with a message type that is not in\n /// [`crate::messages::msg_type`]).\n ///\n /// `handler` must be a function that conforms to the\n /// [`crate::messages::discovery::CustomMessageHandler`] type signature.\n pub comptime fn custom_message_handler(_self: Self, handler: CustomMessageHandler<()>) -> Self {\n Self { custom_message_handler: Option::some(handler) }\n }\n}\n\n/// Enables aztec-nr features on a `contract`.\n///\n/// All aztec-nr contracts should have this macro invoked on them, as it is the one that processes all contract\n/// functions, notes, storage, generates interfaces for external calls, and creates the message processing\n/// boilerplate.\n///\n/// ## Examples\n///\n/// Most contracts can simply invoke the macro with no parameters, resulting in default aztec-nr behavior:\n/// ```noir\n/// #[aztec]\n/// contract MyContract { ... }\n/// ```\n///\n/// Advanced contracts can use [`AztecConfig`] to customize parts of its behavior, such as message\n/// processing.\n/// ```noir\n/// #[aztec(aztec::macros::AztecConfig::new().custom_message_handler(my_handler))]\n/// contract MyAdvancedContract { ... }\n/// ```\n#[varargs]\npub comptime fn aztec(m: Module, args: [AztecConfig]) -> Quoted {\n let num_args = args.len();\n let config = if num_args == 0 {\n AztecConfig::new()\n } else if num_args == 1 {\n args[0]\n } else {\n panic(f\"#[aztec] expects 0 or 1 arguments, got {num_args}\")\n };\n\n // Functions that don't have #[external(...)], #[contract_library_method], or #[test] are not allowed in contracts.\n check_each_fn_macroified(m);\n\n // We generate new functions prefixed with `__aztec_nr_internals__` and we replace the original functions' bodies\n // with `static_assert(false, ...)` to prevent them from being called directly from within the contract.\n let functions = process_functions(m);\n\n // We generate structs and their implementations necessary for convenient functions calls.\n let interface = generate_contract_interface(m);\n let self_call_structs = generate_external_function_self_calls_structs(m);\n let call_internal_struct = generate_call_internal_struct(m);\n\n // We generate ABI exports for all the external functions in the contract.\n let fn_abi_exports = create_fn_abi_exports(m);\n\n // We generate `_compute_note_hash`, `_compute_note_nullifier` (and the deprecated\n // `_compute_note_hash_and_nullifier` wrapper) and `sync_state` functions only if they are not already implemented.\n // If they are implemented we just insert empty quotes.\n let contract_library_method_compute_note_hash_and_nullifier = if !m.functions().any(|f| {\n // Note that we don't test for `_compute_note_hash` or `_compute_note_nullifier` in order to make this simpler\n // - users must either implement all three or none.\n // Down the line we'll remove this check and use `AztecConfig`.\n f.name() == quote { _compute_note_hash_and_nullifier }\n }) {\n generate_contract_library_methods_compute_note_hash_and_nullifier()\n } else {\n quote {}\n };\n let process_custom_message_option = if config.custom_message_handler.is_some() {\n let handler = config.custom_message_handler.unwrap();\n quote { Option::some($handler) }\n } else {\n quote { Option::<aztec::messages::discovery::CustomMessageHandler<()>>::none() }\n };\n\n let offchain_inbox_sync_option = quote {\n Option::some(aztec::messages::processing::offchain::sync_inbox)\n };\n\n let sync_state_fn_and_abi_export = if !m.functions().any(|f| f.name() == quote { sync_state }) {\n generate_sync_state(process_custom_message_option, offchain_inbox_sync_option)\n } else {\n quote {}\n };\n\n if m.functions().any(|f| f.name() == quote { offchain_receive }) {\n panic(\n \"User-defined 'offchain_receive' is not allowed. The function is auto-injected by the #[aztec] macro. See https://docs.aztec.network/errors/7\",\n );\n }\n let offchain_receive_fn_and_abi_export = generate_offchain_receive();\n\n let (has_public_init_nullifier_fn, emit_public_init_nullifier_fn_body) = generate_emit_public_init_nullifier(m);\n let public_dispatch = generate_public_dispatch(m, has_public_init_nullifier_fn);\n\n quote {\n $interface\n $self_call_structs\n $call_internal_struct\n $functions\n $fn_abi_exports\n $contract_library_method_compute_note_hash_and_nullifier\n $public_dispatch\n $sync_state_fn_and_abi_export\n $emit_public_init_nullifier_fn_body\n $offchain_receive_fn_and_abi_export\n }\n}\n\ncomptime fn generate_contract_interface(m: Module) -> Quoted {\n let calls = generate_external_function_calls(m);\n\n let module_name = m.name();\n\n let has_storage_layout = module_has_storage(m) & STORAGE_LAYOUT_NAME.get(m).is_some();\n let storage_layout_getter = if has_storage_layout {\n let storage_layout_name = STORAGE_LAYOUT_NAME.get(m).unwrap();\n quote {\n pub fn storage_layout() -> StorageLayoutFields {\n $storage_layout_name.fields\n }\n }\n } else {\n quote {}\n };\n\n let library_storage_layout_getter = if has_storage_layout {\n quote {\n #[contract_library_method]\n $storage_layout_getter\n }\n } else {\n quote {}\n };\n\n quote {\n pub struct $module_name {\n pub target_contract: aztec::protocol::address::AztecAddress\n }\n\n impl $module_name {\n $calls\n\n pub fn at(\n addr: aztec::protocol::address::AztecAddress\n ) -> Self {\n Self { target_contract: addr }\n }\n\n pub fn interface() -> Self {\n Self { target_contract: aztec::protocol::address::AztecAddress::zero() }\n }\n\n $storage_layout_getter\n }\n\n #[contract_library_method]\n pub fn at(\n addr: aztec::protocol::address::AztecAddress\n ) -> $module_name {\n $module_name { target_contract: addr }\n }\n\n #[contract_library_method]\n pub fn interface() -> $module_name {\n $module_name { target_contract: aztec::protocol::address::AztecAddress::zero() }\n }\n\n $library_storage_layout_getter\n\n }\n}\n\n/// Generates the `sync_state` utility function that performs message discovery.\ncomptime fn generate_sync_state(process_custom_message_option: Quoted, offchain_inbox_sync_option: Quoted) -> Quoted {\n quote {\n pub struct sync_state_parameters {\n pub scope: aztec::protocol::address::AztecAddress,\n }\n\n #[abi(functions)]\n pub struct sync_state_abi {\n parameters: sync_state_parameters,\n }\n\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_utility]\n unconstrained fn sync_state(scope: aztec::protocol::address::AztecAddress) {\n let address = aztec::context::UtilityContext::new().this_address();\n aztec::messages::discovery::do_sync_state(\n address,\n _compute_note_hash,\n _compute_note_nullifier,\n $process_custom_message_option,\n $offchain_inbox_sync_option,\n scope,\n );\n }\n }\n}\n\n/// Generates an `offchain_receive` utility function that lets callers add messages to the offchain message inbox.\n///\n/// For more details, see `aztec::messages::processing::offchain::receive`.\ncomptime fn generate_offchain_receive() -> Quoted {\n let param_type = offchain_receive_param_type(quote { aztec });\n let parameters_struct_name = f\"{OFFCHAIN_RECEIVE_FN_NAME}_parameters\".quoted_contents();\n let abi_struct_name = f\"{OFFCHAIN_RECEIVE_FN_NAME}_abi\".quoted_contents();\n\n quote {\n pub struct $parameters_struct_name {\n pub $OFFCHAIN_RECEIVE_PARAM_NAME: $param_type,\n }\n\n #[abi(functions)]\n pub struct $abi_struct_name {\n parameters: $parameters_struct_name,\n }\n\n /// Receives offchain messages into this contract's offchain inbox for subsequent processing.\n ///\n /// Each message is routed to the inbox scoped to its `recipient` field.\n ///\n /// For more details, see `aztec::messages::processing::offchain::receive`.\n ///\n /// This function is automatically injected by the `#[aztec]` macro.\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_utility]\n unconstrained fn $OFFCHAIN_RECEIVE_FN_NAME($OFFCHAIN_RECEIVE_PARAM_NAME: $param_type) -> $OFFCHAIN_RECEIVE_RETURN_TYPE {\n let address = aztec::context::UtilityContext::new().this_address();\n aztec::messages::processing::offchain::receive(address, $OFFCHAIN_RECEIVE_PARAM_NAME);\n }\n }\n}\n\n/// Checks that all functions in the module have a context macro applied.\n///\n/// Non-macroified functions are not allowed in contracts. They must all be one of\n/// [`crate::macros::functions::external`], [`crate::macros::functions::internal`] or `test`.\ncomptime fn check_each_fn_macroified(m: Module) {\n for f in m.functions() {\n let name = f.name();\n if !is_fn_external(f) & !is_fn_contract_library_method(f) & !is_fn_internal(f) & !is_fn_test(f) {\n // We don't suggest that #[contract_library_method] is allowed because we don't want to introduce another\n // concept\n panic(\n f\"Function {name} must be marked as either #[external(...)], #[internal(...)], or #[test]\",\n );\n }\n }\n}\n"
|
|
50
50
|
},
|
|
51
51
|
"115": {
|
|
52
52
|
"function_locations": [
|
|
@@ -68,61 +68,61 @@
|
|
|
68
68
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/external/utility.nr",
|
|
69
69
|
"source": "use crate::macros::utils::{fn_has_noinitcheck, module_has_initializer, module_has_storage};\n\npub(crate) comptime fn generate_utility_external(f: FunctionDefinition) -> Quoted {\n let module_has_initializer = module_has_initializer(f.module());\n\n // Initialize Storage if module has storage\n let storage_init = if module_has_storage(f.module()) {\n quote {\n let storage = Storage::init(context);\n }\n } else {\n // Contract does not have Storage defined, so we set storage to the unit type `()`. ContractSelfUtility\n // requires a\n // storage struct in its constructor. Using an Option type would lead to worse developer experience and higher\n // constraint counts so we use the unit type `()` instead.\n quote {\n let storage = ();\n }\n };\n\n // Create utility context\n let contract_self_creation = quote {\n #[allow(unused_variables)]\n let mut self = {\n let context = aztec::context::UtilityContext::new();\n $storage_init\n aztec::contract_self::ContractSelfUtility::new(context, storage)\n };\n };\n\n // Initialization checks are not included in contracts that don't have initializers.\n let init_check = if module_has_initializer & !fn_has_noinitcheck(f) {\n quote {\n aztec::macros::functions::initialization_utils::assert_is_initialized_utility(\n self.context,\n );\n }\n } else {\n quote {}\n };\n\n // A quote to be injected at the beginning of the function body.\n let to_prepend = quote {\n aztec::oracle::version::assert_compatible_oracle_version();\n $contract_self_creation\n $init_check\n };\n\n let original_function_name = f.name();\n let fn_name = f\"__aztec_nr_internals__{original_function_name}\".quoted_contents();\n let body = f.body();\n let params = f.parameters().map(|(param_name, param_type)| quote { $param_name: $param_type }).join(quote {, });\n let return_type = f.return_type();\n\n quote {\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_utility]\n unconstrained fn $fn_name($params) -> pub $return_type {\n $to_prepend\n $body\n }\n }\n}\n"
|
|
70
70
|
},
|
|
71
|
-
"
|
|
71
|
+
"154": {
|
|
72
72
|
"function_locations": [
|
|
73
73
|
{
|
|
74
74
|
"name": "receive",
|
|
75
|
-
"start":
|
|
75
|
+
"start": 5332
|
|
76
76
|
},
|
|
77
77
|
{
|
|
78
78
|
"name": "sync_inbox",
|
|
79
|
-
"start":
|
|
79
|
+
"start": 6775
|
|
80
80
|
},
|
|
81
81
|
{
|
|
82
82
|
"name": "test::setup",
|
|
83
|
-
"start":
|
|
83
|
+
"start": 11145
|
|
84
84
|
},
|
|
85
85
|
{
|
|
86
86
|
"name": "test::make_msg",
|
|
87
|
-
"start":
|
|
87
|
+
"start": 11475
|
|
88
88
|
},
|
|
89
89
|
{
|
|
90
90
|
"name": "test::advance_by",
|
|
91
|
-
"start":
|
|
91
|
+
"start": 11758
|
|
92
92
|
},
|
|
93
93
|
{
|
|
94
94
|
"name": "test::empty_inbox_returns_empty_result",
|
|
95
|
-
"start":
|
|
95
|
+
"start": 11949
|
|
96
96
|
},
|
|
97
97
|
{
|
|
98
98
|
"name": "test::tx_bound_msg_expires_after_max_msg_ttl",
|
|
99
|
-
"start":
|
|
99
|
+
"start": 12412
|
|
100
100
|
},
|
|
101
101
|
{
|
|
102
102
|
"name": "test::tx_bound_msg_not_expired_before_max_msg_ttl",
|
|
103
|
-
"start":
|
|
103
|
+
"start": 13377
|
|
104
104
|
},
|
|
105
105
|
{
|
|
106
106
|
"name": "test::tx_less_msg_expires_after_max_msg_ttl",
|
|
107
|
-
"start":
|
|
107
|
+
"start": 14335
|
|
108
108
|
},
|
|
109
109
|
{
|
|
110
110
|
"name": "test::unresolved_tx_stays_in_inbox",
|
|
111
|
-
"start":
|
|
111
|
+
"start": 15277
|
|
112
112
|
},
|
|
113
113
|
{
|
|
114
114
|
"name": "test::multiple_messages_mixed_expiration",
|
|
115
|
-
"start":
|
|
115
|
+
"start": 16171
|
|
116
116
|
},
|
|
117
117
|
{
|
|
118
118
|
"name": "test::resolved_msg_is_ready_to_process",
|
|
119
|
-
"start":
|
|
119
|
+
"start": 17910
|
|
120
120
|
}
|
|
121
121
|
],
|
|
122
122
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/aztec-nr/aztec/src/messages/processing/offchain.nr",
|
|
123
|
-
"source": "use crate::{\n capsules::CapsuleArray,\n context::UtilityContext,\n ephemeral::EphemeralArray,\n messages::{encoding::MESSAGE_CIPHERTEXT_LEN, processing::OffchainMessageWithContext},\n oracle::contract_sync::set_contract_sync_cache_invalid,\n protocol::{\n address::AztecAddress,\n constants::MAX_TX_LIFETIME,\n hash::sha256_to_field,\n traits::{Deserialize, Serialize},\n },\n};\n\n/// Base capsule slot for the persistent inbox of [`PendingOffchainMsg`] entries.\n///\n/// This is the slot where we accumulate messages received through [`receive`].\nglobal OFFCHAIN_INBOX_SLOT: Field = sha256_to_field(\"AZTEC_NR::OFFCHAIN_INBOX_SLOT\".as_bytes());\n\n/// Ephemeral array slot used by [`sync_inbox`] to pass tx hash resolution requests to PXE.\nglobal OFFCHAIN_CONTEXT_REQUESTS_SLOT: Field = sha256_to_field(\"AZTEC_NR::OFFCHAIN_CONTEXT_REQUESTS_SLOT\".as_bytes());\n\n/// Ephemeral array slot used by [`sync_inbox`] to collect messages ready for processing.\nglobal OFFCHAIN_READY_MESSAGES_SLOT: Field = sha256_to_field(\"AZTEC_NR::OFFCHAIN_READY_MESSAGES_SLOT\".as_bytes());\n\n/// Maximum number of offchain messages accepted by `offchain_receive` in a single call.\npub global MAX_OFFCHAIN_MESSAGES_PER_RECEIVE_CALL: u32 = 16;\n\n/// Tolerance added to the `MAX_TX_LIFETIME` cap for message expiration.\nglobal TX_EXPIRATION_TOLERANCE: u64 = 7200; // 2 hours\n\n/// Maximum time-to-live for a tx-bound offchain message.\n///\n/// After `anchor_block_timestamp + MAX_MSG_TTL`, the message is evicted from the inbox.\nglobal MAX_MSG_TTL: u64 = MAX_TX_LIFETIME + TX_EXPIRATION_TOLERANCE;\n\n/// A function that manages offchain-delivered messages for processing during sync.\n///\n/// Offchain messages are messages that are not broadcasted via onchain logs. They are instead delivered to the\n/// recipient by calling the `offchain_receive` utility function (injected by the `#[aztec]` macro). Message transport\n/// is the app's responsibility. Typical examples of transport methods are: messaging apps, email, QR codes, etc.\n///\n/// Once offchain messages are delivered to the recipient's private environment via `offchain_receive`, messages are\n/// locally stored in a persistent inbox.\n///\n/// This function determines when each message in said inbox is ready for processing, when it can be safely disposed\n/// of, etc.\n///\n/// The only current implementation of an `OffchainInboxSync` is [`sync_inbox`], which manages an inbox with expiration\n/// based eviction and automatic transaction context resolution.\npub(crate) type OffchainInboxSync<Env> = unconstrained fn[Env](\n/* contract_address */AztecAddress, /* scope */ AztecAddress) -> EphemeralArray<OffchainMessageWithContext>;\n\n/// A message delivered via the `offchain_receive` utility function.\npub struct OffchainMessage {\n /// The encrypted message payload.\n pub ciphertext: BoundedVec<Field, MESSAGE_CIPHERTEXT_LEN>,\n /// The intended recipient of the message.\n pub recipient: AztecAddress,\n /// The hash of the transaction that produced this message. `Option::none` indicates a tx-less message.\n pub tx_hash: Option<Field>,\n /// Anchor block timestamp at message emission.\n pub anchor_block_timestamp: u64,\n}\n\n/// An offchain message awaiting processing (or re-processing) in the inbox.\n///\n/// Messages remain in the inbox until they expire, even if they have already been processed. This is necessary to\n/// handle reorgs: a processed message may need to be re-processed if the transaction that provided its context is\n/// reverted. On each sync, resolved messages are promoted to [`OffchainMessageWithContext`] for processing.\n#[derive(Serialize, Deserialize)]\nstruct PendingOffchainMsg {\n /// The encrypted message payload.\n ciphertext: BoundedVec<Field, MESSAGE_CIPHERTEXT_LEN>,\n /// The intended recipient of the message.\n recipient: AztecAddress,\n /// The hash of the transaction that produced this message. A value of 0 indicates a tx-less message.\n tx_hash: Field,\n /// Anchor block timestamp at message emission. Used to compute the effective expiration: messages are evicted\n /// after `anchor_block_timestamp + MAX_MSG_TTL`.\n anchor_block_timestamp: u64,\n}\n\n/// Delivers offchain messages to the given contract's offchain inbox for subsequent processing.\n///\n/// Offchain messages are transaction effects that are not broadcasted via onchain logs. Instead, the sender shares the\n/// message to the recipient through an external channel (e.g. a URL accessible by the recipient). The recipient then\n/// calls this function to hand the messages to the contract so they can be processed through the same mechanisms as\n/// onchain messages.\n///\n/// Each message is routed to the inbox scoped to its `recipient` field, so messages for different accounts are\n/// automatically isolated.\n///\n/// Messages are processed when their originating transaction is found onchain (providing the context needed to\n/// validate resulting notes and events).\n///\n/// Messages are kept in the inbox until they expire. The effective expiration is\n/// `anchor_block_timestamp + MAX_MSG_TTL`.\n///\n/// Processing order is not guaranteed.\npub unconstrained fn receive(\n contract_address: AztecAddress,\n messages: BoundedVec<OffchainMessage, MAX_OFFCHAIN_MESSAGES_PER_RECEIVE_CALL>,\n) {\n // May contain duplicates if multiple messages target the same recipient. This is harmless since\n // cache invalidation on the TS side is idempotent (deleting an already-deleted key is a no-op).\n let mut scopes: BoundedVec<AztecAddress, MAX_OFFCHAIN_MESSAGES_PER_RECEIVE_CALL> = BoundedVec::new();\n let mut i = 0;\n let messages_len = messages.len();\n while i < messages_len {\n let msg = messages.get(i);\n let tx_hash = if msg.tx_hash.is_some() {\n msg.tx_hash.unwrap()\n } else {\n 0\n };\n let inbox: CapsuleArray<PendingOffchainMsg> =\n CapsuleArray::at(contract_address, OFFCHAIN_INBOX_SLOT, msg.recipient);\n inbox.push(\n PendingOffchainMsg {\n ciphertext: msg.ciphertext,\n recipient: msg.recipient,\n tx_hash,\n anchor_block_timestamp: msg.anchor_block_timestamp,\n },\n );\n scopes.push(msg.recipient);\n i += 1;\n }\n\n set_contract_sync_cache_invalid(contract_address, scopes);\n}\n\n/// Returns offchain-delivered messages to process during sync.\n///\n/// Messages remain in the inbox and are reprocessed on each sync until their originating transaction is no longer at\n/// risk of being dropped by a reorg.\npub unconstrained fn sync_inbox(\n contract_address: AztecAddress,\n scope: AztecAddress,\n) -> EphemeralArray<OffchainMessageWithContext> {\n let inbox: CapsuleArray<PendingOffchainMsg> = CapsuleArray::at(contract_address, OFFCHAIN_INBOX_SLOT, scope);\n let context_resolution_requests: EphemeralArray<Field> = EphemeralArray::at(OFFCHAIN_CONTEXT_REQUESTS_SLOT).clear();\n let ready_to_process: EphemeralArray<OffchainMessageWithContext> =\n EphemeralArray::at(OFFCHAIN_READY_MESSAGES_SLOT).clear();\n\n // Build a request list aligned with the inbox indices.\n let mut i = 0;\n let inbox_len = inbox.len();\n while i < inbox_len {\n let msg = inbox.get(i);\n context_resolution_requests.push(msg.tx_hash);\n i += 1;\n }\n\n // Ask PXE to resolve contexts for all requested tx hashes. The oracle returns responses in a new\n // ephemeral array.\n let resolved_contexts =\n crate::oracle::message_processing::get_message_contexts_by_tx_hash(context_resolution_requests);\n\n assert_eq(resolved_contexts.len(), inbox_len);\n\n let now = UtilityContext::new().timestamp();\n\n let mut j = inbox_len;\n while j > 0 {\n // This loop decides what to do with each message in the offchain message inbox. We need to handle 3\n // different scenarios for each message.\n //\n // 1. The TX that emitted this message is still not known to PXE: in this case we can't yet process this\n // message, as any notes or events discovered will fail to be validated. So we leave the message in the inbox,\n // awaiting for future syncs to detect that the TX became available.\n //\n // 2. The message is not associated to a TX to begin with. The current version of offchain message processing\n // does not support this case, but in the future it will. Right now, a message without an associated TX will\n // sit in the inbox until it expires.\n //\n // 3. The TX that emitted this message has been found by PXE. That gives us all the information needed to\n // process the message. We add the message to the `ready_to_process` EphemeralArray so that the `sync_state`\n // loop\n // processes it.\n //\n // In all cases, if the message has expired (i.e. `now > anchor_block_timestamp + MAX_MSG_TTL`), we remove it\n // from the inbox.\n //\n // Note: the loop runs backwards because it might call `inbox.remove(j)` to purge expired messages and we also\n // need to align it with `resolved_contexts.get(j)`. Going from last to first simplifies the algorithm as\n // not yet visited element indexes remain stable.\n j -= 1;\n let maybe_ctx = resolved_contexts.get(j);\n let msg = inbox.get(j);\n\n // Compute the message's effective expiration timestamp to determine if we can purge it from the inbox.\n let effective_expiration = msg.anchor_block_timestamp + MAX_MSG_TTL;\n\n // Message expired. We remove it from the inbox.\n if now > effective_expiration {\n inbox.remove(j);\n }\n\n // Scenario 1: associated TX not yet available. We keep the message in the inbox, as it might become\n // processable as new blocks get mined.\n // Scenario 2: no TX associated to message. The message will sit in the inbox until it expires.\n if maybe_ctx.is_none() {\n continue;\n }\n\n // Scenario 3: Message is ready to process, add to result array. Note we still keep it in the inbox unless we\n // consider it has expired: this is because we need to account for reorgs. If reorg occurs after we processed\n // a message, the effects of processing the message get rewind. However, the associated TX can be included in\n // a subsequent block. Should that happen, the message must be re-processed to ensure consistency.\n let message_context = maybe_ctx.unwrap();\n ready_to_process.push(OffchainMessageWithContext { message_ciphertext: msg.ciphertext, message_context });\n }\n\n ready_to_process\n}\n\nmod test {\n use crate::{\n capsules::CapsuleArray, oracle::random::random, protocol::address::AztecAddress,\n test::helpers::test_environment::TestEnvironment,\n };\n use super::{\n MAX_MSG_TTL, MAX_OFFCHAIN_MESSAGES_PER_RECEIVE_CALL, OFFCHAIN_INBOX_SLOT, OffchainMessage, PendingOffchainMsg,\n receive, sync_inbox,\n };\n\n unconstrained fn setup() -> (TestEnvironment, AztecAddress) {\n let mut env = TestEnvironment::new();\n let scope = env.create_light_account();\n (env, scope)\n }\n\n /// Creates an `OffchainMessage` with dummy ciphertext and the given scope as recipient.\n fn make_msg(recipient: AztecAddress, tx_hash: Option<Field>, anchor_block_timestamp: u64) -> OffchainMessage {\n OffchainMessage { ciphertext: BoundedVec::new(), recipient, tx_hash, anchor_block_timestamp }\n }\n\n /// Advances the TXE block timestamp by `offset` seconds and returns the resulting timestamp.\n unconstrained fn advance_by(env: TestEnvironment, offset: u64) -> u64 {\n env.advance_next_block_timestamp_by(offset);\n env.mine_block();\n env.last_block_timestamp()\n }\n\n #[test]\n unconstrained fn empty_inbox_returns_empty_result() {\n let (env, scope) = setup();\n env.utility_context(|context| {\n let result = sync_inbox(context.this_address(), scope);\n let inbox: CapsuleArray<PendingOffchainMsg> =\n CapsuleArray::at(context.this_address(), OFFCHAIN_INBOX_SLOT, scope);\n\n assert_eq(result.len(), 0);\n assert_eq(inbox.len(), 0);\n });\n }\n\n #[test]\n unconstrained fn tx_bound_msg_expires_after_max_msg_ttl() {\n let (env, scope) = setup();\n let anchor_ts = advance_by(env, 10);\n\n env.utility_context(|context| {\n let mut msgs: BoundedVec<OffchainMessage, MAX_OFFCHAIN_MESSAGES_PER_RECEIVE_CALL> = BoundedVec::new();\n msgs.push(make_msg(scope, Option::some(random()), anchor_ts));\n receive(context.this_address(), msgs);\n });\n\n // Advance past anchor_ts + MAX_MSG_TTL.\n let _now = advance_by(env, MAX_MSG_TTL + 1);\n\n env.utility_context(|context| {\n let address = context.this_address();\n let result = sync_inbox(address, scope);\n let inbox: CapsuleArray<PendingOffchainMsg> = CapsuleArray::at(address, OFFCHAIN_INBOX_SLOT, scope);\n\n assert_eq(result.len(), 0); // context is None, not ready\n assert_eq(inbox.len(), 0); // expired, removed\n });\n }\n\n #[test]\n unconstrained fn tx_bound_msg_not_expired_before_max_msg_ttl() {\n let (env, scope) = setup();\n let anchor_ts = advance_by(env, 10);\n\n env.utility_context(|context| {\n let mut msgs: BoundedVec<OffchainMessage, MAX_OFFCHAIN_MESSAGES_PER_RECEIVE_CALL> = BoundedVec::new();\n msgs.push(make_msg(scope, Option::some(random()), anchor_ts));\n receive(context.this_address(), msgs);\n });\n\n // Advance, but not past anchor_ts + MAX_MSG_TTL.\n let _now = advance_by(env, 100);\n\n env.utility_context(|context| {\n let address = context.this_address();\n let result = sync_inbox(address, scope);\n let inbox: CapsuleArray<PendingOffchainMsg> = CapsuleArray::at(address, OFFCHAIN_INBOX_SLOT, scope);\n\n assert_eq(result.len(), 0); // context is None, not ready\n assert_eq(inbox.len(), 1); // not expired, stays\n });\n }\n\n #[test]\n unconstrained fn tx_less_msg_expires_after_max_msg_ttl() {\n let (env, scope) = setup();\n let anchor_ts = advance_by(env, 10);\n\n env.utility_context(|context| {\n let mut msgs: BoundedVec<OffchainMessage, MAX_OFFCHAIN_MESSAGES_PER_RECEIVE_CALL> = BoundedVec::new();\n msgs.push(make_msg(scope, Option::none(), anchor_ts));\n receive(context.this_address(), msgs);\n });\n\n // Advance past anchor_ts + MAX_MSG_TTL.\n let _now = advance_by(env, MAX_MSG_TTL + 1);\n\n env.utility_context(|context| {\n let address = context.this_address();\n let result = sync_inbox(address, scope);\n let inbox: CapsuleArray<PendingOffchainMsg> = CapsuleArray::at(address, OFFCHAIN_INBOX_SLOT, scope);\n\n assert_eq(result.len(), 0); // context is None, not ready\n assert_eq(inbox.len(), 0); // expired, removed\n });\n }\n\n #[test]\n unconstrained fn unresolved_tx_stays_in_inbox() {\n let (env, scope) = setup();\n let anchor_ts = advance_by(env, 10);\n\n env.utility_context(|context| {\n let mut msgs: BoundedVec<OffchainMessage, MAX_OFFCHAIN_MESSAGES_PER_RECEIVE_CALL> = BoundedVec::new();\n msgs.push(make_msg(scope, Option::some(random()), anchor_ts));\n receive(context.this_address(), msgs);\n });\n\n let _now = advance_by(env, 100);\n\n env.utility_context(|context| {\n let address = context.this_address();\n let result = sync_inbox(address, scope);\n let inbox: CapsuleArray<PendingOffchainMsg> = CapsuleArray::at(address, OFFCHAIN_INBOX_SLOT, scope);\n\n assert_eq(result.len(), 0); // not resolved, not ready\n assert_eq(inbox.len(), 1); // not expired, stays\n });\n }\n\n #[test]\n unconstrained fn multiple_messages_mixed_expiration() {\n let (env, scope) = setup();\n let anchor_ts = advance_by(env, 10);\n\n let survivor_tx_hash = random();\n\n env.utility_context(|context| {\n let address = context.this_address();\n let mut msgs: BoundedVec<OffchainMessage, MAX_OFFCHAIN_MESSAGES_PER_RECEIVE_CALL> = BoundedVec::new();\n // Message 0: tx-bound, anchor_ts in the past so it expires at\n // anchor_ts + MAX_MSG_TTL. We set anchor to 0 so it expires quickly.\n msgs.push(make_msg(scope, Option::some(random()), 0));\n // Message 1: tx-bound, anchor_ts is recent so it survives.\n msgs.push(make_msg(scope, Option::some(survivor_tx_hash), anchor_ts));\n // Message 2: tx-less, anchor_ts=0 so it also expires.\n msgs.push(make_msg(scope, Option::none(), 0));\n receive(address, msgs);\n });\n\n // Advance past MAX_MSG_TTL for anchor_ts=0, but not for anchor_ts=anchor_ts.\n let _now = advance_by(env, MAX_MSG_TTL);\n\n env.utility_context(|context| {\n let address = context.this_address();\n let result = sync_inbox(address, scope);\n let inbox: CapsuleArray<PendingOffchainMsg> = CapsuleArray::at(address, OFFCHAIN_INBOX_SLOT, scope);\n\n assert_eq(result.len(), 0); // all contexts are None\n // Message 0 expired (anchor=0), message 1 survived (anchor=anchor_ts),\n // Message 2 expired (anchor=0).\n assert_eq(inbox.len(), 1);\n assert_eq(inbox.get(0).tx_hash, survivor_tx_hash);\n });\n }\n\n // -- Resolved context (ready to process) ------------------------------\n\n #[test]\n unconstrained fn resolved_msg_is_ready_to_process() {\n let (env, scope) = setup();\n // TestEnvironment::new() deploys protocol contracts, creating blocks with tx effects.\n // In TXE, tx hashes equal Fr(blockNumber), so Fr(1) is the tx effect from block 1.\n // We use this as a \"known resolvable\" tx hash.\n let known_tx_hash: Field = 1;\n let anchor_ts = advance_by(env, 10);\n\n env.utility_context(|context| {\n let mut msgs: BoundedVec<OffchainMessage, MAX_OFFCHAIN_MESSAGES_PER_RECEIVE_CALL> = BoundedVec::new();\n msgs.push(make_msg(scope, Option::some(known_tx_hash), anchor_ts));\n receive(context.this_address(), msgs);\n });\n\n let _now = advance_by(env, 100);\n\n env.utility_context(|context| {\n let address = context.this_address();\n let result = sync_inbox(address, scope);\n let inbox: CapsuleArray<PendingOffchainMsg> = CapsuleArray::at(address, OFFCHAIN_INBOX_SLOT, scope);\n\n // The message should be ready to process since its tx context was resolved.\n assert_eq(result.len(), 1);\n\n let ctx = result.get(0).message_context;\n assert_eq(ctx.tx_hash, known_tx_hash);\n assert(ctx.first_nullifier_in_tx != 0, \"resolved context must have a first nullifier\");\n\n // Message stays in inbox (not expired) for potential reorg reprocessing.\n assert_eq(inbox.len(), 1);\n });\n }\n}\n"
|
|
123
|
+
"source": "use crate::{\n capsules::CapsuleArray,\n context::UtilityContext,\n ephemeral::EphemeralArray,\n messages::{encoding::MESSAGE_CIPHERTEXT_LEN, processing::OffchainMessageWithContext},\n oracle::contract_sync::set_contract_sync_cache_invalid,\n protocol::{\n address::AztecAddress,\n constants::MAX_TX_LIFETIME,\n hash::sha256_to_field,\n traits::{Deserialize, Serialize},\n },\n};\n\n/// Base capsule slot for the persistent inbox of [`PendingOffchainMsg`] entries.\n///\n/// This is the slot where we accumulate messages received through [`receive`].\nglobal OFFCHAIN_INBOX_SLOT: Field = sha256_to_field(\"AZTEC_NR::OFFCHAIN_INBOX_SLOT\".as_bytes());\n\n/// Ephemeral array slot used by [`sync_inbox`] to pass tx hash resolution requests to PXE.\nglobal OFFCHAIN_CONTEXT_REQUESTS_SLOT: Field = sha256_to_field(\"AZTEC_NR::OFFCHAIN_CONTEXT_REQUESTS_SLOT\".as_bytes());\n\n/// Ephemeral array slot used by [`sync_inbox`] to collect messages ready for processing.\nglobal OFFCHAIN_READY_MESSAGES_SLOT: Field = sha256_to_field(\"AZTEC_NR::OFFCHAIN_READY_MESSAGES_SLOT\".as_bytes());\n\n/// Maximum number of offchain messages accepted by `offchain_receive` in a single call.\npub global MAX_OFFCHAIN_MESSAGES_PER_RECEIVE_CALL: u32 = 16;\n\n/// Tolerance added to the `MAX_TX_LIFETIME` cap for message expiration.\nglobal TX_EXPIRATION_TOLERANCE: u64 = 7200; // 2 hours\n\n/// Maximum time-to-live for a tx-bound offchain message.\n///\n/// After `anchor_block_timestamp + MAX_MSG_TTL`, the message is evicted from the inbox.\nglobal MAX_MSG_TTL: u64 = MAX_TX_LIFETIME + TX_EXPIRATION_TOLERANCE;\n\n/// A function that manages offchain-delivered messages for processing during sync.\n///\n/// Offchain messages are messages that are not broadcasted via onchain logs. They are instead delivered to the\n/// recipient by calling the `offchain_receive` utility function (injected by the `#[aztec]` macro). Message transport\n/// is the app's responsibility. Typical examples of transport methods are: messaging apps, email, QR codes, etc.\n///\n/// Once offchain messages are delivered to the recipient's private environment via `offchain_receive`, messages are\n/// locally stored in a persistent inbox.\n///\n/// This function determines when each message in said inbox is ready for processing, when it can be safely disposed\n/// of, etc.\n///\n/// The only current implementation of an `OffchainInboxSync` is [`sync_inbox`], which manages an inbox with expiration\n/// based eviction and automatic transaction context resolution.\npub(crate) type OffchainInboxSync<Env> = unconstrained fn[Env](\n/* contract_address */AztecAddress, /* scope */ AztecAddress) -> EphemeralArray<OffchainMessageWithContext>;\n\n/// A message delivered via the `offchain_receive` utility function.\n#[derive(Serialize, Deserialize)]\npub struct OffchainMessage {\n /// The encrypted message payload.\n pub ciphertext: BoundedVec<Field, MESSAGE_CIPHERTEXT_LEN>,\n /// The intended recipient of the message.\n pub recipient: AztecAddress,\n /// The hash of the transaction that produced this message. `Option::none` indicates a tx-less message.\n pub tx_hash: Option<Field>,\n /// Anchor block timestamp at message emission.\n pub anchor_block_timestamp: u64,\n}\n\n/// An offchain message awaiting processing (or re-processing) in the inbox.\n///\n/// Messages remain in the inbox until they expire, even if they have already been processed. This is necessary to\n/// handle reorgs: a processed message may need to be re-processed if the transaction that provided its context is\n/// reverted. On each sync, resolved messages are promoted to [`OffchainMessageWithContext`] for processing.\n#[derive(Serialize, Deserialize)]\nstruct PendingOffchainMsg {\n /// The encrypted message payload.\n ciphertext: BoundedVec<Field, MESSAGE_CIPHERTEXT_LEN>,\n /// The intended recipient of the message.\n recipient: AztecAddress,\n /// The hash of the transaction that produced this message. A value of 0 indicates a tx-less message.\n tx_hash: Field,\n /// Anchor block timestamp at message emission. Used to compute the effective expiration: messages are evicted\n /// after `anchor_block_timestamp + MAX_MSG_TTL`.\n anchor_block_timestamp: u64,\n}\n\n/// Delivers offchain messages to the given contract's offchain inbox for subsequent processing.\n///\n/// Offchain messages are transaction effects that are not broadcasted via onchain logs. Instead, the sender shares the\n/// message to the recipient through an external channel (e.g. a URL accessible by the recipient). The recipient then\n/// calls this function to hand the messages to the contract so they can be processed through the same mechanisms as\n/// onchain messages.\n///\n/// Each message is routed to the inbox scoped to its `recipient` field, so messages for different accounts are\n/// automatically isolated.\n///\n/// Messages are processed when their originating transaction is found onchain (providing the context needed to\n/// validate resulting notes and events).\n///\n/// Messages are kept in the inbox until they expire. The effective expiration is\n/// `anchor_block_timestamp + MAX_MSG_TTL`.\n///\n/// Processing order is not guaranteed.\npub unconstrained fn receive(\n contract_address: AztecAddress,\n messages: BoundedVec<OffchainMessage, MAX_OFFCHAIN_MESSAGES_PER_RECEIVE_CALL>,\n) {\n // May contain duplicates if multiple messages target the same recipient. This is harmless since\n // cache invalidation on the TS side is idempotent (deleting an already-deleted key is a no-op).\n let mut scopes: BoundedVec<AztecAddress, MAX_OFFCHAIN_MESSAGES_PER_RECEIVE_CALL> = BoundedVec::new();\n let mut i = 0;\n let messages_len = messages.len();\n while i < messages_len {\n let msg = messages.get(i);\n let tx_hash = if msg.tx_hash.is_some() {\n msg.tx_hash.unwrap()\n } else {\n 0\n };\n let inbox: CapsuleArray<PendingOffchainMsg> =\n CapsuleArray::at(contract_address, OFFCHAIN_INBOX_SLOT, msg.recipient);\n inbox.push(\n PendingOffchainMsg {\n ciphertext: msg.ciphertext,\n recipient: msg.recipient,\n tx_hash,\n anchor_block_timestamp: msg.anchor_block_timestamp,\n },\n );\n scopes.push(msg.recipient);\n i += 1;\n }\n\n set_contract_sync_cache_invalid(contract_address, scopes);\n}\n\n/// Returns offchain-delivered messages to process during sync.\n///\n/// Messages remain in the inbox and are reprocessed on each sync until their originating transaction is no longer at\n/// risk of being dropped by a reorg.\npub unconstrained fn sync_inbox(\n contract_address: AztecAddress,\n scope: AztecAddress,\n) -> EphemeralArray<OffchainMessageWithContext> {\n let inbox: CapsuleArray<PendingOffchainMsg> = CapsuleArray::at(contract_address, OFFCHAIN_INBOX_SLOT, scope);\n let context_resolution_requests: EphemeralArray<Field> = EphemeralArray::at(OFFCHAIN_CONTEXT_REQUESTS_SLOT).clear();\n let ready_to_process: EphemeralArray<OffchainMessageWithContext> =\n EphemeralArray::at(OFFCHAIN_READY_MESSAGES_SLOT).clear();\n\n // Build a request list aligned with the inbox indices.\n let mut i = 0;\n let inbox_len = inbox.len();\n while i < inbox_len {\n let msg = inbox.get(i);\n context_resolution_requests.push(msg.tx_hash);\n i += 1;\n }\n\n // Ask PXE to resolve contexts for all requested tx hashes. The oracle returns responses in a new\n // ephemeral array.\n let resolved_contexts =\n crate::oracle::message_processing::get_message_contexts_by_tx_hash(context_resolution_requests);\n\n assert_eq(resolved_contexts.len(), inbox_len);\n\n let now = UtilityContext::new().timestamp();\n\n let mut j = inbox_len;\n while j > 0 {\n // This loop decides what to do with each message in the offchain message inbox. We need to handle 3\n // different scenarios for each message.\n //\n // 1. The TX that emitted this message is still not known to PXE: in this case we can't yet process this\n // message, as any notes or events discovered will fail to be validated. So we leave the message in the inbox,\n // awaiting for future syncs to detect that the TX became available.\n //\n // 2. The message is not associated to a TX to begin with. The current version of offchain message processing\n // does not support this case, but in the future it will. Right now, a message without an associated TX will\n // sit in the inbox until it expires.\n //\n // 3. The TX that emitted this message has been found by PXE. That gives us all the information needed to\n // process the message. We add the message to the `ready_to_process` EphemeralArray so that the `sync_state`\n // loop\n // processes it.\n //\n // In all cases, if the message has expired (i.e. `now > anchor_block_timestamp + MAX_MSG_TTL`), we remove it\n // from the inbox.\n //\n // Note: the loop runs backwards because it might call `inbox.remove(j)` to purge expired messages and we also\n // need to align it with `resolved_contexts.get(j)`. Going from last to first simplifies the algorithm as\n // not yet visited element indexes remain stable.\n j -= 1;\n let maybe_ctx = resolved_contexts.get(j);\n let msg = inbox.get(j);\n\n // Compute the message's effective expiration timestamp to determine if we can purge it from the inbox.\n let effective_expiration = msg.anchor_block_timestamp + MAX_MSG_TTL;\n\n // Message expired. We remove it from the inbox.\n if now > effective_expiration {\n inbox.remove(j);\n }\n\n // Scenario 1: associated TX not yet available. We keep the message in the inbox, as it might become\n // processable as new blocks get mined.\n // Scenario 2: no TX associated to message. The message will sit in the inbox until it expires.\n if maybe_ctx.is_none() {\n continue;\n }\n\n // Scenario 3: Message is ready to process, add to result array. Note we still keep it in the inbox unless we\n // consider it has expired: this is because we need to account for reorgs. If reorg occurs after we processed\n // a message, the effects of processing the message get rewind. However, the associated TX can be included in\n // a subsequent block. Should that happen, the message must be re-processed to ensure consistency.\n let message_context = maybe_ctx.unwrap();\n ready_to_process.push(OffchainMessageWithContext { message_ciphertext: msg.ciphertext, message_context });\n }\n\n ready_to_process\n}\n\nmod test {\n use crate::{\n capsules::CapsuleArray, oracle::random::random, protocol::address::AztecAddress,\n test::helpers::test_environment::TestEnvironment,\n };\n use super::{\n MAX_MSG_TTL, MAX_OFFCHAIN_MESSAGES_PER_RECEIVE_CALL, OFFCHAIN_INBOX_SLOT, OffchainMessage, PendingOffchainMsg,\n receive, sync_inbox,\n };\n\n unconstrained fn setup() -> (TestEnvironment, AztecAddress) {\n let mut env = TestEnvironment::new();\n let scope = env.create_light_account();\n (env, scope)\n }\n\n /// Creates an `OffchainMessage` with dummy ciphertext and the given scope as recipient.\n fn make_msg(recipient: AztecAddress, tx_hash: Option<Field>, anchor_block_timestamp: u64) -> OffchainMessage {\n OffchainMessage { ciphertext: BoundedVec::new(), recipient, tx_hash, anchor_block_timestamp }\n }\n\n /// Advances the TXE block timestamp by `offset` seconds and returns the resulting timestamp.\n unconstrained fn advance_by(env: TestEnvironment, offset: u64) -> u64 {\n env.advance_next_block_timestamp_by(offset);\n env.mine_block();\n env.last_block_timestamp()\n }\n\n #[test]\n unconstrained fn empty_inbox_returns_empty_result() {\n let (env, scope) = setup();\n env.utility_context(|context| {\n let result = sync_inbox(context.this_address(), scope);\n let inbox: CapsuleArray<PendingOffchainMsg> =\n CapsuleArray::at(context.this_address(), OFFCHAIN_INBOX_SLOT, scope);\n\n assert_eq(result.len(), 0);\n assert_eq(inbox.len(), 0);\n });\n }\n\n #[test]\n unconstrained fn tx_bound_msg_expires_after_max_msg_ttl() {\n let (env, scope) = setup();\n let anchor_ts = advance_by(env, 10);\n\n env.utility_context(|context| {\n let mut msgs: BoundedVec<OffchainMessage, MAX_OFFCHAIN_MESSAGES_PER_RECEIVE_CALL> = BoundedVec::new();\n msgs.push(make_msg(scope, Option::some(random()), anchor_ts));\n receive(context.this_address(), msgs);\n });\n\n // Advance past anchor_ts + MAX_MSG_TTL.\n let _now = advance_by(env, MAX_MSG_TTL + 1);\n\n env.utility_context(|context| {\n let address = context.this_address();\n let result = sync_inbox(address, scope);\n let inbox: CapsuleArray<PendingOffchainMsg> = CapsuleArray::at(address, OFFCHAIN_INBOX_SLOT, scope);\n\n assert_eq(result.len(), 0); // context is None, not ready\n assert_eq(inbox.len(), 0); // expired, removed\n });\n }\n\n #[test]\n unconstrained fn tx_bound_msg_not_expired_before_max_msg_ttl() {\n let (env, scope) = setup();\n let anchor_ts = advance_by(env, 10);\n\n env.utility_context(|context| {\n let mut msgs: BoundedVec<OffchainMessage, MAX_OFFCHAIN_MESSAGES_PER_RECEIVE_CALL> = BoundedVec::new();\n msgs.push(make_msg(scope, Option::some(random()), anchor_ts));\n receive(context.this_address(), msgs);\n });\n\n // Advance, but not past anchor_ts + MAX_MSG_TTL.\n let _now = advance_by(env, 100);\n\n env.utility_context(|context| {\n let address = context.this_address();\n let result = sync_inbox(address, scope);\n let inbox: CapsuleArray<PendingOffchainMsg> = CapsuleArray::at(address, OFFCHAIN_INBOX_SLOT, scope);\n\n assert_eq(result.len(), 0); // context is None, not ready\n assert_eq(inbox.len(), 1); // not expired, stays\n });\n }\n\n #[test]\n unconstrained fn tx_less_msg_expires_after_max_msg_ttl() {\n let (env, scope) = setup();\n let anchor_ts = advance_by(env, 10);\n\n env.utility_context(|context| {\n let mut msgs: BoundedVec<OffchainMessage, MAX_OFFCHAIN_MESSAGES_PER_RECEIVE_CALL> = BoundedVec::new();\n msgs.push(make_msg(scope, Option::none(), anchor_ts));\n receive(context.this_address(), msgs);\n });\n\n // Advance past anchor_ts + MAX_MSG_TTL.\n let _now = advance_by(env, MAX_MSG_TTL + 1);\n\n env.utility_context(|context| {\n let address = context.this_address();\n let result = sync_inbox(address, scope);\n let inbox: CapsuleArray<PendingOffchainMsg> = CapsuleArray::at(address, OFFCHAIN_INBOX_SLOT, scope);\n\n assert_eq(result.len(), 0); // context is None, not ready\n assert_eq(inbox.len(), 0); // expired, removed\n });\n }\n\n #[test]\n unconstrained fn unresolved_tx_stays_in_inbox() {\n let (env, scope) = setup();\n let anchor_ts = advance_by(env, 10);\n\n env.utility_context(|context| {\n let mut msgs: BoundedVec<OffchainMessage, MAX_OFFCHAIN_MESSAGES_PER_RECEIVE_CALL> = BoundedVec::new();\n msgs.push(make_msg(scope, Option::some(random()), anchor_ts));\n receive(context.this_address(), msgs);\n });\n\n let _now = advance_by(env, 100);\n\n env.utility_context(|context| {\n let address = context.this_address();\n let result = sync_inbox(address, scope);\n let inbox: CapsuleArray<PendingOffchainMsg> = CapsuleArray::at(address, OFFCHAIN_INBOX_SLOT, scope);\n\n assert_eq(result.len(), 0); // not resolved, not ready\n assert_eq(inbox.len(), 1); // not expired, stays\n });\n }\n\n #[test]\n unconstrained fn multiple_messages_mixed_expiration() {\n let (env, scope) = setup();\n let anchor_ts = advance_by(env, 10);\n\n let survivor_tx_hash = random();\n\n env.utility_context(|context| {\n let address = context.this_address();\n let mut msgs: BoundedVec<OffchainMessage, MAX_OFFCHAIN_MESSAGES_PER_RECEIVE_CALL> = BoundedVec::new();\n // Message 0: tx-bound, anchor_ts in the past so it expires at\n // anchor_ts + MAX_MSG_TTL. We set anchor to 0 so it expires quickly.\n msgs.push(make_msg(scope, Option::some(random()), 0));\n // Message 1: tx-bound, anchor_ts is recent so it survives.\n msgs.push(make_msg(scope, Option::some(survivor_tx_hash), anchor_ts));\n // Message 2: tx-less, anchor_ts=0 so it also expires.\n msgs.push(make_msg(scope, Option::none(), 0));\n receive(address, msgs);\n });\n\n // Advance past MAX_MSG_TTL for anchor_ts=0, but not for anchor_ts=anchor_ts.\n let _now = advance_by(env, MAX_MSG_TTL);\n\n env.utility_context(|context| {\n let address = context.this_address();\n let result = sync_inbox(address, scope);\n let inbox: CapsuleArray<PendingOffchainMsg> = CapsuleArray::at(address, OFFCHAIN_INBOX_SLOT, scope);\n\n assert_eq(result.len(), 0); // all contexts are None\n // Message 0 expired (anchor=0), message 1 survived (anchor=anchor_ts),\n // Message 2 expired (anchor=0).\n assert_eq(inbox.len(), 1);\n assert_eq(inbox.get(0).tx_hash, survivor_tx_hash);\n });\n }\n\n // -- Resolved context (ready to process) ------------------------------\n\n #[test]\n unconstrained fn resolved_msg_is_ready_to_process() {\n let (env, scope) = setup();\n // TestEnvironment::new() deploys protocol contracts, creating blocks with tx effects.\n // In TXE, tx hashes equal Fr(blockNumber), so Fr(1) is the tx effect from block 1.\n // We use this as a \"known resolvable\" tx hash.\n let known_tx_hash: Field = 1;\n let anchor_ts = advance_by(env, 10);\n\n env.utility_context(|context| {\n let mut msgs: BoundedVec<OffchainMessage, MAX_OFFCHAIN_MESSAGES_PER_RECEIVE_CALL> = BoundedVec::new();\n msgs.push(make_msg(scope, Option::some(known_tx_hash), anchor_ts));\n receive(context.this_address(), msgs);\n });\n\n let _now = advance_by(env, 100);\n\n env.utility_context(|context| {\n let address = context.this_address();\n let result = sync_inbox(address, scope);\n let inbox: CapsuleArray<PendingOffchainMsg> = CapsuleArray::at(address, OFFCHAIN_INBOX_SLOT, scope);\n\n // The message should be ready to process since its tx context was resolved.\n assert_eq(result.len(), 1);\n\n let ctx = result.get(0).message_context;\n assert_eq(ctx.tx_hash, known_tx_hash);\n assert(ctx.first_nullifier_in_tx != 0, \"resolved context must have a first nullifier\");\n\n // Message stays in inbox (not expired) for potential reorg reprocessing.\n assert_eq(inbox.len(), 1);\n });\n }\n}\n"
|
|
124
124
|
},
|
|
125
|
-
"
|
|
125
|
+
"176": {
|
|
126
126
|
"function_locations": [
|
|
127
127
|
{
|
|
128
128
|
"name": "call_private_function_oracle",
|
|
@@ -136,7 +136,7 @@
|
|
|
136
136
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/aztec-nr/aztec/src/oracle/call_private_function.nr",
|
|
137
137
|
"source": "use crate::protocol::{abis::function_selector::FunctionSelector, address::AztecAddress, utils::reader::Reader};\n\n#[oracle(aztec_prv_callPrivateFunction)]\nunconstrained fn call_private_function_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _start_side_effect_counter: u32,\n _is_static_call: bool,\n) -> [Field; 2] {}\n\npub unconstrained fn call_private_function_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n start_side_effect_counter: u32,\n is_static_call: bool,\n) -> (u32, Field) {\n let fields = call_private_function_oracle(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n );\n\n let mut reader = Reader::new(fields);\n let end_side_effect_counter = reader.read_u32();\n let returns_hash = reader.read();\n\n (end_side_effect_counter, returns_hash)\n}\n"
|
|
138
138
|
},
|
|
139
|
-
"
|
|
139
|
+
"178": {
|
|
140
140
|
"function_locations": [
|
|
141
141
|
{
|
|
142
142
|
"name": "store",
|
|
@@ -230,7 +230,7 @@
|
|
|
230
230
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/aztec-nr/aztec/src/oracle/capsules.nr",
|
|
231
231
|
"source": "use crate::protocol::{address::AztecAddress, traits::{Deserialize, Serialize}};\n\n/// Stores arbitrary information in a per-contract non-volatile database, which can later be retrieved with `load`. If\n/// data was already stored at this slot, it is overwritten.\n// TODO(F-498): review naming consistency\npub unconstrained fn store<T>(contract_address: AztecAddress, slot: Field, value: T, scope: AztecAddress)\nwhere\n T: Serialize,\n{\n let serialized = value.serialize();\n set_capsule_oracle(contract_address, slot, serialized, scope);\n}\n\n/// Returns data previously stored via `storeCapsule` in the per-contract non-volatile database. Returns\n/// Option::none() if nothing was stored at the given slot.\n// TODO(F-498): review naming consistency\npub unconstrained fn load<T>(contract_address: AztecAddress, slot: Field, scope: AztecAddress) -> Option<T>\nwhere\n T: Deserialize,\n{\n let serialized_option = get_capsule_oracle(contract_address, slot, <T as Deserialize>::N, scope);\n serialized_option.map(|arr| Deserialize::deserialize(arr))\n}\n\n/// Deletes data in the per-contract non-volatile database. Does nothing if no data was present.\npub unconstrained fn delete(contract_address: AztecAddress, slot: Field, scope: AztecAddress) {\n delete_oracle(contract_address, slot, scope);\n}\n\n/// Copies a number of contiguous entries in the per-contract non-volatile database. This allows for efficient data\n/// structures by avoiding repeated calls to `loadCapsule` and `storeCapsule`. Supports overlapping source and\n/// destination regions (which will result in the overlapped source values being overwritten). All copied slots must\n/// exist in the database (i.e. have been stored and not deleted)\npub unconstrained fn copy(\n contract_address: AztecAddress,\n src_slot: Field,\n dst_slot: Field,\n num_entries: u32,\n scope: AztecAddress,\n) {\n copy_oracle(contract_address, src_slot, dst_slot, num_entries, scope);\n}\n\n#[oracle(aztec_utl_setCapsule)]\nunconstrained fn set_capsule_oracle<let N: u32>(\n contract_address: AztecAddress,\n slot: Field,\n values: [Field; N],\n scope: AztecAddress,\n) {}\n\n/// We need to pass in `array_len` (the value of N) as a parameter to tell the oracle how many fields the response must\n/// have.\n///\n/// Note that the oracle returns an Option<[Field; N]> because we cannot return an Option<T> directly. That would\n/// require for the oracle resolver to know the shape of T (e.g. if T were a struct of 3 u32 values then the expected\n/// response shape would be 3 single items, whereas it were a struct containing `u32, [Field;10], u32` then the\n/// expected shape would be single, array, single.). Instead, we return the serialization and deserialize in Noir.\n#[oracle(aztec_utl_getCapsule)]\nunconstrained fn get_capsule_oracle<let N: u32>(\n contract_address: AztecAddress,\n slot: Field,\n array_len: u32,\n scope: AztecAddress,\n) -> Option<[Field; N]> {}\n\n#[oracle(aztec_utl_deleteCapsule)]\nunconstrained fn delete_oracle(contract_address: AztecAddress, slot: Field, scope: AztecAddress) {}\n\n#[oracle(aztec_utl_copyCapsule)]\nunconstrained fn copy_oracle(\n contract_address: AztecAddress,\n src_slot: Field,\n dst_slot: Field,\n num_entries: u32,\n scope: AztecAddress,\n) {}\n\nmod test {\n // These tests are sort of redundant since we already test the oracle implementation directly in TypeScript, but\n // they are cheap regardless and help ensure both that the TXE implementation works accordingly and that the Noir\n // oracles are hooked up correctly.\n\n use crate::{\n oracle::capsules::{copy, delete, load, store},\n test::{helpers::test_environment::TestEnvironment, mocks::MockStruct},\n };\n use crate::protocol::{address::AztecAddress, traits::{FromField, ToField}};\n\n global SLOT: Field = 1;\n\n unconstrained fn setup() -> (TestEnvironment, AztecAddress) {\n let mut env = TestEnvironment::new();\n let scope = env.create_light_account();\n (env, scope)\n }\n\n #[test]\n unconstrained fn stores_and_loads() {\n let (env, scope) = setup();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let value = MockStruct::new(5, 6);\n store(contract_address, SLOT, value, scope);\n\n assert_eq(load(contract_address, SLOT, scope).unwrap(), value);\n });\n }\n\n #[test]\n unconstrained fn store_overwrites() {\n let (env, scope) = setup();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let value = MockStruct::new(5, 6);\n store(contract_address, SLOT, value, scope);\n\n let new_value = MockStruct::new(7, 8);\n store(contract_address, SLOT, new_value, scope);\n\n assert_eq(load(contract_address, SLOT, scope).unwrap(), new_value);\n });\n }\n\n #[test]\n unconstrained fn loads_empty_slot() {\n let (env, scope) = setup();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let loaded_value: Option<MockStruct> = load(contract_address, SLOT, scope);\n assert_eq(loaded_value, Option::none());\n });\n }\n\n #[test]\n unconstrained fn deletes_stored_value() {\n let (env, scope) = setup();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let value = MockStruct::new(5, 6);\n store(contract_address, SLOT, value, scope);\n delete(contract_address, SLOT, scope);\n\n let loaded_value: Option<MockStruct> = load(contract_address, SLOT, scope);\n assert_eq(loaded_value, Option::none());\n });\n }\n\n #[test]\n unconstrained fn deletes_empty_slot() {\n let (env, scope) = setup();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n delete(contract_address, SLOT, scope);\n let loaded_value: Option<MockStruct> = load(contract_address, SLOT, scope);\n assert_eq(loaded_value, Option::none());\n });\n }\n\n #[test]\n unconstrained fn copies_non_overlapping_values() {\n let (env, scope) = setup();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let src = 5;\n\n let values = [MockStruct::new(5, 6), MockStruct::new(7, 8), MockStruct::new(9, 10)];\n store(contract_address, src, values[0], scope);\n store(contract_address, src + 1, values[1], scope);\n store(contract_address, src + 2, values[2], scope);\n\n let dst = 10;\n copy(contract_address, src, dst, 3, scope);\n\n assert_eq(load(contract_address, dst, scope).unwrap(), values[0]);\n assert_eq(load(contract_address, dst + 1, scope).unwrap(), values[1]);\n assert_eq(load(contract_address, dst + 2, scope).unwrap(), values[2]);\n });\n }\n\n #[test]\n unconstrained fn copies_overlapping_values_with_src_ahead() {\n let (env, scope) = setup();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let src = 1;\n\n let values = [MockStruct::new(5, 6), MockStruct::new(7, 8), MockStruct::new(9, 10)];\n store(contract_address, src, values[0], scope);\n store(contract_address, src + 1, values[1], scope);\n store(contract_address, src + 2, values[2], scope);\n\n let dst = 2;\n copy(contract_address, src, dst, 3, scope);\n\n assert_eq(load(contract_address, dst, scope).unwrap(), values[0]);\n assert_eq(load(contract_address, dst + 1, scope).unwrap(), values[1]);\n assert_eq(load(contract_address, dst + 2, scope).unwrap(), values[2]);\n\n // src[1] and src[2] should have been overwritten since they are also dst[0] and dst[1]\n assert_eq(load(contract_address, src, scope).unwrap(), values[0]); // src[0] (unchanged)\n assert_eq(load(contract_address, src + 1, scope).unwrap(), values[0]); // dst[0]\n assert_eq(load(contract_address, src + 2, scope).unwrap(), values[1]); // dst[1]\n });\n }\n\n #[test]\n unconstrained fn copies_overlapping_values_with_dst_ahead() {\n let (env, scope) = setup();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let src = 2;\n\n let values = [MockStruct::new(5, 6), MockStruct::new(7, 8), MockStruct::new(9, 10)];\n store(contract_address, src, values[0], scope);\n store(contract_address, src + 1, values[1], scope);\n store(contract_address, src + 2, values[2], scope);\n\n let dst = 1;\n copy(contract_address, src, dst, 3, scope);\n\n assert_eq(load(contract_address, dst, scope).unwrap(), values[0]);\n assert_eq(load(contract_address, dst + 1, scope).unwrap(), values[1]);\n assert_eq(load(contract_address, dst + 2, scope).unwrap(), values[2]);\n\n // src[0] and src[1] should have been overwritten since they are also dst[1] and dst[2]\n assert_eq(load(contract_address, src, scope).unwrap(), values[1]); // dst[1]\n assert_eq(load(contract_address, src + 1, scope).unwrap(), values[2]); // dst[2]\n assert_eq(load(contract_address, src + 2, scope).unwrap(), values[2]); // src[2] (unchanged)\n });\n }\n\n #[test(should_fail_with = \"copy empty slot\")]\n unconstrained fn cannot_copy_empty_values() {\n let (env, scope) = setup();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n copy(contract_address, SLOT, SLOT, 1, scope);\n });\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_store_other_contract() {\n let (env, scope) = setup();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n let value = MockStruct::new(5, 6);\n store(other_contract_address, SLOT, value, scope);\n });\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_load_other_contract() {\n let (env, scope) = setup();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n let _: Option<MockStruct> = load(other_contract_address, SLOT, scope);\n });\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_delete_other_contract() {\n let (env, scope) = setup();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n delete(other_contract_address, SLOT, scope);\n });\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_copy_other_contract() {\n let (env, scope) = setup();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n copy(other_contract_address, SLOT, SLOT, 0, scope);\n });\n }\n}\n"
|
|
232
232
|
},
|
|
233
|
-
"
|
|
233
|
+
"179": {
|
|
234
234
|
"function_locations": [
|
|
235
235
|
{
|
|
236
236
|
"name": "set_contract_sync_cache_invalid_oracle",
|
|
@@ -244,20 +244,6 @@
|
|
|
244
244
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/aztec-nr/aztec/src/oracle/contract_sync.nr",
|
|
245
245
|
"source": "use crate::protocol::address::AztecAddress;\n\n#[oracle(aztec_utl_setContractSyncCacheInvalid)]\nunconstrained fn set_contract_sync_cache_invalid_oracle<let N: u32>(\n contract_address: AztecAddress,\n scopes: BoundedVec<AztecAddress, N>,\n) {}\n\n/// Forces the PXE to re-sync the given contract for a set of scopes on the next query.\n///\n/// Call this after writing data (e.g. offchain messages) that the contract's `sync_state` function needs to discover.\n/// Without invalidation, the sync cache would skip re-running `sync_state` until the next block.\npub unconstrained fn set_contract_sync_cache_invalid<let N: u32>(\n contract_address: AztecAddress,\n scopes: BoundedVec<AztecAddress, N>,\n) {\n set_contract_sync_cache_invalid_oracle(contract_address, scopes);\n}\n"
|
|
246
246
|
},
|
|
247
|
-
"179": {
|
|
248
|
-
"function_locations": [
|
|
249
|
-
{
|
|
250
|
-
"name": "get_utility_context_oracle",
|
|
251
|
-
"start": 140
|
|
252
|
-
},
|
|
253
|
-
{
|
|
254
|
-
"name": "get_utility_context",
|
|
255
|
-
"start": 344
|
|
256
|
-
}
|
|
257
|
-
],
|
|
258
|
-
"path": "/home/aztec-dev/aztec-packages/noir-projects/aztec-nr/aztec/src/oracle/execution.nr",
|
|
259
|
-
"source": "use crate::context::UtilityContext;\n\n#[oracle(aztec_utl_getUtilityContext)]\nunconstrained fn get_utility_context_oracle() -> UtilityContext {}\n\n/// Returns a utility context built from the global variables of anchor block and the contract address of the function\n/// being executed.\npub unconstrained fn get_utility_context() -> UtilityContext {\n get_utility_context_oracle()\n}\n"
|
|
260
|
-
},
|
|
261
247
|
"18": {
|
|
262
248
|
"function_locations": [
|
|
263
249
|
{
|
|
@@ -412,7 +398,21 @@
|
|
|
412
398
|
"path": "std/hash/mod.nr",
|
|
413
399
|
"source": "// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\nuse crate::static_assert;\n\n/// The size of the state accepted by the backend in `poseidon2_permutation`.\nglobal POSEIDON2_CONFIG_STATE_SIZE: u32 = poseidon2_config_state_size();\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\n}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s<let N: u32>(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3<let N: u32>(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3<let N: u32>(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment<let N: u32>(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[inline_always]\npub fn pedersen_commitment_with_separator<let N: u32>(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n points[i] = EmbeddedCurveScalar::from_field(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash<let N: u32>(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[no_predicates]\npub fn pedersen_hash_with_separator<let N: u32>(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n crate::assert_constant(separator);\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = EmbeddedCurveScalar::from_field(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators<let N: u32, let M: u32>(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n crate::assert_constant(starting_index);\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators<let N: u32, let M: u32>(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\npub fn poseidon2_permutation<let N: u32>(input: [Field; N]) -> [Field; N] {\n static_assert(\n N == POSEIDON2_CONFIG_STATE_SIZE,\n f\"the input length must equal the state size in the Poseidon2 config; expected {POSEIDON2_CONFIG_STATE_SIZE}, got {N}\",\n );\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal<let N: u32>(input: [Field; N]) -> [Field; N] {}\n\n#[foreign(poseidon2_config_state_size)]\ncomptime fn poseidon2_config_state_size() -> u32 {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash<H>(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\npub trait Hasher {\n fn finish(self) -> Field;\n\n /// Returns the hash value without consuming the hasher.\n /// Override this for more efficient implementations that avoid copying.\n /// TODO: deprecate finish() and replace it\n fn finish_ref(&self) -> Field {\n (*self).finish()\n }\n\n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault<H>;\n\nimpl<H> BuildHasher for BuildHasherDefault<H>\nwhere\n H: Hasher + Default,\n{\n type H = H;\n\n fn build_hasher(_self: Self) -> H {\n H::default()\n }\n}\n\nimpl<H> Default for BuildHasherDefault<H>\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u8 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash<H>(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl<T, let N: u32> Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl<T> Hash for [T]\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl<A, B> Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl<A, B, C> Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl<A, B, C, D> Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl<A, B, C, D, E> Hash for (A, B, C, D, E)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n },\n );\n}\n"
|
|
414
400
|
},
|
|
415
|
-
"
|
|
401
|
+
"181": {
|
|
402
|
+
"function_locations": [
|
|
403
|
+
{
|
|
404
|
+
"name": "get_utility_context_oracle",
|
|
405
|
+
"start": 140
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
"name": "get_utility_context",
|
|
409
|
+
"start": 344
|
|
410
|
+
}
|
|
411
|
+
],
|
|
412
|
+
"path": "/home/aztec-dev/aztec-packages/noir-projects/aztec-nr/aztec/src/oracle/execution.nr",
|
|
413
|
+
"source": "use crate::context::UtilityContext;\n\n#[oracle(aztec_utl_getUtilityContext)]\nunconstrained fn get_utility_context_oracle() -> UtilityContext {}\n\n/// Returns a utility context built from the global variables of anchor block and the contract address of the function\n/// being executed.\npub unconstrained fn get_utility_context() -> UtilityContext {\n get_utility_context_oracle()\n}\n"
|
|
414
|
+
},
|
|
415
|
+
"182": {
|
|
416
416
|
"function_locations": [
|
|
417
417
|
{
|
|
418
418
|
"name": "store",
|
|
@@ -438,69 +438,7 @@
|
|
|
438
438
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/aztec-nr/aztec/src/oracle/execution_cache.nr",
|
|
439
439
|
"source": "/// Stores values represented as slice in execution cache to be later obtained by its hash.\n// TODO(F-498): review naming consistency\npub fn store<let N: u32>(values: [Field; N], hash: Field) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to\n // call. When loading the values, however, the caller must check that the values are indeed the preimage.\n unsafe { set_hash_preimage_oracle_wrapper(values, hash) };\n}\n\nunconstrained fn set_hash_preimage_oracle_wrapper<let N: u32>(values: [Field; N], hash: Field) {\n set_hash_preimage_oracle(values, hash);\n}\n\n// TODO(F-498): review naming consistency\npub unconstrained fn load<let N: u32>(hash: Field) -> [Field; N] {\n get_hash_preimage_oracle(hash)\n}\n\n#[oracle(aztec_prv_setHashPreimage)]\nunconstrained fn set_hash_preimage_oracle<let N: u32>(_values: [Field; N], _hash: Field) {}\n\n#[oracle(aztec_prv_getHashPreimage)]\nunconstrained fn get_hash_preimage_oracle<let N: u32>(_hash: Field) -> [Field; N] {}\n"
|
|
440
440
|
},
|
|
441
|
-
"
|
|
442
|
-
"function_locations": [
|
|
443
|
-
{
|
|
444
|
-
"name": "notify_created_note",
|
|
445
|
-
"start": 558
|
|
446
|
-
},
|
|
447
|
-
{
|
|
448
|
-
"name": "notify_nullified_note",
|
|
449
|
-
"start": 1268
|
|
450
|
-
},
|
|
451
|
-
{
|
|
452
|
-
"name": "notify_created_note_oracle_wrapper",
|
|
453
|
-
"start": 1722
|
|
454
|
-
},
|
|
455
|
-
{
|
|
456
|
-
"name": "notify_created_note_oracle",
|
|
457
|
-
"start": 2174
|
|
458
|
-
},
|
|
459
|
-
{
|
|
460
|
-
"name": "notify_nullified_note_oracle_wrapper",
|
|
461
|
-
"start": 2282
|
|
462
|
-
},
|
|
463
|
-
{
|
|
464
|
-
"name": "notify_nullified_note_oracle",
|
|
465
|
-
"start": 2492
|
|
466
|
-
},
|
|
467
|
-
{
|
|
468
|
-
"name": "get_notes_oracle",
|
|
469
|
-
"start": 3550
|
|
470
|
-
},
|
|
471
|
-
{
|
|
472
|
-
"name": "get_notes",
|
|
473
|
-
"start": 4105
|
|
474
|
-
},
|
|
475
|
-
{
|
|
476
|
-
"name": "get_next_app_tag_as_sender",
|
|
477
|
-
"start": 7221
|
|
478
|
-
},
|
|
479
|
-
{
|
|
480
|
-
"name": "get_next_app_tag_as_sender_oracle",
|
|
481
|
-
"start": 7435
|
|
482
|
-
},
|
|
483
|
-
{
|
|
484
|
-
"name": "get_sender_for_tags",
|
|
485
|
-
"start": 7973
|
|
486
|
-
},
|
|
487
|
-
{
|
|
488
|
-
"name": "get_sender_for_tags_oracle",
|
|
489
|
-
"start": 8119
|
|
490
|
-
},
|
|
491
|
-
{
|
|
492
|
-
"name": "set_sender_for_tags",
|
|
493
|
-
"start": 8772
|
|
494
|
-
},
|
|
495
|
-
{
|
|
496
|
-
"name": "set_sender_for_tags_oracle",
|
|
497
|
-
"start": 8940
|
|
498
|
-
}
|
|
499
|
-
],
|
|
500
|
-
"path": "/home/aztec-dev/aztec-packages/noir-projects/aztec-nr/aztec/src/oracle/notes.nr",
|
|
501
|
-
"source": "use crate::note::{HintedNote, note_interface::NoteType};\n\nuse crate::protocol::{address::AztecAddress, traits::Packable};\n\n/// Notifies the simulator that a note has been created, so that it can be returned in future read requests in the same\n/// transaction. This note should only be added to the non-volatile database if found in an actual block.\npub fn notify_created_note<let N: u32>(\n owner: AztecAddress,\n storage_slot: Field,\n randomness: Field,\n note_type_id: Field,\n packed_note: [Field; N],\n note_hash: Field,\n counter: u32,\n) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to\n // call.\n unsafe {\n notify_created_note_oracle_wrapper(\n owner,\n storage_slot,\n randomness,\n note_type_id,\n packed_note,\n note_hash,\n counter,\n )\n };\n}\n\n/// Notifies the simulator that a note has been nullified, so that it is no longer returned in future read requests in\n/// the same transaction. This note should only be removed to the non-volatile database if its nullifier is found in an\n/// actual block.\npub fn notify_nullified_note(nullifier: Field, note_hash: Field, counter: u32) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to\n // call.\n unsafe { notify_nullified_note_oracle_wrapper(nullifier, note_hash, counter) };\n}\n\nunconstrained fn notify_created_note_oracle_wrapper<let N: u32>(\n owner: AztecAddress,\n storage_slot: Field,\n randomness: Field,\n note_type_id: Field,\n packed_note: [Field; N],\n note_hash: Field,\n counter: u32,\n) {\n notify_created_note_oracle(\n owner,\n storage_slot,\n randomness,\n note_type_id,\n packed_note,\n note_hash,\n counter,\n );\n}\n\n#[oracle(aztec_prv_notifyCreatedNote)]\nunconstrained fn notify_created_note_oracle<let N: u32>(\n _owner: AztecAddress,\n _storage_slot: Field,\n _randomness: Field,\n _note_type_id: Field,\n _packed_note: [Field; N],\n _note_hash: Field,\n _counter: u32,\n) {}\n\nunconstrained fn notify_nullified_note_oracle_wrapper(nullifier: Field, note_hash: Field, counter: u32) {\n notify_nullified_note_oracle(nullifier, note_hash, counter);\n}\n\n#[oracle(aztec_prv_notifyNullifiedNote)]\nunconstrained fn notify_nullified_note_oracle(_nullifier: Field, _note_hash: Field, _counter: u32) {}\n\n#[oracle(aztec_utl_getNotes)]\nunconstrained fn get_notes_oracle<Note, let M: u32, let MaxNotes: u32>(\n _owner: Option<AztecAddress>,\n _storage_slot: Field,\n _num_selects: u8,\n _select_by_indexes: [u8; M],\n _select_by_offsets: [u8; M],\n _select_by_lengths: [u8; M],\n _select_values: [Field; M],\n _select_comparators: [u8; M],\n _sort_by_indexes: [u8; M],\n _sort_by_offsets: [u8; M],\n _sort_by_lengths: [u8; M],\n _sort_order: [u8; M],\n _limit: u32,\n _offset: u32,\n _status: u8,\n // This is always set to MAX_NOTES. We need to pass it to TS in order to correctly construct the BoundedVec\n _max_notes: u32,\n // This is always set to <HintedNote<Note> as Packable>::N. We need to pass it to TS in order to be able to\n // correctly construct the BoundedVec there.\n _packed_hinted_note_length: u32,\n) -> BoundedVec<[Field; <HintedNote<Note> as Packable>::N], MaxNotes>\nwhere\n // TODO(https://github.com/noir-lang/noir/issues/9399): `Note: Packable` should work here.\n HintedNote<Note>: Packable,\n{}\n\npub unconstrained fn get_notes<Note, let M: u32, let MaxNotes: u32>(\n owner: Option<AztecAddress>,\n storage_slot: Field,\n num_selects: u8,\n select_by_indexes: [u8; M],\n select_by_offsets: [u8; M],\n select_by_lengths: [u8; M],\n select_values: [Field; M],\n select_comparators: [u8; M],\n sort_by_indexes: [u8; M],\n sort_by_offsets: [u8; M],\n sort_by_lengths: [u8; M],\n sort_order: [u8; M],\n limit: u32,\n offset: u32,\n status: u8,\n) -> [Option<HintedNote<Note>>; MaxNotes]\nwhere\n Note: NoteType + Packable,\n{\n let packed_hinted_notes: BoundedVec<[Field; <HintedNote<Note> as Packable>::N], MaxNotes> = get_notes_oracle::<Note, M, MaxNotes>(\n owner,\n storage_slot,\n num_selects,\n select_by_indexes,\n select_by_offsets,\n select_by_lengths,\n select_values,\n select_comparators,\n sort_by_indexes,\n sort_by_offsets,\n sort_by_lengths,\n sort_order,\n limit,\n offset,\n status,\n MaxNotes,\n <HintedNote<Note> as Packable>::N,\n );\n\n let mut notes = BoundedVec::<_, MaxNotes>::new();\n for i in 0..packed_hinted_notes.len() {\n let hinted_note = HintedNote::unpack(packed_hinted_notes.get(i));\n notes.push(hinted_note);\n }\n\n // At last we convert the bounded vector to an array of options. We do this because that is what the filter\n // function needs to have on the output and we've decided to have the same type on the input and output of the\n // filter and preprocessor functions.\n //\n // We have decided to have the same type on the input and output of the filter and preprocessor functions because\n // it allows us to chain multiple filters and preprocessors together.\n //\n // So why do we want the array of options on the output of the filter function?\n //\n // Filter returns an array of options rather than a BoundedVec for performance reasons. Using an array of options\n // allows setting values at known indices in the output array which is much more efficient than pushing to a\n // BoundedVec where the write position depends on previous iterations. The array can then be efficiently converted\n // to a BoundedVec using utils/array/collapse.nr::collapse function from Aztec.nr. This avoids expensive dynamic\n // memory access patterns that would be required when building up a BoundedVec incrementally. For preprocessor\n // functions we could use BoundedVec return value as there the optimization does not matter since it is applied in\n // an unconstrained context. We, however, use the same return value type to be able to use the same function as\n // both a preprocessor and a filter.\n let mut notes_array = [Option::none(); MaxNotes];\n for i in 0..notes.len() {\n notes_array[i] = Option::some(notes.get_unchecked(i));\n }\n\n notes_array\n}\n\n// TODO: Oracles below are generic private log oracles and are not specific to notes. Move them somewhere else.\n\n/// Returns the next app tag for a given sender and recipient pair.\n///\n/// This also notifies the simulator that a tag has been used in a note, and to therefore increment the associated\n/// index so that future notes get a different tag and can be discovered by the recipient. This change should only be\n/// persisted in a non-volatile database if the tagged log is found in an actual block - otherwise e.g. a reverting\n/// transaction can cause the sender to accidentally skip indices and later produce notes that are not found by the\n/// recipient.\npub unconstrained fn get_next_app_tag_as_sender(sender: AztecAddress, recipient: AztecAddress) -> Field {\n get_next_app_tag_as_sender_oracle(sender, recipient)\n}\n\n#[oracle(aztec_prv_getNextAppTagAsSender)]\nunconstrained fn get_next_app_tag_as_sender_oracle(_sender: AztecAddress, _recipient: AztecAddress) -> Field {}\n\n/// Gets the sender for tags.\n///\n/// This unconstrained value is used as the sender when computing an unconstrained shared secret for a tag in order to\n/// emit a log. Constrained tagging should not use this as there is no guarantee that the recipient knows about the\n/// sender, and hence about the shared secret.\n///\n/// The value persists through nested calls, meaning all calls down the stack will use the same 'senderForTags' value\n/// (unless it is replaced).\npub unconstrained fn get_sender_for_tags() -> Option<AztecAddress> {\n get_sender_for_tags_oracle()\n}\n\n#[oracle(aztec_prv_getSenderForTags)]\nunconstrained fn get_sender_for_tags_oracle() -> Option<AztecAddress> {}\n\n/// Sets the sender for tags.\n///\n/// This unconstrained value is used as the sender when computing an unconstrained shared secret for a tag in order to\n/// emit a log. Constrained tagging should not use this as there is no guarantee that the recipient knows about the\n/// sender, and hence about the shared secret.\n///\n/// Account contracts typically set this value before calling other contracts. The value persists through nested calls,\n/// meaning all calls down the stack will use the same 'senderForTags' value (unless it is replaced by another call to\n/// this setter).\npub unconstrained fn set_sender_for_tags(sender_for_tags: AztecAddress) {\n set_sender_for_tags_oracle(sender_for_tags);\n}\n\n#[oracle(aztec_prv_setSenderForTags)]\nunconstrained fn set_sender_for_tags_oracle(_sender_for_tags: AztecAddress) {}\n"
|
|
502
|
-
},
|
|
503
|
-
"192": {
|
|
441
|
+
"194": {
|
|
504
442
|
"function_locations": [
|
|
505
443
|
{
|
|
506
444
|
"name": "notify_created_nullifier",
|
|
@@ -530,7 +468,7 @@
|
|
|
530
468
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/aztec-nr/aztec/src/oracle/nullifiers.nr",
|
|
531
469
|
"source": "//! Nullifier creation, existence checks, etc.\n\nuse crate::protocol::address::aztec_address::AztecAddress;\n\n/// Notifies the simulator that a nullifier has been created, so that its correct status (pending or settled) can be\n/// determined when reading nullifiers in subsequent private function calls. The first non-revertible nullifier emitted\n/// is also used to compute note nonces.\npub fn notify_created_nullifier(inner_nullifier: Field) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to\n // call.\n unsafe { notify_created_nullifier_oracle(inner_nullifier) };\n}\n\n#[oracle(aztec_prv_notifyCreatedNullifier)]\nunconstrained fn notify_created_nullifier_oracle(_inner_nullifier: Field) {}\n\n/// Returns `true` if the nullifier has been emitted in the same transaction, i.e. if [`notify_created_nullifier`] has\n/// been\n/// called for this inner nullifier from the contract with the specified address.\n///\n/// Note that despite sharing pending transaction information with the app, this is not a privacy leak: anyone in the\n/// network can always determine in which transaction a inner nullifier was emitted by a given contract by simply\n/// inspecting transaction effects. What _would_ constitute a leak would be to share the list of inner pending\n/// nullifiers, as that would reveal their preimages.\npub unconstrained fn is_nullifier_pending(inner_nullifier: Field, contract_address: AztecAddress) -> bool {\n is_nullifier_pending_oracle(inner_nullifier, contract_address)\n}\n\n#[oracle(aztec_prv_isNullifierPending)]\nunconstrained fn is_nullifier_pending_oracle(_inner_nullifier: Field, _contract_address: AztecAddress) -> bool {}\n\n/// Returns `true` if the nullifier exists. Note that a `true` value can be constrained by proving existence of the\n/// nullifier, but a `false` value should not be relied upon since other transactions may emit this nullifier before\n/// the current transaction is included in a block. While this might seem of little use at first, certain design\n/// patterns benefit from this abstraction (see e.g. `PrivateMutable`).\n// TODO(F-498): review naming consistency\npub unconstrained fn check_nullifier_exists(inner_nullifier: Field) -> bool {\n does_nullifier_exist_oracle(inner_nullifier)\n}\n\n#[oracle(aztec_utl_doesNullifierExist)]\nunconstrained fn does_nullifier_exist_oracle(_inner_nullifier: Field) -> bool {}\n"
|
|
532
470
|
},
|
|
533
|
-
"
|
|
471
|
+
"196": {
|
|
534
472
|
"function_locations": [
|
|
535
473
|
{
|
|
536
474
|
"name": "assert_valid_public_call_data",
|
|
@@ -548,7 +486,7 @@
|
|
|
548
486
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/aztec-nr/aztec/src/oracle/public_call.nr",
|
|
549
487
|
"source": "/// Validates public calldata by checking that the preimage exists and the cumulative size is within limits.\n///\n/// The check is unconstrained and the only purpose of it is to fail early in case of calldata overflow or a bug in\n/// calldata hashing.\npub(crate) fn assert_valid_public_call_data(calldata_hash: Field) {\n // Safety: This oracle call returns nothing: we only call it for its side effects (validating the calldata).\n // It is therefore always safe to call.\n unsafe {\n assert_valid_public_call_data_oracle_wrapper(calldata_hash)\n }\n}\n\nunconstrained fn assert_valid_public_call_data_oracle_wrapper(calldata_hash: Field) {\n assert_valid_public_call_data_oracle(calldata_hash)\n}\n\n#[oracle(aztec_prv_assertValidPublicCalldata)]\nunconstrained fn assert_valid_public_call_data_oracle(_calldata_hash: Field) {}\n"
|
|
550
488
|
},
|
|
551
|
-
"
|
|
489
|
+
"197": {
|
|
552
490
|
"function_locations": [
|
|
553
491
|
{
|
|
554
492
|
"name": "random",
|
|
@@ -562,7 +500,7 @@
|
|
|
562
500
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/aztec-nr/aztec/src/oracle/random.nr",
|
|
563
501
|
"source": "/// Returns an unconstrained random value. Note that it is not possible to constrain this value to prove that it is\n/// truly random: we assume that the oracle is cooperating and returning random values. In some applications this\n/// behavior might not be acceptable and other techniques might be more suitable, such as producing pseudo-random\n/// values by hashing values outside of user control (like block hashes) or secrets.\npub unconstrained fn random() -> Field {\n rand_oracle()\n}\n\n#[oracle(aztec_utl_getRandomField)]\nunconstrained fn rand_oracle() -> Field {}\n"
|
|
564
502
|
},
|
|
565
|
-
"
|
|
503
|
+
"200": {
|
|
566
504
|
"function_locations": [
|
|
567
505
|
{
|
|
568
506
|
"name": "notify_revertible_phase_start",
|
|
@@ -588,7 +526,7 @@
|
|
|
588
526
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/aztec-nr/aztec/src/oracle/tx_phase.nr",
|
|
589
527
|
"source": "/// Notifies PXE of the side effect counter at which the revertible phase begins.\n///\n/// PXE uses it to classify notes and nullifiers as revertible or non-revertible in its note cache. This information is\n/// then fed to kernels as hints.\npub(crate) fn notify_revertible_phase_start(counter: u32) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to\n // call.\n unsafe { notify_revertible_phase_start_oracle_wrapper(counter) };\n}\n\n/// Returns whether a side effect counter falls in the revertible phase of the transaction.\npub(crate) unconstrained fn is_execution_in_revertible_phase(current_counter: u32) -> bool {\n is_execution_in_revertible_phase_oracle(current_counter)\n}\n\nunconstrained fn notify_revertible_phase_start_oracle_wrapper(counter: u32) {\n notify_revertible_phase_start_oracle(counter);\n}\n\n#[oracle(aztec_prv_notifyRevertiblePhaseStart)]\nunconstrained fn notify_revertible_phase_start_oracle(_counter: u32) {}\n\n#[oracle(aztec_prv_isExecutionInRevertiblePhase)]\nunconstrained fn is_execution_in_revertible_phase_oracle(current_counter: u32) -> bool {}\n"
|
|
590
528
|
},
|
|
591
|
-
"
|
|
529
|
+
"201": {
|
|
592
530
|
"function_locations": [
|
|
593
531
|
{
|
|
594
532
|
"name": "assert_compatible_oracle_version",
|
|
@@ -612,9 +550,9 @@
|
|
|
612
550
|
}
|
|
613
551
|
],
|
|
614
552
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/aztec-nr/aztec/src/oracle/version.nr",
|
|
615
|
-
"source": "/// The oracle version constants are used to check that the oracle interface is in sync between PXE and Aztec.nr.\n/// We version the oracle interface as `major.minor` where:\n/// - `major` = backward-breaking changes (must match exactly between PXE and Aztec.nr)\n/// - `minor` = oracle additions (non-breaking; PXE minor >= contract minor)\n///\n/// The TypeScript counterparts are in `oracle_version.ts`.\n///\n/// @dev Whenever a contract function or Noir test is run, the `aztec_utl_assertCompatibleOracleVersion` oracle is\n/// called. If the major version is incompatible, an error is thrown immediately. The minor version is recorded by\n/// the PXE and used to provide helpful error messages if a contract calls an oracle that doesn't exist. We don't throw\n/// immediately if AZTEC_NR_MINOR > PXE_MINOR because if a contract is updated to use a newer Aztec.nr dependency\n/// without actually using any of the new oracles then there is no reason to throw.\npub global ORACLE_VERSION_MAJOR: Field = 22;\npub global ORACLE_VERSION_MINOR: Field =
|
|
553
|
+
"source": "/// The oracle version constants are used to check that the oracle interface is in sync between PXE and Aztec.nr.\n/// We version the oracle interface as `major.minor` where:\n/// - `major` = backward-breaking changes (must match exactly between PXE and Aztec.nr)\n/// - `minor` = oracle additions (non-breaking; PXE minor >= contract minor)\n///\n/// The TypeScript counterparts are in `oracle_version.ts`.\n///\n/// @dev Whenever a contract function or Noir test is run, the `aztec_utl_assertCompatibleOracleVersion` oracle is\n/// called. If the major version is incompatible, an error is thrown immediately. The minor version is recorded by\n/// the PXE and used to provide helpful error messages if a contract calls an oracle that doesn't exist. We don't throw\n/// immediately if AZTEC_NR_MINOR > PXE_MINOR because if a contract is updated to use a newer Aztec.nr dependency\n/// without actually using any of the new oracles then there is no reason to throw.\npub global ORACLE_VERSION_MAJOR: Field = 22;\npub global ORACLE_VERSION_MINOR: Field = 2;\n\n/// Asserts that the version of the oracle is compatible with the version expected by the contract.\npub fn assert_compatible_oracle_version() {\n // Safety: This oracle call returns nothing: we only call it to check Aztec.nr and Oracle interface versions are\n // compatible. It is therefore always safe to call.\n unsafe {\n assert_compatible_oracle_version_wrapper();\n }\n}\n\nunconstrained fn assert_compatible_oracle_version_wrapper() {\n assert_compatible_oracle_version_oracle(ORACLE_VERSION_MAJOR, ORACLE_VERSION_MINOR);\n}\n\n#[oracle(aztec_utl_assertCompatibleOracleVersionV2)]\nunconstrained fn assert_compatible_oracle_version_oracle(major: Field, minor: Field) {}\n\nmod test {\n use super::{assert_compatible_oracle_version_oracle, ORACLE_VERSION_MAJOR, ORACLE_VERSION_MINOR};\n\n #[test]\n unconstrained fn compatible_oracle_version() {\n assert_compatible_oracle_version_oracle(ORACLE_VERSION_MAJOR, ORACLE_VERSION_MINOR);\n }\n\n #[test(should_fail_with = \"Incompatible aztec cli version:\")]\n unconstrained fn incompatible_oracle_version_major() {\n let arbitrary_incorrect_major = 318183437;\n assert_compatible_oracle_version_oracle(arbitrary_incorrect_major, ORACLE_VERSION_MINOR);\n }\n}\n"
|
|
616
554
|
},
|
|
617
|
-
"
|
|
555
|
+
"268": {
|
|
618
556
|
"function_locations": [
|
|
619
557
|
{
|
|
620
558
|
"name": "Poseidon2::hash",
|
|
@@ -656,7 +594,7 @@
|
|
|
656
594
|
"path": "/home/aztec-dev/nargo/github.com/noir-lang/poseidon/v0.3.0/src/poseidon2.nr",
|
|
657
595
|
"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"
|
|
658
596
|
},
|
|
659
|
-
"
|
|
597
|
+
"326": {
|
|
660
598
|
"function_locations": [
|
|
661
599
|
{
|
|
662
600
|
"name": "<impl Empty for AztecAddress>::empty",
|
|
@@ -750,7 +688,7 @@
|
|
|
750
688
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr",
|
|
751
689
|
"source": "use crate::{\n address::{\n partial_address::PartialAddress, salted_initialization_hash::SaltedInitializationHash,\n },\n constants::{AZTEC_ADDRESS_LENGTH, DOM_SEP__CONTRACT_ADDRESS_V1, MAX_FIELD_VALUE},\n contract_class_id::ContractClassId,\n hash::poseidon2_hash_with_separator,\n public_keys::{IvpkM, NpkM, OvpkM, PublicKeys, ToPoint, TpkM},\n traits::{Deserialize, Empty, FromField, Packable, Serialize, ToField},\n utils::field::sqrt,\n};\n\nuse crate::point::Point;\n\nuse crate::public_keys::AddressPoint;\nuse std::{\n embedded_curve_ops::{EmbeddedCurveScalar, fixed_base_scalar_mul as derive_public_key},\n ops::Add,\n};\nuse std::meta::derive;\n\n// Aztec address\n#[derive(Deserialize, Eq, Packable, Serialize)]\npub struct AztecAddress {\n pub inner: Field,\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self { inner: 0 }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for AztecAddress {\n fn from_field(value: Field) -> AztecAddress {\n AztecAddress { inner: value }\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n /// Returns `true` if the address is valid.\n ///\n /// An invalid address is one that can be proven to not be correctly derived, meaning it contains no contract code,\n /// public keys, etc., and can therefore not receive messages nor execute calls.\n pub fn is_valid(self) -> bool {\n self.get_y().is_some()\n }\n\n /// Returns an address's [`AddressPoint`].\n ///\n /// This can be used to create shared secrets with the owner of the address. If the address is invalid (see\n /// [`AztecAddress::is_valid`]) then this returns `Option::none()`, and no shared secrets can be created.\n pub fn to_address_point(self) -> Option<AddressPoint> {\n self.get_y().map(|y| {\n // If we get a negative y coordinate (y > (r - 1) / 2), we swap it to the\n // positive one (where y <= (r - 1) / 2) by negating it.\n let final_y = if Self::is_positive(y) { y } else { -y };\n\n AddressPoint { inner: Point { x: self.inner, y: final_y, is_infinite: false } }\n })\n }\n\n /// Determines whether a y-coordinate is in the lower (positive) or upper (negative) \"half\" of the field.\n /// I.e.\n /// y <= (r - 1)/2 => positive.\n /// y > (r - 1)/2 => negative.\n /// An AddressPoint always uses the \"positive\" y.\n fn is_positive(y: Field) -> bool {\n // Note: The field modulus r is MAX_FIELD_VALUE + 1.\n let MID = MAX_FIELD_VALUE / 2; // (r - 1) / 2\n let MID_PLUS_1 = MID + 1; // (r - 1)/2 + 1\n // Note: y <= m implies y < m + 1.\n y.lt(MID_PLUS_1)\n }\n\n /// Returns one of the two possible y-coordinates.\n ///\n /// Not all `AztecAddresses` are valid, in which case there is no corresponding y-coordinate. This returns\n /// `Option::none()` for invalid addresses.\n ///\n /// An `AztecAddress` is defined by an x-coordinate, for which two y-coordinates exist as solutions to the curve\n /// equation. This function returns either of them. Note that an [`AddressPoint`] must **always** have a positive\n /// y-coordinate - if trying to obtain the underlying point use [`AztecAddress::to_address_point`] instead.\n fn get_y(self) -> Option<Field> {\n // We compute the address point by taking our address as x, and then solving for y in the\n // equation which defines the grumpkin curve:\n // y^2 = x^3 - 17; x = address\n let x = self.inner;\n let y_squared = x * x * x - 17;\n\n sqrt(y_squared)\n }\n\n pub fn compute(public_keys: PublicKeys, partial_address: PartialAddress) -> AztecAddress {\n //\n // address = address_point.x\n // |\n // address_point = pre_address * G + Ivpk_m (always choose \"positive\" y-coord)\n // | ^\n // | |.....................\n // pre_address .\n // / \\ .\n // / \\ .\n // partial_address public_keys_hash .\n // / \\ / / \\ \\ .\n // / \\ Npk_m Ivpk_m Ovpk_m Tpk_m .\n // contract_class_id \\ |...................\n // / | \\ \\\n // artifact_hash | public_bytecode_commitment salted_initialization_hash\n // | / / \\\n // private_function_tree_root deployer_address salt initialization_hash\n // / \\ / \\\n // ... ... constructor_fn_selector constructor_args_hash\n // / \\\n // / \\ / \\\n // leaf leaf leaf leaf\n // ^\n // |\n // |---h(function_selector, vk_hash)\n // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n // Each of these represents a private function of the contract.\n\n let public_keys_hash = public_keys.hash();\n\n let pre_address = poseidon2_hash_with_separator(\n [public_keys_hash.to_field(), partial_address.to_field()],\n DOM_SEP__CONTRACT_ADDRESS_V1,\n );\n\n // Note: `.add()` will fail within the blackbox fn if either of the points are not on the curve. (See tests below).\n // TODO(F-553): Drop the `.to_embedded()` / `.into()` round-trip once the custom `Point` wrapper is removed and\n // we use `EmbeddedCurvePoint` directly.\n let address_point: Point = derive_public_key(EmbeddedCurveScalar::from_field(pre_address))\n .add(public_keys.ivpk_m.to_point().to_embedded())\n .into();\n\n // Note that our address is only the x-coordinate of the full address_point. This is okay because when people want to encrypt something and send it to us\n // they can recover our full point using the x-coordinate (our address itself). To do this, they recompute the y-coordinate according to the equation y^2 = x^3 - 17.\n // When they do this, they may get a positive y-coordinate (a value that is less than or equal to MAX_FIELD_VALUE / 2) or\n // a negative y-coordinate (a value that is more than MAX_FIELD_VALUE), and we cannot dictate which one they get and hence the recovered point may sometimes be different than the one\n // our secret can decrypt. Regardless though, they should and will always encrypt using point with the positive y-coordinate by convention.\n // This ensures that everyone encrypts to the same point given an arbitrary x-coordinate (address). This is allowed because even though our original point may not have a positive y-coordinate,\n // with our original secret, we will be able to derive the secret to the point with the flipped (and now positive) y-coordinate that everyone encrypts to.\n AztecAddress::from_field(address_point.x)\n }\n\n pub fn compute_from_class_id(\n contract_class_id: ContractClassId,\n salted_initialization_hash: SaltedInitializationHash,\n public_keys: PublicKeys,\n ) -> Self {\n let partial_address = PartialAddress::compute_from_salted_initialization_hash(\n contract_class_id,\n salted_initialization_hash,\n );\n\n AztecAddress::compute(public_keys, partial_address)\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n\n#[test]\nfn check_max_field_value() {\n // Check that it is indeed r-1.\n assert_eq(MAX_FIELD_VALUE + 1, 0);\n}\n\n#[test]\nfn check_is_positive() {\n assert(AztecAddress::is_positive(0));\n assert(AztecAddress::is_positive(1));\n assert(!AztecAddress::is_positive(-1));\n assert(AztecAddress::is_positive(MAX_FIELD_VALUE / 2));\n assert(!AztecAddress::is_positive((MAX_FIELD_VALUE / 2) + 1));\n}\n\n// Gives us confidence that we don't need to manually check that the input public keys need to be on the curve for `add`,\n// because the blackbox function does this check for us.\n#[test(should_fail_with = \"is not on curve\")]\nfn check_embedded_curve_point_add() {\n // Choose a point not on the curve:\n let p1 = Point { x: 1, y: 1, is_infinite: false };\n let p2 = Point::generator();\n let _ = p1 + p2;\n}\n\n// Gives us confidence that we don't need to manually check that the input public keys need to be on the curve for `add`,\n// because the blackbox function does this check for us.\n#[test(should_fail_with = \"is not on curve\")]\nfn check_embedded_curve_point_add_2() {\n // Choose a point not on the curve in the 2nd position.\n let p1 = Point::generator();\n let p2 = Point { x: 1, y: 1, is_infinite: false };\n let _ = p1 + p2;\n}\n\n#[test]\nfn compute_address_from_partial_and_pub_keys() {\n let public_keys = PublicKeys {\n npk_m: NpkM {\n inner: Point {\n x: 0x22f7fcddfa3ce3e8f0cc8e82d7b94cdd740afa3e77f8e4a63ea78a239432dcab,\n y: 0x0471657de2b6216ade6c506d28fbc22ba8b8ed95c871ad9f3e3984e90d9723a7,\n is_infinite: false,\n },\n },\n ivpk_m: IvpkM {\n inner: Point {\n x: 0x111223493147f6785514b1c195bb37a2589f22a6596d30bb2bb145fdc9ca8f1e,\n y: 0x273bbffd678edce8fe30e0deafc4f66d58357c06fd4a820285294b9746c3be95,\n is_infinite: false,\n },\n },\n ovpk_m: OvpkM {\n inner: Point {\n x: 0x09115c96e962322ffed6522f57194627136b8d03ac7469109707f5e44190c484,\n y: 0x0c49773308a13d740a7f0d4f0e6163b02c5a408b6f965856b6a491002d073d5b,\n is_infinite: false,\n },\n },\n tpk_m: TpkM {\n inner: Point {\n x: 0x00d3d81beb009873eb7116327cf47c612d5758ef083d4fda78e9b63980b2a762,\n y: 0x2f567d22d2b02fe1f4ad42db9d58a36afd1983e7e2909d1cab61cafedad6193a,\n is_infinite: false,\n },\n },\n };\n\n let partial_address = PartialAddress::from_field(\n 0x0a7c585381b10f4666044266a02405bf6e01fa564c8517d4ad5823493abd31de,\n );\n\n let address = AztecAddress::compute(public_keys, partial_address);\n\n // The following value was generated by `derivation.test.ts`.\n // --> Run the test with AZTEC_GENERATE_TEST_DATA=1 flag to update test data.\n let expected_computed_address_from_partial_and_pubkeys =\n 0x2f66081d4bb077fbe8e8abe96a3516a713a3d7e34360b4e985da0da95092b37d;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkeys);\n}\n\n#[test]\nfn compute_preaddress_from_partial_and_pub_keys() {\n let pre_address = poseidon2_hash_with_separator([1, 2], DOM_SEP__CONTRACT_ADDRESS_V1);\n let expected_computed_preaddress_from_partial_and_pubkey =\n 0x286c7755f2924b1e53b00bcaf1adaffe7287bd74bba7a02f4ab867e3892d28da;\n assert(pre_address == expected_computed_preaddress_from_partial_and_pubkey);\n}\n\n#[test]\nfn from_field_to_field() {\n let address = AztecAddress { inner: 37 };\n assert_eq(FromField::from_field(address.to_field()), address);\n}\n\n#[test]\nfn serde() {\n let address = AztecAddress { inner: 37 };\n // We use the AZTEC_ADDRESS_LENGTH constant to ensure that there is a match between the derived trait\n // implementation and the constant.\n let serialized: [Field; AZTEC_ADDRESS_LENGTH] = address.serialize();\n let deserialized = AztecAddress::deserialize(serialized);\n assert_eq(address, deserialized);\n}\n\n#[test]\nfn to_address_point_valid() {\n // x = 8 where x^3 - 17 = 512 - 17 = 495, which is a residue in this field\n let address = AztecAddress { inner: 8 };\n\n assert(address.get_y().is_some()); // We don't bother checking the result of get_y as it is only used internally\n assert(address.is_valid());\n\n let maybe_point = address.to_address_point();\n assert(maybe_point.is_some());\n\n let point = maybe_point.unwrap().inner;\n // check that x is preserved\n assert_eq(point.x, Field::from(8));\n\n // check that the curve equation holds: y^2 == x^3 - 17\n assert_eq(point.y * point.y, point.x * point.x * point.x - 17);\n}\n\n#[test]\nunconstrained fn to_address_point_invalid() {\n // x = 3 where x^3 - 17 = 27 - 17 = 10, which is a non-residue in this field\n let address = AztecAddress { inner: 3 };\n\n assert(address.get_y().is_none());\n assert(!address.is_valid());\n\n assert(address.to_address_point().is_none());\n}\n"
|
|
752
690
|
},
|
|
753
|
-
"
|
|
691
|
+
"357": {
|
|
754
692
|
"function_locations": [
|
|
755
693
|
{
|
|
756
694
|
"name": "sha256_to_field",
|
|
@@ -872,7 +810,7 @@
|
|
|
872
810
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr",
|
|
873
811
|
"source": "mod poseidon2_chunks;\n\nuse crate::{\n abis::{\n contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage,\n function_selector::FunctionSelector, nullifier::Nullifier, private_log::PrivateLog,\n transaction::tx_request::TxRequest,\n },\n address::{AztecAddress, EthAddress},\n constants::{\n CONTRACT_CLASS_LOG_SIZE_IN_FIELDS, DOM_SEP__NOTE_HASH_NONCE,\n DOM_SEP__PRIVATE_LOG_FIRST_FIELD, DOM_SEP__SILOED_NOTE_HASH, DOM_SEP__SILOED_NULLIFIER,\n DOM_SEP__UNIQUE_NOTE_HASH, FUNCTION_TREE_HEIGHT, NULL_MSG_SENDER_CONTRACT_ADDRESS,\n TWO_POW_64,\n },\n merkle_tree::root_from_sibling_path,\n messaging::l2_to_l1_message::L2ToL1Message,\n poseidon2::Poseidon2Sponge,\n side_effect::{Counted, Scoped},\n traits::{FromField, Hash, ToField},\n utils::field::{field_from_bytes, field_from_bytes_32_trunc},\n};\n\npub use poseidon2_chunks::poseidon2_absorb_in_chunks_existing_sponge;\nuse poseidon2_chunks::poseidon2_absorb_in_chunks;\nuse std::embedded_curve_ops::EmbeddedCurveScalar;\n\n// TODO: refactor these into their own files: sha256, poseidon2, some protocol-specific hash computations, some merkle computations.\n\npub fn sha256_to_field<let N: u32>(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256::digest(bytes_to_hash);\n let hash_in_a_field = field_from_bytes_32_trunc(sha256_hashed);\n\n hash_in_a_field\n}\n\npub fn private_functions_root_from_siblings(\n selector: FunctionSelector,\n vk_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT],\n) -> Field {\n let function_leaf_preimage = ContractClassFunctionLeafPreimage { selector, vk_hash };\n let function_leaf = function_leaf_preimage.hash();\n root_from_sibling_path(\n function_leaf,\n function_leaf_index,\n function_leaf_sibling_path,\n )\n}\n\n/// Siloing in the context of Aztec refers to the process of hashing a note hash with a contract address (this way\n/// the note hash is scoped to a specific contract). This is used to prevent intermingling of notes between contracts.\npub fn compute_siloed_note_hash(contract_address: AztecAddress, note_hash: Field) -> Field {\n poseidon2_hash_with_separator(\n [contract_address.to_field(), note_hash],\n DOM_SEP__SILOED_NOTE_HASH,\n )\n}\n\n/// Computes unique, siloed note hashes from siloed note hashes.\n///\n/// The protocol injects uniqueness into every note_hash, so that every single note_hash in the\n/// tree is unique. This prevents faerie gold attacks, where a malicious sender could create\n/// two identical note_hashes for a recipient (meaning only one would be nullifiable in future).\n///\n/// Most privacy protocols will inject the note's leaf_index (its position in the Note Hashes Tree)\n/// into the note, but this requires the creator of a note to wait until their tx is included in\n/// a block to know the note's final note hash (the unique, siloed note hash), because inserting\n/// leaves into trees is the job of a block producer.\n///\n/// We took a different approach so that the creator of a note will know each note's unique, siloed\n/// note hash before broadcasting their tx to the network.\n/// (There was also a historical requirement relating to \"chained transactions\" -- a feature that\n/// Aztec Connect had to enable notes to be spent from distinct txs earlier in the same block,\n/// and hence before an archive block root had been established for that block -- but that feature\n/// was abandoned for the Aztec Network for having too many bad tradeoffs).\n///\n/// (\n/// Edit: it is no longer true that all final note_hashes will be known by the creator of a tx\n/// before they send it to the network. If a tx makes public function calls, then _revertible_\n/// note_hashes that are created in private will not be made unique in private by the Reset circuit,\n/// but will instead be made unique by the AVM, because the `note_index_in_tx` will not be known\n/// until the AVM has executed the public functions of the tx. (See an explanation in\n/// reset_output_composer.nr for why).\n/// For some such txs, the `note_index_in_tx` might still be predictable through simulation, but\n/// for txs whose public functions create a varying number of non-revertible notes (determined at\n/// runtime), the `note_index_in_tx` will not be deterministically derivable before submitting the\n/// tx to the network.\n/// )\n///\n/// We use the `first_nullifier` of a tx as a seed of uniqueness. We have a guarantee that there will\n/// always be at least one nullifier per tx, because the init circuit will create one if one isn't\n/// created naturally by any functions of the tx. (Search \"protocol_nullifier\").\n/// We combine the `first_nullifier` with the note's index (its position within this tx's new\n/// note_hashes array) (`note_index_in_tx`) to get a truly unique value to inject into a note, which\n/// we call a `note_nonce`.\npub fn compute_unique_note_hash(note_nonce: Field, siloed_note_hash: Field) -> Field {\n let inputs = [note_nonce, siloed_note_hash];\n poseidon2_hash_with_separator(inputs, DOM_SEP__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_note_hash_nonce(first_nullifier_in_tx: Field, note_index_in_tx: u32) -> Field {\n // Hashing the first nullifier with note index in tx is guaranteed to be unique (because all nullifiers are also\n // unique).\n poseidon2_hash_with_separator(\n [first_nullifier_in_tx, note_index_in_tx as Field],\n DOM_SEP__NOTE_HASH_NONCE,\n )\n}\n\npub fn compute_note_nonce_and_unique_note_hash(\n siloed_note_hash: Field,\n first_nullifier: Field,\n note_index_in_tx: u32,\n) -> Field {\n let note_nonce = compute_note_hash_nonce(first_nullifier, note_index_in_tx);\n compute_unique_note_hash(note_nonce, siloed_note_hash)\n}\n\npub fn compute_siloed_nullifier(contract_address: AztecAddress, nullifier: Field) -> Field {\n poseidon2_hash_with_separator(\n [contract_address.to_field(), nullifier],\n DOM_SEP__SILOED_NULLIFIER,\n )\n}\n\npub fn create_protocol_nullifier(tx_request: TxRequest) -> Scoped<Counted<Nullifier>> {\n // The protocol nullifier is ascribed a special side-effect counter of 1. No other side-effect\n // can have counter 1 (see `validate_as_first_call` for that assertion).\n Nullifier { value: tx_request.hash(), note_hash: 0 }.count(1).scope(\n NULL_MSG_SENDER_CONTRACT_ADDRESS,\n )\n}\n\npub fn compute_log_tag(raw_tag: Field, dom_sep: u32) -> Field {\n poseidon2_hash_with_separator([raw_tag], dom_sep)\n}\n\npub fn compute_siloed_private_log_first_field(\n contract_address: AztecAddress,\n field: Field,\n) -> Field {\n poseidon2_hash_with_separator(\n [contract_address.to_field(), field],\n DOM_SEP__PRIVATE_LOG_FIRST_FIELD,\n )\n}\n\npub fn compute_siloed_private_log(contract_address: AztecAddress, log: PrivateLog) -> PrivateLog {\n let mut fields = log.fields;\n fields[0] = compute_siloed_private_log_first_field(contract_address, fields[0]);\n PrivateLog::new(fields, log.length)\n}\n\npub fn compute_contract_class_log_hash(log: [Field; CONTRACT_CLASS_LOG_SIZE_IN_FIELDS]) -> Field {\n poseidon2_hash(log)\n}\n\npub fn compute_app_siloed_secret_key(\n master_secret_key: EmbeddedCurveScalar,\n app_address: AztecAddress,\n key_type_domain_separator: Field,\n) -> Field {\n poseidon2_hash_with_separator(\n [master_secret_key.hi, master_secret_key.lo, app_address.to_field()],\n key_type_domain_separator,\n )\n}\n\npub fn compute_l2_to_l1_message_hash(\n message: Scoped<L2ToL1Message>,\n rollup_version_id: Field,\n chain_id: Field,\n) -> Field {\n let contract_address_bytes: [u8; 32] = message.contract_address.to_field().to_be_bytes();\n let recipient_bytes: [u8; 20] = message.inner.recipient.to_be_bytes();\n let content_bytes: [u8; 32] = message.inner.content.to_be_bytes();\n let rollup_version_id_bytes: [u8; 32] = rollup_version_id.to_be_bytes();\n let chain_id_bytes: [u8; 32] = chain_id.to_be_bytes();\n\n let mut bytes: [u8; 148] = std::mem::zeroed();\n for i in 0..32 {\n bytes[i] = contract_address_bytes[i];\n bytes[i + 32] = rollup_version_id_bytes[i];\n // 64 - 84 are for recipient.\n bytes[i + 84] = chain_id_bytes[i];\n bytes[i + 116] = content_bytes[i];\n }\n\n for i in 0..20 {\n bytes[64 + i] = recipient_bytes[i];\n }\n\n sha256_to_field(bytes)\n}\n\n// TODO: consider a variant that enables domain separation with a u32 (we seem to have standardised u32s for domain separators)\n/// Computes sha256 hash of 2 input fields.\n///\n/// @returns A truncated field (i.e., the first byte is always 0).\npub fn accumulate_sha256(v0: Field, v1: Field) -> Field {\n // Concatenate two fields into 32 x 2 = 64 bytes\n let v0_as_bytes: [u8; 32] = v0.to_be_bytes();\n let v1_as_bytes: [u8; 32] = v1.to_be_bytes();\n let hash_input_flattened = v0_as_bytes.concat(v1_as_bytes);\n\n sha256_to_field(hash_input_flattened)\n}\n\npub fn poseidon2_hash<let N: u32>(inputs: [Field; N]) -> Field {\n poseidon::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[no_predicates]\npub fn poseidon2_hash_with_separator<let N: u32, T>(inputs: [Field; N], separator: T) -> Field\nwhere\n T: ToField,\n{\n let inputs_with_separator = [separator.to_field()].concat(inputs);\n poseidon2_hash(inputs_with_separator)\n}\n\n/// Computes a Poseidon2 hash over a dynamic-length subarray of the given input.\n/// Only the first `in_len` fields of `input` are absorbed; any remaining fields are ignored.\n/// The caller is responsible for ensuring that the input is padded with zeros if required.\n#[no_predicates]\npub fn poseidon2_hash_subarray<let N: u32>(input: [Field; N], in_len: u32) -> Field {\n let mut sponge = poseidon2_absorb_in_chunks(input, in_len);\n sponge.squeeze()\n}\n\n// This function is unconstrained because it is intended to be used in unconstrained context only as\n// in constrained contexts it would be too inefficient.\npub unconstrained fn poseidon2_hash_with_separator_bounded_vec<let N: u32, T>(\n inputs: BoundedVec<Field, N>,\n separator: T,\n) -> Field\nwhere\n T: ToField,\n{\n let in_len = inputs.len() + 1;\n let iv: Field = (in_len as Field) * TWO_POW_64;\n let mut sponge = Poseidon2Sponge::new(iv);\n sponge.absorb(separator.to_field());\n\n for i in 0..inputs.len() {\n sponge.absorb(inputs.get(i));\n }\n\n sponge.squeeze()\n}\n\n#[no_predicates]\npub fn poseidon2_hash_bytes<let N: u32>(inputs: [u8; N]) -> Field {\n let mut fields = [0; (N + 30) / 31];\n let mut field_index = 0;\n let mut current_field = [0; 31];\n for i in 0..inputs.len() {\n let index = i % 31;\n current_field[index] = inputs[i];\n if index == 30 {\n fields[field_index] = field_from_bytes(current_field, false);\n current_field = [0; 31];\n field_index += 1;\n }\n }\n if field_index != fields.len() {\n fields[field_index] = field_from_bytes(current_field, false);\n }\n poseidon2_hash(fields)\n}\n\n#[test]\nfn subarray_hash_matches_fixed() {\n let values_to_hash = [3; 17];\n let padded = values_to_hash.concat([0; 11]);\n let subarray_hash = poseidon2_hash_subarray(padded, values_to_hash.len());\n\n // Hash the entire values_to_hash.\n let fixed_len_hash = poseidon::poseidon2::Poseidon2::hash(values_to_hash, values_to_hash.len());\n\n assert_eq(subarray_hash, fixed_len_hash);\n}\n\n#[test]\nfn subarray_hash_matches_variable() {\n let values_to_hash = [3; 17];\n let padded = values_to_hash.concat([0; 11]);\n let subarray_hash = poseidon2_hash_subarray(padded, values_to_hash.len());\n\n // Hash up to values_to_hash.len() fields of the padded array.\n let variable_len_hash = poseidon::poseidon2::Poseidon2::hash(padded, values_to_hash.len());\n\n assert_eq(subarray_hash, variable_len_hash);\n}\n\n#[test]\nfn smoke_sha256_to_field() {\n let full_buffer = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\n 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\n 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,\n 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,\n 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,\n 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,\n 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,\n 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,\n ];\n let result = sha256_to_field(full_buffer);\n\n assert(result == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184c7);\n\n // to show correctness of the current ver (truncate one byte) vs old ver (mod full bytes):\n let result_bytes = sha256::digest(full_buffer);\n let truncated_field = crate::utils::field::field_from_bytes_32_trunc(result_bytes);\n assert(truncated_field == result);\n let mod_res = result + (result_bytes[31] as Field);\n assert(mod_res == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184e0);\n}\n\n#[test]\nfn unique_siloed_note_hash_matches_typescript() {\n let inner_note_hash = 1;\n let contract_address = AztecAddress::from_field(2);\n let first_nullifier = 3;\n let note_index_in_tx = 4;\n\n let siloed_note_hash = compute_siloed_note_hash(contract_address, inner_note_hash);\n let siloed_note_hash_from_ts =\n 0x1986a4bea3eddb1fff917d629a13e10f63f514f401bdd61838c6b475db949169;\n assert_eq(siloed_note_hash, siloed_note_hash_from_ts);\n\n let nonce: Field = compute_note_hash_nonce(first_nullifier, note_index_in_tx);\n let note_hash_nonce_from_ts =\n 0x28e7799791bf066a57bb51fdd0fbcaf3f0926414314c7db515ea343f44f5d58b;\n assert_eq(nonce, note_hash_nonce_from_ts);\n\n let unique_siloed_note_hash_from_nonce = compute_unique_note_hash(nonce, siloed_note_hash);\n let unique_siloed_note_hash = compute_note_nonce_and_unique_note_hash(\n siloed_note_hash,\n first_nullifier,\n note_index_in_tx,\n );\n assert_eq(unique_siloed_note_hash_from_nonce, unique_siloed_note_hash);\n\n let unique_siloed_note_hash_from_ts =\n 0x29949aef207b715303b24639737c17fbfeb375c1d965ecfa85c7e4f0febb7d16;\n assert_eq(unique_siloed_note_hash, unique_siloed_note_hash_from_ts);\n}\n\n#[test]\nfn siloed_nullifier_matches_typescript() {\n let contract_address = AztecAddress::from_field(123);\n let nullifier = 456;\n\n let res = compute_siloed_nullifier(contract_address, nullifier);\n\n let siloed_nullifier_from_ts =\n 0x169b50336c1f29afdb8a03d955a81e485f5ac7d5f0b8065673d1e407e5877813;\n\n assert_eq(res, siloed_nullifier_from_ts);\n}\n\n#[test]\nfn siloed_private_log_first_field_matches_typescript() {\n let contract_address = AztecAddress::from_field(123);\n let field = 456;\n let res = compute_siloed_private_log_first_field(contract_address, field);\n\n let siloed_private_log_first_field_from_ts =\n 0x29480984f7b9257fded523d50addbcfc8d1d33adcf2db73ef3390a8fd5cdffaa;\n\n assert_eq(res, siloed_private_log_first_field_from_ts);\n}\n\n#[test]\nfn empty_l2_to_l1_message_hash_matches_typescript() {\n // All zeroes\n let res = compute_l2_to_l1_message_hash(\n L2ToL1Message { recipient: EthAddress::zero(), content: 0 }.scope(AztecAddress::from_field(\n 0,\n )),\n 0,\n 0,\n );\n\n let empty_l2_to_l1_msg_hash_from_ts =\n 0x003b18c58c739716e76429634a61375c45b3b5cd470c22ab6d3e14cee23dd992;\n\n assert_eq(res, empty_l2_to_l1_msg_hash_from_ts);\n}\n\n#[test]\nfn l2_to_l1_message_hash_matches_typescript() {\n let message = L2ToL1Message { recipient: EthAddress::from_field(1), content: 2 }.scope(\n AztecAddress::from_field(3),\n );\n let version = 4;\n let chainId = 5;\n\n let hash = compute_l2_to_l1_message_hash(message, version, chainId);\n\n // The following value was generated by `yarn-project/stdlib/src/hash/hash.test.ts`\n let l2_to_l1_message_hash_from_ts =\n 0x0081edf209e087ad31b3fd24263698723d57190bd1d6e9fe056fc0c0a68ee661;\n\n assert_eq(hash, l2_to_l1_message_hash_from_ts);\n}\n\n#[test]\nunconstrained fn poseidon2_hash_with_separator_bounded_vec_matches_non_bounded_vec_version() {\n let inputs = BoundedVec::<Field, 4>::from_array([1, 2, 3]);\n let separator = 42;\n\n // Hash using bounded vec version\n let bounded_result = poseidon2_hash_with_separator_bounded_vec(inputs, separator);\n\n // Hash using regular version\n let regular_result = poseidon2_hash_with_separator([1, 2, 3], separator);\n\n // Results should match\n assert_eq(bounded_result, regular_result);\n}\n"
|
|
874
812
|
},
|
|
875
|
-
"
|
|
813
|
+
"359": {
|
|
876
814
|
"function_locations": [
|
|
877
815
|
{
|
|
878
816
|
"name": "fatal_log",
|
|
@@ -946,56 +884,6 @@
|
|
|
946
884
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-protocol-circuits/crates/types/src/logging.nr",
|
|
947
885
|
"source": "// Log levels matching the JS logger:\n\n// global SILENT_LOG_LEVEL: u8 = 0;\nglobal FATAL_LOG_LEVEL: u8 = 1;\nglobal ERROR_LOG_LEVEL: u8 = 2;\nglobal WARN_LOG_LEVEL: u8 = 3;\nglobal INFO_LOG_LEVEL: u8 = 4;\nglobal VERBOSE_LOG_LEVEL: u8 = 5;\nglobal DEBUG_LOG_LEVEL: u8 = 6;\nglobal TRACE_LOG_LEVEL: u8 = 7;\n\n// --- Per-level log functions (no format args) ---\n\npub fn fatal_log<let N: u32>(msg: str<N>) {\n fatal_log_format(msg, []);\n}\n\npub fn error_log<let N: u32>(msg: str<N>) {\n error_log_format(msg, []);\n}\n\npub fn warn_log<let N: u32>(msg: str<N>) {\n warn_log_format(msg, []);\n}\n\npub fn info_log<let N: u32>(msg: str<N>) {\n info_log_format(msg, []);\n}\n\npub fn verbose_log<let N: u32>(msg: str<N>) {\n verbose_log_format(msg, []);\n}\n\npub fn debug_log<let N: u32>(msg: str<N>) {\n debug_log_format(msg, []);\n}\n\npub fn trace_log<let N: u32>(msg: str<N>) {\n trace_log_format(msg, []);\n}\n\n// --- Per-level log functions (with format args) ---\n\npub fn fatal_log_format<let M: u32, let N: u32>(msg: str<M>, args: [Field; N]) {\n log_format(FATAL_LOG_LEVEL, msg, args);\n}\n\npub fn error_log_format<let M: u32, let N: u32>(msg: str<M>, args: [Field; N]) {\n log_format(ERROR_LOG_LEVEL, msg, args);\n}\n\npub fn warn_log_format<let M: u32, let N: u32>(msg: str<M>, args: [Field; N]) {\n log_format(WARN_LOG_LEVEL, msg, args);\n}\n\npub fn info_log_format<let M: u32, let N: u32>(msg: str<M>, args: [Field; N]) {\n log_format(INFO_LOG_LEVEL, msg, args);\n}\n\npub fn verbose_log_format<let M: u32, let N: u32>(msg: str<M>, args: [Field; N]) {\n log_format(VERBOSE_LOG_LEVEL, msg, args);\n}\n\npub fn debug_log_format<let M: u32, let N: u32>(msg: str<M>, args: [Field; N]) {\n log_format(DEBUG_LOG_LEVEL, msg, args);\n}\n\npub fn trace_log_format<let M: u32, let N: u32>(msg: str<M>, args: [Field; N]) {\n log_format(TRACE_LOG_LEVEL, msg, args);\n}\n\nfn log_format<let M: u32, let N: u32>(log_level: u8, msg: str<M>, args: [Field; N]) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe\n // to call.\n unsafe { log_oracle_wrapper(log_level, msg, args) };\n}\n\nunconstrained fn log_oracle_wrapper<let M: u32, let N: u32>(\n log_level: u8,\n msg: str<M>,\n args: [Field; N],\n) {\n log_oracle(log_level, msg, N, args);\n}\n\n// While the length parameter might seem unnecessary given that we have N, we keep it around because at the AVM\n// bytecode level we want to support non-comptime-known lengths for such opcodes, even if Noir code will not generally\n// take that route. The AVM transpiler maps this oracle to the DEBUGLOG opcode, which reads the fields size from memory.\n#[oracle(aztec_utl_log)]\nunconstrained fn log_oracle<let M: u32, let N: u32>(\n log_level: u8,\n msg: str<M>,\n length: u32,\n args: [Field; N],\n) {}\n"
|
|
948
886
|
},
|
|
949
|
-
"409": {
|
|
950
|
-
"function_locations": [
|
|
951
|
-
{
|
|
952
|
-
"name": "Reader<N>::new",
|
|
953
|
-
"start": 144
|
|
954
|
-
},
|
|
955
|
-
{
|
|
956
|
-
"name": "Reader<N>::read",
|
|
957
|
-
"start": 222
|
|
958
|
-
},
|
|
959
|
-
{
|
|
960
|
-
"name": "Reader<N>::read_u32",
|
|
961
|
-
"start": 355
|
|
962
|
-
},
|
|
963
|
-
{
|
|
964
|
-
"name": "Reader<N>::read_u64",
|
|
965
|
-
"start": 429
|
|
966
|
-
},
|
|
967
|
-
{
|
|
968
|
-
"name": "Reader<N>::read_bool",
|
|
969
|
-
"start": 505
|
|
970
|
-
},
|
|
971
|
-
{
|
|
972
|
-
"name": "Reader<N>::read_array",
|
|
973
|
-
"start": 598
|
|
974
|
-
},
|
|
975
|
-
{
|
|
976
|
-
"name": "Reader<N>::read_struct",
|
|
977
|
-
"start": 855
|
|
978
|
-
},
|
|
979
|
-
{
|
|
980
|
-
"name": "Reader<N>::read_struct_array",
|
|
981
|
-
"start": 1094
|
|
982
|
-
},
|
|
983
|
-
{
|
|
984
|
-
"name": "Reader<N>::peek_offset",
|
|
985
|
-
"start": 1263
|
|
986
|
-
},
|
|
987
|
-
{
|
|
988
|
-
"name": "Reader<N>::advance_offset",
|
|
989
|
-
"start": 1362
|
|
990
|
-
},
|
|
991
|
-
{
|
|
992
|
-
"name": "Reader<N>::finish",
|
|
993
|
-
"start": 1426
|
|
994
|
-
}
|
|
995
|
-
],
|
|
996
|
-
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-protocol-circuits/crates/serde/src/reader.nr",
|
|
997
|
-
"source": "pub struct Reader<let N: u32> {\n data: [Field; N],\n offset: u32,\n}\n\nimpl<let N: u32> Reader<N> {\n pub fn new(data: [Field; N]) -> Self {\n Self { data, offset: 0 }\n }\n\n pub fn read(&mut self) -> Field {\n let result = self.data[self.offset];\n self.offset += 1;\n result\n }\n\n pub fn read_u32(&mut self) -> u32 {\n self.read() as u32\n }\n\n pub fn read_u64(&mut self) -> u64 {\n self.read() as u64\n }\n\n pub fn read_bool(&mut self) -> bool {\n self.read() != 0\n }\n\n pub fn read_array<let K: u32>(&mut self) -> [Field; K] {\n let mut result = [0; K];\n for i in 0..K {\n result[i] = self.data[self.offset + i];\n }\n self.offset += K;\n result\n }\n\n pub fn read_struct<T, let K: u32>(&mut self, deserialise: fn([Field; K]) -> T) -> T {\n let result = deserialise(self.read_array());\n result\n }\n\n pub fn read_struct_array<T, let K: u32, let C: u32>(\n &mut self,\n deserialise: fn([Field; K]) -> T,\n mut result: [T; C],\n ) -> [T; C] {\n for i in 0..C {\n result[i] = self.read_struct(deserialise);\n }\n result\n }\n\n pub fn peek_offset(&mut self, offset: u32) -> Field {\n self.data[self.offset + offset]\n }\n\n pub fn advance_offset(&mut self, offset: u32) {\n self.offset += offset;\n }\n\n pub fn finish(self) {\n assert_eq(self.offset, self.data.len(), \"Reader did not read all data\");\n }\n}\n"
|
|
998
|
-
},
|
|
999
887
|
"41": {
|
|
1000
888
|
"function_locations": [
|
|
1001
889
|
{
|
|
@@ -1094,7 +982,57 @@
|
|
|
1094
982
|
"path": "std/option.nr",
|
|
1095
983
|
"source": "use crate::cmp::{Eq, Ord, Ordering};\nuse crate::default::Default;\nuse crate::hash::{Hash, Hasher};\n\n/// Represents a value of type T or its absence.\n/// Use `Option::some(value)` to construct a value or `Option::none()` to record the absence of one.\npub struct Option<T> {\n _is_some: bool,\n _value: T,\n}\n\nimpl<T> Option<T> {\n /// Constructs a None value\n pub fn none() -> Self {\n Self { _is_some: false, _value: crate::mem::zeroed() }\n }\n\n /// Constructs a Some wrapper around the given value\n pub fn some(_value: T) -> Self {\n Self { _is_some: true, _value }\n }\n\n /// True if this Option is None\n pub fn is_none(&self) -> bool {\n !self._is_some\n }\n\n /// True if this Option is Some\n pub fn is_some(&self) -> bool {\n self._is_some\n }\n\n /// Asserts `self.is_some()` and returns the wrapped value.\n pub fn unwrap(self) -> T {\n assert(self._is_some);\n self._value\n }\n\n /// Returns the inner value without asserting `self.is_some()`\n /// Note that if `self` is `None`, there is no guarantee what value will be returned,\n /// only that it will be of type `T`.\n pub fn unwrap_unchecked(self) -> T {\n self._value\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value.\n pub fn unwrap_or(self, default: T) -> T {\n if self._is_some {\n self._value\n } else {\n default\n }\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return\n /// a default value.\n pub fn unwrap_or_else<Env>(self, default: fn[Env]() -> T) -> T {\n if self._is_some {\n self._value\n } else {\n default()\n }\n }\n\n /// Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value\n pub fn expect<let N: u32, MessageTypes>(self, message: fmtstr<N, MessageTypes>) -> T {\n assert(self.is_some(), message);\n self._value\n }\n\n /// If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`.\n pub fn map<U, Env>(self, f: fn[Env](T) -> U) -> Option<U> {\n if self._is_some {\n Option::some(f(self._value))\n } else {\n Option::none()\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value.\n pub fn map_or<U, Env>(self, default: U, f: fn[Env](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`.\n pub fn map_or_else<U, Env1, Env2>(self, default: fn[Env1]() -> U, f: fn[Env2](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default()\n }\n }\n\n /// Returns None if self is None. Otherwise, this returns `other`.\n pub fn and(self, other: Self) -> Self {\n if self.is_none() {\n Option::none()\n } else {\n other\n }\n }\n\n /// If self is None, this returns None. Otherwise, this calls the given function\n /// with the Some value contained within self, and returns the result of that call.\n ///\n /// In some languages this function is called `flat_map` or `bind`.\n pub fn and_then<U, Env>(self, f: fn[Env](T) -> Option<U>) -> Option<U> {\n if self._is_some {\n f(self._value)\n } else {\n Option::none()\n }\n }\n\n /// If self is Some, return self. Otherwise, return `other`.\n pub fn or(self, other: Self) -> Self {\n if self._is_some {\n self\n } else {\n other\n }\n }\n\n /// If self is Some, return self. Otherwise, return `default()`.\n pub fn or_else<Env>(self, default: fn[Env]() -> Self) -> Self {\n if self._is_some {\n self\n } else {\n default()\n }\n }\n\n // If only one of the two Options is Some, return that option.\n // Otherwise, if both options are Some or both are None, None is returned.\n pub fn xor(self, other: Self) -> Self {\n if self._is_some {\n if other._is_some {\n Option::none()\n } else {\n self\n }\n } else if other._is_some {\n other\n } else {\n Option::none()\n }\n }\n\n /// Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true.\n /// Otherwise, this returns `None`\n pub fn filter<Env>(self, predicate: fn[Env](T) -> bool) -> Self {\n if self._is_some {\n if predicate(self._value) {\n self\n } else {\n Option::none()\n }\n } else {\n Option::none()\n }\n }\n\n /// Flattens an Option<Option<T>> into a Option<T>.\n /// This returns None if the outer Option is None. Otherwise, this returns the inner Option.\n pub fn flatten(option: Option<Option<T>>) -> Option<T> {\n if option._is_some {\n option._value\n } else {\n Option::none()\n }\n }\n}\n\nimpl<T> Default for Option<T> {\n fn default() -> Self {\n Option::none()\n }\n}\n\nimpl<T> Eq for Option<T>\nwhere\n T: Eq,\n{\n fn eq(self, other: Self) -> bool {\n if self._is_some == other._is_some {\n if self._is_some {\n self._value == other._value\n } else {\n true\n }\n } else {\n false\n }\n }\n}\n\nimpl<T> Hash for Option<T>\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self._is_some.hash(state);\n if self._is_some {\n self._value.hash(state);\n }\n }\n}\n\n// For this impl we're declaring Option::none < Option::some\nimpl<T> Ord for Option<T>\nwhere\n T: Ord,\n{\n fn cmp(self, other: Self) -> Ordering {\n if self._is_some {\n if other._is_some {\n self._value.cmp(other._value)\n } else {\n Ordering::greater()\n }\n } else if other._is_some {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n"
|
|
1096
984
|
},
|
|
1097
|
-
"
|
|
985
|
+
"411": {
|
|
986
|
+
"function_locations": [
|
|
987
|
+
{
|
|
988
|
+
"name": "Reader<N>::new",
|
|
989
|
+
"start": 144
|
|
990
|
+
},
|
|
991
|
+
{
|
|
992
|
+
"name": "Reader<N>::read",
|
|
993
|
+
"start": 222
|
|
994
|
+
},
|
|
995
|
+
{
|
|
996
|
+
"name": "Reader<N>::read_u32",
|
|
997
|
+
"start": 355
|
|
998
|
+
},
|
|
999
|
+
{
|
|
1000
|
+
"name": "Reader<N>::read_u64",
|
|
1001
|
+
"start": 429
|
|
1002
|
+
},
|
|
1003
|
+
{
|
|
1004
|
+
"name": "Reader<N>::read_bool",
|
|
1005
|
+
"start": 505
|
|
1006
|
+
},
|
|
1007
|
+
{
|
|
1008
|
+
"name": "Reader<N>::read_array",
|
|
1009
|
+
"start": 598
|
|
1010
|
+
},
|
|
1011
|
+
{
|
|
1012
|
+
"name": "Reader<N>::read_struct",
|
|
1013
|
+
"start": 855
|
|
1014
|
+
},
|
|
1015
|
+
{
|
|
1016
|
+
"name": "Reader<N>::read_struct_array",
|
|
1017
|
+
"start": 1094
|
|
1018
|
+
},
|
|
1019
|
+
{
|
|
1020
|
+
"name": "Reader<N>::peek_offset",
|
|
1021
|
+
"start": 1263
|
|
1022
|
+
},
|
|
1023
|
+
{
|
|
1024
|
+
"name": "Reader<N>::advance_offset",
|
|
1025
|
+
"start": 1362
|
|
1026
|
+
},
|
|
1027
|
+
{
|
|
1028
|
+
"name": "Reader<N>::finish",
|
|
1029
|
+
"start": 1426
|
|
1030
|
+
}
|
|
1031
|
+
],
|
|
1032
|
+
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-protocol-circuits/crates/serde/src/reader.nr",
|
|
1033
|
+
"source": "pub struct Reader<let N: u32> {\n data: [Field; N],\n offset: u32,\n}\n\nimpl<let N: u32> Reader<N> {\n pub fn new(data: [Field; N]) -> Self {\n Self { data, offset: 0 }\n }\n\n pub fn read(&mut self) -> Field {\n let result = self.data[self.offset];\n self.offset += 1;\n result\n }\n\n pub fn read_u32(&mut self) -> u32 {\n self.read() as u32\n }\n\n pub fn read_u64(&mut self) -> u64 {\n self.read() as u64\n }\n\n pub fn read_bool(&mut self) -> bool {\n self.read() != 0\n }\n\n pub fn read_array<let K: u32>(&mut self) -> [Field; K] {\n let mut result = [0; K];\n for i in 0..K {\n result[i] = self.data[self.offset + i];\n }\n self.offset += K;\n result\n }\n\n pub fn read_struct<T, let K: u32>(&mut self, deserialise: fn([Field; K]) -> T) -> T {\n let result = deserialise(self.read_array());\n result\n }\n\n pub fn read_struct_array<T, let K: u32, let C: u32>(\n &mut self,\n deserialise: fn([Field; K]) -> T,\n mut result: [T; C],\n ) -> [T; C] {\n for i in 0..C {\n result[i] = self.read_struct(deserialise);\n }\n result\n }\n\n pub fn peek_offset(&mut self, offset: u32) -> Field {\n self.data[self.offset + offset]\n }\n\n pub fn advance_offset(&mut self, offset: u32) {\n self.offset += offset;\n }\n\n pub fn finish(self) {\n assert_eq(self.offset, self.data.len(), \"Reader did not read all data\");\n }\n}\n"
|
|
1034
|
+
},
|
|
1035
|
+
"412": {
|
|
1098
1036
|
"function_locations": [
|
|
1099
1037
|
{
|
|
1100
1038
|
"name": "derive_serialize",
|
|
@@ -1120,7 +1058,7 @@
|
|
|
1120
1058
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-protocol-circuits/crates/serde/src/serialization.nr",
|
|
1121
1059
|
"source": "use crate::{reader::Reader, writer::Writer};\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\n // We care only about the name and type so we drop the last item of the tuple\n let params = nested_struct.0.fields(nested_struct.1).map(|(name, typ, _)| (name, typ));\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(|(name, _typ): (Quoted, Type)| {\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.0.fields(nested_struct.1);\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(|(_, param_type, _): (Quoted, Type, Quoted)| {\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(|(param_name, param_type, _): (Quoted, Type, Quoted)| {\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(|(param_name, _, _): (Quoted, Type, Quoted)| quote { $param_name })\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].0;\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` - An array of tuples where each tuple contains a quoted parameter name and its Type. The type needs\n/// 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: [(Quoted, Type)]) -> Quoted {\n if params.len() == 0 {\n quote { 0 }\n } else {\n let params_quote_without_parentheses = params\n .map(|(_, param_type): (Quoted, Type)| {\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(|(name, maybe_integer_typ)| {\n // The second item in the generics tuple is an Option of an integer type that is Some only if\n // 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 // The second item in the generics tuple is an Option of an integer type that is Some only if the generic is\n // numeric.\n let non_numeric_generics =\n generics.filter(|(_, maybe_integer_typ)| maybe_integer_typ.is_none());\n\n if non_numeric_generics.len() > 0 {\n let non_numeric_generics_declarations =\n non_numeric_generics.map(|(name, _)| quote {$name: $trait_name}).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"
|
|
1122
1060
|
},
|
|
1123
|
-
"
|
|
1061
|
+
"414": {
|
|
1124
1062
|
"function_locations": [
|
|
1125
1063
|
{
|
|
1126
1064
|
"name": "<impl Serialize for bool>::serialize",
|
|
@@ -1434,7 +1372,7 @@
|
|
|
1434
1372
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-protocol-circuits/crates/serde/src/type_impls.nr",
|
|
1435
1373
|
"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"
|
|
1436
1374
|
},
|
|
1437
|
-
"
|
|
1375
|
+
"415": {
|
|
1438
1376
|
"function_locations": [
|
|
1439
1377
|
{
|
|
1440
1378
|
"name": "Writer<N>::new",
|
|
@@ -1484,27 +1422,27 @@
|
|
|
1484
1422
|
"function_locations": [
|
|
1485
1423
|
{
|
|
1486
1424
|
"name": "SimulatedSchnorrAccount::constructor",
|
|
1487
|
-
"start":
|
|
1425
|
+
"start": 1388
|
|
1488
1426
|
},
|
|
1489
1427
|
{
|
|
1490
1428
|
"name": "SimulatedSchnorrAccount::entrypoint",
|
|
1491
|
-
"start":
|
|
1429
|
+
"start": 2774
|
|
1492
1430
|
},
|
|
1493
1431
|
{
|
|
1494
1432
|
"name": "SimulatedSchnorrAccount::verify_private_authwit",
|
|
1495
|
-
"start":
|
|
1433
|
+
"start": 3027
|
|
1496
1434
|
},
|
|
1497
1435
|
{
|
|
1498
1436
|
"name": "SimulatedSchnorrAccount::is_valid_impl",
|
|
1499
|
-
"start":
|
|
1437
|
+
"start": 3173
|
|
1500
1438
|
},
|
|
1501
1439
|
{
|
|
1502
1440
|
"name": "SimulatedSchnorrAccount::sync_state",
|
|
1503
|
-
"start":
|
|
1441
|
+
"start": 3256
|
|
1504
1442
|
}
|
|
1505
1443
|
],
|
|
1506
1444
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/account/simulated_schnorr_account_contract/src/main.nr",
|
|
1507
|
-
"source": "use aztec::macros::aztec;\n\n// Stub account contract for Schnorr accounts used during simulation.\n// Matches the constructor signature of SchnorrAccount so that deployment\n// simulations using this stub as an override do not fail on selector lookup.\n// See simulated_account_contract for the base stub without a constructor.\n#[aztec]\npub contract SimulatedSchnorrAccount {\n use aztec::{\n authwit::{account::AccountActions, auth::IS_VALID_SELECTOR, entrypoint::app::AppPayload},\n context::PrivateContext,\n macros::functions::{allow_phase_change, external, view},\n messages::encoding::MESSAGE_CIPHERTEXT_LEN,\n oracle::
|
|
1445
|
+
"source": "use aztec::macros::aztec;\n\n// Stub account contract for Schnorr accounts used during simulation.\n// Matches the constructor signature of SchnorrAccount so that deployment\n// simulations using this stub as an override do not fail on selector lookup.\n// See simulated_account_contract for the base stub without a constructor.\n#[aztec]\npub contract SimulatedSchnorrAccount {\n use aztec::{\n authwit::{account::AccountActions, auth::IS_VALID_SELECTOR, entrypoint::app::AppPayload},\n context::PrivateContext,\n macros::functions::{allow_phase_change, external, view},\n messages::encoding::MESSAGE_CIPHERTEXT_LEN,\n oracle::random::random,\n };\n\n // Stub constructor matching the SchnorrAccount constructor signature.\n // Does NOT use #[initializer] so that the macro does not inject\n // assert_initialization_matches_address_preimage_private, which would fail during kernelless\n // simulation because the stub instance has a different initialization hash than the real account.\n // Emits the same shape of side effects as the real constructor (one nullifier for\n // SinglePrivateImmutable initialization, one note hash for the key note, and one private\n // log tied to that note hash) so that gas estimation produces accurate results.\n #[external(\"private\")]\n fn constructor(_signing_pub_key_x: Field, _signing_pub_key_y: Field) {\n // Safety: Random seeds are only used to produce dummy side effects that match the shape of\n // the real SchnorrAccount constructor. The values are never constrained or used for any\n // security purpose.\n let seed = unsafe { random() };\n\n // Emit the initialization nullifier for the signing_public_key SinglePrivateImmutable.\n self.context.push_nullifier(seed);\n\n // Emit the note hash for the signing key note.\n self.context.push_note_hash(seed + 1);\n\n // Emit a private log tied to the note hash, matching the length of a real note delivery\n // log (MESSAGE_CIPHERTEXT_LEN fields). The signing key note is a SinglePrivateImmutable\n // and is therefore never nullified, so in practice the log will never be squashed. We\n // pass the note hash counter anyway for correctness.\n let dummy_log: [Field; MESSAGE_CIPHERTEXT_LEN] = [seed + 2; MESSAGE_CIPHERTEXT_LEN];\n self.context.emit_raw_note_log_vec_unsafe(\n seed + 3,\n BoundedVec::from_array(dummy_log),\n self.context.side_effect_counter,\n );\n }\n\n // @dev: If you globally change the entrypoint signature don't forget to update account_entrypoint.ts\n #[external(\"private\")]\n #[allow_phase_change]\n fn entrypoint(app_payload: AppPayload, fee_payment_method: u8, cancellable: bool) {\n let actions = AccountActions::init(self.context, is_valid_impl);\n actions.entrypoint(app_payload, fee_payment_method, cancellable);\n }\n\n #[external(\"private\")]\n #[view]\n fn verify_private_authwit(inner_hash: Field) -> Field {\n IS_VALID_SELECTOR\n }\n\n #[contract_library_method]\n fn is_valid_impl(_context: &mut PrivateContext, _outer_hash: Field) -> bool {\n true\n }\n\n #[external(\"utility\")]\n unconstrained fn sync_state() {\n assert(\n false,\n \"BUG ALERT: sync_state on a simulated account contract should never be triggered.\",\n );\n }\n}\n"
|
|
1508
1446
|
},
|
|
1509
1447
|
"51": {
|
|
1510
1448
|
"function_locations": [
|
|
@@ -1528,15 +1466,15 @@
|
|
|
1528
1466
|
"function_locations": [
|
|
1529
1467
|
{
|
|
1530
1468
|
"name": "<impl Hash for AppPayload>::hash",
|
|
1531
|
-
"start":
|
|
1469
|
+
"start": 956
|
|
1532
1470
|
},
|
|
1533
1471
|
{
|
|
1534
1472
|
"name": "AppPayload::execute_calls",
|
|
1535
|
-
"start":
|
|
1473
|
+
"start": 1175
|
|
1536
1474
|
}
|
|
1537
1475
|
],
|
|
1538
1476
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/aztec-nr/aztec/src/authwit/entrypoint/app.nr",
|
|
1539
|
-
"source": "use crate::{authwit::entrypoint::FunctionCall, context::PrivateContext};\nuse crate::protocol::{\n constants::DOM_SEP__SIGNATURE_PAYLOAD,\n hash::poseidon2_hash_with_separator,\n traits::{Hash, Serialize},\n};\nuse std::meta::derive;\n\nglobal ACCOUNT_MAX_CALLS: u32 = 5;\n\n// @dev: If you change the following struct you have to update:\n// - default_entrypoint.ts\n// - account_entrypoint.ts (specifically `getEntrypointAbi()`)\n// - default_multi_call_entrypoint.ts (specifically `getEntrypointAbi()`)\n#[derive(Serialize)]\npub struct AppPayload {\n function_calls: [FunctionCall; ACCOUNT_MAX_CALLS],\n // A nonce that enables transaction cancellation. When the cancellable flag is enabled, this nonce is used to\n // compute a nullifier that is then emitted. This guarantees that we can cancel the transaction by using the same\n // nonce.\n pub tx_nonce: Field,\n}\n\nimpl Hash for AppPayload {\n fn hash(self) -> Field {\n poseidon2_hash_with_separator(self.serialize(), DOM_SEP__SIGNATURE_PAYLOAD)\n }\n}\n\nimpl AppPayload {\n // Executes all private and public calls\n pub fn execute_calls(self, context: &mut PrivateContext) {\n for call in self.function_calls {\n if !call.target_address.is_zero() {\n if call.is_public {\n context.call_public_function_with_calldata_hash(\n call.target_address,\n call.args_hash,\n call.is_static,\n call.hide_msg_sender,\n );\n } else {\n assert(\n !call.hide_msg_sender,\n \"Incompatible flag. `hide_msg_sender = true` is only available for public calls.\",\n );\n let _result = context.call_private_function_with_args_hash(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n );\n }\n }\n }\n }\n}\n"
|
|
1477
|
+
"source": "use crate::{authwit::entrypoint::FunctionCall, context::PrivateContext};\nuse crate::protocol::{\n constants::DOM_SEP__SIGNATURE_PAYLOAD,\n hash::poseidon2_hash_with_separator,\n traits::{Deserialize, Hash, Serialize},\n};\nuse std::meta::derive;\n\nglobal ACCOUNT_MAX_CALLS: u32 = 5;\n\n// @dev: If you change the following struct you have to update:\n// - default_entrypoint.ts\n// - account_entrypoint.ts (specifically `getEntrypointAbi()`)\n// - default_multi_call_entrypoint.ts (specifically `getEntrypointAbi()`)\n#[derive(Deserialize, Serialize)]\npub struct AppPayload {\n function_calls: [FunctionCall; ACCOUNT_MAX_CALLS],\n // A nonce that enables transaction cancellation. When the cancellable flag is enabled, this nonce is used to\n // compute a nullifier that is then emitted. This guarantees that we can cancel the transaction by using the same\n // nonce.\n pub tx_nonce: Field,\n}\n\nimpl Hash for AppPayload {\n fn hash(self) -> Field {\n poseidon2_hash_with_separator(self.serialize(), DOM_SEP__SIGNATURE_PAYLOAD)\n }\n}\n\nimpl AppPayload {\n // Executes all private and public calls\n pub fn execute_calls(self, context: &mut PrivateContext) {\n for call in self.function_calls {\n if !call.target_address.is_zero() {\n if call.is_public {\n context.call_public_function_with_calldata_hash(\n call.target_address,\n call.args_hash,\n call.is_static,\n call.hide_msg_sender,\n );\n } else {\n assert(\n !call.hide_msg_sender,\n \"Incompatible flag. `hide_msg_sender = true` is only available for public calls.\",\n );\n let _result = context.call_private_function_with_args_hash(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n );\n }\n }\n }\n }\n}\n"
|
|
1540
1478
|
},
|
|
1541
1479
|
"59": {
|
|
1542
1480
|
"function_locations": [
|
|
@@ -4143,14 +4081,14 @@
|
|
|
4143
4081
|
"visibility": "databus"
|
|
4144
4082
|
}
|
|
4145
4083
|
},
|
|
4146
|
-
"bytecode": "H4sIAAAAAAAA/+2dZ3xVxd6F81+DDaQIiF1DUcFKsRcEQlBUEMGCIMaQHOBISOLJCYKV2Lsp9CYdBOwNe++z7A3Fgr2Lveu7AQntauaErBd/3nu/3Nw4+1mzZ8/Mnj0Tn+vKy8YsbJqVlX16MpaTlZ/
|
|
4084
|
+
"bytecode": "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",
|
|
4147
4085
|
"custom_attributes": [
|
|
4148
4086
|
"abi_private"
|
|
4149
4087
|
],
|
|
4150
|
-
"debug_symbols": "
|
|
4088
|
+
"debug_symbols": "tZfbbuMgEIbfxde9gDnAkFdZrSo39VaRrCRyk0qrqu++QzrYTiSj1N3e5Ac7fB5mhgHem+fu6fzyuNv/Obw2m1/vzdOw6/vdy2N/2Lan3WGvT98bl388NRv6eGj8pYPNBrUDl44+8trB0oEP7RXC42nouvxmhtQPHduh25+azf7c9w/NW9ufL396Pbb7i57aQd+6h6bbP6sq8M+u73Lr42Ea7ZaHUiQbTBLH4T7FewHf+HZIaIMjpXE4uLsBnl0wgmeZI/y9iJgCG0Ic4OQBz1cIrliBEosVBKusAAwFAeRh0YpYQfggBQEwhVKujZBlQkJXXJGQJiOQr5MhVRCOSkiTS24R4Su+wBGBIpMzg1wTfIXgfPEmOuB1DO9KZqPHCgMra8vHwiBws9X1BTMClQzHwLRuKiG/NcYsxW8ZtfwkojE/kyzmp68kqNdQlAzVdpomE+IXIDSuV+8Y/BKkMhkGLunBMKsat5OBmkME47hihSAs2VGHRIAREmfZfv9kfBgj4wNPi5bvL6IxlPTwcxtuCEAVREJIhZE0Zxe9USmjLCU7AobZTkRfMIPG1aLtgItmVDJMgKQUoNymNUERGd0hKa4JikxBkeWgYBXh02SFbg9LE0H/s94A9KUMalNWeAPIybQ9hjUEZBxtmJWeW3/W8pMjlnlom+KiP8PP+pO1Ao92oFusXyj/oX7VIdPpEYQB10F42lskuNWW4AwS10G+X46Zpr2FcfkgVzuRhlh2uBhmqXpB/NZuu90N1zcPz2qj3jlCPoGqRlMxTbkC6DXEmeabiJYGAFPMx0dVMuV8hlQNptFUbHzKq0hvMi4fIlTzZUafI5jma4/+H8lUeahuwWCqPNTvopgqj9Qj5Ey9KZhiPkupkimbBtOYD1iq8smn9KnsTDNP7WUwRVMyNfvY7ONoajzO9uVAvLXDrn3qu+z0HJfzfltioN3T32N5U+6Hx+Gw7Z7PQ5fjdXmnEfwH",
|
|
4151
4089
|
"is_unconstrained": false,
|
|
4152
4090
|
"name": "constructor",
|
|
4153
|
-
"verification_key": "
|
|
4091
|
+
"verification_key": "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"
|
|
4154
4092
|
},
|
|
4155
4093
|
{
|
|
4156
4094
|
"abi": {
|
|
@@ -6033,14 +5971,14 @@
|
|
|
6033
5971
|
"visibility": "databus"
|
|
6034
5972
|
}
|
|
6035
5973
|
},
|
|
6036
|
-
"bytecode": "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",
|
|
5974
|
+
"bytecode": "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",
|
|
6037
5975
|
"custom_attributes": [
|
|
6038
5976
|
"abi_private"
|
|
6039
5977
|
],
|
|
6040
|
-
"debug_symbols": "tZ3RbizGcW3/Rc96mK6qXd2dX7kIDMdxAgGCHTh2gIvA/3455NTaR8YlI0vOi6aPLXXNIWdt8vDUrP3f3/3r7//lL//+mx/+8G9//M/v/un//Pd3//KnH3788Yd//82Pf/zdb//8wx//8Pa//vd3j+c/Vn33Tyv/+v136/1Xb/9cb7+I5y/O2z9XfP/dyddjvR71fHz7t/LjP9kf//NaZw73dYjH69+s93/zed/zdjHq8farfv7q+W/m29z18RAfD/nxUB8P+nh4+/f77WF/PJyPh7eJ++0JPT4e1sfD2y337SE/Ht5uuW/j9gyPv779aj4gv/nzn37/++f/881H6O3j9h+//dPv//Dn7/7pD3/58cfvv/uv3/74l/d/6T//47d/eH/882//9Pb/Pr7/7vd/+Ne3x7cL/+2HH3//PP31e//Xj8//07P3ef3X58TignXXz73iV0zvZPijPHvrZz/9k3PBPZ9eUJ9fkK3XBbn9DOpxf3KBPr8gai6I3p9e8POewclPL/jiY3BjLrjZn34Mzq/9LXz1aVS/LtiP/c1LqH72pzHFi/DxzQXn514QoZrfQ5zLFan9c69YeszvYumbK9b92R+Hfflcnkf4k7nWTz8X64uXw8qz52lU/KKnEbGSD8Y3r+rnK/wnT6M/v6PicV93VOxvXhXrp3Cv/cUre+flpf04n9/xxWvzNs/j9upv7ohfdkfmp3fE49f/XmL9A+6IL+6I5o448fnv5YvncXNeYVePzz+i/RUrXLGk8/mz+CI4116D7Nqxf9Hz2D1ffPZZnz+L/Ws/Fl/Blj03RK34lPm4X9yx+gDsNx+K89OvwfnVF4F8+KtAxTcB+NOnkV+9Lh41uXEf9/H5HV+9Prkij18X0f3TG/KLGx5rPqD5CP2yO9ZjXhi58os7vnh91toPEvDbL2vn7/itBLA+1L/st9I1X5bevlOoX3iHDnf0L/y09Frc8c3Xtr/rjgvyeet+eket/91Py938Vu7+/Gl8RX0V32/Ut995/g319dVX+rdX93xa3s7Xn9vef8clxfcc66FvvoPvn/2dzxtxQPt2HTfoZ38f/wZZwNs3Ofo3N9T56kk87v8Pe/00A+uLGL314COxvrnhp58S/QNSVP+AFNWvTlH9A3D98lOy+I441zffl//tp+SrK3Lzp5v65o94f3OFvvgaH/tevjq+fdukz17h2r/+zwdffzguv5eIz38vX32hPw/lN7+XT2n98pKf+wHpr2LUX5rePi9+pd+/ueKLF+nbS4JvAk/p049pf/EyjccZZuPtpzW/7PMScP/23XF89nlpff1K53P7du5PP6RfXrKOv+tYn39yv74k1/G3Lr/4mVznce7z6SX31yPz1R0/81W2169/le349a+y/+ETc/yJKX36Md1ffLX2dw1196c/5/j6xc6PBzL700z+Kgt/7idl/wM+Ked/Gf0KvkKV1mcfjfPVj338g44V3/z87G++Wp8vXqInCPUT33x7/RZMf8fTuHxEs+rTp/FFlu4MouPtnJ9+XTj11e+l/CPVt/On35T+D8+En1LszNAvu+TtBe5Lvvn+428v+eq1zkdV3/z5629/Mvn102hy8O38xQfkixzsE/M83m5wlvbPf300fypebz81//T18fgS2jK0n15x48sf9ALt258p76dfnb68pE/O96Zv58+T9MtL6ip4Jo/H+UWflr3nFdb75mefli8/sfz1ydvxs0/s1x/Sy2f27VyffzTOr/2NfHnDz3qFfn3Dz/lQfJnmCn480I9Pv7a9/Vn51/8Jbj3y1/8Rbj3q1/4Zbj3063/28z9c8vP+JPj1JT/zJzfrcX71j27+hyfy83528+XrrP2b6fr0u4a1vvq29CbfRb2d+9MvC2t98WoV31L2t391d+PveSLFi+Tt3Pn5E/lHfNn/6m+/mj/r7/7mp1nvPxP757df/vZ3P/zppxsA+fyr+7f/KM/zU/H2eD8e6/F6XK/HeD3m67Fej3o99utxvx5f99XrPr3u0+s+ve7T6z697tPrPr3u0+s+ve7T675+3dev+/p1X7/u69d9/bqvX/f1675+3dev+/brvv26b7/u26/79uu+/bpvv+7br/v26779uu+87jvridr375sU9dqkeP5l73OT4v3x7b7nq+f06/Htvnr7OnDO89uCt8f78Xgfr8f1/Mr79hjPL91vj/l6rOcL5e1Rr8d+frP09vh23/NFcc/zNfH2eD8e3348P4fnqsR9HuL5ynsecg41h7dbj56HnsOew5nDfR3WYw7r+bfJz8Pznues9Xp2a73dc9f3H6sjH4fz/HrxWh15PzwXQm49D2sO8br5uRbycZhn+FwN+Tj0HOYZxjzDmGeY8wyfayIfh7n5uSry/pxTz7+rfB56DnsO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vMPgHQbvMHiHwTsM3mHwDoN3GLzD4B0G7zB4h8E7DN5h8A6Ddxi8w+AdBu8weIfBOwzeYfAOg3cYvMPgHQbvMHiHwTsM3mHwDoN3GLzD4B0G7zB4h8E7DN5h8A6Ddxi8w+AdBu8weIfB+87geh40h+fN73+jvefwvPk+D/d1eGfw/bDmEHN4Kgye70m77xKDj5M4NafN6XC6c3qi+DotTsGJGZcZlxmXGZcZlxl3Zrz94+Hj8jF8TB/LR/nYPm4fj4+etjxtedrytOVpy9OWpy1PW562PG15WnhaeFp4WnhaeFp4WnhaeFp4Wnhaelp6Wnpaelp6Wnpaelp6Wnpaelp5WnlaeVp5WnlaeVp5WnlaeVp5mjxNniZPk6fJ0+Rp8jR5mjxNntae1p7Wntae1p7Wntae1p7Wntaetj1te9r2tO1p29O2p21P2562PW172vG042nH046nHU87nnY87Xja8bTjadfTrqddT7uedj3tetr1tOtp19OcJctZspwly1mynCXLWbKcJctZspwly1mynCXLWbKcJctZspwly1mynCXLWbKcJctZspwly1mynCXLWbKcJctZspwly1mynCXLWbKcJctZspwly1mynCXLWbKcJctZspwly1mynCXLWbKcJctZspwly1mynCXLWbKcJctZspwly1mynCXLWbKcJctZspwly1mynCXLWbKcJctZspwly1mynCXLWbKcJctZspwly1mynCXLWbKcJctZspwly1mynCXLWbKcJctZspwly1mynCXLWbKcJctZspwly1mynCXLWbKcJctZspwly1mynCXLWbKcJctZspwly1mynCXhLAlnSThLwlkSzpJwloSzJJwl4SwJZ0k4S8JZEs6ScJaEsyScJeEsCWdJOEvCWRLOknCWhLMknCXhLAlnSThLwlkSzpJwloSzJJwl4SwJZ0k4S8JZEs6ScJaEsyScJeEsCWdJOEvCWRLOknCWhLMknCXhLAlnSThLwlkSzpJwloSzJJwl4SwJZ0k4S8JZEs6ScJaEsyScJeEsCWdJOEvCWRLOknCWhLMknCXhLAlnSThLwlkSzpJwloSzJJwl4SwJZ0k4S8JZEs6ScJaEsyScJeEsCWdJOEvCWRLOknCWhLMknCXhLAlnSThLwlmSzpJ0lqSzJJ0l6SxJZ0k6S9JZks6SdJaksySdJeksSWdJ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cQkmLsHEJZi4BBOXYOISTFyCiUswcQkmLsHEJZi4BBOXYOISTFyCiUswcQkmLsHEJZi4BBOXYOISTFyCiUswcQkmLsHEJZi4BBOXYOISTFyCiUswcQkmLsHEJZi4BBOXYOISTFyCiUswcQkmLsHEJZi4BBOXYOISTFyCiUswcQkmLsHEJZi4BBOXYOISTFyCiUswcQkmLsHEJZi4BBOXYOISTFyCiUswcQkmLsHEJZi4BBOXYOISTFyCiUswcQkmLsHEJZi4BBOXYOISTFyCiUswcQkmLsHEJZi4BBOXYOISTFyCiUswcQkmLsHEJZi4BBOXYOISTFyCiUswcQkmLsHEJZi4BBOXYOISTFyCiUswcQkmLsHEJZi4BBOXYOISTFyCiUswcQkmLsHEJZi4BBOXYOISTFyCiUswcQkmLsHEJZi4BBOXYOISTFyCiUswcQkmLsHEJZi4BBOXYOISTFyCiUswcQkmLsHEJZi4BBOXYOISTFyCiUswcQkmLsHEJZi4BBOXYOISTFyCiUswcQkmLsHEJZi4BBOXYOISTFyCiUswcQkmLsHEJZi4BBOXYOISTFyCiUswcQkmLsHEJZi4BBOXYOISLFyChUuwcAkWLsHCJVi4BAuXYOESLFyChUuwcAkWLsHCJVi4BAuXYOESLFyChUuwcAkWLsHCJVi4BAuXYOESLFyChUuwcAkWLsHCJVi4BAuXYOESLFyChUuwcAkWLsHCJVi4BAuXYOESLFyChUuwcAkWLsHCJVi4BAuXYOESLFyChUuwcAkWLsHCJVi4BAuXYOESLFyChUuwcAkWLsHCJVi4BAuXYOESLFyChUuwcAkWLsHCJVi4BAuXYOESLFyChUuwcAkWLsHCJVi4BAuXYOESLFyChUuwcAkWLsHCJVi4BAuXYOESLFyChUuwcAkWLsHCJVi4BAuXYOESLFyChUuwcAkWLsFacI5LsHAJFi7BwiVYuAQLl2DhEixcgoVLsHAJFi7BwiVYuAQLl2DhEixcgoVLsHAJFi7BwiVYuAQLl2DhEixcgoVLsHAJFi7BwiVYuAQLl2DhEixcgoVLsHAJFi7BwiVYuAQLl2DhEixcgoVLsHAJFi7BwiVYuAQLl2DhEixcgoVLsHAJFi7BwiVYuAQLl2DhEixcgoVLsHAJFi7BwiVYuAQLl2DhEixcgoVLsHAJFi7BwiVY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0cMsephFD7PoYRY9zKKHWfQwix5m0cMsephFD7PoYRY9zKKHWfQwix5m0cMsephFD7PoYRY9zKKHWfQwix5m0cMsephFD7PoYRY9zKKHWfQwix5m0cMsephFD7PoYRY9zKKHWfQwix5m0cMsephFD7PoYRY9zKKHWfQwix5m0cMsephFD7PoYRY9zKKHWfQwix5m0cMsephFD7PoYRY9zKKHWfQwix5m0cMsephFD7PoYRY9zKKHWfQwix5m0cMsephFD7PoYRY9zKKHWfQwix5m0cMsephFD7PoYRY9zKKHWfQwix5m0cMsephFD7PoYRY9zKKHWfQwix5m0cMsephFD7PoYRY9zKKHWfQwix5m0cMsephFD7PoYRY9zKKHWfQwix5m0cMsephFD7PoYRY9zKKHWfQwix5m0cMsephFD7PoYRY9zKKHWfQwix5m0cMsephFD7PoYRY9zKKHWfQwix5m0cMsephFD7PoYRY9zKKHWfQwix5m0cMsephFD7PoYRY9zKKHWfQwix5m0cMsephFD7PoYRY9zKKHWfQwix5m0cMsephFD7NwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegcAkKl6BwCQqXoHAJCpegPlyC+/20OAWn54z1fipOzxn5fmpOzxn3/XQ43Tm9c/5xWpyCU3Ka/Vq5Q1juEJY7hOUOYblDWO4QljuE5Q5huUNY7hCWO4TlDmG5Q1juEJY7hOUOYblDWO4QljuE5Q5huUNY7hCWO4TlDmG5Q1juEJY7hOUOYblDWO4QljuE5Q5huUNY7hCWO4TlDmG5Q1juEJY7hOUOYblDWO4QljuE5Q5huUNY7hCWO4TlDmG5Q1juEJY7hOUOYblDWO4QljuE5Q5huUNY7hCWO4TlDmG5Q1juEJY7hOUOYblDWO4QljuE5Q5huUNY7hCWO4TlDmG5Q1juEJY7hOUOYblDWO4QljuE5Q5huUNY7hCWO4TlDmG5Q1juEJY7hOUOYblDWO4QljuE5Q5huUNY7hCWO4TlDmG5Q1juEJY7hOUOYblDWO4QljuE5Q5huUO43SHc7hBudwi3O4TbHcLtDuF2h3C7Q7jdIdzuEG53CLc7hNsdwu0O4XaHcLtDuN0h3O4QbncItzuE2x3C7Q7hdodwu0O43SHc7hBudwi3O4TbHcLtDuF2h3C7Q7jdIdzuEG53CLc7hNsdwu0O4XaHcLtDuN0h3O4QbncItzuE2x3C7Q7hdodwu0O43SHc7hBudwi3O4TbHcLtDuF2h3C7Q7jdIdzuEG53CLc7hNsdwu0O4XaHcLtDuN0h3O4QbncItzuE2x3C7Q7hdodwu0O43SHc7hBudwi3O4TbHcLtDuF2h3C7Q7jdIdzuEG53CLc7hNsdwu0O4XaHcLtDuN0h3O4QbncItzuE2x3C7Q7hdodwu0O43SHc7hBudwi3O4TffuD38HH5GD6mj+WjfGwft4/HR09zlrhDuN0h3O4QbncItzuE2x3C7Q7hdodwu0O43SHc7hBudwi3O4TbHcLtDuF2h3C7Q7jdIdzuEG53CPdylixnyXKWLGfJcpYsZ8lylixnyXKWLGfJcpYsZ8lylixnyXKWLGfJcpYsZ8lylixnyXKWLGfJcpYsZ8lylixnyXKWLGfJcpYsZ8lylixnyXKWLGfJcpYsZ8lylixnyXKWLGfJcpYsZ8lylixnyXKWLGfJcpYsZ8lylixnyXKWLGfJcpYsZ8lylixnyXKWLGfJcpYsZ8lylixnyXKWLGfJcpYsZ8lylixnyXKWhLMknCXhLAlnSThLwlkSzpJwloSzJJwl4SwJZ0k4S8JZEs6ScJaEsyScJeEsCWdJOEvCWRLOknCWhLMknCXhLAlnSThLwlkSzpJwltjO2LYztu2MbTtj287YtjO27YxtO2Pbzti2M7btjG07Y9vO2LYztu2MbTtj287YtjO27YxtO2Pbzti2M7btjG07Y9vO2LYztu2MbTtj287YtjO27YxtO2Pbzti2M7btjG07Y9vO2LYztu2MbTtj287YtjO27YxtO2Pbzti2M7btjG07Y9vO2LYztu2MbTtj287YtjO27YxtO2Pbzti2M7btjG07Y9vO2LYztu2MbTtj287YtjO27YxtO2Pbzti2M7btjG07Y9vO2LYztu2MbTtj287YtjO27YxtO2Pbzti2M7btjG07Y9vO2LYztu2MbTtj287YtjO27YxtO2Pbzti2M7btjG07Y9vO2LYztu2MbTtj287YtjO27YxtO2Pbzti2M7btjG07Y9vO2LYztu2MbTtj287YtjO27YxtO2Pbzti2M7btjG07Y9vO2LYztu2MbTtj287YtjO27YxtO2Pbzti2M7btjG07Y9vO2LYztu2MbTtj287YtjO27YxtO2Pbzti2M7btjG07Y9vO2LYztu2MbTtj287YtjO27YxtO2Pbzti2M7btjG07Y9vO2LYztu2MbTtj287YtjO27YxtO2Pbzti2M7btjG07Y9vO2LYztu2MbTtj287YtjO27YxtO2Pbzti2M7btjG07Y9vO2LYztu2MbTtj287YtjO27YxtO2Pbzti2M7btjG07Y9vO2LYztu2MbTtj287YtjO27YxtO2Pbzti2M7btjG07Y9vO2LYztu2MbTtj287YtjO27YxtO2Pbzti2M7btjG07Y9vO2LYztu2MbTtj287YtjO27Yz9sjOu92P7uH18/r1DvZ/unOY9zF3zHuaueQ9z17yHuWvew9w172Humvcwd817mLvmPcxd8x7mrs2MzYzNjM2MzYzNjM2MzYzNjM2Mw4zDjMOMw4zDjMOMw4zDjMOMw4zLjMuMy4zLjMuMy4zLjMuMy4x5D3Nr3sPcmvcwt+Y9zK15D3Nr3sPcmvcwt+Y9zK15D3Nr3sPcejBjMWMxYzFjMWMxYzFjMWMxYzFjMSOYEcwIZgQzghnBjGBGMCOYEcxIZiQzkhnJjGRGMiOZkcxIZiQzihnFjGJGMaOYUcwoZhQzihnFDDFDzBAzxAwxQ8wQM8QMMUPMgHPBueBccC44F5wLzgXngnPBueBccC44F5wLzgXngnPBueBccC44F5wLzgXngnPBueBccC44F5wLzgXngnPBueBccC44F5wLzgXnDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3nDecN5w3n7zuUTxNFv+9Qvk589/MyF34cz8fGRn9sUb6fPr77v+/H5WP4+PxOa+X78fmd1nof8P7d/+vYPm4fj493jh/ewqW/fv/df/32Tz/89l9+/P1/fvdP//32y3/7yx9+9+cf/viH1y///H//Y/6ff/nTDz/++MO//+Y//vTH3/3+X//yp9//5sc//u75/30Xz3+8Pbv/s9f3Z/3z27+b87+8/UXI929/PfHPf/3rX//5r/8P",
|
|
5978
|
+
"debug_symbols": "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",
|
|
6041
5979
|
"is_unconstrained": false,
|
|
6042
5980
|
"name": "entrypoint",
|
|
6043
|
-
"verification_key": "
|
|
5981
|
+
"verification_key": "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"
|
|
6044
5982
|
},
|
|
6045
5983
|
{
|
|
6046
5984
|
"abi": {
|
|
@@ -6053,11 +5991,11 @@
|
|
|
6053
5991
|
"parameters": [],
|
|
6054
5992
|
"return_type": null
|
|
6055
5993
|
},
|
|
6056
|
-
"bytecode": "H4sIAAAAAAAA/82Wz0/
|
|
5994
|
+
"bytecode": "H4sIAAAAAAAA/82Wz0/UQBTHuyz+RPEnyJGLBy8mrIR41W5J1sSQgMvFQzNun5tJZqd1OmusJ+dovEyLxLss1QT9C7z6T5DwN/gHeGKahaWUvC0NHJjbzGfed74zfXmv9ST+tjvvuuSjhI7LhUu5BMEJC103jHjHDSWRYMVq57mgjNGuTRj7amm9ofXfeWv8qGkz4qRcf8+aU9u2z0O5odImFdCRE+pHy2ztgthqP2mUH1WMr1WK/+QU461q5ztqkL1MPDXS+bkKjEj6HirexDqpUK+q8Cvz4hFJbD+IRldy8p5y4kPn02d27pyD88Ga9IM4QZwWvpG9vUyBeaWys8XA5ikDJ9JVkH3B1c6yL4B2efZSm7uPhtncl8wlYQhC2n4vMBbfMFgRpMNgHURIfb7e0DpRv19CzxfRM88TEIYj78h6M1HpGu0FDIYeC7NjRv4c+eiCbEvKqIzMTSV8kHvWg+IJuTfFSB0lkyi5hJLLKLmCkqsouYaS6yiZQskNlNxEyTRKbqHkNkruoOQuSu6h5D5KZlAyixI8d+ayxBqXoRd+dqwklW5ZWqykOWgvNJ6OXy13qvW4Wvy9vXC2JnIagZpp+JQTEZmYlWAzVwdS513ftG8jghTp9EW/F7Te5mr45MxBjzGp2OLesP6h3XppEXf38P/jL1ufX/9Tg1eCZH1iFH/423BQsfcBO3nCetgIAAA=",
|
|
6057
5995
|
"custom_attributes": [
|
|
6058
5996
|
"abi_utility"
|
|
6059
5997
|
],
|
|
6060
|
-
"debug_symbols": "
|
|
5998
|
+
"debug_symbols": "jZLLjoQgEEX/hbULioegvzLpGFTskBA0tE4yMf77gN34WGh6wwWKOtSFmlGr6+lZGdf1L1T+zKj2xlrzrGzfqNH0LuzOCMcBGCpphoCjMg+So1IEEW+RbylWIeG8WJYMJUg1eq0j40ANdw3Kazei0k3WZuhX2Wk99BqUW3VUPkRxhrRrgwZgZ6yOsyXbs/F1KuTAPtmQC7IBAMQJATcIKkVCMFJsCILhhCA3CI7zhODyGnFjpJCbD0zg0ge7JjCSamBMbABxfkp+nU95+gcq5F6A/NoCJTJVQEmxe+ChhEdYqcb4U9ctkeWNqq3+LLvJNYfo+DekSOrawfeNbievI+nQuhD6jUBG6GOJt/0D",
|
|
6061
5999
|
"is_unconstrained": true,
|
|
6062
6000
|
"name": "sync_state"
|
|
6063
6001
|
},
|
|
@@ -7849,15 +7787,15 @@
|
|
|
7849
7787
|
"visibility": "databus"
|
|
7850
7788
|
}
|
|
7851
7789
|
},
|
|
7852
|
-
"bytecode": "H4sIAAAAAAAA/+2cd3xVxbqG871DRyxUCyUUERSVotgVCEFQKYLYNYawgS0hiTs7FCuxNyQJIEV6F0Sxi71gn1fsimLB3ntv564QTSFg1gbe+/N6z/nnxDDzfN+
|
|
7790
|
+
"bytecode": "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",
|
|
7853
7791
|
"custom_attributes": [
|
|
7854
7792
|
"abi_private",
|
|
7855
7793
|
"abi_view"
|
|
7856
7794
|
],
|
|
7857
|
-
"debug_symbols": "rZfbjtowEIbfJddceE4+8CrVasWy2RVSBCgLlaoV794xsXNoZZdDb/gTgj/
|
|
7795
|
+
"debug_symbols": "rZfbjtowEIbfJddceE4+8CrVasWy2RVSBCgLlaoV794xsXNoZZdDb/gTgj/GM+Pfznfz3r6dP193+4/DV7P+8d289buu232+doft5rQ77PXb78bED+BmTZdVA9cbataoNxhvSJ/AqiFRueiXeezrqW/b+IMZTP/iuOnb/alZ789dt2p+brrz9Udfx83+qqdNr0/Nqmn376oK/Nh1bby6rKbRpjxUfEiDLbpxOHi8FWADJYDjMALQ3BwBiLGJABrNDAG3IlywkhDeIE3TAFkguBIFeZejYHwoCiSbEciAxShsBQHWZwTO6uGXQbgyIZDJqQjEUxAkboHwFYThXNJggikiQhlBI4G8n3Jp/QIAlWSS5dwVZIUfZACMjFlb3MUIwJkR5g3+J4PKDAaXVyijma+yO8Jw41SCK4dRa09mHtsz+GJ7QqU/waDkBtXrMNXFujsgPC5XMIJQgtRsCyWvNcGZafw1mUqToic3LljPaIuTqUIc4ghxs26/fTJsKOeDjS8bR81EJxsGN1su5OwCgZU2FaZcW2GZcsrAS0bFRsWanA2xwGWG1Hw0rxYUnBHk9i3J5LpqWqSYT3S11RLGmeg1uVJd0T9t5xie93Myzxs6wbOOTvi8G/+jKuM2jWK4uNqo0qM8rTYPjxx5RKPITS5kiv1F9j+YTx3CbvR0L7Ok3gWRaWPw1jwcCc0g7jHI816qzuWm2jzkpc663CDOzra4K+JFbzfbXb889IMe53UM2Hh6VHVJfdIwKJpoz6qQFGPfqVJSjgdOVUlqo4eouqQ+aRjGk4nGogpxMatidHxVShpfQ/zwtnFVm9Ql9fE4oRoGZZMUkmLckVRp+D/mpJLURl9WdUl90jCopPlKmq9g0sQTjieiSyxFv9u8dW1MZsz3eb/NudXb069jfpJfuY79Ydu+n/s21uFaguHtSl+adIsjernEUv0G",
|
|
7858
7796
|
"is_unconstrained": false,
|
|
7859
7797
|
"name": "verify_private_authwit",
|
|
7860
|
-
"verification_key": "
|
|
7798
|
+
"verification_key": "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"
|
|
7861
7799
|
},
|
|
7862
7800
|
{
|
|
7863
7801
|
"abi": {
|
|
@@ -7989,11 +7927,11 @@
|
|
|
7989
7927
|
],
|
|
7990
7928
|
"return_type": null
|
|
7991
7929
|
},
|
|
7992
|
-
"bytecode": "H4sIAAAAAAAA/+
|
|
7930
|
+
"bytecode": "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",
|
|
7993
7931
|
"custom_attributes": [
|
|
7994
7932
|
"abi_utility"
|
|
7995
7933
|
],
|
|
7996
|
-
"debug_symbols": "
|
|
7934
|
+
"debug_symbols": "tZndbhs5DEbfxde+GFI/FPMqQVG4qbswYDiBmyywKPLuS2b0acZZSPDa7U10kniOKQ4paexfm+/7b29/fT2cfjz/3Dw8/tp8Ox+Ox8NfX4/PT7vXw/PJ/vprM/mPzGXzELY26uYh2ximOlIduY6hjrGOqY65jlLHUsfqi9UXqy9WX7LXiY3Z/q4+ch3NT+SQAPYO5CFmARSAVpAJQAAGBEAEJADMArPALDAXmAvMBeYCc4G5wFxgLjAXmAvMCrPCrDArzAqzVrNMflVyIAAD/DXZIQMEYO/Ok4NWoAlAAAYEgL07++WUABkgADeLg1bgCeBmdTBz8OA5ACIgATJAAAWgFbw2ZyAAzAHmALMXaPC0eIXOIAA3e4RepB/gVTqDX+4xR3txJAd7cXRh1AppAlgYMTowIAAiIAEyQABu9niSVsgTgABu9sByAESAm4tDBgigALSCN8gMBHCzz9QbZIYISAAzJ0+CN8gMBWDmxAbeIDMQgAEBEAEJ4GbPoTfIDAWgFbxBkifKGyR5sXmDzBAAbvZseIPMkAECKACdoXgTzeDm4sCAAIgAX+kmhwwQgC925KAVvK0yOxCAAQHgS2h2cLO/hbfVDAIoAK3gbTUDAdysDgFgZvEwvK1myAAzi7+7t9UMWsHbagYCMCAA3BwcEiADBODm6KAVvK1mIIBflRwEUAB+lc/L+2sGAng8PkHvrxkiIAEyQAAFYObi98v7awYCMMDN+f19u8Em+fX1vN/7HrnaNW0vfdmd96fXzcPp7Xjcbv7eHd8+XvTzZXf6GF93Z/uvKfen7zaa8MfhuHd63y5XT/1LabJFrF5uLNQUNF1KqC+Jvjh/KGKUJpDL67l/fUiYQZCyBFDo+llYl7VZlJK6s4h9ScocqiPZSWJRpHihSH0FZ+aqYDt8NEW+OgbbKhGD7VLdGAYKOzRJVdgsYldR+grb06vBlvJFIHr9NFoMyTacbgw0uKeBSVEVHFInl2ODtroKU+kZBoUZiWGIFPSG+2mLIxJRYugnYuBQgkJ5mUSkq2PQhA7PE8ebamoKiyL2FSSDHtWMqiKVxZEuq4oGdUlCaC+yU0JXoaNkIggtq6XGlp2rDbqsl5S6Ch6sl8wRDubUvafMoxWvrTQ0JeqHEYbFya04V10a6fKu8rAyJl2Ka+o7RqtmTG3RlJWBbisM7ReGjO5JoHZPVp36ScGDKHJKLRdJ401RUMbCafF0owiDVS+mthlLvy7CaDunzG3V0/U95UvHqD5TuyEprAzp+ii4VVZkkX4Ug+okLtjSKRD14xg4goS2D5Wp9OPIf9ZBmWLLaSYJ3V4LgxrVpMiIrmv0P45hJGFZA+2zln7Xx9HunJdDX+zemaEhtqRerF6fDKP9fQpYeuyoJP15DBwcMA9OfFMUXNr6V3K/RmV0dJ3aSm5l0p9H/g25yHfnIt+di3x/LtJ0fy5GjutyMTTcnQsLvrR5ZLqp26/ORfqzjivzme7O53BP0jaPMFjHk/6GPWlUn4KVL60fVD+fYkcHjVBwTOD1U+L/OatEaqfYtDqCflLkcO9ZJY9250nR7ZbM/p6Y0+g5MS9PmoVvdLSpmK70HXJvhQ/zeVVdjI7z3NJpX870n1dlUJz2BQdSYd9shM5D89BQuH2EYZ/U3WSQ0gxyw4O7fQUVWiJC/4l3eNbK7QSrmfJt57W1I/TrW37Djihy/woud9f30NBfwb/Yr7unw/nia8d3V50Pu2/Hff31x9vpafXf139e8B98bflyfn7af3877920fHdpPx6LfapclL9sN/b57aOdwbeZxX7zj98fi+pWJ/ry7rH8Cw==",
|
|
7997
7935
|
"is_unconstrained": true,
|
|
7998
7936
|
"name": "offchain_receive"
|
|
7999
7937
|
},
|
|
@@ -8026,7 +7964,7 @@
|
|
|
8026
7964
|
}
|
|
8027
7965
|
],
|
|
8028
7966
|
"name": "SimulatedSchnorrAccount",
|
|
8029
|
-
"noir_version": "1.0.0-beta.20+
|
|
7967
|
+
"noir_version": "1.0.0-beta.20+20391fdcb15a8ec9086a4ad69c15b33d72ce5ea8",
|
|
8030
7968
|
"outputs": {
|
|
8031
7969
|
"globals": {},
|
|
8032
7970
|
"structs": {
|