@aztec/protocol-contracts 0.42.0 → 0.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- { "transpiled": true, "noir_version": "0.30.0+c363d6fb324a83b35cf5aa1bfd39f62b9198f0b6", "name": "KeyRegistry", "functions": [{ "name": "rotate_npk_m", "is_unconstrained": true, "custom_attributes": ["aztec(public)"], "abi": { "error_types": {}, "param_witnesses": { "address": [{ "end": 4, "start": 3 }], "inputs": [{ "end": 3, "start": 0 }], "new_npk_m": [{ "end": 6, "start": 4 }], "nonce": [{ "end": 7, "start": 6 }] }, "parameters": [{ "name": "inputs", "type": { "fields": [{ "name": "selector", "type": { "kind": "field" } }, { "name": "args_hash", "type": { "kind": "field" } }, { "name": "is_static_call", "type": { "kind": "boolean" } }], "kind": "struct", "path": "aztec::context::inputs::public_context_inputs::PublicContextInputs" }, "visibility": "private" }, { "name": "address", "type": { "fields": [{ "name": "inner", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::address::aztec_address::AztecAddress" }, "visibility": "private" }, { "name": "new_npk_m", "type": { "fields": [{ "name": "x", "type": { "kind": "field" } }, { "name": "y", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint" }, "visibility": "private" }, { "name": "nonce", "type": { "kind": "field" }, "visibility": "private" }], "return_type": null, "return_witnesses": [] }, "bytecode": "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", "debug_symbols": "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" }, { "name": "register", "is_unconstrained": true, "custom_attributes": ["aztec(public)"], "abi": { "error_types": {}, "param_witnesses": { "address": [{ "end": 4, "start": 3 }], "inputs": [{ "end": 3, "start": 0 }], "keys": [{ "end": 13, "start": 5 }], "partial_address": [{ "end": 5, "start": 4 }] }, "parameters": [{ "name": "inputs", "type": { "fields": [{ "name": "selector", "type": { "kind": "field" } }, { "name": "args_hash", "type": { "kind": "field" } }, { "name": "is_static_call", "type": { "kind": "boolean" } }], "kind": "struct", "path": "aztec::context::inputs::public_context_inputs::PublicContextInputs" }, "visibility": "private" }, { "name": "address", "type": { "fields": [{ "name": "inner", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::address::aztec_address::AztecAddress" }, "visibility": "private" }, { "name": "partial_address", "type": { "fields": [{ "name": "inner", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::address::partial_address::PartialAddress" }, "visibility": "private" }, { "name": "keys", "type": { "fields": [{ "name": "npk_m", "type": { "fields": [{ "name": "x", "type": { "kind": "field" } }, { "name": "y", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint" } }, { "name": "ivpk_m", "type": { "fields": [{ "name": "x", "type": { "kind": "field" } }, { "name": "y", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint" } }, { "name": "ovpk_m", "type": { "fields": [{ "name": "x", "type": { "kind": "field" } }, { "name": "y", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint" } }, { "name": "tpk_m", "type": { "fields": [{ "name": "x", "type": { "kind": "field" } }, { "name": "y", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint" } }], "kind": "struct", "path": "aztec::keys::public_keys::PublicKeys" }, "visibility": "private" }], "return_type": null, "return_witnesses": [] }, "bytecode": "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", "debug_symbols": "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yArbkRV2ICvsQFbYgaywA1lhB7LCDmSFHcgKO5AVdiAr7EBW2ImssBNZYSeywk5khZ3ICjuRFXYiK+xEVtiJrLATWGFrAlbYmoAVtiZgha0JWGFrAlbYmoAVtiZgha0JWGFrAlbYmpAVNiMrbEZW2IyssBlZYTOywmZkhc3ICpuRFTYjK2xGVlhBVlhBVlhBVlhBVlhBVlhBVlhBVlhBVlhBVlhBVtiCrLAFWWELssIWZIUtyApbkBW2ICtsQVbYgqywBVlhFVlhFVlhFVlhFVlhLVKe3lc8ssIqssIqssIqssIqssJWZIWtyApbkRUWOdOpImc6VeRMp4qc6VSRM50qcqZTRc50qsiZThU506kiZzpV5EynipzpVJEznSpyplNFznSqyJlOFTnTqSJnOlXkTKeKnOlUkTOdKnKmU0XOdKrImU4VOdOpImc6VeRMp4qc6VSRM50qcqZTRc50qsiZThU506kiZzpV5EynipzpVJEznSpyplNFznSqyJlOFTnTqSJnOlXkTKeKnOlUkTOdKnKmU0XOdGrImU4NOdOpIWc6NeRMp5aAFbYhZzo15Eynhpzp1JAznRpyplNDznRqyJlODTnTqSFnOjXkTKeGnOnUkDOdGnKmU0POdGrImU4NOdOpIWc6NeRMp4ac6dSQM50acqZTQ850asiZTg0506khZzo15Eynhpzp1JAznRpyplNDznRqyJlODTnTqSFnOjXkTKeGnOnUkDOdGnKmU0POdGrImU4NOdOpIWc6NeRMp4ac6dSQM50acqZTQ850asiZTg0506khZzo15Eynhpzp1JAznRpyplNDznRqyJlODTnTqSFnOjXkTKeGnOnUkDOdGnKmU0POdGrImU4NOdOpIWc6NeRMp4ac6dSQM50acqZTQ850asiZTg0506khZzo15Eynhpzp1JAznRpyplNDznRqyJlODTnTqSFnOjXkTKeGnOnUkDOdGnKmU0POdGrImU4NOdOpIWc6NeRMp4ac6dSQM50acqZTQ850asiZTh0506kjZzp15Eynjpzp1BOwwnbkTKeOnOnUkTOdOnKmU0fOdOrImU4dOdOpI2c6deRMp46c6dSRM506cqZTR8506siZTh0506kjZzp15Eynjpzp1JEznTpyplM/yHTStBevWk8uM/dO5xgnpee6FZ/n52cljcVn+8jbF/cx5PPT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" }, { "name": "compute_note_hash_and_nullifier", "is_unconstrained": true, "custom_attributes": [], "abi": { "error_types": {}, "param_witnesses": { "contract_address": [{ "end": 1, "start": 0 }], "nonce": [{ "end": 2, "start": 1 }], "note_type_id": [{ "end": 4, "start": 3 }], "serialized_note": [], "storage_slot": [{ "end": 3, "start": 2 }] }, "parameters": [{ "name": "contract_address", "type": { "fields": [{ "name": "inner", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::address::aztec_address::AztecAddress" }, "visibility": "private" }, { "name": "nonce", "type": { "kind": "field" }, "visibility": "private" }, { "name": "storage_slot", "type": { "kind": "field" }, "visibility": "private" }, { "name": "note_type_id", "type": { "kind": "field" }, "visibility": "private" }, { "name": "serialized_note", "type": { "kind": "array", "length": 0, "type": { "kind": "field" } }, "visibility": "private" }], "return_type": { "abi_type": { "kind": "array", "length": 4, "type": { "kind": "field" } }, "visibility": "public" }, "return_witnesses": [4, 5, 6, 7] }, "bytecode": "H4sIAAAAAAAA/+2b227iMBCGE8ohNMshIYTzobQ3exdYCvSOl9l9671fad9htZ3UUwZrWjnqxIolLKFMjOP/m9+HppXre2+l9frxVdzQrrRgm7O6Zl8rW8G+sjI5fUc4a45w3gly+gwnXOsqhivM5aZ3Pc/fy1lwklBRCgUDc0fqPoK7eghKUwWBBnyWgD5lpybpnEJDCRU4BQhJIj6pw2drpA53kLvg0kVTPod9QMwT6/d1QMNL2u/cIYnxO9Cekrp6STk25HMsy7t8VaI/DdVvi9yjV20VC+6wW6rtq0+baHpqjDCekLbYDv2okTGG0vEu49/+5Lm69lyXtGky+Z892fxbGk9LY24oJigR8Gp7QEljk0G/9/L9Xo15XRuTe5JTR9zv3Qn2hNC7LvpPmTOJO4TnmzhPti0nz7ex6xJ2mX6f9+BVT/Mq1LzqkjaUoVeCfz7Rxb7xvsdoy3lxOIF238CLPsPTt+xFn9EW9OIFtCMDLyKGJ7LsRcRoy3lx/AHasYEXMcMTW/YiZrTlvNjl7xYDAy8GDM/AshcDRltwjeTzIjHwImF4EsteJIy2oBe/QHto4MWQ4Rla9mLIaAt68RO0UwMvUoYntexFymgL7p35+8XIwIsRwzOy7MWI0Rb0YgfaYwMvxgzP2LIXY0ZbcI3k2hMDLyYMz8SyF/R31CLMAweZUweZ4wowB1oso33I98+pgRdThmdq2QvUK8qcVIA50GIZ7cMzaM8MvJgxPDPLXqBeUebIQebYQeahg8yJg8ypg8xVmM+BFstoH/M9dG7gxZzhmVv2AvWKMkcOMk8dZI4rwBxosYz2Mf/b3MLAiwXDs7DsBeoVZR45yNyvAHOgxTLaxwNoLw28WDI8S8teoF5R5rGDzKmDzFMHmWMHmYcOMicOMt/WoB3mqALM9EzT31J5di+hxoOeeRqjpzGGJKbnYFbijFlGx2dFtNbyWltuvuD9ulTt3Qn63cjnlL/LP6q+8AzfhsnpScXS57keSb8+0cH6Oon/kLbYDv3AdYvsMO8eVPz0yXNL7bkuafPA5H/2ZPPfaDwbjRnG5DfhWItz7E4m87rvXdbyd8JTwj64p2dysZjsOyXtMduS8szoGb5/nuyaXmteBZpXXdKG7tHrEvwzmV835hvzR8z0fSIgdfj9itTVtFzo/zJgezgz/B/4fzqFFjUAAA==", "debug_symbols": "ndpBattQGIXRvWgciu8v6ekpWymlOIlTDMYOsVMoJnuv3dIF9Mz0JN3ZNzq86/Cye/r48X1/fD2dh8ev1+Fwet5e9qfj7XQdNl+q/Xl7ftse7y/Ol+37ZXgcKw/D7vhyf2qfD8Pr/rC7P4+f3x7uo0VGXUYrjMaNjCKjktEoo0lGs4ykiFGKGKWIUYqYpIhJipikiEmKmKSISYqYpIhJipikiEmKmKWIWYqYpYhZipiliFmKmKWIWYqYpYhZimhSRJMimhTRpIgmRTQpokkRTYpoUkSTIhYpYpEiFilikSIWKWKRIhYpYpEiFilikSK6FNGliC5FdCmiSxFdiuhSRJciuhTRpYhVililiFWKWKWIVYpYpYhVililiFWKWKWIbDa0Cq2KViOtJlrNtGq0WmjVaUVthNoItRFqI9RGqI1QG6E2Qm2E2gi1UdRGURtFbRS1UdRGURvEmSHPDIFmSDRDpBkyzRBqhlQzxJoh1wzBZkg2Q7QZss0QboZ0M8SbId8MAWdIOEPEGTLOEHKGlDPEnCHnDEFnSDpD1BmyzhB2hrQzxJ0h7wyBZ0g8Q+QZMs8QeobUM8SeIfcMwWdIPkP0GbLPEH6G9DPEnyH/DAFoSEBDBBoy0BCChhQ0xKAhBw1BaEhCQxQastAQhoY0NMShIQ8NgWhIREMkGjLREIqGVDTEoiEXLXLRIhctctEiFy1y0SIXLXLRIhctctEiFy1y0SIXLXLRIhctctEiFy1y0SIXLXLRIhctctEiFy1y0SIXLXLRIhctu+Zp9zztoie5aJGLFrlokYsWuWj9t4veTj+37/vt02F3v9l7//hxfP530fd2vPx6+/vl9u9v" }], "outputs": { "globals": { "storage": [{ "fields": [{ "name": "npk_m_x_registry", "value": { "fields": [{ "name": "slot", "value": { "kind": "integer", "sign": false, "value": "1" } }, { "name": "typ", "value": { "kind": "string", "value": "Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY, Context>, Context>" } }], "kind": "struct" } }, { "name": "npk_m_y_registry", "value": { "fields": [{ "name": "slot", "value": { "kind": "integer", "sign": false, "value": "2" } }, { "name": "typ", "value": { "kind": "string", "value": "Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY, Context>, Context>" } }], "kind": "struct" } }, { "name": "ivpk_m_x_registry", "value": { "fields": [{ "name": "slot", "value": { "kind": "integer", "sign": false, "value": "3" } }, { "name": "typ", "value": { "kind": "string", "value": "Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY, Context>, Context>" } }], "kind": "struct" } }, { "name": "ivpk_m_y_registry", "value": { "fields": [{ "name": "slot", "value": { "kind": "integer", "sign": false, "value": "4" } }, { "name": "typ", "value": { "kind": "string", "value": "Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY, Context>, Context>" } }], "kind": "struct" } }, { "name": "ovpk_m_x_registry", "value": { "fields": [{ "name": "slot", "value": { "kind": "integer", "sign": false, "value": "5" } }, { "name": "typ", "value": { "kind": "string", "value": "Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY, Context>, Context>" } }], "kind": "struct" } }, { "name": "ovpk_m_y_registry", "value": { "fields": [{ "name": "slot", "value": { "kind": "integer", "sign": false, "value": "6" } }, { "name": "typ", "value": { "kind": "string", "value": "Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY, Context>, Context>" } }], "kind": "struct" } }, { "name": "tpk_m_x_registry", "value": { "fields": [{ "name": "slot", "value": { "kind": "integer", "sign": false, "value": "7" } }, { "name": "typ", "value": { "kind": "string", "value": "Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY, Context>, Context>" } }], "kind": "struct" } }, { "name": "tpk_m_y_registry", "value": { "fields": [{ "name": "slot", "value": { "kind": "integer", "sign": false, "value": "8" } }, { "name": "typ", "value": { "kind": "string", "value": "Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY, Context>, Context>" } }], "kind": "struct" } }], "kind": "struct" }] }, "structs": { "functions": [{ "fields": [{ "name": "parameters", "type": { "fields": [{ "name": "address", "type": { "fields": [{ "name": "inner", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::address::aztec_address::AztecAddress" } }, { "name": "new_npk_m", "type": { "fields": [{ "name": "x", "type": { "kind": "field" } }, { "name": "y", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint" } }, { "name": "nonce", "type": { "kind": "field" } }], "kind": "struct", "path": "KeyRegistry::rotate_npk_m_parameters" } }], "kind": "struct", "path": "KeyRegistry::rotate_npk_m_abi" }, { "fields": [{ "name": "parameters", "type": { "fields": [{ "name": "address", "type": { "fields": [{ "name": "inner", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::address::aztec_address::AztecAddress" } }, { "name": "partial_address", "type": { "fields": [{ "name": "inner", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::address::partial_address::PartialAddress" } }, { "name": "keys", "type": { "fields": [{ "name": "npk_m", "type": { "fields": [{ "name": "x", "type": { "kind": "field" } }, { "name": "y", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint" } }, { "name": "ivpk_m", "type": { "fields": [{ "name": "x", "type": { "kind": "field" } }, { "name": "y", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint" } }, { "name": "ovpk_m", "type": { "fields": [{ "name": "x", "type": { "kind": "field" } }, { "name": "y", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint" } }, { "name": "tpk_m", "type": { "fields": [{ "name": "x", "type": { "kind": "field" } }, { "name": "y", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint" } }], "kind": "struct", "path": "aztec::keys::public_keys::PublicKeys" } }], "kind": "struct", "path": "KeyRegistry::register_parameters" } }], "kind": "struct", "path": "KeyRegistry::register_abi" }] } }, "file_map": { "117": { "path": "/usr/src/noir-projects/aztec-nr/aztec/src/oracle/storage.nr", "source": "use dep::protocol_types::traits::{Deserialize, Serialize};\n\n#[oracle(storageRead)]\nfn storage_read_oracle<N>(_storage_slot: Field, _number_of_elements: Field) -> [Field; N] {}\n\nunconstrained fn storage_read_oracle_wrapper<N>(_storage_slot: Field) -> [Field; N] {\n storage_read_oracle(_storage_slot, N)\n}\n\npub fn storage_read<N>(storage_slot: Field) -> [Field; N] {\n storage_read_oracle_wrapper(storage_slot)\n}\n\n#[oracle(storageWrite)]\nfn storage_write_oracle<N>(_storage_slot: Field, _values: [Field; N]) -> [Field; N] {}\n\nunconstrained pub fn storage_write<N>(storage_slot: Field, fields: [Field; N]) {\n let _hash = storage_write_oracle(storage_slot, fields);\n}\n" }, "130": { "path": "/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/map.nr", "source": "use dep::protocol_types::{hash::pedersen_hash, storage::map::derive_storage_slot_in_map, traits::ToField};\nuse crate::state_vars::storage::Storage;\n\n// docs:start:map\nstruct Map<K, V, Context> {\n context: Context,\n storage_slot: Field,\n state_var_constructor: fn(Context, Field) -> V,\n}\n// docs:end:map\n\nimpl<K, T, Context> Storage<T> for Map<K, T, Context> {}\n\nimpl<K, V, Context> Map<K, V, Context> {\n // docs:start:new\n pub fn new(\n context: Context,\n storage_slot: Field,\n state_var_constructor: fn(Context, Field) -> V\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Map { context, storage_slot, state_var_constructor }\n }\n // docs:end:new\n\n // docs:start:at\n pub fn at(self, key: K) -> V where K: ToField {\n // TODO(#1204): use a generator index for the storage slot\n let derived_storage_slot = derive_storage_slot_in_map(self.storage_slot, key);\n\n let state_var_constructor = self.state_var_constructor;\n state_var_constructor(self.context, derived_storage_slot)\n }\n // docs:end:at\n}\n" }, "139": { "path": "/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change.nr", "source": "use dep::protocol_types::traits::{Serialize, Deserialize, FromField, ToField};\nuse dep::std::cmp::min;\n\nmod test;\n\n// This data structure is used by SharedMutable to store the minimum delay with which a ScheduledValueChange object can\n// schedule a change.\n// This delay is initally equal to INITIAL_DELAY, and can be safely mutated to any other value over time. This mutation \n// is performed via `schedule_change` in order to satisfy ScheduleValueChange constraints: if e.g. we allowed for the \n// delay to be decreased immediately then it'd be possible for the state variable to schedule a value change with a \n// reduced delay, invalidating prior private reads.\nstruct ScheduledDelayChange<INITIAL_DELAY> {\n // Both pre and post are stored in public storage, so by default they are zeroed. By wrapping them in an Option, \n // they default to Option::none(), which we detect and replace with INITIAL_DELAY. The end result is that a\n // ScheduledDelayChange that has not been initialized has a delay equal to INITIAL_DELAY, which is the desired\n // effect. Once initialized, the Option will never be none again.\n pre: Option<u32>,\n post: Option<u32>,\n // Block at which `post` value is used instead of `pre`\n block_of_change: u32,\n // The _dummy variable forces INITIAL_DELAY to be interpreted as a numeric value. This is a workaround to\n // https://github.com/noir-lang/noir/issues/4633. Remove once resolved.\n _dummy: [Field; INITIAL_DELAY],\n}\n\nimpl<INITIAL_DELAY> ScheduledDelayChange<INITIAL_DELAY> {\n pub fn new(pre: Option<u32>, post: Option<u32>, block_of_change: u32) -> Self {\n Self { pre, post, block_of_change, _dummy: [0; INITIAL_DELAY] }\n }\n\n /// Returns the current value of the delay stored in the data structure.\n /// This function only returns a meaningful value when called in public with the current block number - for\n /// historical private reads use `get_effective_minimum_delay_at` instead.\n pub fn get_current(self, current_block_number: u32) -> u32 {\n // The post value becomes the current one at the block of change, so any transaction that is included in the\n // block of change will use the post value.\n\n if current_block_number < self.block_of_change {\n self.pre.unwrap_or(INITIAL_DELAY)\n } else {\n self.post.unwrap_or(INITIAL_DELAY)\n }\n }\n\n /// Returns the scheduled change, i.e. the post-change delay and the block at which it will become the current\n /// delay. Note that this block may be in the past if the change has already taken place.\n /// Additionally, further changes might be later scheduled, potentially canceling the one returned by this function.\n pub fn get_scheduled(self) -> (u32, u32) {\n (self.post.unwrap_or(INITIAL_DELAY), self.block_of_change)\n }\n\n /// Mutates the delay change by scheduling a change at the current block number. This function is only meaningful\n /// when called in public with the current block number.\n /// The block at which the new delay will become effective is determined automatically:\n /// - when increasing the delay, the change is effective immediately\n /// - when reducing the delay, the change will take effect after a delay equal to the difference between old and\n /// new delay. For example, if reducing from 3 days to 1 day, the reduction will be scheduled to happen after 2\n /// days.\n pub fn schedule_change(&mut self, new: u32, current_block_number: u32) {\n let current = self.get_current(current_block_number);\n\n // When changing the delay value we must ensure that it is not possible to produce a value change with a delay\n // shorter than the current one.\n let blocks_until_change = if new > current {\n // Increasing the delay value can therefore be done immediately: this does not invalidate prior contraints\n // about how quickly a value might be changed (indeed it strengthens them).\n 0\n } else {\n // Decreasing the delay requires waiting for the difference between current and new delay in order to ensure\n // that overall the current delay is respected.\n //\n // current delay earliest value block of change\n // block block of change if delay remained unchanged\n // =======N=========================|================================X=================>\n // ^ ^ ^\n // |-------------------------|--------------------------------|\n // | blocks until change new delay |\n // ------------------------------------------------------------\n // current delay\n current - new\n };\n\n self.pre = Option::some(current);\n self.post = Option::some(new);\n self.block_of_change = current_block_number + blocks_until_change;\n }\n\n /// Returns the minimum delay before a value might mutate due to a scheduled change, from the perspective of some\n /// historical block number. It only returns a meaningful value when called in private with historical blocks. This \n /// function can be used alongside `ScheduledValueChange.get_block_horizon` to properly constrain the\n /// `max_block_number` transaction property when reading mutable shared state.\n /// This value typically equals the current delay at the block following the historical one (the earliest one in\n /// which a value change could be scheduled), but it also considers scenarios in which a delay reduction is \n /// scheduled to happen in the near future, resulting in a way to schedule a change with an overall delay lower than\n /// the current one.\n pub fn get_effective_minimum_delay_at(self, historical_block_number: u32) -> u32 {\n if self.block_of_change <= historical_block_number {\n // If no delay changes were scheduled, then the delay value at the historical block (post) is guaranteed to\n // hold due to how further delay changes would be scheduled by `schedule_change`.\n self.post.unwrap_or(INITIAL_DELAY)\n } else {\n // If a change is scheduled, then the effective delay might be lower than the current one (pre). At the\n // block of change the current delay will be the scheduled one, with an overall delay from the historical\n // block number equal to the number of blocks until the change plus the new delay. If this value is lower\n // than the current delay, then that is the effective minimum delay.\n //\n // historical\n // block delay actual earliest value\n // v block of change block of change\n // =========NS=====================|=============================X===========Y=====>\n // ^ ^ ^ ^\n // earliest block in | | |\n // which to schedule change | | |\n // | | | |\n // |----------------------|------------------------------ |\n // | blocks new delay |\n // | until change |\n // | |\n // |----------------------------------------------------------------|\n // current delay at the earliest block in \n // which to scheduled value change\n\n let blocks_until_change = self.block_of_change - (historical_block_number + 1);\n\n min(\n self.pre.unwrap_or(INITIAL_DELAY),\n blocks_until_change + self.post.unwrap_or(INITIAL_DELAY)\n )\n }\n }\n}\n\nimpl<INITIAL_DELAY> Serialize<1> for ScheduledDelayChange<INITIAL_DELAY> {\n fn serialize(self) -> [Field; 1] {\n // We pack all three u32 values into a single U128, which is made up of two u64 limbs.\n // Low limb: [ pre_inner: u32 | post_inner: u32 ]\n // High limb: [ empty | pre_is_some: u8 | post_is_some: u8 | block_of_change: u32 ]\n\n let lo = ((self.pre.unwrap_unchecked() as u64) * (1 << 32))\n + (self.post.unwrap_unchecked() as u64);\n\n let hi = (self.pre.is_some() as u64) * (1 << 33) \n + (self.post.is_some() as u64 * (1 << 32)) \n + self.block_of_change as u64;\n\n let packed = U128::from_u64s_le(lo, hi);\n\n [packed.to_integer()]\n }\n}\n\nimpl<INITIAL_DELAY> Deserialize<1> for ScheduledDelayChange<INITIAL_DELAY> {\n fn deserialize(input: [Field; 1]) -> Self {\n let packed = U128::from_integer(input[0]);\n\n // We use division and modulo to clear the bits that correspond to other values when unpacking.\n\n let pre_is_some = ((packed.hi as u64) / (1 << 33)) as bool;\n let pre_inner = ((packed.lo as u64) / (1 << 32)) as u32;\n\n let post_is_some = (((packed.hi as u64) / (1 << 32)) % (1 << 1)) as bool;\n let post_inner = ((packed.lo as u64) % (1 << 32)) as u32;\n\n let block_of_change = ((packed.hi as u64) % (1 << 32)) as u32;\n\n Self {\n pre: if pre_is_some { Option::some(pre_inner) } else { Option::none() },\n post: if post_is_some { Option::some(post_inner) } else { Option::none() },\n block_of_change,\n _dummy: [0; INITIAL_DELAY],\n }\n }\n}\n" }, "143": { "path": "/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change.nr", "source": "use dep::protocol_types::traits::{Serialize, Deserialize, FromField, ToField};\nuse dep::std::cmp::min;\n\nmod test;\n\n// This data structure is used by SharedMutable to represent a value that changes from `pre` to `post` at some block\n// called the `block_of_change`. The value can only be made to change by scheduling a change event at some future block\n// of change after some minimum delay measured in blocks has elapsed. This means that at any given block number we know\n// both the current value and the smallest block number at which the value might change - this is called the\n// 'block horizon'.\nstruct ScheduledValueChange<T> {\n pre: T,\n post: T,\n // Block at which `post` value is used instead of `pre`\n block_of_change: u32,\n}\n\nimpl<T> ScheduledValueChange<T> {\n pub fn new(pre: T, post: T, block_of_change: u32) -> Self {\n Self { pre, post, block_of_change }\n }\n\n /// Returns the value stored in the data structure at a given block. This function can be called both in public\n /// (where `block_number` is simply the current block number, i.e. the number of the block in which the current\n /// transaction will be included) and in private (where `block_number` is the historical block number that is used\n /// to construct the proof).\n /// Reading in private is only safe if the transaction's `max_block_number` property is set to a value lower or\n /// equal to the block horizon (see `get_block_horizon()`).\n pub fn get_current_at(self, block_number: u32) -> T {\n // The post value becomes the current one at the block of change. This means different things in each realm:\n // - in public, any transaction that is included in the block of change will use the post value\n // - in private, any transaction that includes the block of change as part of the historical state will use the\n // post value (barring any follow-up changes)\n\n if block_number < self.block_of_change {\n self.pre\n } else {\n self.post\n }\n }\n\n /// Returns the scheduled change, i.e. the post-change value and the block at which it will become the current\n /// value. Note that this block may be in the past if the change has already taken place.\n /// Additionally, further changes might be later scheduled, potentially canceling the one returned by this function.\n pub fn get_scheduled(self) -> (T, u32) {\n (self.post, self.block_of_change)\n }\n\n /// Returns the largest block number at which the value returned by `get_current_at` is known to remain the current\n /// value. This value is only meaningful in private when constructing a proof at some `historical_block_number`,\n /// since due to its asynchronous nature private execution cannot know about any later scheduled changes.\n /// The caller of this function must know how quickly the value can change due to a scheduled change in the form of\n /// `minimum_delay`. If the delay itself is immutable, then this is just its duration. If the delay is mutable\n /// however, then this value is the 'effective minimum delay' (obtained by calling\n /// `ScheduledDelayChange.get_effective_minimum_delay_at`), which equals the minimum number of blocks that need to\n /// elapse from the next block until the value changes, regardless of further delay changes.\n /// The value returned by `get_current_at` in private when called with a historical block number is only safe to use\n /// if the transaction's `max_block_number` property is set to a value lower or equal to the block horizon computed\n /// using the same historical block number.\n pub fn get_block_horizon(self, historical_block_number: u32, minimum_delay: u32) -> u32 {\n // The block horizon is the very last block in which the current value is known. Any block past the horizon\n // (i.e. with a block number larger than the block horizon) may have a different current value. Reading the\n // current value in private typically requires constraining the maximum valid block number to be equal to the\n // block horizon.\n\n if historical_block_number >= self.block_of_change {\n // Once the block of change has been mined, the current value (post) will not change unless a new value\n // change is scheduled. This did not happen at the historical block number (or else it would not be\n // greater or equal to the block of change), and therefore could only happen after the historical block\n // number. The earliest would be the immediate next block, and so the smallest possible next block of change\n // equals `historical_block_number + 1 + minimum_delay`. Our block horizon is simply the previous block to\n // that one.\n //\n // block of historical\n // change block block horizon\n // =======|=============N===================H===========>\n // ^ ^\n // ---------------------\n // minimum delay\n\n historical_block_number + minimum_delay\n } else {\n // If the block of change has not yet been mined however, then there are two possible scenarios.\n // a) It could be so far into the future that the block horizon is actually determined by the minimum\n // delay, because a new change could be scheduled and take place _before_ the currently scheduled one.\n // This is similar to the scenario where the block of change is in the past: the time horizon is the\n // block prior to the earliest one in which a new block of change might land.\n //\n // historical\n // block block horizon block of change\n // =====N=================================H=================|=========>\n // ^ ^\n // | |\n // -----------------------------------\n // minimum delay\n //\n // b) It could be fewer than `minimum_delay` blocks away from the historical block number, in which case\n // the block of change would become the limiting factor for the time horizon, which would equal the\n // block right before the block of change (since by definition the value changes at the block of\n // change).\n //\n // historical block horizon\n // block block of change if not scheduled\n // =======N=============|===================H=================>\n // ^ ^ ^\n // | actual horizon |\n // -----------------------------------\n // minimum delay\n //\n // Note that the current implementation does not allow the caller to set the block of change to an arbitrary\n // value, and therefore scenario a) is not currently possible. However implementing #5501 would allow for\n // this to happen.\n\n // Because historical_block_number < self.block_of_change, then block_of_change > 0 and we can safely\n // subtract 1.\n min(\n self.block_of_change - 1,\n historical_block_number + minimum_delay\n )\n }\n }\n\n /// Mutates the value by scheduling a change at the current block number. This function is only meaningful when\n /// called in public with the current block number.\n pub fn schedule_change(\n &mut self,\n new_value: T,\n current_block_number: u32,\n minimum_delay: u32,\n block_of_change: u32\n ) {\n assert(block_of_change >= current_block_number + minimum_delay);\n\n self.pre = self.get_current_at(current_block_number);\n self.post = new_value;\n self.block_of_change = block_of_change;\n }\n}\n\nimpl<T> Serialize<3> for ScheduledValueChange<T> {\n fn serialize(self) -> [Field; 3] where T: ToField {\n [self.pre.to_field(), self.post.to_field(), self.block_of_change.to_field()]\n }\n}\n\nimpl<T> Deserialize<3> for ScheduledValueChange<T> {\n fn deserialize(input: [Field; 3]) -> Self where T: FromField {\n Self {\n pre: FromField::from_field(input[0]),\n post: FromField::from_field(input[1]),\n block_of_change: FromField::from_field(input[2]),\n }\n }\n}\n" }, "144": { "path": "/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr", "source": "use dep::protocol_types::{hash::pedersen_hash, traits::FromField};\n\nuse crate::context::{PrivateContext, PublicContext};\nuse crate::public_storage;\nuse crate::state_vars::{\n storage::Storage,\n shared_mutable::{scheduled_value_change::ScheduledValueChange, scheduled_delay_change::ScheduledDelayChange}\n};\n\nmod test;\n\nstruct SharedMutable<T, INITIAL_DELAY, Context> {\n context: Context,\n storage_slot: Field,\n}\n\n// This will make the Aztec macros require that T implements the Serialize<N> trait, and allocate N storage slots to\n// this state variable. This is incorrect, since what we actually store is:\n// - a ScheduledValueChange<T>, which requires 1 + 2 * M storage slots, where M is the serialization length of T\n// - a ScheduledDelayChange, which requires another storage slot\n//\n// TODO https://github.com/AztecProtocol/aztec-packages/issues/5736: change the storage allocation scheme so that we \n// can actually use it here\nimpl<T, INITIAL_DELAY, Context> Storage<T> for SharedMutable<T, INITIAL_DELAY, Context> {}\n\n// SharedMutable<T> stores a value of type T that is:\n// - publicly known (i.e. unencrypted)\n// - mutable in public\n// - readable in private with no contention (i.e. multiple parties can all read the same value without blocking one\n// another nor needing to coordinate)\n// This is famously a hard problem to solve. SharedMutable makes it work by introducing a delay to public mutation:\n// the value is not changed immediately but rather a value change is scheduled to happen in the future after some delay\n// measured in blocks. Reads in private are only valid as long as they are included in a block not too far into the \n// future, so that they can guarantee the value will not have possibly changed by then (because of the delay).\n// The delay for changing a value is initially equal to INITIAL_DELAY, but can be changed by calling \n// `schedule_delay_change`.\nimpl<T, INITIAL_DELAY, Context> SharedMutable<T, INITIAL_DELAY, Context> {\n pub fn new(context: Context, storage_slot: Field) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Self { context, storage_slot }\n }\n\n // Since we can't rely on the native storage allocation scheme, we hash the storage slot to get a unique location in\n // which we can safely store as much data as we need. \n // See https://github.com/AztecProtocol/aztec-packages/issues/5492 and \n // https://github.com/AztecProtocol/aztec-packages/issues/5736\n fn get_value_change_storage_slot(self) -> Field {\n pedersen_hash([self.storage_slot, 0], 0)\n }\n\n fn get_delay_change_storage_slot(self) -> Field {\n pedersen_hash([self.storage_slot, 1], 0)\n }\n}\n\nimpl<T, INITIAL_DELAY> SharedMutable<T, INITIAL_DELAY, &mut PublicContext> {\n pub fn schedule_value_change(self, new_value: T) {\n let mut value_change = self.read_value_change();\n let delay_change = self.read_delay_change();\n\n let block_number = self.context.block_number() as u32;\n let current_delay = delay_change.get_current(block_number);\n\n // TODO: make this configurable\n // https://github.com/AztecProtocol/aztec-packages/issues/5501\n let block_of_change = block_number + current_delay;\n value_change.schedule_change(new_value, block_number, current_delay, block_of_change);\n\n self.write_value_change(value_change);\n }\n\n pub fn schedule_delay_change(self, new_delay: u32) {\n let mut delay_change = self.read_delay_change();\n\n let block_number = self.context.block_number() as u32;\n\n delay_change.schedule_change(new_delay, block_number);\n\n self.write_delay_change(delay_change);\n }\n\n pub fn get_current_value_in_public(self) -> T {\n let block_number = self.context.block_number() as u32;\n self.read_value_change().get_current_at(block_number)\n }\n\n pub fn get_current_delay_in_public(self) -> u32 {\n let block_number = self.context.block_number() as u32;\n self.read_delay_change().get_current(block_number)\n }\n\n pub fn get_scheduled_value_in_public(self) -> (T, u32) {\n self.read_value_change().get_scheduled()\n }\n\n pub fn get_scheduled_delay_in_public(self) -> (u32, u32) {\n self.read_delay_change().get_scheduled()\n }\n\n fn read_value_change(self) -> ScheduledValueChange<T> {\n public_storage::read(self.get_value_change_storage_slot())\n }\n\n fn read_delay_change(self) -> ScheduledDelayChange<INITIAL_DELAY> {\n public_storage::read(self.get_delay_change_storage_slot())\n }\n\n fn write_value_change(self, value_change: ScheduledValueChange<T>) {\n public_storage::write(self.get_value_change_storage_slot(), value_change);\n }\n\n fn write_delay_change(self, delay_change: ScheduledDelayChange<INITIAL_DELAY>) {\n public_storage::write(self.get_delay_change_storage_slot(), delay_change);\n }\n}\n\nimpl<T, INITIAL_DELAY> SharedMutable<T, INITIAL_DELAY, &mut PrivateContext> {\n pub fn get_current_value_in_private(self) -> T where T: FromField {\n // When reading the current value in private we construct a historical state proof for the public value.\n // However, since this value might change, we must constrain the maximum transaction block number as this proof\n // will only be valid for however many blocks we can ensure the value will not change, which will depend on the\n // current delay and any scheduled delay changes.\n\n let (value_change, delay_change, historical_block_number) = self.historical_read_from_public_storage(*self.context);\n\n // We use the effective minimum delay as opposed to the current delay at the historical block as this one also\n // takes into consideration any scheduled delay changes. \n // For example, consider a scenario in which at block 200 the current delay was 50. We may naively think that\n // the earliest we could change the value would be at block 251 by scheduling immediately after the historical\n // block, i.e. at block 201. But if there was a delay change scheduled for block 210 to reduce the delay to 20 \n // blocks, then if a value change was scheduled at block 210 it would go into effect at block 230, which is \n // earlier than what we'd expect if we only considered the current delay.\n let effective_minimum_delay = delay_change.get_effective_minimum_delay_at(historical_block_number);\n let block_horizon = value_change.get_block_horizon(historical_block_number, effective_minimum_delay);\n\n // We prevent this transaction from being included in any block after the block horizon, ensuring that the \n // historical public value matches the current one, since it can only change after the horizon.\n self.context.set_tx_max_block_number(block_horizon);\n value_change.get_current_at(historical_block_number)\n }\n\n fn historical_read_from_public_storage(\n self,\n context: PrivateContext\n ) -> (ScheduledValueChange<T>, ScheduledDelayChange<INITIAL_DELAY>, u32) where T: FromField {\n let header = context.get_header();\n // Ideally the following would be simply public_storage::read_historical, but we can't implement that yet.\n let value_change_slot = self.get_value_change_storage_slot();\n let mut raw_value_change_fields = [0; 3];\n for i in 0..3 {\n raw_value_change_fields[i] = header.public_storage_historical_read(\n value_change_slot + i as Field,\n context.this_address()\n );\n }\n\n // Ideally the following would be simply public_storage::read_historical, but we can't implement that yet.\n let delay_change_slot = self.get_delay_change_storage_slot();\n let raw_delay_change_fields = [header.public_storage_historical_read(delay_change_slot, context.this_address())];\n\n let value_change = ScheduledValueChange::deserialize(raw_value_change_fields);\n let delay_change = ScheduledDelayChange::deserialize(raw_delay_change_fields);\n\n let historical_block_number = context.historical_header.global_variables.block_number as u32;\n\n (value_change, delay_change, historical_block_number)\n }\n}\n" }, "173": { "path": "/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr", "source": "use crate::utils::field::field_from_bytes;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Serialize, Deserialize, FromField, ToField, Empty};\n\nglobal SELECTOR_SIZE = 4;\n\nstruct FunctionSelector {\n // 1st 4-bytes of abi-encoding of function.\n inner: u32,\n}\n\nimpl Eq for FunctionSelector {\n fn eq(self, function_selector: FunctionSelector) -> bool {\n function_selector.inner == self.inner\n }\n}\n\nimpl Serialize<1> for FunctionSelector {\n fn serialize(self: Self) -> [Field; 1] {\n [self.inner as Field]\n }\n}\n\nimpl Deserialize<1> for FunctionSelector {\n fn deserialize(fields: [Field; 1]) -> Self {\n Self {\n inner: fields[0] as u32\n }\n }\n}\n\nimpl FromField for FunctionSelector {\n fn from_field(field: Field) -> Self {\n Self { inner: field as u32 }\n }\n}\n\nimpl ToField for FunctionSelector {\n fn to_field(self) -> Field {\n self.inner as Field\n }\n}\n\nimpl Empty for FunctionSelector {\n fn empty() -> Self {\n Self { inner: 0 as u32 }\n }\n}\n\nimpl FunctionSelector {\n pub fn from_u32(value: u32) -> Self {\n Self { inner: value }\n }\n\n pub fn from_signature<N>(signature: str<N>) -> Self {\n let bytes = signature.as_bytes();\n let hash = dep::std::hash::keccak256(bytes, bytes.len() as u32);\n\n let mut selector_be_bytes = [0; SELECTOR_SIZE];\n for i in 0..SELECTOR_SIZE {\n selector_be_bytes[i] = hash[i];\n }\n\n FunctionSelector::from_field(field_from_bytes(selector_be_bytes, true))\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n" }, "208": { "path": "/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/storage/map.nr", "source": "use crate::{hash::pedersen_hash, traits::ToField};\n\npub fn derive_storage_slot_in_map<K>(storage_slot: Field, key: K) -> Field where K: ToField {\n pedersen_hash([storage_slot, key.to_field()], 0)\n}\n" }, "215": { "path": "/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/type_serialization.nr", "source": "use crate::traits::{Serialize, Deserialize};\n\nglobal BOOL_SERIALIZED_LEN: Field = 1;\nglobal U8_SERIALIZED_LEN: Field = 1;\nglobal U32_SERIALIZED_LEN: Field = 1;\nglobal U64_SERIALIZED_LEN: Field = 1;\nglobal U128_SERIALIZED_LEN: Field = 1;\nglobal FIELD_SERIALIZED_LEN: Field = 1;\n\nimpl Serialize<BOOL_SERIALIZED_LEN> for bool {\n fn serialize(self) -> [Field; BOOL_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize<BOOL_SERIALIZED_LEN> for bool {\n fn deserialize(fields: [Field; BOOL_SERIALIZED_LEN]) -> bool {\n fields[0] as bool\n }\n}\n\nimpl Serialize<U8_SERIALIZED_LEN> for u8 {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize<U8_SERIALIZED_LEN> for u8 {\n fn deserialize(fields: [Field; U8_SERIALIZED_LEN]) -> Self {\n fields[0] as u8\n }\n}\n\nimpl Serialize<U32_SERIALIZED_LEN> for u32 {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize<U32_SERIALIZED_LEN> for u32 {\n fn deserialize(fields: [Field; U32_SERIALIZED_LEN]) -> Self {\n fields[0] as u32\n }\n}\n\nimpl Serialize<U64_SERIALIZED_LEN> for u64 {\n fn serialize(self) -> [Field; U64_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize<U64_SERIALIZED_LEN> for u64 {\n fn deserialize(fields: [Field; U64_SERIALIZED_LEN]) -> Self {\n fields[0] as u64\n }\n}\n\nimpl Serialize<U128_SERIALIZED_LEN> for U128 {\n fn serialize(self) -> [Field; 1] {\n [self.to_integer()]\n }\n\n}\n\nimpl Deserialize<U128_SERIALIZED_LEN> for U128 {\n fn deserialize(fields: [Field; U128_SERIALIZED_LEN]) -> Self {\n U128::from_integer(fields[0])\n }\n}\n\nimpl Serialize<FIELD_SERIALIZED_LEN> for Field {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self]\n }\n}\n\nimpl Deserialize<FIELD_SERIALIZED_LEN> for Field {\n fn deserialize(fields: [Field; FIELD_SERIALIZED_LEN]) -> Self {\n fields[0]\n }\n}\n" }, "216": { "path": "/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/traits.nr", "source": "use dep::std::cmp::Eq;\nuse crate::utils::field::field_from_bytes;\n\n// Trait: is_empty\n//\n// The general is_empty trait checks if a data type is is empty,\n// and it defines empty for the basic data types as 0.\n//\n// If a Field is equal to zero, then it is regarded as zero.\n// We will go with this definition for now, however it can be problematic \n// if a value can actually be zero. In a future refactor, we can \n// use the optional type for safety. Doing it now would lead to a worse devex\n// and would make it harder to sync up with the cpp code.\n// Preferred over Default trait to convey intent, as default doesn't necessarily mean empty.\ntrait Empty {\n fn empty() -> Self;\n}\n\nimpl Empty for Field { fn empty() -> Self {0} }\n\nimpl Empty for u1 { fn empty() -> Self {0} }\nimpl Empty for u8 { fn empty() -> Self {0} }\nimpl Empty for u32 { fn empty() -> Self {0} }\nimpl Empty for u64 { fn empty() -> Self {0} }\nimpl Empty for U128 { fn empty() -> Self {U128::from_integer(0)} }\n\npub fn is_empty<T>(item: T) -> bool where T: Empty + Eq {\n item.eq(T::empty())\n}\n\npub fn is_empty_array<T, N>(array: [T; N]) -> bool where T: Empty + Eq {\n array.all(|elem| is_empty(elem))\n}\n\ntrait Hash {\n fn hash(self) -> Field;\n}\n\ntrait ToField {\n fn to_field(self) -> Field;\n}\n\nimpl ToField for Field {\n fn to_field(self) -> Field {\n self\n }\n}\n\nimpl ToField for bool { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u1 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u8 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u32 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u64 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for U128 {\n fn to_field(self) -> Field {\n self.to_integer()\n }\n}\nimpl<N> ToField for str<N> {\n fn to_field(self) -> Field {\n assert(N < 32, \"String doesn't fit in a field, consider using Serialize instead\");\n field_from_bytes(self.as_bytes(), true)\n }\n}\n\ntrait FromField {\n fn from_field(value: Field) -> Self;\n}\n\nimpl FromField for Field {\n fn from_field(value: Field) -> Self {\n value\n }\n}\n\nimpl FromField for bool { fn from_field(value: Field) -> Self { value as bool } }\nimpl FromField for u1 { fn from_field(value: Field) -> Self { value as u1 } }\nimpl FromField for u8 { fn from_field(value: Field) -> Self { value as u8 } }\nimpl FromField for u32 { fn from_field(value: Field) -> Self { value as u32 } }\nimpl FromField for u64 { fn from_field(value: Field) -> Self { value as u64 } }\nimpl FromField for U128 {\n fn from_field(value: Field) -> Self {\n U128::from_integer(value)\n }\n}\n\n// docs:start:serialize\ntrait Serialize<N> {\n fn serialize(self) -> [Field; N];\n}\n// docs:end:serialize\n\nimpl<N> Serialize<N> for str<N> {\n fn serialize(self) -> [Field; N] {\n let mut result = [0; N];\n let bytes: [u8; N] = self.as_bytes();\n for i in 0..N {\n result[i] = field_from_bytes([bytes[i];1], true);\n }\n result\n }\n}\n\n// docs:start:deserialize\ntrait Deserialize<N> {\n fn deserialize(fields: [Field; N]) -> Self;\n}\n// docs:end:deserialize" }, "22": { "path": "std/field.nr", "source": "mod bn254;\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n pub fn to_le_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_le_bits(bit_size)\n }\n\n pub fn to_be_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_be_bits(bit_size)\n }\n\n #[builtin(to_le_bits)]\n fn __to_le_bits(self, _bit_size: u32) -> [u1] {}\n\n #[builtin(to_be_bits)]\n fn __to_be_bits(self, bit_size: u32) -> [u1] {}\n\n #[builtin(apply_range_constraint)]\n fn __assert_max_bit_size(self, bit_size: u32) {}\n\n pub fn assert_max_bit_size(self: Self, bit_size: u32) {\n crate::assert_constant(bit_size);\n assert(bit_size < modulus_num_bits() as u32);\n self.__assert_max_bit_size(bit_size);\n }\n\n pub fn to_le_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_le_radix(256, byte_size)\n }\n\n pub fn to_be_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_be_radix(256, byte_size)\n }\n\n pub fn to_le_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_le_radix(radix, result_len)\n }\n\n pub fn to_be_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_be_radix(radix, result_len)\n }\n\n // decompose `_self` into a `_result_len` vector over the `_radix` basis\n // `_radix` must be less than 256\n #[builtin(to_le_radix)]\n fn __to_le_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n #[builtin(to_be_radix)]\n fn __to_be_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b = exponent.to_le_bits(32);\n\n for i in 1..33 {\n r *= r;\n r = (b[32-i] as Field) * (r * self) + (1 - b[32-i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n}\n\n#[builtin(modulus_num_bits)]\npub fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub fn modulus_le_bytes() -> [u8] {}\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n let num_bytes = (modulus_num_bits() as u32 + 7) / 8;\n let x_bytes = x.to_le_bytes(num_bytes);\n let y_bytes = y.to_le_bytes(num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i] as u8;\n let y_byte = y_bytes[num_bytes - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\n" }, "224": { "path": "/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr", "source": "use crate::address::{AztecAddress, EthAddress};\nuse crate::recursion::verification_key::VerificationKey;\nuse crate::abis::function_selector::FunctionSelector;\nuse crate::abis::contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage;\nuse crate::contract_class_id::ContractClassId;\nuse crate::abis::log_hash::LogHash;\nuse crate::traits::is_empty;\nuse crate::utils::{uint256::U256, field::field_from_bytes_32_trunc};\nuse crate::constants::{\n FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER,\n GENERATOR_INDEX__VK, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH,\n MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX\n};\nuse crate::traits::Hash;\nuse crate::messaging::l2_to_l1_message::L2ToL1Message;\nuse crate::merkle_tree::root::root_from_sibling_path;\nuse dep::std::hash::{pedersen_hash_with_separator, sha256};\n\npub fn sha256_to_field<N>(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256(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(function_leaf, function_leaf_index, function_leaf_sibling_path)\n}\n\npub fn compute_note_hash_nonce(first_nullifier: Field, note_hash_index: u64) -> Field {\n pedersen_hash(\n [\n first_nullifier,\n note_hash_index as Field\n ],\n GENERATOR_INDEX__NOTE_HASH_NONCE\n )\n}\n\npub fn compute_unique_note_hash(nonce: Field, note_hash: Field) -> Field {\n pedersen_hash(\n [\n nonce,\n note_hash\n ],\n GENERATOR_INDEX__UNIQUE_NOTE_HASH\n )\n}\n\npub fn silo_note_hash(address: AztecAddress, unique_note_hash: Field) -> Field {\n pedersen_hash(\n [\n address.to_field(),\n unique_note_hash\n ],\n GENERATOR_INDEX__SILOED_NOTE_HASH\n )\n}\n\npub fn silo_nullifier(address: AztecAddress, nullifier: Field) -> Field {\n pedersen_hash(\n [\n address.to_field(),\n nullifier\n ],\n GENERATOR_INDEX__OUTER_NULLIFIER\n )\n}\n\npub fn silo_encrypted_log(address: AztecAddress, randomness: Field, log_hash: Field) -> Field {\n // TODO: Using 0 GENERATOR_INDEX here as interim before we move to posiedon\n // NB: A unique separator will be needed for masked_contract_address\n let mut masked_contract_address = pedersen_hash([address.to_field(), randomness], 0);\n if randomness == 0 {\n // In some cases, we actually want to reveal the contract address we are siloing with:\n // e.g. 'handshaking' contract w/ known address\n // An app providing randomness = 0 signals to not mask the address.\n masked_contract_address = address.to_field();\n }\n accumulate_sha256([masked_contract_address, log_hash])\n}\n\npub fn silo_unencrypted_log(address: AztecAddress, log_hash: Field) -> Field {\n accumulate_sha256([address.to_field(), log_hash])\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n pedersen_hash([left, right], 0)\n}\n\npub fn stdlib_recursion_verification_key_compress_native_vk(_vk: VerificationKey) -> Field {\n // Original cpp code\n // stdlib::recursion::verification_key<CT::bn254>::compress_native(private_call.vk, GeneratorIndex::VK);\n // The above cpp method is only ever called on verification key, so it has been special cased here\n let _hash_index = GENERATOR_INDEX__VK;\n 0\n}\n\npub fn compute_l2_to_l1_hash(\n contract_address: AztecAddress,\n rollup_version_id: Field,\n chain_id: Field,\n message: L2ToL1Message\n) -> Field {\n let mut bytes: BoundedVec<u8, 160> = BoundedVec::new();\n\n let inputs = [\n contract_address.to_field(), rollup_version_id, message.recipient.to_field(), chain_id, message.content\n ];\n for i in 0..inputs.len() {\n // TODO are bytes be in fr.to_buffer() ?\n let item_bytes = inputs[i].to_be_bytes(32);\n for j in 0..32 {\n bytes.push(item_bytes[j]);\n }\n }\n\n sha256_to_field(bytes.storage)\n}\n\n// Computes sha256 hash of 2 input hashes.\n//\n// NB: This method now takes in two 31 byte fields - it assumes that any input\n// is the result of a sha_to_field hash and => is truncated\n//\n// TODO(Jan and David): This is used for the encrypted_log hashes.\n// Can we check to see if we can just use hash_to_field or pedersen_compress here?\n//\npub fn accumulate_sha256(input: [Field; 2]) -> Field {\n // This is a note about the cpp code, since it takes an array of Fields\n // instead of a U128.\n // 4 Field elements when converted to bytes will usually \n // occupy 4 * 32 = 128 bytes.\n // However, this function is making the assumption that each Field \n // only occupies 128 bits.\n //\n // TODO(David): This does not seem to be getting guaranteed anywhere in the code?\n\n // Concatentate two fields into 32x2 = 64 bytes\n // accumulate_sha256 assumes that the inputs are pre-truncated 31 byte numbers\n let mut hash_input_flattened = [0; 64];\n for offset in 0..input.len() {\n let input_as_bytes = input[offset].to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n\n sha256_to_field(hash_input_flattened)\n}\n\n// Computes the final logs hash for a tx.\n// NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX\n// to avoid doubling code, since we can't define the byte len to be 32*N directly. \npub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn compute_tx_note_logs_hash(logs: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_NOTE_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn pedersen_hash<N>(inputs: [Field; N], hash_index: u32) -> Field {\n dep::std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash<N>(inputs: [Field; N]) -> Field {\n dep::std::hash::poseidon2::Poseidon2::hash(inputs, N)\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,\n 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\n 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\n 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\n 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\n 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\n 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\n 140, 141, 142, 143, 144, 145, 146, 147, 148, 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(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 compute_l2_l1_hash() {\n // All zeroes\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(0), 0, 0, L2ToL1Message::empty());\n assert(hash_result == 0xb393978842a0fa3d3e1470196f098f473f9678e72463cb65ec4ab5581856c2);\n\n // Non-zero case\n let message = L2ToL1Message { recipient: EthAddress::from_field(3), content: 5, counter: 1234 };\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(1), 2, 4, message);\n assert(hash_result == 0x3f88c1044a05e5340ed20466276500f6d45ca5603913b9091e957161734e16);\n}\n" }, "246": { "path": "/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils/field.nr", "source": "pub fn field_from_bytes<N>(bytes: [u8; N], big_endian: bool) -> Field {\n assert(bytes.len() < 32, \"field_from_bytes: N must be less than 32\");\n let mut as_field = 0;\n let mut offset = 1;\n for i in 0..N {\n let mut index = i;\n if big_endian {\n index = N - i - 1;\n }\n as_field += (bytes[index] as Field) * offset;\n offset *= 256;\n }\n\n as_field\n}\n\n// Convert a 32 byte array to a field element by truncating the final byte\npub fn field_from_bytes_32_trunc(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..15 {\n // covers bytes 16..30 (31 is truncated and ignored)\n low = low + (bytes32[15 + 15 - i] as Field) * v;\n v = v * 256;\n // covers bytes 0..14\n high = high + (bytes32[14 - i] as Field) * v;\n }\n // covers byte 15\n low = low + (bytes32[15] as Field) * v;\n\n low + high * v\n}\n\n// TODO to radix returns u8, so we cannot use bigger radixes. It'd be ideal to use a radix of the maximum range-constrained integer noir supports\npub fn full_field_less_than(lhs: Field, rhs: Field) -> bool {\n lhs.lt(rhs)\n}\n\npub fn full_field_greater_than(lhs: Field, rhs: Field) -> bool {\n rhs.lt(lhs)\n}\n\n#[test]\nunconstrained fn bytes_field_test() {\n // Tests correctness of field_from_bytes_32_trunc against existing methods\n // Bytes representing 0x543e0a6642ffeb8039296861765a53407bba62bd1c97ca43374de950bbe0a7\n let inputs = [\n 84, 62, 10, 102, 66, 255, 235, 128, 57, 41, 104, 97, 118, 90, 83, 64, 123, 186, 98, 189, 28, 151, 202, 67, 55, 77, 233, 80, 187, 224, 167\n ];\n let field = field_from_bytes(inputs, true);\n let return_bytes = field.to_be_bytes(31);\n for i in 0..31 {\n assert_eq(inputs[i], return_bytes[i]);\n }\n // 32 bytes - we remove the final byte, and check it matches the field\n let inputs2 = [\n 84, 62, 10, 102, 66, 255, 235, 128, 57, 41, 104, 97, 118, 90, 83, 64, 123, 186, 98, 189, 28, 151, 202, 67, 55, 77, 233, 80, 187, 224, 167, 158\n ];\n let field2 = field_from_bytes_32_trunc(inputs2);\n let return_bytes2 = field.to_be_bytes(31);\n\n for i in 0..31 {\n assert_eq(return_bytes2[i], return_bytes[i]);\n }\n assert_eq(field2, field);\n}\n" }, "260": { "path": "/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr", "source": "use crate::{\n crate::address::{eth_address::EthAddress, partial_address::PartialAddress, public_keys_hash::PublicKeysHash},\n constants::{AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1},\n contract_class_id::ContractClassId, hash::poseidon2_hash, grumpkin_point::GrumpkinPoint,\n traits::{Empty, FromField, ToField, Serialize, Deserialize}, utils\n};\n\n// Aztec address\nstruct AztecAddress {\n inner : Field\n}\n\nimpl Eq for AztecAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\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 Serialize<AZTEC_ADDRESS_LENGTH> for AztecAddress {\n fn serialize(self: Self) -> [Field; AZTEC_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize<AZTEC_ADDRESS_LENGTH> for AztecAddress {\n fn deserialize(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self {\n FromField::from_field(fields[0])\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn compute(pub_keys_hash: PublicKeysHash, partial_address: PartialAddress) -> AztecAddress {\n AztecAddress::from_field(\n poseidon2_hash([pub_keys_hash.to_field(), partial_address.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1])\n )\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 pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n\n#[test]\nfn compute_address_from_partial_and_pub_keys_hash() {\n let pub_keys_hash = PublicKeysHash::from_field(1);\n let partial_address = PartialAddress::from_field(2);\n\n let address = AztecAddress::compute(pub_keys_hash, partial_address);\n let expected_computed_address_from_partial_and_pubkey = 0x1b6ead051e7b42665064ca6cf1ec77da0a36d86e00d1ff6e44077966c0c3a9fa;\n assert(address.to_field() == expected_computed_address_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 assert_eq(Deserialize::deserialize(address.serialize()), address);\n}\n" }, "28": { "path": "std/hash/poseidon2.nr", "source": "use crate::hash::Hasher;\nuse crate::default::Default;\n\nglobal RATE: u32 = 3;\n\nstruct 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\n pub fn hash<N>(input: [Field; N], message_size: u64) -> Field {\n if message_size == N {\n Poseidon2::hash_internal(input, N, false)\n } else {\n Poseidon2::hash_internal(input, message_size, true)\n }\n }\n\n fn new(iv: Field) -> Poseidon2 {\n let mut result = 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) -> [Field; RATE] {\n // zero-pad the cache\n for i in 0..RATE {\n if i >= self.cache_size {\n self.cache[i] = 0;\n }\n }\n // add the cache into sponge state\n for i in 0..RATE {\n self.state[i] += self.cache[i];\n }\n self.state = crate::hash::poseidon2_permutation(self.state, 4);\n // return `RATE` number of field elements from the sponge state.\n let mut result = [0; RATE];\n for i in 0..RATE {\n result[i] = self.state[i];\n }\n result\n }\n\n fn absorb(&mut self, input: Field) {\n if (!self.squeeze_mode) & (self.cache_size == RATE) {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n let _ = self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else if (!self.squeeze_mode) & (self.cache_size != RATE) {\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 } else if self.squeeze_mode {\n // If we're in squeeze mode, switch to absorb mode and add the input into the cache.\n // N.B. I don't think this code path can be reached?!\n self.cache[0] = input;\n self.cache_size = 1;\n self.squeeze_mode = false;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n if self.squeeze_mode & (self.cache_size == 0) {\n // If we're in squeze mode and the cache is empty, there is nothing left to squeeze out of the sponge!\n // Switch to absorb mode.\n self.squeeze_mode = false;\n self.cache_size = 0;\n }\n if !self.squeeze_mode {\n // If we're in absorb mode, apply sponge permutation to compress the cache, populate cache with compressed\n // state and switch to squeeze mode. Note: this code block will execute if the previous `if` condition was\n // matched\n let new_output_elements = self.perform_duplex();\n self.squeeze_mode = true;\n for i in 0..RATE {\n self.cache[i] = new_output_elements[i];\n }\n self.cache_size = RATE;\n }\n // By this point, we should have a non-empty cache. Pop one item off the top of the cache and return it.\n let result = self.cache[0];\n for i in 1..RATE {\n if i < self.cache_size {\n self.cache[i - 1] = self.cache[i];\n }\n }\n self.cache_size -= 1;\n self.cache[self.cache_size] = 0;\n result\n }\n\n fn hash_internal<N>(input: [Field; N], in_len: u64, is_variable_length: bool) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv : Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\nstruct 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 {\n _state: &[],\n }\n }\n}\n" }, "323": { "path": "/usr/src/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr", "source": "contract KeyRegistry {\n use dep::authwit::auth::assert_current_call_valid_authwit_public;\n\n use dep::aztec::{\n keys::PublicKeys, state_vars::{SharedMutable, Map},\n protocol_types::{grumpkin_point::GrumpkinPoint, address::{AztecAddress, PartialAddress}}\n };\n\n global KEY_ROTATION_DELAY = 5;\n\n #[aztec(storage)]\n struct Storage {\n // The following stores a hash of individual master public keys\n // If you change slots of vars below, you must update the slots in `SharedMutablePrivateGetter` in aztec-nr/keys.\n // We store x and y coordinates in individual shared mutables as shared mutable currently supports only 1 field\n npk_m_x_registry: Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY>>,\n npk_m_y_registry: Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY>>,\n\n ivpk_m_x_registry: Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY>>,\n ivpk_m_y_registry: Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY>>,\n \n ovpk_m_x_registry: Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY>>,\n ovpk_m_y_registry: Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY>>,\n \n tpk_m_x_registry: Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY>>,\n tpk_m_y_registry: Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY>>,\n }\n\n #[aztec(public)]\n fn rotate_npk_m(address: AztecAddress, new_npk_m: GrumpkinPoint, nonce: Field) {\n // TODO: (#6137)\n if (!address.eq(context.msg_sender())) {\n assert_current_call_valid_authwit_public(&mut context, address);\n } else {\n assert(nonce == 0, \"invalid nonce\");\n }\n\n let npk_m_x_registry = storage.npk_m_x_registry.at(address);\n let npk_m_y_registry = storage.npk_m_y_registry.at(address);\n npk_m_x_registry.schedule_value_change(new_npk_m.x);\n npk_m_y_registry.schedule_value_change(new_npk_m.y);\n }\n\n #[aztec(public)]\n fn register(address: AztecAddress, partial_address: PartialAddress, keys: PublicKeys) {\n let computed_address = AztecAddress::compute(keys.hash(), partial_address);\n\n assert(computed_address.eq(address), \"Computed address does not match supplied address\");\n\n let npk_m_x_registry = storage.npk_m_x_registry.at(address);\n let npk_m_y_registry = storage.npk_m_y_registry.at(address);\n let ivpk_m_x_registry = storage.ivpk_m_x_registry.at(address);\n let ivpk_m_y_registry = storage.ivpk_m_y_registry.at(address);\n let ovpk_m_x_registry = storage.ovpk_m_x_registry.at(address);\n let ovpk_m_y_registry = storage.ovpk_m_y_registry.at(address);\n let tpk_m_x_registry = storage.tpk_m_x_registry.at(address);\n let tpk_m_y_registry = storage.tpk_m_y_registry.at(address);\n\n npk_m_x_registry.schedule_value_change(keys.npk_m.x);\n npk_m_y_registry.schedule_value_change(keys.npk_m.y);\n ivpk_m_x_registry.schedule_value_change(keys.ivpk_m.x);\n ivpk_m_y_registry.schedule_value_change(keys.ivpk_m.y);\n ovpk_m_x_registry.schedule_value_change(keys.ovpk_m.x);\n ovpk_m_y_registry.schedule_value_change(keys.ovpk_m.y);\n tpk_m_x_registry.schedule_value_change(keys.tpk_m.x);\n tpk_m_y_registry.schedule_value_change(keys.tpk_m.y);\n }\n}\n" }, "44": { "path": "std/uint128.nr", "source": "use crate::ops::{Add, Sub, Mul, Div, Rem, Not, BitOr, BitAnd, BitXor, Shl, Shr};\nuse crate::cmp::{Eq, Ord, Ordering};\nuse crate::println;\n\nglobal pow64 : Field = 18446744073709551616; //2^64;\nglobal pow63 : Field = 9223372036854775808; // 2^63;\nstruct U128 {\n lo: Field,\n hi: Field,\n}\n\nimpl U128 {\n\n pub fn from_u64s_le(lo: u64, hi: u64) -> U128 {\n // in order to handle multiplication, we need to represent the product of two u64 without overflow\n assert(crate::field::modulus_num_bits() as u32 > 128);\n U128 { lo: lo as Field, hi: hi as Field }\n }\n\n pub fn from_u64s_be(hi: u64, lo: u64) -> U128 {\n U128::from_u64s_le(lo, hi)\n }\n\n pub fn zero() -> U128 {\n U128 { lo: 0, hi: 0 }\n }\n\n pub fn one() -> U128 {\n U128 { lo: 1, hi: 0 }\n }\n pub fn from_le_bytes(bytes: [u8; 16]) -> U128 {\n let mut lo = 0;\n let mut base = 1;\n for i in 0..8 {\n lo += (bytes[i] as Field)*base;\n base *= 256;\n }\n let mut hi = 0;\n base = 1;\n for i in 8..16 {\n hi += (bytes[i] as Field)*base;\n base *= 256;\n }\n U128 { lo, hi }\n }\n\n pub fn to_be_bytes(self: Self) -> [u8; 16] {\n let lo = self.lo.to_be_bytes(8);\n let hi = self.hi.to_be_bytes(8);\n let mut bytes = [0; 16];\n for i in 0..8 {\n bytes[i] = hi[i];\n bytes[i+8] = lo[i];\n }\n bytes\n }\n\n pub fn to_le_bytes(self: Self) -> [u8; 16] {\n let lo = self.lo.to_le_bytes(8);\n let hi = self.hi.to_le_bytes(8);\n let mut bytes = [0; 16];\n for i in 0..8 {\n bytes[i] = lo[i];\n bytes[i+8] = hi[i];\n }\n bytes\n }\n\n pub fn from_hex<N>(hex: str<N>) -> U128 {\n let N = N as u32;\n let bytes = hex.as_bytes();\n // string must starts with \"0x\"\n assert((bytes[0] == 48) & (bytes[1] == 120), \"Invalid hexadecimal string\");\n assert(N < 35, \"Input does not fit into a U128\");\n\n let mut lo = 0;\n let mut hi = 0;\n let mut base = 1;\n if N <= 18 {\n for i in 0..N - 2 {\n lo += U128::decode_ascii(bytes[N-i-1])*base;\n base = base*16;\n }\n } else {\n for i in 0..16 {\n lo += U128::decode_ascii(bytes[N-i-1])*base;\n base = base*16;\n }\n base = 1;\n for i in 17..N - 1 {\n hi += U128::decode_ascii(bytes[N-i])*base;\n base = base*16;\n }\n }\n U128 { lo: lo as Field, hi: hi as Field }\n }\n\n unconstrained fn uconstrained_check_is_upper_ascii(ascii: u8) -> bool {\n ((ascii >= 65) & (ascii <= 90)) // Between 'A' and 'Z'\n }\n\n fn decode_ascii(ascii: u8) -> Field {\n if ascii < 58 {\n ascii - 48\n } else {\n let ascii = ascii + 32 * (U128::uconstrained_check_is_upper_ascii(ascii) as u8);\n assert(ascii >= 97); // enforce >= 'a'\n assert(ascii <= 102); // enforce <= 'f'\n ascii - 87\n } as Field\n }\n\n // TODO: Replace with a faster version. \n // A circuit that uses this function can be slow to compute\n // (we're doing up to 127 calls to compute the quotient)\n unconstrained fn unconstrained_div(self: Self, b: U128) -> (U128, U128) {\n if b == U128::zero() {\n // Return 0,0 to avoid eternal loop\n (U128::zero(), U128::zero())\n } else if self < b {\n (U128::zero(), self)\n } else if self == b {\n (U128::one(), U128::zero())\n } else {\n let (q,r) = if b.hi as u64 >= pow63 as u64 {\n // The result of multiplication by 2 would overflow\n (U128::zero(), self)\n } else {\n self.unconstrained_div(b * U128::from_u64s_le(2, 0))\n };\n let q_mul_2 = q * U128::from_u64s_le(2, 0);\n if r < b {\n (q_mul_2, r)\n } else {\n (q_mul_2 + U128::one(), r - b)\n }\n }\n }\n\n pub fn from_integer<T>(i: T) -> U128 {\n let f = crate::as_field(i);\n // Reject values which would overflow a u128\n f.assert_max_bit_size(128);\n let lo = f as u64 as Field;\n let hi = (f - lo) / pow64;\n U128 { lo, hi }\n }\n\n pub fn to_integer<T>(self) -> T {\n crate::from_field(self.lo + self.hi * pow64)\n }\n\n fn wrapping_mul(self: Self, b: U128) -> U128 {\n let low = self.lo * b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64;\n let high = self.lo * b.hi + self.hi * b.lo + carry;\n let hi = high as u64 as Field;\n U128 { lo, hi }\n }\n}\n\nimpl Add for U128 {\n fn add(self: Self, b: U128) -> U128 {\n let low = self.lo + b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64; \n let high = self.hi + b.hi + carry;\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to add with overflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Sub for U128 {\n fn sub(self: Self, b: U128) -> U128 {\n let low = pow64 + self.lo - b.lo;\n let lo = low as u64 as Field;\n let borrow = (low == lo) as Field;\n let high = self.hi - b.hi - borrow;\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to subtract with underflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Mul for U128 {\n fn mul(self: Self, b: U128) -> U128 {\n assert(self.hi*b.hi == 0, \"attempt to multiply with overflow\");\n let low = self.lo*b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64;\n let high = if crate::field::modulus_num_bits() as u32 > 196 {\n (self.lo+self.hi)*(b.lo+b.hi) - low + carry\n } else {\n self.lo*b.hi + self.hi*b.lo + carry\n };\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to multiply with overflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Div for U128 {\n fn div(self: Self, b: U128) -> U128 {\n let (q,r) = self.unconstrained_div(b);\n let a = b * q + r;\n assert_eq(self, a);\n assert(r < b);\n q\n }\n}\n\nimpl Rem for U128 {\n fn rem(self: Self, b: U128) -> U128 {\n let (q,r) = self.unconstrained_div(b);\n let a = b * q + r;\n assert_eq(self, a);\n assert(r < b);\n r\n }\n}\n\nimpl Eq for U128 {\n fn eq(self: Self, b: U128) -> bool {\n (self.lo == b.lo) & (self.hi == b.hi)\n }\n}\n\nimpl Ord for U128 {\n fn cmp(self, other: Self) -> Ordering {\n let hi_ordering = (self.hi as u64).cmp((other.hi as u64));\n let lo_ordering = (self.lo as u64).cmp((other.lo as u64));\n \n if hi_ordering == Ordering::equal() {\n lo_ordering\n } else {\n hi_ordering\n }\n }\n}\n\nimpl Not for U128 { \n fn not(self) -> U128 {\n U128 {\n lo: (!(self.lo as u64)) as Field,\n hi: (!(self.hi as u64)) as Field\n }\n }\n}\n\nimpl BitOr for U128 { \n fn bitor(self, other: U128) -> U128 {\n U128 {\n lo: ((self.lo as u64) | (other.lo as u64)) as Field,\n hi: ((self.hi as u64) | (other.hi as u64)) as Field\n }\n }\n}\n\nimpl BitAnd for U128 {\n fn bitand(self, other: U128) -> U128 { \n U128 {\n lo: ((self.lo as u64) & (other.lo as u64)) as Field,\n hi: ((self.hi as u64) & (other.hi as u64)) as Field\n }\n }\n}\n\nimpl BitXor for U128 {\n fn bitxor(self, other: U128) -> U128 { \n U128 {\n lo: ((self.lo as u64) ^ (other.lo as u64)) as Field,\n hi: ((self.hi as u64) ^ (other.hi as u64)) as Field\n }\n }\n}\n\nimpl Shl for U128 { \n fn shl(self, other: u8) -> U128 { \n assert(other < 128, \"attempt to shift left with overflow\");\n let exp_bits = (other as Field).to_be_bits(7);\n\n let mut r: Field = 2;\n let mut y: Field = 1;\n for i in 1..8 {\n y = (exp_bits[7-i] as Field) * (r * y) + (1 - exp_bits[7-i] as Field) * y;\n r *= r;\n }\n self.wrapping_mul(U128::from_integer(y))\n } \n}\n\nimpl Shr for U128 { \n fn shr(self, other: u8) -> U128 { \n assert(other < 128, \"attempt to shift right with overflow\");\n let exp_bits = (other as Field).to_be_bits(7);\n\n let mut r: Field = 2;\n let mut y: Field = 1;\n for i in 1..8 {\n y = (exp_bits[7-i] as Field) * (r * y) + (1 - exp_bits[7-i] as Field) * y;\n r *= r;\n }\n self / U128::from_integer(y)\n } \n}\n\nmod tests {\n use crate::uint128::{U128, pow64, pow63};\n\n #[test]\n fn test_not() {\n let num = U128::from_u64s_le(0, 0);\n let not_num = num.not();\n\n let max_u64: Field = pow64 - 1;\n assert_eq(not_num.hi, max_u64);\n assert_eq(not_num.lo, max_u64);\n\n let not_not_num = not_num.not();\n assert_eq(num, not_not_num);\n }\n #[test]\n fn test_construction() {\n // Check little-endian u64 is inversed with big-endian u64 construction\n let a = U128::from_u64s_le(2, 1);\n let b = U128::from_u64s_be(1, 2);\n assert_eq(a, b);\n // Check byte construction is equivalent\n let c = U128::from_le_bytes([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);\n let d = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908);\n assert_eq(c, d);\n }\n #[test]\n fn test_byte_decomposition() {\n let a = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908);\n // Get big-endian and little-endian byte decompostions\n let le_bytes_a= a.to_le_bytes();\n let be_bytes_a= a.to_be_bytes();\n\n // Check equivalence\n for i in 0..16 {\n assert_eq(le_bytes_a[i], be_bytes_a[15 - i]);\n }\n // Reconstruct U128 from byte decomposition\n let b= U128::from_le_bytes(le_bytes_a);\n // Check that it's the same element\n assert_eq(a, b);\n }\n #[test]\n fn test_hex_constuction() {\n let a = U128::from_u64s_le(0x1, 0x2);\n let b = U128::from_hex(\"0x20000000000000001\");\n assert_eq(a, b);\n\n let c= U128::from_hex(\"0xffffffffffffffffffffffffffffffff\");\n let d= U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff);\n assert_eq(c, d);\n\n let e= U128::from_hex(\"0x00000000000000000000000000000000\");\n let f= U128::from_u64s_le(0, 0);\n assert_eq(e, f);\n }\n\n // Ascii decode tests\n\n #[test]\n fn test_ascii_decode_correct_range() {\n // '0'..'9' range\n for i in 0..10 {\n let decoded= U128::decode_ascii(48 + i);\n assert_eq(decoded, i as Field);\n }\n // 'A'..'F' range\n for i in 0..6 {\n let decoded = U128::decode_ascii(65 + i);\n assert_eq(decoded, (i + 10) as Field);\n }\n // 'a'..'f' range\n for i in 0..6 {\n let decoded = U128::decode_ascii(97 + i);\n assert_eq(decoded, (i + 10) as Field);\n }\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_range_less_than_48_fails_0() {\n crate::println(U128::decode_ascii(0));\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_less_than_48_fails_1() {\n crate::println(U128::decode_ascii(47));\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_range_58_64_fails_0() {\n let _ = U128::decode_ascii(58);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_58_64_fails_1() {\n let _ = U128::decode_ascii(64);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_71_96_fails_0() {\n let _ = U128::decode_ascii(71);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_71_96_fails_1() {\n let _ = U128::decode_ascii(96);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_greater_than_102_fails() {\n let _ = U128::decode_ascii(103);\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_regression() {\n // This code will actually fail because of ascii_decode,\n // but in the past it was possible to create a value > (1<<128)\n let a = U128::from_hex(\"0x~fffffffffffffffffffffffffffffff\");\n let b:Field= a.to_integer();\n let c= b.to_le_bytes(17);\n assert(c[16] != 0);\n }\n\n #[test]\n fn test_unconstrained_div() {\n // Test the potential overflow case\n let a= U128::from_u64s_le(0x0, 0xffffffffffffffff);\n let b= U128::from_u64s_le(0x0, 0xfffffffffffffffe);\n let c= U128::one();\n let d= U128::from_u64s_le(0x0, 0x1);\n let (q,r) = a.unconstrained_div(b);\n assert_eq(q, c);\n assert_eq(r, d);\n\n let a = U128::from_u64s_le(2, 0);\n let b = U128::one();\n // Check the case where a is a multiple of b\n let (c,d ) = a.unconstrained_div(b);\n assert_eq((c, d), (a, U128::zero()));\n\n // Check where b is a multiple of a\n let (c,d) = b.unconstrained_div(a);\n assert_eq((c, d), (U128::zero(), b));\n\n // Dividing by zero returns 0,0\n let a = U128::from_u64s_le(0x1, 0x0);\n let b = U128::zero();\n let (c,d)= a.unconstrained_div(b);\n assert_eq((c, d), (U128::zero(), U128::zero()));\n\n // Dividing 1<<127 by 1<<127 (special case)\n let a = U128::from_u64s_le(0x0, pow63 as u64);\n let b = U128::from_u64s_le(0x0, pow63 as u64);\n let (c,d )= a.unconstrained_div(b);\n assert_eq((c, d), (U128::one(), U128::zero()));\n }\n\n #[test]\n fn integer_conversions() {\n // Maximum\n let start:Field = 0xffffffffffffffffffffffffffffffff;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // Minimum\n let start:Field = 0x0;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // Low limb\n let start:Field = 0xffffffffffffffff;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // High limb\n let start:Field = 0xffffffffffffffff0000000000000000;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n }\n #[test]\n fn test_wrapping_mul() {\n // 1*0==0\n assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::one()));\n\n // 0*1==0\n assert_eq(U128::zero(), U128::one().wrapping_mul(U128::zero()));\n\n // 1*1==1\n assert_eq(U128::one(), U128::one().wrapping_mul(U128::one()));\n\n // 0 * ( 1 << 64 ) == 0\n assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::from_u64s_le(0, 1)));\n\n // ( 1 << 64 ) * 0 == 0\n assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::zero()));\n\n // 1 * ( 1 << 64 ) == 1 << 64\n assert_eq(U128::from_u64s_le(0, 1), U128::from_u64s_le(0, 1).wrapping_mul(U128::one()));\n\n // ( 1 << 64 ) * 1 == 1 << 64\n assert_eq(U128::from_u64s_le(0, 1), U128::one().wrapping_mul(U128::from_u64s_le(0, 1)));\n\n // ( 1 << 64 ) * ( 1 << 64 ) == 1 << 64\n assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::from_u64s_le(0, 1)));\n // -1 * -1 == 1\n assert_eq(\n U128::one(), U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff).wrapping_mul(U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff))\n );\n }\n}\n" }, "51": { "path": "/usr/src/noir-projects/aztec-nr/authwit/src/auth.nr", "source": "use dep::aztec::protocol_types::{\n abis::function_selector::FunctionSelector, address::AztecAddress,\n constants::{GENERATOR_INDEX__AUTHWIT_INNER, GENERATOR_INDEX__AUTHWIT_OUTER}, hash::pedersen_hash\n};\nuse dep::aztec::{prelude::Deserialize, context::{PrivateContext, PublicContext, gas::GasOpts}, hash::hash_args_array};\n\nglobal IS_VALID_SELECTOR = 0xabf64ad4; // 4 first bytes of keccak256(\"IS_VALID()\")\n\n// docs:start:assert_current_call_valid_authwit\n// Assert that `on_behalf_of` have authorized the current call with a valid authentication witness\npub fn assert_current_call_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress) {\n let function_selector = FunctionSelector::from_signature(\"spend_private_authwit(Field)\");\n let inner_hash = compute_inner_authwit_hash([context.msg_sender().to_field(), context.selector().to_field(), context.args_hash]);\n let result: Field = context.call_private_function(on_behalf_of, function_selector, [inner_hash]).unpack_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n}\n// docs:end:assert_current_call_valid_authwit\n\n// docs:start:assert_current_call_valid_authwit_public\n// Assert that `on_behalf_of` have authorized the current call in a public context\npub fn assert_current_call_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress) {\n let function_selector = FunctionSelector::from_signature(\"spend_public_authwit(Field)\");\n let inner_hash = compute_inner_authwit_hash(\n [(*context).msg_sender().to_field(), (*context).selector().to_field(), (*context).get_args_hash()]\n );\n let result: Field = context.call_public_function(\n on_behalf_of,\n function_selector,\n [inner_hash].as_slice(),\n GasOpts::default()\n ).deserialize_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n}\n// docs:end:assert_current_call_valid_authwit_public\n\n// docs:start:compute_call_authwit_hash\n// Compute the message hash to be used by an authentication witness \npub fn compute_call_authwit_hash<N>(\n caller: AztecAddress,\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n selector: FunctionSelector,\n args: [Field; N]\n) -> Field {\n let args_hash = hash_args_array(args);\n let inner_hash = compute_inner_authwit_hash([caller.to_field(), selector.to_field(), args_hash]);\n compute_outer_authwit_hash(consumer, chain_id, version, inner_hash)\n}\n// docs:end:compute_call_authwit_hash\n\npub fn compute_inner_authwit_hash<N>(args: [Field; N]) -> Field {\n pedersen_hash(args, GENERATOR_INDEX__AUTHWIT_INNER)\n}\n\npub fn compute_outer_authwit_hash(\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n inner_hash: Field\n) -> Field {\n pedersen_hash(\n [\n consumer.to_field(),\n chain_id,\n version,\n inner_hash\n ],\n GENERATOR_INDEX__AUTHWIT_OUTER\n )\n}\n" }, "62": { "path": "/usr/src/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr", "source": "use dep::protocol_types::{\n address::PublicKeysHash, constants::GENERATOR_INDEX__PUBLIC_KEYS_HASH, hash::poseidon2_hash,\n grumpkin_point::GrumpkinPoint, traits::{Deserialize, Serialize}\n};\nuse crate::keys::constants::{NUM_KEY_TYPES, NULLIFIER_INDEX, INCOMING_INDEX, OUTGOING_INDEX};\n\nglobal PUBLIC_KEYS_LENGTH = 8;\n\nstruct PublicKeys {\n npk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n ovpk_m: GrumpkinPoint,\n tpk_m: GrumpkinPoint,\n}\n\nimpl PublicKeys {\n pub fn hash(self) -> PublicKeysHash {\n PublicKeysHash::from_field(\n poseidon2_hash(\n [\n self.npk_m.x,\n self.npk_m.y,\n self.ivpk_m.x,\n self.ivpk_m.y,\n self.ovpk_m.x,\n self.ovpk_m.y,\n self.tpk_m.x,\n self.tpk_m.y,\n GENERATOR_INDEX__PUBLIC_KEYS_HASH\n ]\n )\n )\n }\n\n pub fn get_key_by_index(self, index: Field) -> GrumpkinPoint {\n assert(index as u8 < NUM_KEY_TYPES, \"Invalid key index\");\n if index == NULLIFIER_INDEX {\n self.npk_m\n } else if index == INCOMING_INDEX {\n self.ivpk_m\n } else if index == OUTGOING_INDEX {\n self.ovpk_m\n } else {\n self.tpk_m\n }\n }\n}\n\nimpl Serialize<PUBLIC_KEYS_LENGTH> for PublicKeys {\n fn serialize(self) -> [Field; PUBLIC_KEYS_LENGTH] {\n [\n self.npk_m.x,\n self.npk_m.y,\n self.ivpk_m.x,\n self.ivpk_m.y,\n self.ovpk_m.x,\n self.ovpk_m.y,\n self.tpk_m.x,\n self.tpk_m.y,\n ]\n }\n}\n\nimpl Deserialize<PUBLIC_KEYS_LENGTH> for PublicKeys {\n fn deserialize(serialized: [Field; PUBLIC_KEYS_LENGTH]) -> PublicKeys {\n PublicKeys {\n npk_m: GrumpkinPoint { x: serialized[0], y: serialized[1] },\n ivpk_m: GrumpkinPoint { x: serialized[2], y: serialized[3] },\n ovpk_m: GrumpkinPoint { x: serialized[4], y: serialized[5] },\n tpk_m: GrumpkinPoint { x: serialized[6], y: serialized[7] },\n }\n }\n}\n\n#[test]\nfn compute_public_keys_hash() {\n let keys = PublicKeys {\n npk_m: GrumpkinPoint { x: 1, y: 2 },\n ivpk_m: GrumpkinPoint { x: 3, y: 4 },\n ovpk_m: GrumpkinPoint { x: 5, y: 6 },\n tpk_m: GrumpkinPoint { x: 7, y: 8 }\n };\n\n let actual = keys.hash();\n let expected_public_keys_hash = 0x1936abe4f6a920d16a9f6917f10a679507687e2cd935dd1f1cdcb1e908c027f3;\n assert(actual.to_field() == expected_public_keys_hash);\n}\n\n#[test]\nfn test_public_keys_serialization() {\n let keys = PublicKeys {\n npk_m: GrumpkinPoint { x: 1, y: 2 },\n ivpk_m: GrumpkinPoint { x: 3, y: 4 },\n ovpk_m: GrumpkinPoint { x: 5, y: 6 },\n tpk_m: GrumpkinPoint { x: 7, y: 8 }\n };\n\n let serialized = keys.serialize();\n let deserialized = PublicKeys::deserialize(serialized);\n\n assert_eq(keys.npk_m.x, deserialized.npk_m.x);\n assert_eq(keys.npk_m.y, deserialized.npk_m.y);\n assert_eq(keys.ivpk_m.x, deserialized.ivpk_m.x);\n assert_eq(keys.ivpk_m.y, deserialized.ivpk_m.y);\n assert_eq(keys.ovpk_m.x, deserialized.ovpk_m.x);\n assert_eq(keys.ovpk_m.y, deserialized.ovpk_m.y);\n assert_eq(keys.tpk_m.x, deserialized.tpk_m.x);\n assert_eq(keys.tpk_m.y, deserialized.tpk_m.y);\n}\n" }, "63": { "path": "/usr/src/noir-projects/aztec-nr/aztec/src/public_storage.nr", "source": "use dep::protocol_types::traits::{Deserialize, Serialize};\nuse crate::oracle::storage::{storage_read, storage_write};\n\npub fn read<T, N>(storage_slot: Field) -> T where T: Deserialize<N> {\n T::deserialize(storage_read(storage_slot))\n}\n\npub fn write<T, N>(storage_slot: Field, value: T) where T: Serialize<N> {\n storage_write(storage_slot, value.serialize());\n}\n\n// Ideally we'd do the following, but we cannot because of https://github.com/noir-lang/noir/issues/4633\n// pub fn read_historical<T, N>(\n// storage_slot: Field,\n// context: PrivateContext\n// ) -> T where T: Deserialize<N> {\n// let mut fields = [0; N];\n// for i in 0..N {\n// fields[i] = public_storage_historical_read(\n// context,\n// storage_slot + i as Field,\n// context.this_address()\n// );\n// }\n// T::deserialize(fields)\n// }\n\nmod tests {\n use dep::std::test::OracleMock;\n use dep::protocol_types::traits::{Deserialize, Serialize};\n use crate::public_storage;\n\n struct TestStruct {\n a: Field,\n b: Field,\n }\n\n impl Deserialize<2> for TestStruct {\n fn deserialize(fields: [Field; 2]) -> TestStruct {\n TestStruct { a: fields[0], b: fields[1] }\n }\n }\n\n impl Serialize<2> for TestStruct {\n fn serialize(self) -> [Field; 2] {\n [self.a, self.b]\n }\n }\n\n #[test]\n fn test_read() {\n let slot = 7;\n let written = TestStruct { a: 13, b: 42 };\n\n OracleMock::mock(\"storageRead\").with_params((slot, 2)).returns(written.serialize());\n\n let read: TestStruct = public_storage::read(slot);\n assert_eq(read.a, 13);\n assert_eq(read.b, 42);\n }\n\n #[test]\n fn test_write() {\n let slot = 7;\n let to_write = TestStruct { a: 13, b: 42 };\n\n let mock = OracleMock::mock(\"storageWrite\").returns([0; 2]); // The return value is unused\n\n public_storage::write(slot, to_write);\n assert_eq(mock.get_last_params(), (slot, to_write.serialize()));\n }\n}\n" }, "85": { "path": "/usr/src/noir-projects/aztec-nr/aztec/src/context/public_context.nr", "source": "use crate::hash::{compute_secret_hash, compute_message_hash, compute_message_nullifier};\nuse dep::protocol_types::address::{AztecAddress, EthAddress};\nuse dep::protocol_types::traits::{Deserialize, Empty};\nuse dep::protocol_types::abis::function_selector::FunctionSelector;\nuse crate::context::inputs::public_context_inputs::PublicContextInputs;\nuse crate::context::gas::GasOpts;\n\nstruct PublicContext {\n inputs: PublicContextInputs,\n}\n\nimpl PublicContext {\n pub fn new(inputs: PublicContextInputs) -> Self {\n PublicContext { inputs }\n }\n\n pub fn storage_address(self) -> AztecAddress {\n storage_address()\n }\n pub fn fee_per_l2_gas(self) -> Field {\n fee_per_l2_gas()\n }\n pub fn fee_per_da_gas(self) -> Field {\n fee_per_da_gas()\n }\n /**\n * Emit a log with the given event selector and message.\n *\n * @param event_selector The event selector for the log.\n * @param message The message to emit in the log.\n * Should be automatically convertible to [Field; N]. For example str<N> works with\n * one char per field. Otherwise you can use CompressedString.\n */\n pub fn emit_unencrypted_log_with_selector<T>(&mut self, event_selector: Field, log: T) {\n emit_unencrypted_log(event_selector, log);\n }\n pub fn note_hash_exists(self, note_hash: Field, leaf_index: Field) -> bool {\n note_hash_exists(note_hash, leaf_index) == 1\n }\n pub fn l1_to_l2_msg_exists(self, msg_hash: Field, msg_leaf_index: Field) -> bool {\n l1_to_l2_msg_exists(msg_hash, msg_leaf_index) == 1\n }\n\n fn block_number(self) -> Field {\n block_number()\n }\n\n fn timestamp(self) -> u64 {\n timestamp()\n }\n\n fn transaction_fee(self) -> Field {\n transaction_fee()\n }\n\n fn nullifier_exists(self, unsiloed_nullifier: Field, address: AztecAddress) -> bool {\n nullifier_exists(unsiloed_nullifier, address.to_field()) == 1\n }\n\n fn emit_unencrypted_log<T, N, M>(&mut self, log: T) {\n let event_selector = 5; // Matches current PublicContext.\n self.emit_unencrypted_log_with_selector(event_selector, log);\n }\n\n fn consume_l1_to_l2_message(\n &mut self,\n content: Field,\n secret: Field,\n sender: EthAddress,\n leaf_index: Field\n ) {\n let secret_hash = compute_secret_hash(secret);\n let message_hash = compute_message_hash(\n sender,\n self.chain_id(),\n /*recipient=*/ self.this_address(),\n self.version(),\n content,\n secret_hash\n );\n let nullifier = compute_message_nullifier(message_hash, secret, leaf_index);\n\n assert(\n !self.nullifier_exists(nullifier, self.this_address()), \"L1-to-L2 message is already nullified\"\n );\n assert(\n self.l1_to_l2_msg_exists(message_hash, leaf_index), \"Tried to consume nonexistent L1-to-L2 message\"\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0);\n }\n\n fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n send_l2_to_l1_msg(recipient, content);\n }\n\n fn call_public_function<RETURNS_COUNT>(\n self: &mut Self,\n contract_address: AztecAddress,\n temporary_function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts\n ) -> FunctionReturns<RETURNS_COUNT> {\n let results = call(\n gas_for_call(gas_opts),\n contract_address,\n args,\n temporary_function_selector.to_field()\n );\n let data_to_return: [Field; RETURNS_COUNT] = results.0;\n let success: u8 = results.1;\n assert(success == 1, \"Nested call failed!\");\n\n FunctionReturns::new(data_to_return)\n }\n\n fn static_call_public_function<RETURNS_COUNT>(\n self: &mut Self,\n contract_address: AztecAddress,\n temporary_function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts\n ) -> FunctionReturns<RETURNS_COUNT> {\n let (data_to_return, success): ([Field; RETURNS_COUNT], u8) = call_static(\n gas_for_call(gas_opts),\n contract_address,\n args,\n temporary_function_selector.to_field()\n );\n\n assert(success == 1, \"Nested static call failed!\");\n FunctionReturns::new(data_to_return)\n }\n\n fn delegate_call_public_function<RETURNS_COUNT>(\n self: &mut Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field]\n ) -> FunctionReturns<RETURNS_COUNT> {\n assert(false, \"'delegate_call_public_function' not implemented!\");\n FunctionReturns::new([0; RETURNS_COUNT])\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n emit_note_hash(note_hash);\n }\n fn push_new_nullifier(&mut self, nullifier: Field, _nullified_commitment: Field) {\n // Cannot nullify pending commitments in AVM, so `nullified_commitment` is not used\n emit_nullifier(nullifier);\n }\n fn msg_sender(self) -> AztecAddress {\n sender()\n }\n fn this_address(self) -> AztecAddress {\n address()\n }\n fn chain_id(self) -> Field {\n chain_id()\n }\n fn version(self) -> Field {\n version()\n }\n fn selector(self) -> FunctionSelector {\n FunctionSelector::from_field(self.inputs.selector)\n }\n fn get_args_hash(self) -> Field {\n self.inputs.args_hash\n }\n}\n\n// Helper functions\nfn gas_for_call(user_gas: GasOpts) -> [Field; 2] {\n // It's ok to use the max possible gas here, because the gas will be\n // capped by the gas left in the (STATIC)CALL instruction.\n let MAX_POSSIBLE_FIELD: Field = 0 - 1;\n [\n user_gas.l2_gas.unwrap_or(MAX_POSSIBLE_FIELD),\n user_gas.da_gas.unwrap_or(MAX_POSSIBLE_FIELD)\n ]\n}\n\n// Unconstrained opcode wrappers (do not use directly).\n// TODO(https://github.com/AztecProtocol/aztec-packages/issues/6420): reconsider.\nunconstrained fn address() -> AztecAddress {\n address_opcode()\n}\nunconstrained fn storage_address() -> AztecAddress {\n storage_address_opcode()\n}\nunconstrained fn sender() -> AztecAddress {\n sender_opcode()\n}\nunconstrained fn portal() -> EthAddress {\n portal_opcode()\n}\nunconstrained fn fee_per_l2_gas() -> Field {\n fee_per_l2_gas_opcode()\n}\nunconstrained fn fee_per_da_gas() -> Field {\n fee_per_da_gas_opcode()\n}\nunconstrained fn transaction_fee() -> Field {\n transaction_fee_opcode()\n}\nunconstrained fn chain_id() -> Field {\n chain_id_opcode()\n}\nunconstrained fn version() -> Field {\n version_opcode()\n}\nunconstrained fn block_number() -> Field {\n block_number_opcode()\n}\nunconstrained fn timestamp() -> u64 {\n timestamp_opcode()\n}\nunconstrained fn l2_gas_left() -> Field {\n l2_gas_left_opcode()\n}\nunconstrained fn da_gas_left() -> Field {\n da_gas_left_opcode()\n}\nunconstrained fn note_hash_exists(note_hash: Field, leaf_index: Field) -> u8 {\n note_hash_exists_opcode(note_hash, leaf_index)\n}\nunconstrained fn emit_note_hash(note_hash: Field) {\n emit_note_hash_opcode(note_hash)\n}\nunconstrained fn nullifier_exists(nullifier: Field, address: Field) -> u8 {\n nullifier_exists_opcode(nullifier, address)\n}\nunconstrained fn emit_nullifier(nullifier: Field) {\n emit_nullifier_opcode(nullifier)\n}\nunconstrained fn emit_unencrypted_log<T>(event_selector: Field, message: T) {\n emit_unencrypted_log_opcode(event_selector, message)\n}\nunconstrained fn l1_to_l2_msg_exists(msg_hash: Field, msg_leaf_index: Field) -> u8 {\n l1_to_l2_msg_exists_opcode(msg_hash, msg_leaf_index)\n}\nunconstrained fn send_l2_to_l1_msg(recipient: EthAddress, content: Field) {\n send_l2_to_l1_msg_opcode(recipient, content)\n}\nunconstrained fn call<RET_SIZE>(\n gas: [Field; 2],\n address: AztecAddress,\n args: [Field],\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {\n call_opcode(gas, address, args, function_selector)\n}\nunconstrained fn call_static<RET_SIZE>(\n gas: [Field; 2],\n address: AztecAddress,\n args: [Field],\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {\n call_static_opcode(gas, address, args, function_selector)\n}\n\nimpl Empty for PublicContext {\n fn empty() -> Self {\n PublicContext::new(PublicContextInputs::empty())\n }\n}\n\n// AVM oracles (opcodes) follow, do not use directly.\n#[oracle(avmOpcodeAddress)]\nfn address_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodeStorageAddress)]\nfn storage_address_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodeSender)]\nfn sender_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodePortal)]\nfn portal_opcode() -> EthAddress {}\n\n#[oracle(avmOpcodeFeePerL2Gas)]\nfn fee_per_l2_gas_opcode() -> Field {}\n\n#[oracle(avmOpcodeFeePerDaGas)]\nfn fee_per_da_gas_opcode() -> Field {}\n\n#[oracle(avmOpcodeTransactionFee)]\nfn transaction_fee_opcode() -> Field {}\n\n#[oracle(avmOpcodeChainId)]\nfn chain_id_opcode() -> Field {}\n\n#[oracle(avmOpcodeVersion)]\nfn version_opcode() -> Field {}\n\n#[oracle(avmOpcodeBlockNumber)]\nfn block_number_opcode() -> Field {}\n\n#[oracle(avmOpcodeTimestamp)]\nfn timestamp_opcode() -> u64 {}\n\n#[oracle(avmOpcodeL2GasLeft)]\nfn l2_gas_left_opcode() -> Field {}\n\n#[oracle(avmOpcodeDaGasLeft)]\nfn da_gas_left_opcode() -> Field {}\n\n#[oracle(avmOpcodeNoteHashExists)]\nfn note_hash_exists_opcode(note_hash: Field, leaf_index: Field) -> u8 {}\n\n#[oracle(avmOpcodeEmitNoteHash)]\nfn emit_note_hash_opcode(note_hash: Field) {}\n\n#[oracle(avmOpcodeNullifierExists)]\nfn nullifier_exists_opcode(nullifier: Field, address: Field) -> u8 {}\n\n#[oracle(avmOpcodeEmitNullifier)]\nfn emit_nullifier_opcode(nullifier: Field) {}\n\n#[oracle(amvOpcodeEmitUnencryptedLog)]\nfn emit_unencrypted_log_opcode<T>(event_selector: Field, message: T) {}\n\n#[oracle(avmOpcodeL1ToL2MsgExists)]\nfn l1_to_l2_msg_exists_opcode(msg_hash: Field, msg_leaf_index: Field) -> u8 {}\n\n#[oracle(avmOpcodeSendL2ToL1Msg)]\nfn send_l2_to_l1_msg_opcode(recipient: EthAddress, content: Field) {}\n\n#[oracle(avmOpcodeCall)]\nfn call_opcode<RET_SIZE>(\n gas: [Field; 2], // gas allocation: [l2_gas, da_gas]\n address: AztecAddress,\n args: [Field],\n // TODO(5110): consider passing in calldata directly\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {}\n// ^ return data ^ success\n\n#[oracle(avmOpcodeStaticCall)]\nfn call_static_opcode<RET_SIZE>(\n gas: [Field; 2], // gas allocation: [l2_gas, da_gas]\n address: AztecAddress,\n args: [Field],\n // TODO(5110): consider passing in calldata directly\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {}\n// ^ return data ^ success\n\nstruct FunctionReturns<N> {\n values: [Field; N]\n}\n\nimpl<N> FunctionReturns<N> {\n pub fn new(values: [Field; N]) -> FunctionReturns<N> {\n FunctionReturns { values }\n }\n\n pub fn assert_empty(returns: FunctionReturns<0>) {\n assert(returns.values.len() == 0);\n }\n\n pub fn raw(self) -> [Field; N] {\n self.values\n }\n\n pub fn deserialize_into<T>(self) -> T where T: Deserialize<N> {\n Deserialize::deserialize(self.raw())\n }\n}\n" } } }
1
+ { "transpiled": true, "noir_version": "0.30.0+a2f687687559d15fde52abce54838f6e144a0aa4", "name": "KeyRegistry", "functions": [{ "name": "compute_note_hash_and_optionally_a_nullifier", "is_unconstrained": true, "custom_attributes": [], "abi": { "error_types": {}, "parameters": [{ "name": "contract_address", "type": { "fields": [{ "name": "inner", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::address::aztec_address::AztecAddress" }, "visibility": "private" }, { "name": "nonce", "type": { "kind": "field" }, "visibility": "private" }, { "name": "storage_slot", "type": { "kind": "field" }, "visibility": "private" }, { "name": "note_type_id", "type": { "kind": "field" }, "visibility": "private" }, { "name": "compute_nullifier", "type": { "kind": "boolean" }, "visibility": "private" }, { "name": "serialized_note", "type": { "kind": "array", "length": 0, "type": { "kind": "field" } }, "visibility": "private" }], "return_type": { "abi_type": { "kind": "array", "length": 4, "type": { "kind": "field" } }, "visibility": "public" } }, "bytecode": "H4sIAAAAAAAA/+2b227aQBCG18RJTJ24YGMMgQQIyUXvDA2nO16mfe3eV+orVM2YnTJsp2hRx1tWYqWIsb2e/5t/D1jICdSuRe9/gY6v9eeN+rNhn63+LP+tzQRzlXVyBp5wNjzhvPKEMxTkDBhO+Ax1DOsO1tytOlyPv9tWqChTlELBBLoi19URwIMboUU6oBfHUuDrcnNDklNwpcFDfQ0/ASfW1yhYrIus+pBzWGiDnEOdK3IOd0bUibQpwvUuoj2yXN73CQA1NHUu5I5JTK8NiXVhTTVey9f4VsuYlLtVjGNyrXPfkmP0Cj0U/OaYUe1A/zWJptJjhPGA9MV+6EeDjDG0e7Wf180j94XGfQnpc8PUPxau/9bgMecsjEFLx204xj2BsH0g9W1l2ErIG8vnndExCHVu5I9JTYm43/M15L9Th838VhqTOCE89+I85ayeOndj95Gwy+RdvIFXLcOrO8OrhPShDK0a/AuILubG4xajLefFcg3abQsv2gxP27EXbUZb0IsNaKcWXqQMT+rYi5TRlvNi9Rm0MwsvMoYnc+xFxmjLeTGvni06Fl50GJ6OYy86jLbgGqnmRW7hRc7w5I69yBltQS++gnbXwosuw9N17EWX0Rb04gtoFxZeFAxP4diLgtEW3Dur54uehRc9hqfn2Iseoy3oxRy0+xZe9BmevmMv+oy24BqptB8svHhgeB4ce4F6pzJ3PGQuPGTOzoA5MmIZ7WW1fw4svBgwPAPHXtDfck5hzs+AOTJiGe3lArSHFl4MGZ6hYy9Q71Tm1EPmzEPmrofMuYfMhYfM5zCfIyOW0V5Ve+ijhRePDM+jYy9Q71Tm1EPmgYfM2RkwR0Yso72qfpt7svDiieF5cuwF6p3K3POQuX0GzJERy2ivlqA9svBixPCMHHuBeqcy9z1kLjxkHnjInHnI3PWQOfeQ+bIG3TCnZ8AM773gOzA/auWZb2KDBz1TBqMyGGMSJ4QR+26V3PsqiVE7ak3E/diNjzlf8HhSq/Z8DXmn8jVVz/IvOhe+wzdlanrVcSDs5wvJGxAdPB+S+Dvpi/3QD1y3yA7vXD3r+PXIfSPjvoT0eWbqHwvXPzV4pgYzjMk3wlHH3LKZ1y21X8ufCE8N++AbfScXm82+Q/cYQZ5ZTXWW9B2+n0p2TU8Mr5qGVwnpQ/fo/7VvXpgvzH9jps8TTXKO8uC5hlEL/f+GCcnxC57ToyHuNQAA", "debug_symbols": "ndpBattQGIXRvWgciu8vPT0pWymlOIlTDMYOsVMoJnuv3dIF9Mz0JN3ZNzq86/Cye/r48X1/fD2dh8ev1+Fwet5e9qfj7XQdNl9q+fP2/LY93l+cL9v3y/A49noYdseX+1P/fBhe94fd7Xlsn98e7qMVRuNGRpFRyWiU0SSjJqNZRl1GUsQoRUxSxCRFTFLEJEVMUsQkRUxSxCRFTFLEJEU0KaJJEU2KaFJEkyKaFNGkiCZFNCmiSRGzFDFLEbMUMUsRsxQxSxGzFDFLEbMUMUsRXYroUkSXIroU0aWILkV0KaJLEV2K6FLEIkUsUsQiRSxSxCJFLFLEIkUsUsQiRSxSxCpFrFLEKkWsUsQqRaxSxCpFrFLEKkWsUkQ2G1qFVkWrkVYTrRqtZlp1Wi20ojZCbYTaCLURaiPURqiNUBuhNkJthNooaqOojaI2itooaqOojaI2itog0AyJZog0Q6YZQs2QaoZYM+SaIdgMyWaINkO2GcLNkG6GeDPkmyHgDAlniDhDxhlCzpByhpgz5Jwh6AxJZ4g6Q9YZws6Qdoa4M+SdIfAMiWeIPEPmGULPkHqG2DPkniH4DMlniD5D9hnCz5B+hvgz5J8hAA0JaIhAQwYaQtCQgoYYNOSgIQgNSWiIQkMWGsLQkIaGODTkoSEQDYloiERDJhpC0ZCKhlg05KJFLlrkokUuWuSiRS5a5KJFLlrkokUuWuSiRS5a5KJFLlrkokUuWuSiRS5a5KJFLlrkokUuWuSiRS5a5KJFLlrkokUuWuSiZRc9yUWLXLTIRYtctMhFi1y0yEXrv130dvq5fd9vnw67+93e+8eP4/O/q7634+XX298vt39/Aw==" }, { "name": "rotate_npk_m", "is_unconstrained": true, "custom_attributes": ["aztec(public)"], "abi": { "error_types": {}, "parameters": [{ "name": "inputs", "type": { "fields": [{ "name": "selector", "type": { "kind": "field" } }, { "name": "args_hash", "type": { "kind": "field" } }, { "name": "is_static_call", "type": { "kind": "boolean" } }], "kind": "struct", "path": "aztec::context::inputs::public_context_inputs::PublicContextInputs" }, "visibility": "private" }, { "name": "address", "type": { "fields": [{ "name": "inner", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::address::aztec_address::AztecAddress" }, "visibility": "private" }, { "name": "new_npk_m", "type": { "fields": [{ "name": "x", "type": { "kind": "field" } }, { "name": "y", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint" }, "visibility": "private" }, { "name": "nonce", "type": { "kind": "field" }, "visibility": "private" }], "return_type": null }, "bytecode": "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", "debug_symbols": "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4rylIM5bCuK8pSDOWwrivKUgzlsK4rylIM5bCuK8pSDOWwrivKUgzlsK4rylIM5bCuK8pSDOWwrivKUgzlsK4rylIM5bCuK8pSDOWwrivKUgzlsK4rylIM5bCuK8pSDOWwrivKUgzlsK4rylIM5bCuK8pSDOWwrivKUgzlsK4rylIM5bCuK8pSDOWwrivKUgzlsK4rylIM5bCuK8pSDOWwrivKUgzlsK4rylIM5bCuK8pSDOWwrivKUgzlsK4rylIM5bCuK8pSDOWwrivKUgzlsK4rylIM5bCuK8pSDOWwrivKUgzlsK4rylIM5bCuK8pSDOWwrivKUgzlsK4rylIM5bCuK8pSDOWwrivKUgzlsK4rylIM5bCuK8pSDOWwrivKUgzlsK4rylIM5bCuK8pSDOWwrivKUgzltK4rylJM5bSuK8pSTOW8rC66tJnLeUxHlLSZy3lMR5S0mct5TEeUtJnLeUxHlLSZy3lMR5S0mct5TEeUtJnLeUxHlLSZy3lMR5S0mct5TEeUtJnLeUxHlLSZy3lMR5S0mct5TEeUtJnLeUxHlLSZy3lMR5S0mct5TEeUtJnLeUxHlLSZy3lMR5S0mct5TEeUtJnLeUxHlLSZy3lMR5S0mct5TEeUtJnLeUxHlLSZy3lMR5S0mct5TEeUtJnLeUxHlLSZy3lMR5S0mct5TEeUtJnLeUxHlLSZy3lMR5S0mct5TEeUtJnLeUxHlLSZy3lMR5S0mct5TEeUtJnLeUxHlLSZy3lMR5S0mct5TEeUtJnLeUxHlLSZy3lMR5S0mct5TEeUtJnLeUxHlLSZy3lMR5S0mct5TEeUtJnLeUxHlLSZy3lK/lLYWvaFLqwShd8+XinnmAfBl5/eD+uLbK7udaWy/uXtrjapUVvVKjb9TojRq9U6MPavSdGH1/LcGIBL1Qo2d2q16Y3aoXZrfqhdmtemF2q16Y3aq/lmhEgv4Cr/2g7yZdCjF2IcZeibErMfZGjN2IsTsx9iDGnsTYiX21EvtqJfbVSuyrldhXK7GvVmJfrcS+Wol9tRL7aiX2VSX2VSX2VSX2VSX2VSX2VSX2VSX2VSX2VSX2VSX21Ubsq43YVxuxrzZiX23EvtqIfbUR+2oj9tVG7KuN2FeN2FeN2FeN2FeN2FeN2FeN2FeN2FeN2FeN2FeN2Fed2Fed2Fed2Fed2Fed2Fed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" }, { "name": "register", "is_unconstrained": true, "custom_attributes": ["aztec(public)"], "abi": { "error_types": {}, "parameters": [{ "name": "inputs", "type": { "fields": [{ "name": "selector", "type": { "kind": "field" } }, { "name": "args_hash", "type": { "kind": "field" } }, { "name": "is_static_call", "type": { "kind": "boolean" } }], "kind": "struct", "path": "aztec::context::inputs::public_context_inputs::PublicContextInputs" }, "visibility": "private" }, { "name": "address", "type": { "fields": [{ "name": "inner", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::address::aztec_address::AztecAddress" }, "visibility": "private" }, { "name": "partial_address", "type": { "fields": [{ "name": "inner", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::address::partial_address::PartialAddress" }, "visibility": "private" }, { "name": "keys", "type": { "fields": [{ "name": "npk_m", "type": { "fields": [{ "name": "x", "type": { "kind": "field" } }, { "name": "y", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint" } }, { "name": "ivpk_m", "type": { "fields": [{ "name": "x", "type": { "kind": "field" } }, { "name": "y", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint" } }, { "name": "ovpk_m", "type": { "fields": [{ "name": "x", "type": { "kind": "field" } }, { "name": "y", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint" } }, { "name": "tpk_m", "type": { "fields": [{ "name": "x", "type": { "kind": "field" } }, { "name": "y", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint" } }], "kind": "struct", "path": "aztec::keys::public_keys::PublicKeys" }, "visibility": "private" }], "return_type": null }, "bytecode": "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", "debug_symbols": "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" }], "outputs": { "globals": { "storage": [{ "fields": [{ "name": "npk_m_x_registry", "value": { "fields": [{ "name": "slot", "value": { "kind": "integer", "sign": false, "value": "1" } }, { "name": "typ", "value": { "kind": "string", "value": "Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY, Context>, Context>" } }], "kind": "struct" } }, { "name": "npk_m_y_registry", "value": { "fields": [{ "name": "slot", "value": { "kind": "integer", "sign": false, "value": "2" } }, { "name": "typ", "value": { "kind": "string", "value": "Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY, Context>, Context>" } }], "kind": "struct" } }, { "name": "ivpk_m_x_registry", "value": { "fields": [{ "name": "slot", "value": { "kind": "integer", "sign": false, "value": "3" } }, { "name": "typ", "value": { "kind": "string", "value": "Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY, Context>, Context>" } }], "kind": "struct" } }, { "name": "ivpk_m_y_registry", "value": { "fields": [{ "name": "slot", "value": { "kind": "integer", "sign": false, "value": "4" } }, { "name": "typ", "value": { "kind": "string", "value": "Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY, Context>, Context>" } }], "kind": "struct" } }, { "name": "ovpk_m_x_registry", "value": { "fields": [{ "name": "slot", "value": { "kind": "integer", "sign": false, "value": "5" } }, { "name": "typ", "value": { "kind": "string", "value": "Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY, Context>, Context>" } }], "kind": "struct" } }, { "name": "ovpk_m_y_registry", "value": { "fields": [{ "name": "slot", "value": { "kind": "integer", "sign": false, "value": "6" } }, { "name": "typ", "value": { "kind": "string", "value": "Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY, Context>, Context>" } }], "kind": "struct" } }, { "name": "tpk_m_x_registry", "value": { "fields": [{ "name": "slot", "value": { "kind": "integer", "sign": false, "value": "7" } }, { "name": "typ", "value": { "kind": "string", "value": "Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY, Context>, Context>" } }], "kind": "struct" } }, { "name": "tpk_m_y_registry", "value": { "fields": [{ "name": "slot", "value": { "kind": "integer", "sign": false, "value": "8" } }, { "name": "typ", "value": { "kind": "string", "value": "Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY, Context>, Context>" } }], "kind": "struct" } }], "kind": "struct" }] }, "structs": { "functions": [{ "fields": [{ "name": "parameters", "type": { "fields": [{ "name": "address", "type": { "fields": [{ "name": "inner", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::address::aztec_address::AztecAddress" } }, { "name": "new_npk_m", "type": { "fields": [{ "name": "x", "type": { "kind": "field" } }, { "name": "y", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint" } }, { "name": "nonce", "type": { "kind": "field" } }], "kind": "struct", "path": "KeyRegistry::rotate_npk_m_parameters" } }], "kind": "struct", "path": "KeyRegistry::rotate_npk_m_abi" }, { "fields": [{ "name": "parameters", "type": { "fields": [{ "name": "address", "type": { "fields": [{ "name": "inner", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::address::aztec_address::AztecAddress" } }, { "name": "partial_address", "type": { "fields": [{ "name": "inner", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::address::partial_address::PartialAddress" } }, { "name": "keys", "type": { "fields": [{ "name": "npk_m", "type": { "fields": [{ "name": "x", "type": { "kind": "field" } }, { "name": "y", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint" } }, { "name": "ivpk_m", "type": { "fields": [{ "name": "x", "type": { "kind": "field" } }, { "name": "y", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint" } }, { "name": "ovpk_m", "type": { "fields": [{ "name": "x", "type": { "kind": "field" } }, { "name": "y", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint" } }, { "name": "tpk_m", "type": { "fields": [{ "name": "x", "type": { "kind": "field" } }, { "name": "y", "type": { "kind": "field" } }], "kind": "struct", "path": "authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint" } }], "kind": "struct", "path": "aztec::keys::public_keys::PublicKeys" } }], "kind": "struct", "path": "KeyRegistry::register_parameters" } }], "kind": "struct", "path": "KeyRegistry::register_abi" }] } }, "file_map": { "123": { "path": "/usr/src/noir-projects/aztec-nr/aztec/src/oracle/storage.nr", "source": "use dep::protocol_types::traits::{Deserialize, Serialize};\n\n#[oracle(storageRead)]\nunconstrained fn storage_read_oracle<N>(_storage_slot: Field, _number_of_elements: Field) -> [Field; N] {}\n\nunconstrained fn storage_read_oracle_wrapper<N>(_storage_slot: Field) -> [Field; N] {\n storage_read_oracle(_storage_slot, N)\n}\n\npub fn storage_read<N>(storage_slot: Field) -> [Field; N] {\n storage_read_oracle_wrapper(storage_slot)\n}\n\n#[oracle(storageWrite)]\nunconstrained fn storage_write_oracle<N>(_storage_slot: Field, _values: [Field; N]) -> [Field; N] {}\n\nunconstrained pub fn storage_write<N>(storage_slot: Field, fields: [Field; N]) {\n let _hash = storage_write_oracle(storage_slot, fields);\n}\n" }, "136": { "path": "/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/map.nr", "source": "use dep::protocol_types::{hash::pedersen_hash, storage::map::derive_storage_slot_in_map, traits::ToField};\nuse crate::state_vars::storage::Storage;\n\n// docs:start:map\nstruct Map<K, V, Context> {\n context: Context,\n storage_slot: Field,\n state_var_constructor: fn(Context, Field) -> V,\n}\n// docs:end:map\n\nimpl<K, T, Context> Storage<T> for Map<K, T, Context> {}\n\nimpl<K, V, Context> Map<K, V, Context> {\n // docs:start:new\n pub fn new(\n context: Context,\n storage_slot: Field,\n state_var_constructor: fn(Context, Field) -> V\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Map { context, storage_slot, state_var_constructor }\n }\n // docs:end:new\n\n // docs:start:at\n pub fn at(self, key: K) -> V where K: ToField {\n // TODO(#1204): use a generator index for the storage slot\n let derived_storage_slot = derive_storage_slot_in_map(self.storage_slot, key);\n\n let state_var_constructor = self.state_var_constructor;\n state_var_constructor(self.context, derived_storage_slot)\n }\n // docs:end:at\n}\n" }, "145": { "path": "/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change.nr", "source": "use dep::protocol_types::traits::{Serialize, Deserialize, FromField, ToField};\nuse dep::std::cmp::min;\n\nmod test;\n\n// This data structure is used by SharedMutable to store the minimum delay with which a ScheduledValueChange object can\n// schedule a change.\n// This delay is initally equal to INITIAL_DELAY, and can be safely mutated to any other value over time. This mutation \n// is performed via `schedule_change` in order to satisfy ScheduleValueChange constraints: if e.g. we allowed for the \n// delay to be decreased immediately then it'd be possible for the state variable to schedule a value change with a \n// reduced delay, invalidating prior private reads.\nstruct ScheduledDelayChange<INITIAL_DELAY> {\n // Both pre and post are stored in public storage, so by default they are zeroed. By wrapping them in an Option, \n // they default to Option::none(), which we detect and replace with INITIAL_DELAY. The end result is that a\n // ScheduledDelayChange that has not been initialized has a delay equal to INITIAL_DELAY, which is the desired\n // effect. Once initialized, the Option will never be none again.\n pre: Option<u32>,\n post: Option<u32>,\n // Block at which `post` value is used instead of `pre`\n block_of_change: u32,\n // The _dummy variable forces INITIAL_DELAY to be interpreted as a numeric value. This is a workaround to\n // https://github.com/noir-lang/noir/issues/4633. Remove once resolved.\n _dummy: [Field; INITIAL_DELAY],\n}\n\nimpl<INITIAL_DELAY> ScheduledDelayChange<INITIAL_DELAY> {\n pub fn new(pre: Option<u32>, post: Option<u32>, block_of_change: u32) -> Self {\n Self { pre, post, block_of_change, _dummy: [0; INITIAL_DELAY] }\n }\n\n /// Returns the current value of the delay stored in the data structure.\n /// This function only returns a meaningful value when called in public with the current block number - for\n /// historical private reads use `get_effective_minimum_delay_at` instead.\n pub fn get_current(self, current_block_number: u32) -> u32 {\n // The post value becomes the current one at the block of change, so any transaction that is included in the\n // block of change will use the post value.\n\n if current_block_number < self.block_of_change {\n self.pre.unwrap_or(INITIAL_DELAY)\n } else {\n self.post.unwrap_or(INITIAL_DELAY)\n }\n }\n\n /// Returns the scheduled change, i.e. the post-change delay and the block at which it will become the current\n /// delay. Note that this block may be in the past if the change has already taken place.\n /// Additionally, further changes might be later scheduled, potentially canceling the one returned by this function.\n pub fn get_scheduled(self) -> (u32, u32) {\n (self.post.unwrap_or(INITIAL_DELAY), self.block_of_change)\n }\n\n /// Mutates the delay change by scheduling a change at the current block number. This function is only meaningful\n /// when called in public with the current block number.\n /// The block at which the new delay will become effective is determined automatically:\n /// - when increasing the delay, the change is effective immediately\n /// - when reducing the delay, the change will take effect after a delay equal to the difference between old and\n /// new delay. For example, if reducing from 3 days to 1 day, the reduction will be scheduled to happen after 2\n /// days.\n pub fn schedule_change(&mut self, new: u32, current_block_number: u32) {\n let current = self.get_current(current_block_number);\n\n // When changing the delay value we must ensure that it is not possible to produce a value change with a delay\n // shorter than the current one.\n let blocks_until_change = if new > current {\n // Increasing the delay value can therefore be done immediately: this does not invalidate prior contraints\n // about how quickly a value might be changed (indeed it strengthens them).\n 0\n } else {\n // Decreasing the delay requires waiting for the difference between current and new delay in order to ensure\n // that overall the current delay is respected.\n //\n // current delay earliest value block of change\n // block block of change if delay remained unchanged\n // =======N=========================|================================X=================>\n // ^ ^ ^\n // |-------------------------|--------------------------------|\n // | blocks until change new delay |\n // ------------------------------------------------------------\n // current delay\n current - new\n };\n\n self.pre = Option::some(current);\n self.post = Option::some(new);\n self.block_of_change = current_block_number + blocks_until_change;\n }\n\n /// Returns the minimum delay before a value might mutate due to a scheduled change, from the perspective of some\n /// historical block number. It only returns a meaningful value when called in private with historical blocks. This \n /// function can be used alongside `ScheduledValueChange.get_block_horizon` to properly constrain the\n /// `max_block_number` transaction property when reading mutable shared state.\n /// This value typically equals the current delay at the block following the historical one (the earliest one in\n /// which a value change could be scheduled), but it also considers scenarios in which a delay reduction is \n /// scheduled to happen in the near future, resulting in a way to schedule a change with an overall delay lower than\n /// the current one.\n pub fn get_effective_minimum_delay_at(self, historical_block_number: u32) -> u32 {\n if self.block_of_change <= historical_block_number {\n // If no delay changes were scheduled, then the delay value at the historical block (post) is guaranteed to\n // hold due to how further delay changes would be scheduled by `schedule_change`.\n self.post.unwrap_or(INITIAL_DELAY)\n } else {\n // If a change is scheduled, then the effective delay might be lower than the current one (pre). At the\n // block of change the current delay will be the scheduled one, with an overall delay from the historical\n // block number equal to the number of blocks until the change plus the new delay. If this value is lower\n // than the current delay, then that is the effective minimum delay.\n //\n // historical\n // block delay actual earliest value\n // v block of change block of change\n // =========NS=====================|=============================X===========Y=====>\n // ^ ^ ^ ^\n // earliest block in | | |\n // which to schedule change | | |\n // | | | |\n // |----------------------|------------------------------ |\n // | blocks new delay |\n // | until change |\n // | |\n // |----------------------------------------------------------------|\n // current delay at the earliest block in \n // which to scheduled value change\n\n let blocks_until_change = self.block_of_change - (historical_block_number + 1);\n\n min(\n self.pre.unwrap_or(INITIAL_DELAY),\n blocks_until_change + self.post.unwrap_or(INITIAL_DELAY)\n )\n }\n }\n}\n\nimpl<INITIAL_DELAY> Serialize<1> for ScheduledDelayChange<INITIAL_DELAY> {\n fn serialize(self) -> [Field; 1] {\n // We pack all three u32 values into a single U128, which is made up of two u64 limbs.\n // Low limb: [ pre_inner: u32 | post_inner: u32 ]\n // High limb: [ empty | pre_is_some: u8 | post_is_some: u8 | block_of_change: u32 ]\n\n let lo = ((self.pre.unwrap_unchecked() as u64) * (1 << 32))\n + (self.post.unwrap_unchecked() as u64);\n\n let hi = (self.pre.is_some() as u64) * (1 << 33) \n + (self.post.is_some() as u64 * (1 << 32)) \n + self.block_of_change as u64;\n\n let packed = U128::from_u64s_le(lo, hi);\n\n [packed.to_integer()]\n }\n}\n\nimpl<INITIAL_DELAY> Deserialize<1> for ScheduledDelayChange<INITIAL_DELAY> {\n fn deserialize(input: [Field; 1]) -> Self {\n let packed = U128::from_integer(input[0]);\n\n // We use division and modulo to clear the bits that correspond to other values when unpacking.\n\n let pre_is_some = ((packed.hi as u64) / (1 << 33)) as bool;\n let pre_inner = ((packed.lo as u64) / (1 << 32)) as u32;\n\n let post_is_some = (((packed.hi as u64) / (1 << 32)) % (1 << 1)) as bool;\n let post_inner = ((packed.lo as u64) % (1 << 32)) as u32;\n\n let block_of_change = ((packed.hi as u64) % (1 << 32)) as u32;\n\n Self {\n pre: if pre_is_some { Option::some(pre_inner) } else { Option::none() },\n post: if post_is_some { Option::some(post_inner) } else { Option::none() },\n block_of_change,\n _dummy: [0; INITIAL_DELAY],\n }\n }\n}\n" }, "149": { "path": "/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change.nr", "source": "use dep::protocol_types::traits::{Serialize, Deserialize, FromField, ToField};\nuse dep::std::cmp::min;\n\nmod test;\n\n// This data structure is used by SharedMutable to represent a value that changes from `pre` to `post` at some block\n// called the `block_of_change`. The value can only be made to change by scheduling a change event at some future block\n// of change after some minimum delay measured in blocks has elapsed. This means that at any given block number we know\n// both the current value and the smallest block number at which the value might change - this is called the\n// 'block horizon'.\nstruct ScheduledValueChange<T> {\n pre: T,\n post: T,\n // Block at which `post` value is used instead of `pre`\n block_of_change: u32,\n}\n\nimpl<T> ScheduledValueChange<T> {\n pub fn new(pre: T, post: T, block_of_change: u32) -> Self {\n Self { pre, post, block_of_change }\n }\n\n /// Returns the value stored in the data structure at a given block. This function can be called both in public\n /// (where `block_number` is simply the current block number, i.e. the number of the block in which the current\n /// transaction will be included) and in private (where `block_number` is the historical block number that is used\n /// to construct the proof).\n /// Reading in private is only safe if the transaction's `max_block_number` property is set to a value lower or\n /// equal to the block horizon (see `get_block_horizon()`).\n pub fn get_current_at(self, block_number: u32) -> T {\n // The post value becomes the current one at the block of change. This means different things in each realm:\n // - in public, any transaction that is included in the block of change will use the post value\n // - in private, any transaction that includes the block of change as part of the historical state will use the\n // post value (barring any follow-up changes)\n\n if block_number < self.block_of_change {\n self.pre\n } else {\n self.post\n }\n }\n\n /// Returns the scheduled change, i.e. the post-change value and the block at which it will become the current\n /// value. Note that this block may be in the past if the change has already taken place.\n /// Additionally, further changes might be later scheduled, potentially canceling the one returned by this function.\n pub fn get_scheduled(self) -> (T, u32) {\n (self.post, self.block_of_change)\n }\n\n /// Returns the largest block number at which the value returned by `get_current_at` is known to remain the current\n /// value. This value is only meaningful in private when constructing a proof at some `historical_block_number`,\n /// since due to its asynchronous nature private execution cannot know about any later scheduled changes.\n /// The caller of this function must know how quickly the value can change due to a scheduled change in the form of\n /// `minimum_delay`. If the delay itself is immutable, then this is just its duration. If the delay is mutable\n /// however, then this value is the 'effective minimum delay' (obtained by calling\n /// `ScheduledDelayChange.get_effective_minimum_delay_at`), which equals the minimum number of blocks that need to\n /// elapse from the next block until the value changes, regardless of further delay changes.\n /// The value returned by `get_current_at` in private when called with a historical block number is only safe to use\n /// if the transaction's `max_block_number` property is set to a value lower or equal to the block horizon computed\n /// using the same historical block number.\n pub fn get_block_horizon(self, historical_block_number: u32, minimum_delay: u32) -> u32 {\n // The block horizon is the very last block in which the current value is known. Any block past the horizon\n // (i.e. with a block number larger than the block horizon) may have a different current value. Reading the\n // current value in private typically requires constraining the maximum valid block number to be equal to the\n // block horizon.\n\n if historical_block_number >= self.block_of_change {\n // Once the block of change has been mined, the current value (post) will not change unless a new value\n // change is scheduled. This did not happen at the historical block number (or else it would not be\n // greater or equal to the block of change), and therefore could only happen after the historical block\n // number. The earliest would be the immediate next block, and so the smallest possible next block of change\n // equals `historical_block_number + 1 + minimum_delay`. Our block horizon is simply the previous block to\n // that one.\n //\n // block of historical\n // change block block horizon\n // =======|=============N===================H===========>\n // ^ ^\n // ---------------------\n // minimum delay\n\n historical_block_number + minimum_delay\n } else {\n // If the block of change has not yet been mined however, then there are two possible scenarios.\n // a) It could be so far into the future that the block horizon is actually determined by the minimum\n // delay, because a new change could be scheduled and take place _before_ the currently scheduled one.\n // This is similar to the scenario where the block of change is in the past: the time horizon is the\n // block prior to the earliest one in which a new block of change might land.\n //\n // historical\n // block block horizon block of change\n // =====N=================================H=================|=========>\n // ^ ^\n // | |\n // -----------------------------------\n // minimum delay\n //\n // b) It could be fewer than `minimum_delay` blocks away from the historical block number, in which case\n // the block of change would become the limiting factor for the time horizon, which would equal the\n // block right before the block of change (since by definition the value changes at the block of\n // change).\n //\n // historical block horizon\n // block block of change if not scheduled\n // =======N=============|===================H=================>\n // ^ ^ ^\n // | actual horizon |\n // -----------------------------------\n // minimum delay\n //\n // Note that the current implementation does not allow the caller to set the block of change to an arbitrary\n // value, and therefore scenario a) is not currently possible. However implementing #5501 would allow for\n // this to happen.\n\n // Because historical_block_number < self.block_of_change, then block_of_change > 0 and we can safely\n // subtract 1.\n min(\n self.block_of_change - 1,\n historical_block_number + minimum_delay\n )\n }\n }\n\n /// Mutates the value by scheduling a change at the current block number. This function is only meaningful when\n /// called in public with the current block number.\n pub fn schedule_change(\n &mut self,\n new_value: T,\n current_block_number: u32,\n minimum_delay: u32,\n block_of_change: u32\n ) {\n assert(block_of_change >= current_block_number + minimum_delay);\n\n self.pre = self.get_current_at(current_block_number);\n self.post = new_value;\n self.block_of_change = block_of_change;\n }\n}\n\nimpl<T> Serialize<3> for ScheduledValueChange<T> {\n fn serialize(self) -> [Field; 3] where T: ToField {\n [self.pre.to_field(), self.post.to_field(), self.block_of_change.to_field()]\n }\n}\n\nimpl<T> Deserialize<3> for ScheduledValueChange<T> {\n fn deserialize(input: [Field; 3]) -> Self where T: FromField {\n Self {\n pre: FromField::from_field(input[0]),\n post: FromField::from_field(input[1]),\n block_of_change: FromField::from_field(input[2]),\n }\n }\n}\n" }, "150": { "path": "/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr", "source": "use dep::protocol_types::{hash::pedersen_hash, traits::FromField};\n\nuse crate::context::{PrivateContext, PublicContext};\nuse crate::public_storage;\nuse crate::state_vars::{\n storage::Storage,\n shared_mutable::{scheduled_value_change::ScheduledValueChange, scheduled_delay_change::ScheduledDelayChange}\n};\n\nmod test;\n\nstruct SharedMutable<T, INITIAL_DELAY, Context> {\n context: Context,\n storage_slot: Field,\n}\n\n// This will make the Aztec macros require that T implements the Serialize<N> trait, and allocate N storage slots to\n// this state variable. This is incorrect, since what we actually store is:\n// - a ScheduledValueChange<T>, which requires 1 + 2 * M storage slots, where M is the serialization length of T\n// - a ScheduledDelayChange, which requires another storage slot\n//\n// TODO https://github.com/AztecProtocol/aztec-packages/issues/5736: change the storage allocation scheme so that we \n// can actually use it here\nimpl<T, INITIAL_DELAY, Context> Storage<T> for SharedMutable<T, INITIAL_DELAY, Context> {}\n\n// SharedMutable<T> stores a value of type T that is:\n// - publicly known (i.e. unencrypted)\n// - mutable in public\n// - readable in private with no contention (i.e. multiple parties can all read the same value without blocking one\n// another nor needing to coordinate)\n// This is famously a hard problem to solve. SharedMutable makes it work by introducing a delay to public mutation:\n// the value is not changed immediately but rather a value change is scheduled to happen in the future after some delay\n// measured in blocks. Reads in private are only valid as long as they are included in a block not too far into the \n// future, so that they can guarantee the value will not have possibly changed by then (because of the delay).\n// The delay for changing a value is initially equal to INITIAL_DELAY, but can be changed by calling \n// `schedule_delay_change`.\nimpl<T, INITIAL_DELAY, Context> SharedMutable<T, INITIAL_DELAY, Context> {\n pub fn new(context: Context, storage_slot: Field) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Self { context, storage_slot }\n }\n\n // Since we can't rely on the native storage allocation scheme, we hash the storage slot to get a unique location in\n // which we can safely store as much data as we need. \n // See https://github.com/AztecProtocol/aztec-packages/issues/5492 and \n // https://github.com/AztecProtocol/aztec-packages/issues/5736\n fn get_value_change_storage_slot(self) -> Field {\n pedersen_hash([self.storage_slot, 0], 0)\n }\n\n fn get_delay_change_storage_slot(self) -> Field {\n pedersen_hash([self.storage_slot, 1], 0)\n }\n}\n\nimpl<T, INITIAL_DELAY> SharedMutable<T, INITIAL_DELAY, &mut PublicContext> {\n pub fn schedule_value_change(self, new_value: T) {\n let mut value_change = self.read_value_change();\n let delay_change = self.read_delay_change();\n\n let block_number = self.context.block_number() as u32;\n let current_delay = delay_change.get_current(block_number);\n\n // TODO: make this configurable\n // https://github.com/AztecProtocol/aztec-packages/issues/5501\n let block_of_change = block_number + current_delay;\n value_change.schedule_change(new_value, block_number, current_delay, block_of_change);\n\n self.write_value_change(value_change);\n }\n\n pub fn schedule_delay_change(self, new_delay: u32) {\n let mut delay_change = self.read_delay_change();\n\n let block_number = self.context.block_number() as u32;\n\n delay_change.schedule_change(new_delay, block_number);\n\n self.write_delay_change(delay_change);\n }\n\n pub fn get_current_value_in_public(self) -> T {\n let block_number = self.context.block_number() as u32;\n self.read_value_change().get_current_at(block_number)\n }\n\n pub fn get_current_delay_in_public(self) -> u32 {\n let block_number = self.context.block_number() as u32;\n self.read_delay_change().get_current(block_number)\n }\n\n pub fn get_scheduled_value_in_public(self) -> (T, u32) {\n self.read_value_change().get_scheduled()\n }\n\n pub fn get_scheduled_delay_in_public(self) -> (u32, u32) {\n self.read_delay_change().get_scheduled()\n }\n\n fn read_value_change(self) -> ScheduledValueChange<T> {\n public_storage::read(self.get_value_change_storage_slot())\n }\n\n fn read_delay_change(self) -> ScheduledDelayChange<INITIAL_DELAY> {\n public_storage::read(self.get_delay_change_storage_slot())\n }\n\n fn write_value_change(self, value_change: ScheduledValueChange<T>) {\n public_storage::write(self.get_value_change_storage_slot(), value_change);\n }\n\n fn write_delay_change(self, delay_change: ScheduledDelayChange<INITIAL_DELAY>) {\n public_storage::write(self.get_delay_change_storage_slot(), delay_change);\n }\n}\n\nimpl<T, INITIAL_DELAY> SharedMutable<T, INITIAL_DELAY, &mut PrivateContext> {\n pub fn get_current_value_in_private(self) -> T where T: FromField {\n // When reading the current value in private we construct a historical state proof for the public value.\n // However, since this value might change, we must constrain the maximum transaction block number as this proof\n // will only be valid for however many blocks we can ensure the value will not change, which will depend on the\n // current delay and any scheduled delay changes.\n\n let (value_change, delay_change, historical_block_number) = self.historical_read_from_public_storage(*self.context);\n\n // We use the effective minimum delay as opposed to the current delay at the historical block as this one also\n // takes into consideration any scheduled delay changes. \n // For example, consider a scenario in which at block 200 the current delay was 50. We may naively think that\n // the earliest we could change the value would be at block 251 by scheduling immediately after the historical\n // block, i.e. at block 201. But if there was a delay change scheduled for block 210 to reduce the delay to 20 \n // blocks, then if a value change was scheduled at block 210 it would go into effect at block 230, which is \n // earlier than what we'd expect if we only considered the current delay.\n let effective_minimum_delay = delay_change.get_effective_minimum_delay_at(historical_block_number);\n let block_horizon = value_change.get_block_horizon(historical_block_number, effective_minimum_delay);\n\n // We prevent this transaction from being included in any block after the block horizon, ensuring that the \n // historical public value matches the current one, since it can only change after the horizon.\n self.context.set_tx_max_block_number(block_horizon);\n value_change.get_current_at(historical_block_number)\n }\n\n fn historical_read_from_public_storage(\n self,\n context: PrivateContext\n ) -> (ScheduledValueChange<T>, ScheduledDelayChange<INITIAL_DELAY>, u32) where T: FromField {\n let header = context.get_header();\n // Ideally the following would be simply public_storage::read_historical, but we can't implement that yet.\n let value_change_slot = self.get_value_change_storage_slot();\n let mut raw_value_change_fields = [0; 3];\n for i in 0..3 {\n raw_value_change_fields[i] = header.public_storage_historical_read(\n value_change_slot + i as Field,\n context.this_address()\n );\n }\n\n // Ideally the following would be simply public_storage::read_historical, but we can't implement that yet.\n let delay_change_slot = self.get_delay_change_storage_slot();\n let raw_delay_change_fields = [header.public_storage_historical_read(delay_change_slot, context.this_address())];\n\n let value_change = ScheduledValueChange::deserialize(raw_value_change_fields);\n let delay_change = ScheduledDelayChange::deserialize(raw_delay_change_fields);\n\n let historical_block_number = context.historical_header.global_variables.block_number as u32;\n\n (value_change, delay_change, historical_block_number)\n }\n}\n" }, "180": { "path": "/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr", "source": "use crate::utils::field::field_from_bytes;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Serialize, Deserialize, FromField, ToField, Empty};\n\nglobal SELECTOR_SIZE = 4;\n\nstruct FunctionSelector {\n // 1st 4-bytes of abi-encoding of function.\n inner: u32,\n}\n\nimpl Eq for FunctionSelector {\n fn eq(self, function_selector: FunctionSelector) -> bool {\n function_selector.inner == self.inner\n }\n}\n\nimpl Serialize<1> for FunctionSelector {\n fn serialize(self: Self) -> [Field; 1] {\n [self.inner as Field]\n }\n}\n\nimpl Deserialize<1> for FunctionSelector {\n fn deserialize(fields: [Field; 1]) -> Self {\n Self {\n inner: fields[0] as u32\n }\n }\n}\n\nimpl FromField for FunctionSelector {\n fn from_field(field: Field) -> Self {\n Self { inner: field as u32 }\n }\n}\n\nimpl ToField for FunctionSelector {\n fn to_field(self) -> Field {\n self.inner as Field\n }\n}\n\nimpl Empty for FunctionSelector {\n fn empty() -> Self {\n Self { inner: 0 as u32 }\n }\n}\n\nimpl FunctionSelector {\n pub fn from_u32(value: u32) -> Self {\n Self { inner: value }\n }\n\n pub fn from_signature<N>(signature: str<N>) -> Self {\n let bytes = signature.as_bytes();\n let hash = dep::std::hash::keccak256(bytes, bytes.len() as u32);\n\n let mut selector_be_bytes = [0; SELECTOR_SIZE];\n for i in 0..SELECTOR_SIZE {\n selector_be_bytes[i] = hash[i];\n }\n\n FunctionSelector::from_field(field_from_bytes(selector_be_bytes, true))\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n" }, "215": { "path": "/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/storage/map.nr", "source": "use crate::{hash::pedersen_hash, traits::ToField};\n\npub fn derive_storage_slot_in_map<K>(storage_slot: Field, key: K) -> Field where K: ToField {\n pedersen_hash([storage_slot, key.to_field()], 0)\n}\n" }, "22": { "path": "std/field.nr", "source": "mod bn254;\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n pub fn to_le_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_le_bits(bit_size)\n }\n\n pub fn to_be_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_be_bits(bit_size)\n }\n\n #[builtin(to_le_bits)]\n fn __to_le_bits(self, _bit_size: u32) -> [u1] {}\n\n #[builtin(to_be_bits)]\n fn __to_be_bits(self, bit_size: u32) -> [u1] {}\n\n #[builtin(apply_range_constraint)]\n fn __assert_max_bit_size(self, bit_size: u32) {}\n\n pub fn assert_max_bit_size(self: Self, bit_size: u32) {\n crate::assert_constant(bit_size);\n assert(bit_size < modulus_num_bits() as u32);\n self.__assert_max_bit_size(bit_size);\n }\n\n pub fn to_le_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_le_radix(256, byte_size)\n }\n\n pub fn to_be_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_be_radix(256, byte_size)\n }\n\n pub fn to_le_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_le_radix(radix, result_len)\n }\n\n pub fn to_be_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_be_radix(radix, result_len)\n }\n\n // decompose `_self` into a `_result_len` vector over the `_radix` basis\n // `_radix` must be less than 256\n #[builtin(to_le_radix)]\n fn __to_le_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n #[builtin(to_be_radix)]\n fn __to_be_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b = exponent.to_le_bits(32);\n\n for i in 1..33 {\n r *= r;\n r = (b[32-i] as Field) * (r * self) + (1 - b[32-i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n}\n\n#[builtin(modulus_num_bits)]\npub fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub fn modulus_le_bytes() -> [u8] {}\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n let num_bytes = (modulus_num_bits() as u32 + 7) / 8;\n let x_bytes = x.to_le_bytes(num_bytes);\n let y_bytes = y.to_le_bytes(num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i] as u8;\n let y_byte = y_bytes[num_bytes - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\n" }, "222": { "path": "/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/type_serialization.nr", "source": "use crate::traits::{Serialize, Deserialize};\n\nglobal BOOL_SERIALIZED_LEN: Field = 1;\nglobal U8_SERIALIZED_LEN: Field = 1;\nglobal U32_SERIALIZED_LEN: Field = 1;\nglobal U64_SERIALIZED_LEN: Field = 1;\nglobal U128_SERIALIZED_LEN: Field = 1;\nglobal FIELD_SERIALIZED_LEN: Field = 1;\n\nimpl Serialize<BOOL_SERIALIZED_LEN> for bool {\n fn serialize(self) -> [Field; BOOL_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize<BOOL_SERIALIZED_LEN> for bool {\n fn deserialize(fields: [Field; BOOL_SERIALIZED_LEN]) -> bool {\n fields[0] as bool\n }\n}\n\nimpl Serialize<U8_SERIALIZED_LEN> for u8 {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize<U8_SERIALIZED_LEN> for u8 {\n fn deserialize(fields: [Field; U8_SERIALIZED_LEN]) -> Self {\n fields[0] as u8\n }\n}\n\nimpl Serialize<U32_SERIALIZED_LEN> for u32 {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize<U32_SERIALIZED_LEN> for u32 {\n fn deserialize(fields: [Field; U32_SERIALIZED_LEN]) -> Self {\n fields[0] as u32\n }\n}\n\nimpl Serialize<U64_SERIALIZED_LEN> for u64 {\n fn serialize(self) -> [Field; U64_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize<U64_SERIALIZED_LEN> for u64 {\n fn deserialize(fields: [Field; U64_SERIALIZED_LEN]) -> Self {\n fields[0] as u64\n }\n}\n\nimpl Serialize<U128_SERIALIZED_LEN> for U128 {\n fn serialize(self) -> [Field; 1] {\n [self.to_integer()]\n }\n\n}\n\nimpl Deserialize<U128_SERIALIZED_LEN> for U128 {\n fn deserialize(fields: [Field; U128_SERIALIZED_LEN]) -> Self {\n U128::from_integer(fields[0])\n }\n}\n\nimpl Serialize<FIELD_SERIALIZED_LEN> for Field {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self]\n }\n}\n\nimpl Deserialize<FIELD_SERIALIZED_LEN> for Field {\n fn deserialize(fields: [Field; FIELD_SERIALIZED_LEN]) -> Self {\n fields[0]\n }\n}\n" }, "223": { "path": "/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/traits.nr", "source": "use dep::std::cmp::Eq;\nuse crate::utils::field::field_from_bytes;\n\n// Trait: is_empty\n//\n// The general is_empty trait checks if a data type is is empty,\n// and it defines empty for the basic data types as 0.\n//\n// If a Field is equal to zero, then it is regarded as zero.\n// We will go with this definition for now, however it can be problematic \n// if a value can actually be zero. In a future refactor, we can \n// use the optional type for safety. Doing it now would lead to a worse devex\n// and would make it harder to sync up with the cpp code.\n// Preferred over Default trait to convey intent, as default doesn't necessarily mean empty.\ntrait Empty {\n fn empty() -> Self;\n}\n\nimpl Empty for Field { fn empty() -> Self {0} }\n\nimpl Empty for u1 { fn empty() -> Self {0} }\nimpl Empty for u8 { fn empty() -> Self {0} }\nimpl Empty for u32 { fn empty() -> Self {0} }\nimpl Empty for u64 { fn empty() -> Self {0} }\nimpl Empty for U128 { fn empty() -> Self {U128::from_integer(0)} }\n\npub fn is_empty<T>(item: T) -> bool where T: Empty + Eq {\n item.eq(T::empty())\n}\n\npub fn is_empty_array<T, N>(array: [T; N]) -> bool where T: Empty + Eq {\n array.all(|elem| is_empty(elem))\n}\n\ntrait Hash {\n fn hash(self) -> Field;\n}\n\ntrait ToField {\n fn to_field(self) -> Field;\n}\n\nimpl ToField for Field {\n fn to_field(self) -> Field {\n self\n }\n}\n\nimpl ToField for bool { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u1 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u8 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u32 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u64 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for U128 {\n fn to_field(self) -> Field {\n self.to_integer()\n }\n}\nimpl<N> ToField for str<N> {\n fn to_field(self) -> Field {\n assert(N < 32, \"String doesn't fit in a field, consider using Serialize instead\");\n field_from_bytes(self.as_bytes(), true)\n }\n}\n\ntrait FromField {\n fn from_field(value: Field) -> Self;\n}\n\nimpl FromField for Field {\n fn from_field(value: Field) -> Self {\n value\n }\n}\n\nimpl FromField for bool { fn from_field(value: Field) -> Self { value as bool } }\nimpl FromField for u1 { fn from_field(value: Field) -> Self { value as u1 } }\nimpl FromField for u8 { fn from_field(value: Field) -> Self { value as u8 } }\nimpl FromField for u32 { fn from_field(value: Field) -> Self { value as u32 } }\nimpl FromField for u64 { fn from_field(value: Field) -> Self { value as u64 } }\nimpl FromField for U128 {\n fn from_field(value: Field) -> Self {\n U128::from_integer(value)\n }\n}\n\n// docs:start:serialize\ntrait Serialize<N> {\n fn serialize(self) -> [Field; N];\n}\n// docs:end:serialize\n\nimpl<N> Serialize<N> for [Field; N] {\n fn serialize(self) -> [Field; N] {\n self\n }\n}\nimpl<N> Serialize<N> for str<N> {\n fn serialize(self) -> [Field; N] {\n let mut result = [0; N];\n let bytes: [u8; N] = self.as_bytes();\n for i in 0..N {\n result[i] = field_from_bytes([bytes[i];1], true);\n }\n result\n }\n}\n\n// docs:start:deserialize\ntrait Deserialize<N> {\n fn deserialize(fields: [Field; N]) -> Self;\n}\n// docs:end:deserialize" }, "231": { "path": "/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr", "source": "use crate::{\n abis::{\n contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage,\n function_selector::FunctionSelector, log_hash::{LogHash, ScopedLogHash, ScopedEncryptedLogHash},\n note_hash::ScopedNoteHash, nullifier::ScopedNullifier\n},\n address::{AztecAddress, EthAddress},\n constants::{\n FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER,\n GENERATOR_INDEX__VK, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH,\n MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX\n},\n contract_class_id::ContractClassId, merkle_tree::root::root_from_sibling_path,\n messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message},\n recursion::verification_key::VerificationKey, traits::{Hash, is_empty},\n utils::{uint256::U256, field::field_from_bytes_32_trunc}\n};\nuse dep::std::hash::{pedersen_hash_with_separator, sha256};\n\npub fn sha256_to_field<N>(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256(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(function_leaf, function_leaf_index, function_leaf_sibling_path)\n}\n\npub fn compute_note_hash_nonce(first_nullifier: Field, note_hash_index: u32) -> Field {\n pedersen_hash(\n [\n first_nullifier,\n note_hash_index as Field\n ],\n GENERATOR_INDEX__NOTE_HASH_NONCE\n )\n}\n\nfn compute_unique_note_hash(nonce: Field, note_hash: Field) -> Field {\n pedersen_hash(\n [\n nonce,\n note_hash\n ],\n GENERATOR_INDEX__UNIQUE_NOTE_HASH\n )\n}\n\npub fn compute_siloed_note_hash(address: AztecAddress, unique_note_hash: Field) -> Field {\n pedersen_hash(\n [\n address.to_field(),\n unique_note_hash\n ],\n GENERATOR_INDEX__SILOED_NOTE_HASH\n )\n}\n\npub fn silo_note_hash(note_hash: ScopedNoteHash, first_nullifier: Field, index: u32) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n let nonce = compute_note_hash_nonce(first_nullifier, index);\n let unique_note_hash = compute_unique_note_hash(nonce, note_hash.value());\n compute_siloed_note_hash(note_hash.contract_address, unique_note_hash)\n }\n}\n\npub fn compute_siloed_nullifier(address: AztecAddress, nullifier: Field) -> Field {\n pedersen_hash(\n [\n address.to_field(),\n nullifier\n ],\n GENERATOR_INDEX__OUTER_NULLIFIER\n )\n}\n\npub fn silo_nullifier(nullifier: ScopedNullifier) -> Field {\n if nullifier.contract_address.is_zero() {\n nullifier.value() // Return value instead of 0 because the first nullifier's contract address is zero.\n } else {\n compute_siloed_nullifier(nullifier.contract_address, nullifier.value())\n }\n}\n\npub fn compute_siloed_encrypted_log_hash(address: AztecAddress, randomness: Field, log_hash: Field) -> Field {\n // TODO: Using 0 GENERATOR_INDEX here as interim before we move to posiedon\n // NB: A unique separator will be needed for masked_contract_address\n let mut masked_contract_address = pedersen_hash([address.to_field(), randomness], 0);\n if randomness == 0 {\n // In some cases, we actually want to reveal the contract address we are siloing with:\n // e.g. 'handshaking' contract w/ known address\n // An app providing randomness = 0 signals to not mask the address.\n masked_contract_address = address.to_field();\n }\n accumulate_sha256([masked_contract_address, log_hash])\n}\n\npub fn silo_encrypted_log_hash(log_hash: ScopedEncryptedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_encrypted_log_hash(\n log_hash.contract_address,\n log_hash.log_hash.randomness,\n log_hash.log_hash.value\n )\n }\n}\n\npub fn compute_siloed_unencrypted_log_hash(address: AztecAddress, log_hash: Field) -> Field {\n accumulate_sha256([address.to_field(), log_hash])\n}\n\npub fn silo_unencrypted_log_hash(log_hash: ScopedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_unencrypted_log_hash(log_hash.contract_address, log_hash.value())\n }\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n pedersen_hash([left, right], 0)\n}\n\npub fn stdlib_recursion_verification_key_compress_native_vk(_vk: VerificationKey) -> Field {\n // Original cpp code\n // stdlib::recursion::verification_key<CT::bn254>::compress_native(private_call.vk, GeneratorIndex::VK);\n // The above cpp method is only ever called on verification key, so it has been special cased here\n let _hash_index = GENERATOR_INDEX__VK;\n 0\n}\n\npub fn compute_l2_to_l1_hash(\n contract_address: AztecAddress,\n recipient: EthAddress,\n content: Field,\n rollup_version_id: Field,\n chain_id: Field\n) -> Field {\n let mut bytes: BoundedVec<u8, 160> = BoundedVec::new();\n\n let inputs = [contract_address.to_field(), rollup_version_id, recipient.to_field(), chain_id, content];\n for i in 0..inputs.len() {\n // TODO are bytes be in fr.to_buffer() ?\n let item_bytes = inputs[i].to_be_bytes(32);\n for j in 0..32 {\n bytes.push(item_bytes[j]);\n }\n }\n\n sha256_to_field(bytes.storage)\n}\n\npub fn silo_l2_to_l1_message(msg: ScopedL2ToL1Message, rollup_version_id: Field, chain_id: Field) -> Field {\n if msg.contract_address.is_zero() {\n 0\n } else {\n compute_l2_to_l1_hash(\n msg.contract_address,\n msg.message.recipient,\n msg.message.content,\n rollup_version_id,\n chain_id\n )\n }\n}\n\n// Computes sha256 hash of 2 input hashes.\n//\n// NB: This method now takes in two 31 byte fields - it assumes that any input\n// is the result of a sha_to_field hash and => is truncated\n//\n// TODO(Jan and David): This is used for the encrypted_log hashes.\n// Can we check to see if we can just use hash_to_field or pedersen_compress here?\n//\npub fn accumulate_sha256(input: [Field; 2]) -> Field {\n // This is a note about the cpp code, since it takes an array of Fields\n // instead of a U128.\n // 4 Field elements when converted to bytes will usually \n // occupy 4 * 32 = 128 bytes.\n // However, this function is making the assumption that each Field \n // only occupies 128 bits.\n //\n // TODO(David): This does not seem to be getting guaranteed anywhere in the code?\n\n // Concatentate two fields into 32x2 = 64 bytes\n // accumulate_sha256 assumes that the inputs are pre-truncated 31 byte numbers\n let mut hash_input_flattened = [0; 64];\n for offset in 0..input.len() {\n let input_as_bytes = input[offset].to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n\n sha256_to_field(hash_input_flattened)\n}\n\n// Computes the final logs hash for a tx.\n// NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX\n// to avoid doubling code, since we can't define the byte len to be 32*N directly. \npub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn compute_tx_note_logs_hash(logs: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_NOTE_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn pedersen_hash<N>(inputs: [Field; N], hash_index: u32) -> Field {\n dep::std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash<N>(inputs: [Field; N]) -> Field {\n dep::std::hash::poseidon2::Poseidon2::hash(inputs, N)\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,\n 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\n 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\n 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\n 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\n 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\n 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\n 140, 141, 142, 143, 144, 145, 146, 147, 148, 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(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 compute_l2_l1_hash() {\n // All zeroes\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(0), EthAddress::zero(), 0, 0, 0);\n assert(hash_result == 0xb393978842a0fa3d3e1470196f098f473f9678e72463cb65ec4ab5581856c2);\n\n // Non-zero case\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(1), EthAddress::from_field(3), 5, 2, 4);\n assert(hash_result == 0x3f88c1044a05e5340ed20466276500f6d45ca5603913b9091e957161734e16);\n}\n" }, "259": { "path": "/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils/field.nr", "source": "pub fn field_from_bytes<N>(bytes: [u8; N], big_endian: bool) -> Field {\n assert(bytes.len() < 32, \"field_from_bytes: N must be less than 32\");\n let mut as_field = 0;\n let mut offset = 1;\n for i in 0..N {\n let mut index = i;\n if big_endian {\n index = N - i - 1;\n }\n as_field += (bytes[index] as Field) * offset;\n offset *= 256;\n }\n\n as_field\n}\n\n// Convert a 32 byte array to a field element by truncating the final byte\npub fn field_from_bytes_32_trunc(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..15 {\n // covers bytes 16..30 (31 is truncated and ignored)\n low = low + (bytes32[15 + 15 - i] as Field) * v;\n v = v * 256;\n // covers bytes 0..14\n high = high + (bytes32[14 - i] as Field) * v;\n }\n // covers byte 15\n low = low + (bytes32[15] as Field) * v;\n\n low + high * v\n}\n\n// TODO to radix returns u8, so we cannot use bigger radixes. It'd be ideal to use a radix of the maximum range-constrained integer noir supports\npub fn full_field_less_than(lhs: Field, rhs: Field) -> bool {\n lhs.lt(rhs)\n}\n\npub fn full_field_greater_than(lhs: Field, rhs: Field) -> bool {\n rhs.lt(lhs)\n}\n\n#[test]\nunconstrained fn bytes_field_test() {\n // Tests correctness of field_from_bytes_32_trunc against existing methods\n // Bytes representing 0x543e0a6642ffeb8039296861765a53407bba62bd1c97ca43374de950bbe0a7\n let inputs = [\n 84, 62, 10, 102, 66, 255, 235, 128, 57, 41, 104, 97, 118, 90, 83, 64, 123, 186, 98, 189, 28, 151, 202, 67, 55, 77, 233, 80, 187, 224, 167\n ];\n let field = field_from_bytes(inputs, true);\n let return_bytes = field.to_be_bytes(31);\n for i in 0..31 {\n assert_eq(inputs[i], return_bytes[i]);\n }\n // 32 bytes - we remove the final byte, and check it matches the field\n let inputs2 = [\n 84, 62, 10, 102, 66, 255, 235, 128, 57, 41, 104, 97, 118, 90, 83, 64, 123, 186, 98, 189, 28, 151, 202, 67, 55, 77, 233, 80, 187, 224, 167, 158\n ];\n let field2 = field_from_bytes_32_trunc(inputs2);\n let return_bytes2 = field.to_be_bytes(31);\n\n for i in 0..31 {\n assert_eq(return_bytes2[i], return_bytes[i]);\n }\n assert_eq(field2, field);\n}\n" }, "273": { "path": "/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr", "source": "use crate::{\n crate::address::{eth_address::EthAddress, partial_address::PartialAddress, public_keys_hash::PublicKeysHash},\n constants::{AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1},\n contract_class_id::ContractClassId, hash::poseidon2_hash, grumpkin_point::GrumpkinPoint,\n traits::{Empty, FromField, ToField, Serialize, Deserialize}, utils\n};\n\n// Aztec address\nstruct AztecAddress {\n inner : Field\n}\n\nimpl Eq for AztecAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\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 Serialize<AZTEC_ADDRESS_LENGTH> for AztecAddress {\n fn serialize(self: Self) -> [Field; AZTEC_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize<AZTEC_ADDRESS_LENGTH> for AztecAddress {\n fn deserialize(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self {\n FromField::from_field(fields[0])\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn compute(pub_keys_hash: PublicKeysHash, partial_address: PartialAddress) -> AztecAddress {\n AztecAddress::from_field(\n poseidon2_hash([pub_keys_hash.to_field(), partial_address.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1])\n )\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 pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n\n#[test]\nfn compute_address_from_partial_and_pub_keys_hash() {\n let pub_keys_hash = PublicKeysHash::from_field(1);\n let partial_address = PartialAddress::from_field(2);\n\n let address = AztecAddress::compute(pub_keys_hash, partial_address);\n let expected_computed_address_from_partial_and_pubkey = 0x1b6ead051e7b42665064ca6cf1ec77da0a36d86e00d1ff6e44077966c0c3a9fa;\n assert(address.to_field() == expected_computed_address_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 assert_eq(Deserialize::deserialize(address.serialize()), address);\n}\n" }, "28": { "path": "std/hash/poseidon2.nr", "source": "use crate::hash::Hasher;\nuse crate::default::Default;\n\nglobal RATE: u32 = 3;\n\nstruct 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\n pub fn hash<N>(input: [Field; N], message_size: u32) -> Field {\n if message_size == N {\n Poseidon2::hash_internal(input, N, false)\n } else {\n Poseidon2::hash_internal(input, message_size, true)\n }\n }\n\n fn new(iv: Field) -> Poseidon2 {\n let mut result = 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) -> [Field; RATE] {\n // zero-pad the cache\n for i in 0..RATE {\n if i >= self.cache_size {\n self.cache[i] = 0;\n }\n }\n // add the cache into sponge state\n for i in 0..RATE {\n self.state[i] += self.cache[i];\n }\n self.state = crate::hash::poseidon2_permutation(self.state, 4);\n // return `RATE` number of field elements from the sponge state.\n let mut result = [0; RATE];\n for i in 0..RATE {\n result[i] = self.state[i];\n }\n result\n }\n\n fn absorb(&mut self, input: Field) {\n if (!self.squeeze_mode) & (self.cache_size == RATE) {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n let _ = self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else if (!self.squeeze_mode) & (self.cache_size != RATE) {\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 } else if self.squeeze_mode {\n // If we're in squeeze mode, switch to absorb mode and add the input into the cache.\n // N.B. I don't think this code path can be reached?!\n self.cache[0] = input;\n self.cache_size = 1;\n self.squeeze_mode = false;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n if self.squeeze_mode & (self.cache_size == 0) {\n // If we're in squeze mode and the cache is empty, there is nothing left to squeeze out of the sponge!\n // Switch to absorb mode.\n self.squeeze_mode = false;\n self.cache_size = 0;\n }\n if !self.squeeze_mode {\n // If we're in absorb mode, apply sponge permutation to compress the cache, populate cache with compressed\n // state and switch to squeeze mode. Note: this code block will execute if the previous `if` condition was\n // matched\n let new_output_elements = self.perform_duplex();\n self.squeeze_mode = true;\n for i in 0..RATE {\n self.cache[i] = new_output_elements[i];\n }\n self.cache_size = RATE;\n }\n // By this point, we should have a non-empty cache. Pop one item off the top of the cache and return it.\n let result = self.cache[0];\n for i in 1..RATE {\n if i < self.cache_size {\n self.cache[i - 1] = self.cache[i];\n }\n }\n self.cache_size -= 1;\n self.cache[self.cache_size] = 0;\n result\n }\n\n fn hash_internal<N>(input: [Field; N], in_len: u32, is_variable_length: bool) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv : Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\nstruct 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 {\n _state: &[],\n }\n }\n}\n" }, "335": { "path": "/usr/src/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr", "source": "contract KeyRegistry {\n use dep::authwit::auth::assert_current_call_valid_authwit_public;\n\n use dep::aztec::{\n keys::PublicKeys, state_vars::{SharedMutable, Map},\n protocol_types::{grumpkin_point::GrumpkinPoint, address::{AztecAddress, PartialAddress}}\n };\n\n global KEY_ROTATION_DELAY = 5;\n\n #[aztec(storage)]\n struct Storage {\n // The following stores a hash of individual master public keys\n // If you change slots of vars below, you must update the slots in `SharedMutablePrivateGetter` in aztec-nr/keys.\n // We store x and y coordinates in individual shared mutables as shared mutable currently supports only 1 field\n npk_m_x_registry: Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY>>,\n npk_m_y_registry: Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY>>,\n\n ivpk_m_x_registry: Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY>>,\n ivpk_m_y_registry: Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY>>,\n \n ovpk_m_x_registry: Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY>>,\n ovpk_m_y_registry: Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY>>,\n \n tpk_m_x_registry: Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY>>,\n tpk_m_y_registry: Map<AztecAddress, SharedMutable<Field, KEY_ROTATION_DELAY>>,\n }\n\n #[aztec(public)]\n fn rotate_npk_m(address: AztecAddress, new_npk_m: GrumpkinPoint, nonce: Field) {\n // TODO: (#6137)\n if (!address.eq(context.msg_sender())) {\n assert_current_call_valid_authwit_public(&mut context, address);\n } else {\n assert(nonce == 0, \"invalid nonce\");\n }\n\n let npk_m_x_registry = storage.npk_m_x_registry.at(address);\n let npk_m_y_registry = storage.npk_m_y_registry.at(address);\n npk_m_x_registry.schedule_value_change(new_npk_m.x);\n npk_m_y_registry.schedule_value_change(new_npk_m.y);\n }\n\n #[aztec(public)]\n fn register(address: AztecAddress, partial_address: PartialAddress, keys: PublicKeys) {\n let computed_address = AztecAddress::compute(keys.hash(), partial_address);\n\n assert(computed_address.eq(address), \"Computed address does not match supplied address\");\n\n let npk_m_x_registry = storage.npk_m_x_registry.at(address);\n let npk_m_y_registry = storage.npk_m_y_registry.at(address);\n let ivpk_m_x_registry = storage.ivpk_m_x_registry.at(address);\n let ivpk_m_y_registry = storage.ivpk_m_y_registry.at(address);\n let ovpk_m_x_registry = storage.ovpk_m_x_registry.at(address);\n let ovpk_m_y_registry = storage.ovpk_m_y_registry.at(address);\n let tpk_m_x_registry = storage.tpk_m_x_registry.at(address);\n let tpk_m_y_registry = storage.tpk_m_y_registry.at(address);\n\n npk_m_x_registry.schedule_value_change(keys.npk_m.x);\n npk_m_y_registry.schedule_value_change(keys.npk_m.y);\n ivpk_m_x_registry.schedule_value_change(keys.ivpk_m.x);\n ivpk_m_y_registry.schedule_value_change(keys.ivpk_m.y);\n ovpk_m_x_registry.schedule_value_change(keys.ovpk_m.x);\n ovpk_m_y_registry.schedule_value_change(keys.ovpk_m.y);\n tpk_m_x_registry.schedule_value_change(keys.tpk_m.x);\n tpk_m_y_registry.schedule_value_change(keys.tpk_m.y);\n }\n}\n" }, "44": { "path": "std/uint128.nr", "source": "use crate::ops::{Add, Sub, Mul, Div, Rem, Not, BitOr, BitAnd, BitXor, Shl, Shr};\nuse crate::cmp::{Eq, Ord, Ordering};\nuse crate::println;\n\nglobal pow64 : Field = 18446744073709551616; //2^64;\nglobal pow63 : Field = 9223372036854775808; // 2^63;\nstruct U128 {\n lo: Field,\n hi: Field,\n}\n\nimpl U128 {\n\n pub fn from_u64s_le(lo: u64, hi: u64) -> U128 {\n // in order to handle multiplication, we need to represent the product of two u64 without overflow\n assert(crate::field::modulus_num_bits() as u32 > 128);\n U128 { lo: lo as Field, hi: hi as Field }\n }\n\n pub fn from_u64s_be(hi: u64, lo: u64) -> U128 {\n U128::from_u64s_le(lo, hi)\n }\n\n pub fn zero() -> U128 {\n U128 { lo: 0, hi: 0 }\n }\n\n pub fn one() -> U128 {\n U128 { lo: 1, hi: 0 }\n }\n pub fn from_le_bytes(bytes: [u8; 16]) -> U128 {\n let mut lo = 0;\n let mut base = 1;\n for i in 0..8 {\n lo += (bytes[i] as Field)*base;\n base *= 256;\n }\n let mut hi = 0;\n base = 1;\n for i in 8..16 {\n hi += (bytes[i] as Field)*base;\n base *= 256;\n }\n U128 { lo, hi }\n }\n\n pub fn to_be_bytes(self: Self) -> [u8; 16] {\n let lo = self.lo.to_be_bytes(8);\n let hi = self.hi.to_be_bytes(8);\n let mut bytes = [0; 16];\n for i in 0..8 {\n bytes[i] = hi[i];\n bytes[i+8] = lo[i];\n }\n bytes\n }\n\n pub fn to_le_bytes(self: Self) -> [u8; 16] {\n let lo = self.lo.to_le_bytes(8);\n let hi = self.hi.to_le_bytes(8);\n let mut bytes = [0; 16];\n for i in 0..8 {\n bytes[i] = lo[i];\n bytes[i+8] = hi[i];\n }\n bytes\n }\n\n pub fn from_hex<N>(hex: str<N>) -> U128 {\n let N = N as u32;\n let bytes = hex.as_bytes();\n // string must starts with \"0x\"\n assert((bytes[0] == 48) & (bytes[1] == 120), \"Invalid hexadecimal string\");\n assert(N < 35, \"Input does not fit into a U128\");\n\n let mut lo = 0;\n let mut hi = 0;\n let mut base = 1;\n if N <= 18 {\n for i in 0..N - 2 {\n lo += U128::decode_ascii(bytes[N-i-1])*base;\n base = base*16;\n }\n } else {\n for i in 0..16 {\n lo += U128::decode_ascii(bytes[N-i-1])*base;\n base = base*16;\n }\n base = 1;\n for i in 17..N - 1 {\n hi += U128::decode_ascii(bytes[N-i])*base;\n base = base*16;\n }\n }\n U128 { lo: lo as Field, hi: hi as Field }\n }\n\n unconstrained fn uconstrained_check_is_upper_ascii(ascii: u8) -> bool {\n ((ascii >= 65) & (ascii <= 90)) // Between 'A' and 'Z'\n }\n\n fn decode_ascii(ascii: u8) -> Field {\n if ascii < 58 {\n ascii - 48\n } else {\n let ascii = ascii + 32 * (U128::uconstrained_check_is_upper_ascii(ascii) as u8);\n assert(ascii >= 97); // enforce >= 'a'\n assert(ascii <= 102); // enforce <= 'f'\n ascii - 87\n } as Field\n }\n\n // TODO: Replace with a faster version. \n // A circuit that uses this function can be slow to compute\n // (we're doing up to 127 calls to compute the quotient)\n unconstrained fn unconstrained_div(self: Self, b: U128) -> (U128, U128) {\n if b == U128::zero() {\n // Return 0,0 to avoid eternal loop\n (U128::zero(), U128::zero())\n } else if self < b {\n (U128::zero(), self)\n } else if self == b {\n (U128::one(), U128::zero())\n } else {\n let (q,r) = if b.hi as u64 >= pow63 as u64 {\n // The result of multiplication by 2 would overflow\n (U128::zero(), self)\n } else {\n self.unconstrained_div(b * U128::from_u64s_le(2, 0))\n };\n let q_mul_2 = q * U128::from_u64s_le(2, 0);\n if r < b {\n (q_mul_2, r)\n } else {\n (q_mul_2 + U128::one(), r - b)\n }\n }\n }\n\n pub fn from_integer<T>(i: T) -> U128 {\n let f = crate::as_field(i);\n // Reject values which would overflow a u128\n f.assert_max_bit_size(128);\n let lo = f as u64 as Field;\n let hi = (f - lo) / pow64;\n U128 { lo, hi }\n }\n\n pub fn to_integer<T>(self) -> T {\n crate::from_field(self.lo + self.hi * pow64)\n }\n\n fn wrapping_mul(self: Self, b: U128) -> U128 {\n let low = self.lo * b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64;\n let high = self.lo * b.hi + self.hi * b.lo + carry;\n let hi = high as u64 as Field;\n U128 { lo, hi }\n }\n}\n\nimpl Add for U128 {\n fn add(self: Self, b: U128) -> U128 {\n let low = self.lo + b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64; \n let high = self.hi + b.hi + carry;\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to add with overflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Sub for U128 {\n fn sub(self: Self, b: U128) -> U128 {\n let low = pow64 + self.lo - b.lo;\n let lo = low as u64 as Field;\n let borrow = (low == lo) as Field;\n let high = self.hi - b.hi - borrow;\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to subtract with underflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Mul for U128 {\n fn mul(self: Self, b: U128) -> U128 {\n assert(self.hi*b.hi == 0, \"attempt to multiply with overflow\");\n let low = self.lo*b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64;\n let high = if crate::field::modulus_num_bits() as u32 > 196 {\n (self.lo+self.hi)*(b.lo+b.hi) - low + carry\n } else {\n self.lo*b.hi + self.hi*b.lo + carry\n };\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to multiply with overflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Div for U128 {\n fn div(self: Self, b: U128) -> U128 {\n let (q,r) = self.unconstrained_div(b);\n let a = b * q + r;\n assert_eq(self, a);\n assert(r < b);\n q\n }\n}\n\nimpl Rem for U128 {\n fn rem(self: Self, b: U128) -> U128 {\n let (q,r) = self.unconstrained_div(b);\n let a = b * q + r;\n assert_eq(self, a);\n assert(r < b);\n r\n }\n}\n\nimpl Eq for U128 {\n fn eq(self: Self, b: U128) -> bool {\n (self.lo == b.lo) & (self.hi == b.hi)\n }\n}\n\nimpl Ord for U128 {\n fn cmp(self, other: Self) -> Ordering {\n let hi_ordering = (self.hi as u64).cmp((other.hi as u64));\n let lo_ordering = (self.lo as u64).cmp((other.lo as u64));\n \n if hi_ordering == Ordering::equal() {\n lo_ordering\n } else {\n hi_ordering\n }\n }\n}\n\nimpl Not for U128 { \n fn not(self) -> U128 {\n U128 {\n lo: (!(self.lo as u64)) as Field,\n hi: (!(self.hi as u64)) as Field\n }\n }\n}\n\nimpl BitOr for U128 { \n fn bitor(self, other: U128) -> U128 {\n U128 {\n lo: ((self.lo as u64) | (other.lo as u64)) as Field,\n hi: ((self.hi as u64) | (other.hi as u64)) as Field\n }\n }\n}\n\nimpl BitAnd for U128 {\n fn bitand(self, other: U128) -> U128 { \n U128 {\n lo: ((self.lo as u64) & (other.lo as u64)) as Field,\n hi: ((self.hi as u64) & (other.hi as u64)) as Field\n }\n }\n}\n\nimpl BitXor for U128 {\n fn bitxor(self, other: U128) -> U128 { \n U128 {\n lo: ((self.lo as u64) ^ (other.lo as u64)) as Field,\n hi: ((self.hi as u64) ^ (other.hi as u64)) as Field\n }\n }\n}\n\nimpl Shl for U128 { \n fn shl(self, other: u8) -> U128 { \n assert(other < 128, \"attempt to shift left with overflow\");\n let exp_bits = (other as Field).to_be_bits(7);\n\n let mut r: Field = 2;\n let mut y: Field = 1;\n for i in 1..8 {\n y = (exp_bits[7-i] as Field) * (r * y) + (1 - exp_bits[7-i] as Field) * y;\n r *= r;\n }\n self.wrapping_mul(U128::from_integer(y))\n } \n}\n\nimpl Shr for U128 { \n fn shr(self, other: u8) -> U128 { \n assert(other < 128, \"attempt to shift right with overflow\");\n let exp_bits = (other as Field).to_be_bits(7);\n\n let mut r: Field = 2;\n let mut y: Field = 1;\n for i in 1..8 {\n y = (exp_bits[7-i] as Field) * (r * y) + (1 - exp_bits[7-i] as Field) * y;\n r *= r;\n }\n self / U128::from_integer(y)\n } \n}\n\nmod tests {\n use crate::uint128::{U128, pow64, pow63};\n\n #[test]\n fn test_not() {\n let num = U128::from_u64s_le(0, 0);\n let not_num = num.not();\n\n let max_u64: Field = pow64 - 1;\n assert_eq(not_num.hi, max_u64);\n assert_eq(not_num.lo, max_u64);\n\n let not_not_num = not_num.not();\n assert_eq(num, not_not_num);\n }\n #[test]\n fn test_construction() {\n // Check little-endian u64 is inversed with big-endian u64 construction\n let a = U128::from_u64s_le(2, 1);\n let b = U128::from_u64s_be(1, 2);\n assert_eq(a, b);\n // Check byte construction is equivalent\n let c = U128::from_le_bytes([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);\n let d = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908);\n assert_eq(c, d);\n }\n #[test]\n fn test_byte_decomposition() {\n let a = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908);\n // Get big-endian and little-endian byte decompostions\n let le_bytes_a= a.to_le_bytes();\n let be_bytes_a= a.to_be_bytes();\n\n // Check equivalence\n for i in 0..16 {\n assert_eq(le_bytes_a[i], be_bytes_a[15 - i]);\n }\n // Reconstruct U128 from byte decomposition\n let b= U128::from_le_bytes(le_bytes_a);\n // Check that it's the same element\n assert_eq(a, b);\n }\n #[test]\n fn test_hex_constuction() {\n let a = U128::from_u64s_le(0x1, 0x2);\n let b = U128::from_hex(\"0x20000000000000001\");\n assert_eq(a, b);\n\n let c= U128::from_hex(\"0xffffffffffffffffffffffffffffffff\");\n let d= U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff);\n assert_eq(c, d);\n\n let e= U128::from_hex(\"0x00000000000000000000000000000000\");\n let f= U128::from_u64s_le(0, 0);\n assert_eq(e, f);\n }\n\n // Ascii decode tests\n\n #[test]\n fn test_ascii_decode_correct_range() {\n // '0'..'9' range\n for i in 0..10 {\n let decoded= U128::decode_ascii(48 + i);\n assert_eq(decoded, i as Field);\n }\n // 'A'..'F' range\n for i in 0..6 {\n let decoded = U128::decode_ascii(65 + i);\n assert_eq(decoded, (i + 10) as Field);\n }\n // 'a'..'f' range\n for i in 0..6 {\n let decoded = U128::decode_ascii(97 + i);\n assert_eq(decoded, (i + 10) as Field);\n }\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_range_less_than_48_fails_0() {\n crate::println(U128::decode_ascii(0));\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_less_than_48_fails_1() {\n crate::println(U128::decode_ascii(47));\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_range_58_64_fails_0() {\n let _ = U128::decode_ascii(58);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_58_64_fails_1() {\n let _ = U128::decode_ascii(64);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_71_96_fails_0() {\n let _ = U128::decode_ascii(71);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_71_96_fails_1() {\n let _ = U128::decode_ascii(96);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_greater_than_102_fails() {\n let _ = U128::decode_ascii(103);\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_regression() {\n // This code will actually fail because of ascii_decode,\n // but in the past it was possible to create a value > (1<<128)\n let a = U128::from_hex(\"0x~fffffffffffffffffffffffffffffff\");\n let b:Field= a.to_integer();\n let c= b.to_le_bytes(17);\n assert(c[16] != 0);\n }\n\n #[test]\n fn test_unconstrained_div() {\n // Test the potential overflow case\n let a= U128::from_u64s_le(0x0, 0xffffffffffffffff);\n let b= U128::from_u64s_le(0x0, 0xfffffffffffffffe);\n let c= U128::one();\n let d= U128::from_u64s_le(0x0, 0x1);\n let (q,r) = a.unconstrained_div(b);\n assert_eq(q, c);\n assert_eq(r, d);\n\n let a = U128::from_u64s_le(2, 0);\n let b = U128::one();\n // Check the case where a is a multiple of b\n let (c,d ) = a.unconstrained_div(b);\n assert_eq((c, d), (a, U128::zero()));\n\n // Check where b is a multiple of a\n let (c,d) = b.unconstrained_div(a);\n assert_eq((c, d), (U128::zero(), b));\n\n // Dividing by zero returns 0,0\n let a = U128::from_u64s_le(0x1, 0x0);\n let b = U128::zero();\n let (c,d)= a.unconstrained_div(b);\n assert_eq((c, d), (U128::zero(), U128::zero()));\n\n // Dividing 1<<127 by 1<<127 (special case)\n let a = U128::from_u64s_le(0x0, pow63 as u64);\n let b = U128::from_u64s_le(0x0, pow63 as u64);\n let (c,d )= a.unconstrained_div(b);\n assert_eq((c, d), (U128::one(), U128::zero()));\n }\n\n #[test]\n fn integer_conversions() {\n // Maximum\n let start:Field = 0xffffffffffffffffffffffffffffffff;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // Minimum\n let start:Field = 0x0;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // Low limb\n let start:Field = 0xffffffffffffffff;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // High limb\n let start:Field = 0xffffffffffffffff0000000000000000;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n }\n #[test]\n fn test_wrapping_mul() {\n // 1*0==0\n assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::one()));\n\n // 0*1==0\n assert_eq(U128::zero(), U128::one().wrapping_mul(U128::zero()));\n\n // 1*1==1\n assert_eq(U128::one(), U128::one().wrapping_mul(U128::one()));\n\n // 0 * ( 1 << 64 ) == 0\n assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::from_u64s_le(0, 1)));\n\n // ( 1 << 64 ) * 0 == 0\n assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::zero()));\n\n // 1 * ( 1 << 64 ) == 1 << 64\n assert_eq(U128::from_u64s_le(0, 1), U128::from_u64s_le(0, 1).wrapping_mul(U128::one()));\n\n // ( 1 << 64 ) * 1 == 1 << 64\n assert_eq(U128::from_u64s_le(0, 1), U128::one().wrapping_mul(U128::from_u64s_le(0, 1)));\n\n // ( 1 << 64 ) * ( 1 << 64 ) == 1 << 64\n assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::from_u64s_le(0, 1)));\n // -1 * -1 == 1\n assert_eq(\n U128::one(), U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff).wrapping_mul(U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff))\n );\n }\n}\n" }, "51": { "path": "/usr/src/noir-projects/aztec-nr/authwit/src/auth.nr", "source": "use dep::aztec::protocol_types::{\n abis::function_selector::FunctionSelector, address::AztecAddress,\n constants::{GENERATOR_INDEX__AUTHWIT_INNER, GENERATOR_INDEX__AUTHWIT_OUTER, CANONICAL_AUTH_REGISTRY_ADDRESS},\n hash::pedersen_hash\n};\nuse dep::aztec::{prelude::Deserialize, context::{PrivateContext, PublicContext, gas::GasOpts}, hash::hash_args_array};\n\nglobal IS_VALID_SELECTOR = 0xabf64ad4; // 4 first bytes of keccak256(\"IS_VALID()\")\n\n// docs:start:assert_current_call_valid_authwit\n// Assert that `on_behalf_of` have authorized the current call with a valid authentication witness\npub fn assert_current_call_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress) {\n let function_selector = FunctionSelector::from_signature(\"spend_private_authwit(Field)\");\n let inner_hash = compute_inner_authwit_hash([context.msg_sender().to_field(), context.selector().to_field(), context.args_hash]);\n let result: Field = context.call_private_function(on_behalf_of, function_selector, [inner_hash]).unpack_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n}\n// docs:end:assert_current_call_valid_authwit\n\n// docs:start:assert_current_call_valid_authwit_public\n// Assert that `on_behalf_of` have authorized the current call in a public context\npub fn assert_current_call_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress) {\n let inner_hash = compute_inner_authwit_hash(\n [(*context).msg_sender().to_field(), (*context).selector().to_field(), (*context).get_args_hash()]\n );\n\n let result: Field = context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"consume((Field),Field)\"),\n [on_behalf_of.to_field(), inner_hash].as_slice(),\n GasOpts::default()\n ).deserialize_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n}\n// docs:end:assert_current_call_valid_authwit_public\n\n// docs:start:compute_call_authwit_hash\n// Compute the message hash to be used by an authentication witness \npub fn compute_call_authwit_hash<N>(\n caller: AztecAddress,\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n selector: FunctionSelector,\n args: [Field; N]\n) -> Field {\n let args_hash = hash_args_array(args);\n let inner_hash = compute_inner_authwit_hash([caller.to_field(), selector.to_field(), args_hash]);\n compute_outer_authwit_hash(consumer, chain_id, version, inner_hash)\n}\n// docs:end:compute_call_authwit_hash\n\npub fn compute_inner_authwit_hash<N>(args: [Field; N]) -> Field {\n pedersen_hash(args, GENERATOR_INDEX__AUTHWIT_INNER)\n}\n\npub fn compute_outer_authwit_hash(\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n inner_hash: Field\n) -> Field {\n pedersen_hash(\n [\n consumer.to_field(),\n chain_id,\n version,\n inner_hash\n ],\n GENERATOR_INDEX__AUTHWIT_OUTER\n )\n}\n\n/**\n * Helper function to set the authorization status of a message hash\n * \n * @param message_hash The hash of the message to authorize\n * @param authorize True if the message should be authorized, false if it should be revoked\n */\npub fn set_authorized(context: &mut PublicContext, message_hash: Field, authorize: bool) {\n context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"set_authorized(Field,bool)\"),\n [message_hash, authorize as Field].as_slice(),\n GasOpts::default()\n ).assert_empty();\n}\n\n/**\n * Helper function to reject all authwits\n *\n * @param reject True if all authwits should be rejected, false otherwise \n */\npub fn set_reject_all(context: &mut PublicContext, reject: bool) {\n context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"set_reject_all(bool)\"),\n [context.this_address().to_field(), reject as Field].as_slice(),\n GasOpts::default()\n ).assert_empty();\n}\n" }, "63": { "path": "/usr/src/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr", "source": "use dep::protocol_types::{\n address::PublicKeysHash, constants::GENERATOR_INDEX__PUBLIC_KEYS_HASH, hash::poseidon2_hash,\n grumpkin_point::GrumpkinPoint, traits::{Deserialize, Serialize}\n};\nuse crate::keys::constants::{NUM_KEY_TYPES, NULLIFIER_INDEX, INCOMING_INDEX, OUTGOING_INDEX};\n\nglobal PUBLIC_KEYS_LENGTH = 8;\n\nstruct PublicKeys {\n npk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n ovpk_m: GrumpkinPoint,\n tpk_m: GrumpkinPoint,\n}\n\nimpl PublicKeys {\n pub fn hash(self) -> PublicKeysHash {\n PublicKeysHash::from_field(\n poseidon2_hash(\n [\n self.npk_m.x,\n self.npk_m.y,\n self.ivpk_m.x,\n self.ivpk_m.y,\n self.ovpk_m.x,\n self.ovpk_m.y,\n self.tpk_m.x,\n self.tpk_m.y,\n GENERATOR_INDEX__PUBLIC_KEYS_HASH\n ]\n )\n )\n }\n\n pub fn get_key_by_index(self, index: Field) -> GrumpkinPoint {\n assert(index as u8 < NUM_KEY_TYPES, \"Invalid key index\");\n if index == NULLIFIER_INDEX {\n self.npk_m\n } else if index == INCOMING_INDEX {\n self.ivpk_m\n } else if index == OUTGOING_INDEX {\n self.ovpk_m\n } else {\n self.tpk_m\n }\n }\n}\n\nimpl Serialize<PUBLIC_KEYS_LENGTH> for PublicKeys {\n fn serialize(self) -> [Field; PUBLIC_KEYS_LENGTH] {\n [\n self.npk_m.x,\n self.npk_m.y,\n self.ivpk_m.x,\n self.ivpk_m.y,\n self.ovpk_m.x,\n self.ovpk_m.y,\n self.tpk_m.x,\n self.tpk_m.y,\n ]\n }\n}\n\nimpl Deserialize<PUBLIC_KEYS_LENGTH> for PublicKeys {\n fn deserialize(serialized: [Field; PUBLIC_KEYS_LENGTH]) -> PublicKeys {\n PublicKeys {\n npk_m: GrumpkinPoint { x: serialized[0], y: serialized[1] },\n ivpk_m: GrumpkinPoint { x: serialized[2], y: serialized[3] },\n ovpk_m: GrumpkinPoint { x: serialized[4], y: serialized[5] },\n tpk_m: GrumpkinPoint { x: serialized[6], y: serialized[7] },\n }\n }\n}\n\n#[test]\nfn compute_public_keys_hash() {\n let keys = PublicKeys {\n npk_m: GrumpkinPoint { x: 1, y: 2 },\n ivpk_m: GrumpkinPoint { x: 3, y: 4 },\n ovpk_m: GrumpkinPoint { x: 5, y: 6 },\n tpk_m: GrumpkinPoint { x: 7, y: 8 }\n };\n\n let actual = keys.hash();\n let expected_public_keys_hash = 0x1936abe4f6a920d16a9f6917f10a679507687e2cd935dd1f1cdcb1e908c027f3;\n assert(actual.to_field() == expected_public_keys_hash);\n}\n\n#[test]\nfn test_public_keys_serialization() {\n let keys = PublicKeys {\n npk_m: GrumpkinPoint { x: 1, y: 2 },\n ivpk_m: GrumpkinPoint { x: 3, y: 4 },\n ovpk_m: GrumpkinPoint { x: 5, y: 6 },\n tpk_m: GrumpkinPoint { x: 7, y: 8 }\n };\n\n let serialized = keys.serialize();\n let deserialized = PublicKeys::deserialize(serialized);\n\n assert_eq(keys.npk_m.x, deserialized.npk_m.x);\n assert_eq(keys.npk_m.y, deserialized.npk_m.y);\n assert_eq(keys.ivpk_m.x, deserialized.ivpk_m.x);\n assert_eq(keys.ivpk_m.y, deserialized.ivpk_m.y);\n assert_eq(keys.ovpk_m.x, deserialized.ovpk_m.x);\n assert_eq(keys.ovpk_m.y, deserialized.ovpk_m.y);\n assert_eq(keys.tpk_m.x, deserialized.tpk_m.x);\n assert_eq(keys.tpk_m.y, deserialized.tpk_m.y);\n}\n" }, "65": { "path": "/usr/src/noir-projects/aztec-nr/aztec/src/public_storage.nr", "source": "use dep::protocol_types::traits::{Deserialize, Serialize};\nuse crate::oracle::storage::{storage_read, storage_write};\n\npub fn read<T, N>(storage_slot: Field) -> T where T: Deserialize<N> {\n T::deserialize(storage_read(storage_slot))\n}\n\npub fn write<T, N>(storage_slot: Field, value: T) where T: Serialize<N> {\n storage_write(storage_slot, value.serialize());\n}\n\n// Ideally we'd do the following, but we cannot because of https://github.com/noir-lang/noir/issues/4633\n// pub fn read_historical<T, N>(\n// storage_slot: Field,\n// context: PrivateContext\n// ) -> T where T: Deserialize<N> {\n// let mut fields = [0; N];\n// for i in 0..N {\n// fields[i] = public_storage_historical_read(\n// context,\n// storage_slot + i as Field,\n// context.this_address()\n// );\n// }\n// T::deserialize(fields)\n// }\n\nmod tests {\n use dep::std::test::OracleMock;\n use dep::protocol_types::traits::{Deserialize, Serialize};\n use crate::public_storage;\n\n struct TestStruct {\n a: Field,\n b: Field,\n }\n\n impl Deserialize<2> for TestStruct {\n fn deserialize(fields: [Field; 2]) -> TestStruct {\n TestStruct { a: fields[0], b: fields[1] }\n }\n }\n\n impl Serialize<2> for TestStruct {\n fn serialize(self) -> [Field; 2] {\n [self.a, self.b]\n }\n }\n\n #[test]\n fn test_read() {\n let slot = 7;\n let written = TestStruct { a: 13, b: 42 };\n\n OracleMock::mock(\"storageRead\").with_params((slot, 2)).returns(written.serialize());\n\n let read: TestStruct = public_storage::read(slot);\n assert_eq(read.a, 13);\n assert_eq(read.b, 42);\n }\n\n #[test]\n fn test_write() {\n let slot = 7;\n let to_write = TestStruct { a: 13, b: 42 };\n\n let mock = OracleMock::mock(\"storageWrite\").returns([0; 2]); // The return value is unused\n\n public_storage::write(slot, to_write);\n assert_eq(mock.get_last_params(), (slot, to_write.serialize()));\n }\n}\n" }, "88": { "path": "/usr/src/noir-projects/aztec-nr/aztec/src/context/public_context.nr", "source": "use crate::hash::{compute_secret_hash, compute_message_hash, compute_message_nullifier};\nuse dep::protocol_types::address::{AztecAddress, EthAddress};\nuse dep::protocol_types::traits::{Serialize, Deserialize, Empty};\nuse dep::protocol_types::abis::function_selector::FunctionSelector;\nuse crate::context::inputs::public_context_inputs::PublicContextInputs;\nuse crate::context::gas::GasOpts;\n\nstruct PublicContext {\n inputs: PublicContextInputs,\n}\n\nimpl PublicContext {\n pub fn new(inputs: PublicContextInputs) -> Self {\n PublicContext { inputs }\n }\n\n pub fn storage_address(self) -> AztecAddress {\n storage_address()\n }\n pub fn fee_per_l2_gas(self) -> Field {\n fee_per_l2_gas()\n }\n pub fn fee_per_da_gas(self) -> Field {\n fee_per_da_gas()\n }\n /**\n * Emit a log with the given event selector and message.\n *\n * @param event_selector The event selector for the log.\n * @param message The message to emit in the log.\n */\n pub fn emit_unencrypted_log_with_selector<T, N>(\n &mut self,\n event_selector: Field,\n log: T\n ) where T: Serialize<N> {\n emit_unencrypted_log(event_selector, Serialize::serialize(log).as_slice());\n }\n // For compatibility with the selector-less API. We'll probably rename the above one.\n pub fn emit_unencrypted_log<T, N>(&mut self, log: T) where T: Serialize<N> {\n self.emit_unencrypted_log_with_selector(/*event_selector=*/ 5, log);\n }\n pub fn note_hash_exists(self, note_hash: Field, leaf_index: Field) -> bool {\n note_hash_exists(note_hash, leaf_index) == 1\n }\n pub fn l1_to_l2_msg_exists(self, msg_hash: Field, msg_leaf_index: Field) -> bool {\n l1_to_l2_msg_exists(msg_hash, msg_leaf_index) == 1\n }\n\n fn block_number(self) -> Field {\n block_number()\n }\n\n fn timestamp(self) -> u64 {\n timestamp()\n }\n\n fn transaction_fee(self) -> Field {\n transaction_fee()\n }\n\n fn nullifier_exists(self, unsiloed_nullifier: Field, address: AztecAddress) -> bool {\n nullifier_exists(unsiloed_nullifier, address.to_field()) == 1\n }\n\n fn consume_l1_to_l2_message(\n &mut self,\n content: Field,\n secret: Field,\n sender: EthAddress,\n leaf_index: Field\n ) {\n let secret_hash = compute_secret_hash(secret);\n let message_hash = compute_message_hash(\n sender,\n self.chain_id(),\n /*recipient=*/ self.this_address(),\n self.version(),\n content,\n secret_hash\n );\n let nullifier = compute_message_nullifier(message_hash, secret, leaf_index);\n\n assert(\n !self.nullifier_exists(nullifier, self.this_address()), \"L1-to-L2 message is already nullified\"\n );\n assert(\n self.l1_to_l2_msg_exists(message_hash, leaf_index), \"Tried to consume nonexistent L1-to-L2 message\"\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0);\n }\n\n fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n send_l2_to_l1_msg(recipient, content);\n }\n\n fn call_public_function<RETURNS_COUNT>(\n self: &mut Self,\n contract_address: AztecAddress,\n temporary_function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts\n ) -> FunctionReturns<RETURNS_COUNT> {\n let results = call(\n gas_for_call(gas_opts),\n contract_address,\n args,\n temporary_function_selector.to_field()\n );\n let data_to_return: [Field; RETURNS_COUNT] = results.0;\n let success: u8 = results.1;\n assert(success == 1, \"Nested call failed!\");\n\n FunctionReturns::new(data_to_return)\n }\n\n fn static_call_public_function<RETURNS_COUNT>(\n self: &mut Self,\n contract_address: AztecAddress,\n temporary_function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts\n ) -> FunctionReturns<RETURNS_COUNT> {\n let (data_to_return, success): ([Field; RETURNS_COUNT], u8) = call_static(\n gas_for_call(gas_opts),\n contract_address,\n args,\n temporary_function_selector.to_field()\n );\n\n assert(success == 1, \"Nested static call failed!\");\n FunctionReturns::new(data_to_return)\n }\n\n fn delegate_call_public_function<RETURNS_COUNT>(\n self: &mut Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field]\n ) -> FunctionReturns<RETURNS_COUNT> {\n assert(false, \"'delegate_call_public_function' not implemented!\");\n FunctionReturns::new([0; RETURNS_COUNT])\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n emit_note_hash(note_hash);\n }\n fn push_new_nullifier(&mut self, nullifier: Field, _nullified_commitment: Field) {\n // Cannot nullify pending commitments in AVM, so `nullified_commitment` is not used\n emit_nullifier(nullifier);\n }\n fn msg_sender(self) -> AztecAddress {\n sender()\n }\n fn this_address(self) -> AztecAddress {\n address()\n }\n fn chain_id(self) -> Field {\n chain_id()\n }\n fn version(self) -> Field {\n version()\n }\n fn selector(self) -> FunctionSelector {\n FunctionSelector::from_field(self.inputs.selector)\n }\n fn get_args_hash(self) -> Field {\n self.inputs.args_hash\n }\n fn l2_gas_left(self) -> Field {\n l2_gas_left()\n }\n fn da_gas_left(self) -> Field {\n da_gas_left()\n }\n}\n\n// Helper functions\nfn gas_for_call(user_gas: GasOpts) -> [Field; 2] {\n // It's ok to use the max possible gas here, because the gas will be\n // capped by the gas left in the (STATIC)CALL instruction.\n let MAX_POSSIBLE_FIELD: Field = 0 - 1;\n [\n user_gas.l2_gas.unwrap_or(MAX_POSSIBLE_FIELD),\n user_gas.da_gas.unwrap_or(MAX_POSSIBLE_FIELD)\n ]\n}\n\n// Unconstrained opcode wrappers (do not use directly).\n// TODO(https://github.com/AztecProtocol/aztec-packages/issues/6420): reconsider.\nunconstrained fn address() -> AztecAddress {\n address_opcode()\n}\nunconstrained fn storage_address() -> AztecAddress {\n storage_address_opcode()\n}\nunconstrained fn sender() -> AztecAddress {\n sender_opcode()\n}\nunconstrained fn portal() -> EthAddress {\n portal_opcode()\n}\nunconstrained fn fee_per_l2_gas() -> Field {\n fee_per_l2_gas_opcode()\n}\nunconstrained fn fee_per_da_gas() -> Field {\n fee_per_da_gas_opcode()\n}\nunconstrained fn transaction_fee() -> Field {\n transaction_fee_opcode()\n}\nunconstrained fn chain_id() -> Field {\n chain_id_opcode()\n}\nunconstrained fn version() -> Field {\n version_opcode()\n}\nunconstrained fn block_number() -> Field {\n block_number_opcode()\n}\nunconstrained fn timestamp() -> u64 {\n timestamp_opcode()\n}\nunconstrained fn l2_gas_left() -> Field {\n l2_gas_left_opcode()\n}\nunconstrained fn da_gas_left() -> Field {\n da_gas_left_opcode()\n}\nunconstrained fn note_hash_exists(note_hash: Field, leaf_index: Field) -> u8 {\n note_hash_exists_opcode(note_hash, leaf_index)\n}\nunconstrained fn emit_note_hash(note_hash: Field) {\n emit_note_hash_opcode(note_hash)\n}\nunconstrained fn nullifier_exists(nullifier: Field, address: Field) -> u8 {\n nullifier_exists_opcode(nullifier, address)\n}\nunconstrained fn emit_nullifier(nullifier: Field) {\n emit_nullifier_opcode(nullifier)\n}\nunconstrained fn emit_unencrypted_log(event_selector: Field, message: [Field]) {\n emit_unencrypted_log_opcode(event_selector, message)\n}\nunconstrained fn l1_to_l2_msg_exists(msg_hash: Field, msg_leaf_index: Field) -> u8 {\n l1_to_l2_msg_exists_opcode(msg_hash, msg_leaf_index)\n}\nunconstrained fn send_l2_to_l1_msg(recipient: EthAddress, content: Field) {\n send_l2_to_l1_msg_opcode(recipient, content)\n}\nunconstrained fn call<RET_SIZE>(\n gas: [Field; 2],\n address: AztecAddress,\n args: [Field],\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {\n call_opcode(gas, address, args, function_selector)\n}\nunconstrained fn call_static<RET_SIZE>(\n gas: [Field; 2],\n address: AztecAddress,\n args: [Field],\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {\n call_static_opcode(gas, address, args, function_selector)\n}\n\nimpl Empty for PublicContext {\n fn empty() -> Self {\n PublicContext::new(PublicContextInputs::empty())\n }\n}\n\n// AVM oracles (opcodes) follow, do not use directly.\n#[oracle(avmOpcodeAddress)]\nunconstrained fn address_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodeStorageAddress)]\nunconstrained fn storage_address_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodeSender)]\nunconstrained fn sender_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodePortal)]\nunconstrained fn portal_opcode() -> EthAddress {}\n\n#[oracle(avmOpcodeFeePerL2Gas)]\nunconstrained fn fee_per_l2_gas_opcode() -> Field {}\n\n#[oracle(avmOpcodeFeePerDaGas)]\nunconstrained fn fee_per_da_gas_opcode() -> Field {}\n\n#[oracle(avmOpcodeTransactionFee)]\nunconstrained fn transaction_fee_opcode() -> Field {}\n\n#[oracle(avmOpcodeChainId)]\nunconstrained fn chain_id_opcode() -> Field {}\n\n#[oracle(avmOpcodeVersion)]\nunconstrained fn version_opcode() -> Field {}\n\n#[oracle(avmOpcodeBlockNumber)]\nunconstrained fn block_number_opcode() -> Field {}\n\n#[oracle(avmOpcodeTimestamp)]\nunconstrained fn timestamp_opcode() -> u64 {}\n\n#[oracle(avmOpcodeL2GasLeft)]\nunconstrained fn l2_gas_left_opcode() -> Field {}\n\n#[oracle(avmOpcodeDaGasLeft)]\nunconstrained fn da_gas_left_opcode() -> Field {}\n\n#[oracle(avmOpcodeNoteHashExists)]\nunconstrained fn note_hash_exists_opcode(note_hash: Field, leaf_index: Field) -> u8 {}\n\n#[oracle(avmOpcodeEmitNoteHash)]\nunconstrained fn emit_note_hash_opcode(note_hash: Field) {}\n\n#[oracle(avmOpcodeNullifierExists)]\nunconstrained fn nullifier_exists_opcode(nullifier: Field, address: Field) -> u8 {}\n\n#[oracle(avmOpcodeEmitNullifier)]\nunconstrained fn emit_nullifier_opcode(nullifier: Field) {}\n\n#[oracle(amvOpcodeEmitUnencryptedLog)]\nunconstrained fn emit_unencrypted_log_opcode(event_selector: Field, message: [Field]) {}\n\n#[oracle(avmOpcodeL1ToL2MsgExists)]\nunconstrained fn l1_to_l2_msg_exists_opcode(msg_hash: Field, msg_leaf_index: Field) -> u8 {}\n\n#[oracle(avmOpcodeSendL2ToL1Msg)]\nunconstrained fn send_l2_to_l1_msg_opcode(recipient: EthAddress, content: Field) {}\n\n#[oracle(avmOpcodeCall)]\nunconstrained fn call_opcode<RET_SIZE>(\n gas: [Field; 2], // gas allocation: [l2_gas, da_gas]\n address: AztecAddress,\n args: [Field],\n // TODO(5110): consider passing in calldata directly\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {}\n// ^ return data ^ success\n\n#[oracle(avmOpcodeStaticCall)]\nunconstrained fn call_static_opcode<RET_SIZE>(\n gas: [Field; 2], // gas allocation: [l2_gas, da_gas]\n address: AztecAddress,\n args: [Field],\n // TODO(5110): consider passing in calldata directly\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {}\n// ^ return data ^ success\n\nstruct FunctionReturns<N> {\n values: [Field; N]\n}\n\nimpl<N> FunctionReturns<N> {\n pub fn new(values: [Field; N]) -> FunctionReturns<N> {\n FunctionReturns { values }\n }\n\n pub fn assert_empty(returns: FunctionReturns<0>) {\n assert(returns.values.len() == 0);\n }\n\n pub fn raw(self) -> [Field; N] {\n self.values\n }\n\n pub fn deserialize_into<T>(self) -> T where T: Deserialize<N> {\n Deserialize::deserialize(self.raw())\n }\n}\n" } } }